145039663SJohn Forte /*
245039663SJohn Forte  * CDDL HEADER START
345039663SJohn Forte  *
445039663SJohn Forte  * The contents of this file are subject to the terms of the
545039663SJohn Forte  * Common Development and Distribution License (the "License").
645039663SJohn Forte  * You may not use this file except in compliance with the License.
745039663SJohn Forte  *
845039663SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945039663SJohn Forte  * or http://www.opensolaris.org/os/licensing.
1045039663SJohn Forte  * See the License for the specific language governing permissions
1145039663SJohn Forte  * and limitations under the License.
1245039663SJohn Forte  *
1345039663SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
1445039663SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545039663SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
1645039663SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
1745039663SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
1845039663SJohn Forte  *
1945039663SJohn Forte  * CDDL HEADER END
2045039663SJohn Forte  */
2145039663SJohn Forte /*
2291159e90SJohn Forte  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2345039663SJohn Forte  */
2445039663SJohn Forte 
2545039663SJohn Forte /*
2645039663SJohn Forte  * XXX TODO
2745039663SJohn Forte  * #includes cribbed from stmf.c -- undoubtedly only a small subset of these
2845039663SJohn Forte  * are actually needed.
2945039663SJohn Forte  */
3045039663SJohn Forte #include <sys/conf.h>
3145039663SJohn Forte #include <sys/file.h>
3245039663SJohn Forte #include <sys/ddi.h>
3345039663SJohn Forte #include <sys/sunddi.h>
3445039663SJohn Forte #include <sys/scsi/scsi.h>
35716c1805SNattuvetty Bhavyan #include <sys/scsi/generic/persist.h>
3645039663SJohn Forte #include <sys/byteorder.h>
3745039663SJohn Forte #include <sys/nvpair.h>
3845039663SJohn Forte #include <sys/door.h>
3945039663SJohn Forte 
4045039663SJohn Forte #include <sys/stmf.h>
4145039663SJohn Forte #include <sys/lpif.h>
4245039663SJohn Forte #include <sys/stmf_ioctl.h>
4345039663SJohn Forte #include <sys/portif.h>
4445039663SJohn Forte #include <sys/pppt_ic_if.h>
4545039663SJohn Forte 
464558d122SViswanathan Kannappan #include "pppt.h"
4745039663SJohn Forte 
4845039663SJohn Forte /*
4945039663SJohn Forte  * Macros
5045039663SJohn Forte  */
5145039663SJohn Forte 
5245039663SJohn Forte /* Free a struct if it was allocated */
5345039663SJohn Forte #define	FREE_IF_ALLOC(m)					\
5445039663SJohn Forte 	do {							\
5545039663SJohn Forte 		if ((m)) kmem_free((m), sizeof (*(m)));		\
5645039663SJohn Forte 		_NOTE(CONSTCOND)				\
5745039663SJohn Forte 	} while (0)
5845039663SJohn Forte 
5945039663SJohn Forte /*
6045039663SJohn Forte  * Macros to simplify the addition of struct fields to an nvlist.
6145039663SJohn Forte  * The name of the fields in the nvlist is the same as the name
6245039663SJohn Forte  * of the struct field.
6345039663SJohn Forte  *
6445039663SJohn Forte  * These macros require an int rc and a "done:" return retval label;
6545039663SJohn Forte  * they assume that the nvlist is named "nvl".
6645039663SJohn Forte  */
6745039663SJohn Forte #define	NVLIST_ADD_FIELD(type, structure, field)			\
6845039663SJohn Forte 	do {								\
6945039663SJohn Forte 		rc = nvlist_add_##type(nvl, #field, structure->field);  \
7045039663SJohn Forte 		if (rc) goto done;					\
7145039663SJohn Forte 		_NOTE(CONSTCOND)					\
7245039663SJohn Forte 	} while (0)
7345039663SJohn Forte 
7445039663SJohn Forte /* use this macro when the array is defined as part of the struct */
7545039663SJohn Forte #define	NVLIST_ADD_ARRAY(type, structure, field)			\
7645039663SJohn Forte 	do {								\
7745039663SJohn Forte 		rc = nvlist_add_##type##_array(nvl, #field,		\
7845039663SJohn Forte 		    structure->field, sizeof (structure->field));	\
7945039663SJohn Forte 		if (rc) goto done;					\
8045039663SJohn Forte 		_NOTE(CONSTCOND)					\
8145039663SJohn Forte 	} while (0)
8245039663SJohn Forte 
8345039663SJohn Forte /*
8445039663SJohn Forte  * use this macro when the array field is a ptr or you need to explictly
8545039663SJohn Forte  * call out the size.
8645039663SJohn Forte  */
8745039663SJohn Forte #define	NVLIST_ADD_ARRAY_LEN(type, structure, field, len)		\
8845039663SJohn Forte 	do {								\
8945039663SJohn Forte 		rc = nvlist_add_##type##_array(nvl, #field,		\
9045039663SJohn Forte 		    structure->field, len);				\
9145039663SJohn Forte 		if (rc) goto done;					\
9245039663SJohn Forte 		_NOTE(CONSTCOND)					\
9345039663SJohn Forte 	} while (0)
9445039663SJohn Forte 
9545039663SJohn Forte #define	NVLIST_ADD_DEVID(structure, field)				\
9645039663SJohn Forte 	do {								\
9745039663SJohn Forte 		rc = stmf_ic_scsi_devid_desc_marshal(nvl, #field,	\
9845039663SJohn Forte 		    structure->field);					\
9945039663SJohn Forte 		if (rc) goto done;					\
10045039663SJohn Forte 		_NOTE(CONSTCOND)					\
10145039663SJohn Forte 	} while (0)
10245039663SJohn Forte 
103716c1805SNattuvetty Bhavyan #define	NVLIST_ADD_RPORT(structure, field)				\
104716c1805SNattuvetty Bhavyan 	do {								\
105716c1805SNattuvetty Bhavyan 		rc = stmf_ic_remote_port_marshal(nvl, #field,		\
106716c1805SNattuvetty Bhavyan 		    structure->field);					\
107716c1805SNattuvetty Bhavyan 		if (rc) goto done;					\
108716c1805SNattuvetty Bhavyan 		_NOTE(CONSTCOND)					\
109716c1805SNattuvetty Bhavyan 	} while (0)
110716c1805SNattuvetty Bhavyan 
11145039663SJohn Forte #define	NVLIST_ADD_FIELD_UINT8(structure, field)			\
11245039663SJohn Forte 	NVLIST_ADD_FIELD(structure, field, uint8)
11345039663SJohn Forte 
11445039663SJohn Forte /*
11545039663SJohn Forte  * Macros to simplify the extraction of struct fields from an nvlist.
11645039663SJohn Forte  * The name of the fields in the nvlist is the same as the name
11745039663SJohn Forte  * of the struct field.
11845039663SJohn Forte  *
11945039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
12045039663SJohn Forte  * Assumes that the nvlist is named "nvl".
12145039663SJohn Forte  *
12245039663SJohn Forte  * Sample usage: NVLIST_LOOKUP_FIELD(uint8, structname, fieldname);
12345039663SJohn Forte  */
12445039663SJohn Forte #define	NVLIST_LOOKUP_FIELD(type, structure, field)			\
12545039663SJohn Forte 	do {								\
12645039663SJohn Forte 		rc = nvlist_lookup_##type(nvl, #field,			\
12745039663SJohn Forte 		    &(structure->field));				\
12845039663SJohn Forte 		if (rc) { 						\
12945039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
13045039663SJohn Forte 			goto done;					\
13145039663SJohn Forte 		}							\
13245039663SJohn Forte 		_NOTE(CONSTCOND)					\
13345039663SJohn Forte 	} while (0)
13445039663SJohn Forte 
13545039663SJohn Forte /*
13645039663SJohn Forte  * Look up a field which gets stored into a structure bit field.
13745039663SJohn Forte  * The type passed is a uint type which can hold the largest value
13845039663SJohn Forte  * in the bit field.
13945039663SJohn Forte  *
14045039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
14145039663SJohn Forte  * Assumes that the nvlist is named "nvl".
14245039663SJohn Forte  *
14345039663SJohn Forte  * Sample usage: NVLIST_LOOKUP_BIT_FIELD(uint8, structname, fieldname);
14445039663SJohn Forte  */
14545039663SJohn Forte #define	NVLIST_LOOKUP_BIT_FIELD(type, structure, field)			\
14645039663SJohn Forte 	do {								\
14745039663SJohn Forte 		type##_t tmp;						\
14845039663SJohn Forte 		rc = nvlist_lookup_##type(nvl, #field, &tmp);		\
14945039663SJohn Forte 		if (rc) { 						\
15045039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
15145039663SJohn Forte 			goto done;					\
15245039663SJohn Forte 		}							\
15345039663SJohn Forte 		structure->field = tmp;					\
15445039663SJohn Forte 		_NOTE(CONSTCOND)					\
15545039663SJohn Forte 	} while (0)
15645039663SJohn Forte 
15745039663SJohn Forte /*
15845039663SJohn Forte  * Look up a boolean field which gets stored into a structure bit field.
15945039663SJohn Forte  *
16045039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
16145039663SJohn Forte  * Assumes that the nvlist is named "nvl".
16245039663SJohn Forte  */
16345039663SJohn Forte #define	NVLIST_LOOKUP_BIT_FIELD_BOOLEAN(structure, field)		\
16445039663SJohn Forte 	do {								\
16545039663SJohn Forte 		boolean_t tmp;						\
16645039663SJohn Forte 		rc = nvlist_lookup_boolean_value(nvl, #field, &tmp);	\
16745039663SJohn Forte 		if (rc) { 						\
16845039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
16945039663SJohn Forte 			goto done;					\
17045039663SJohn Forte 		}							\
17145039663SJohn Forte 		structure->field = (tmp ?  1 : 0);			\
17245039663SJohn Forte 		_NOTE(CONSTCOND)					\
17345039663SJohn Forte 	} while (0)
17445039663SJohn Forte 
17545039663SJohn Forte /* shorthand  for nvlist_lookup_pairs() args */
17645039663SJohn Forte #define	NV_PAIR(type, strct, field) #field, DATA_TYPE_##type, &(strct->field)
17745039663SJohn Forte 
17845039663SJohn Forte /* number of times to retry the upcall to transmit */
17945039663SJohn Forte #define	STMF_MSG_TRANSMIT_RETRY	    3
18045039663SJohn Forte 
18145039663SJohn Forte /*
18245039663SJohn Forte  * How was the message constructed?
18345039663SJohn Forte  *
18445039663SJohn Forte  * We need to know this when we free the message in order to
18545039663SJohn Forte  * determine what to do with pointers in the message:
18645039663SJohn Forte  *
18745039663SJohn Forte  * - messages which were unmarshaled from an nvlist may point to
18845039663SJohn Forte  *   memory within that nvlist; this memory should not be freed since
18945039663SJohn Forte  *   it will be deallocated when we free the nvlist.
19045039663SJohn Forte  *
19145039663SJohn Forte  * - messages which built using a constructor (alloc) function may
19245039663SJohn Forte  *   point to memory which was explicitly allocated by the constructor;
19345039663SJohn Forte  *   it should be freed when the message is freed.
19445039663SJohn Forte  *
19545039663SJohn Forte  */
19645039663SJohn Forte typedef enum {
19745039663SJohn Forte 	STMF_CONSTRUCTOR = 0,
19845039663SJohn Forte 	STMF_UNMARSHAL
19945039663SJohn Forte } stmf_ic_msg_construction_method_t;
20045039663SJohn Forte 
20145039663SJohn Forte 
20245039663SJohn Forte /*
20345039663SJohn Forte  * Function prototypes.
20445039663SJohn Forte  */
20545039663SJohn Forte 
20645039663SJohn Forte /*
20745039663SJohn Forte  * Helpers for msg_alloc routines, used when the msg payload is
20845039663SJohn Forte  * the same for multiple types of messages.
20945039663SJohn Forte  */
21045039663SJohn Forte static stmf_ic_msg_t *stmf_ic_reg_dereg_lun_msg_alloc(
21145039663SJohn Forte     stmf_ic_msg_type_t msg_type, uint8_t *lun_id,
21245039663SJohn Forte     char *lu_provider_name, uint16_t cb_arg_len,
21345039663SJohn Forte     uint8_t *cb_arg, stmf_ic_msgid_t msgid);
21445039663SJohn Forte 
21545039663SJohn Forte static stmf_ic_msg_t *stmf_ic_session_create_destroy_msg_alloc(
21645039663SJohn Forte     stmf_ic_msg_type_t msg_type,
21745039663SJohn Forte     stmf_scsi_session_t *session,
21845039663SJohn Forte     stmf_ic_msgid_t msgid);
21945039663SJohn Forte 
22045039663SJohn Forte static stmf_ic_msg_t *stmf_ic_echo_request_reply_msg_alloc(
22145039663SJohn Forte     stmf_ic_msg_type_t msg_type,
22245039663SJohn Forte     uint32_t data_len,
22345039663SJohn Forte     uint8_t *data,
22445039663SJohn Forte     stmf_ic_msgid_t msgid);
22545039663SJohn Forte 
22645039663SJohn Forte /*
22745039663SJohn Forte  * Msg free routines.
22845039663SJohn Forte  */
22945039663SJohn Forte static void stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
23045039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
23145039663SJohn Forte static void stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
23245039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
23345039663SJohn Forte static void stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
23445039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
23545039663SJohn Forte static void stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
23645039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
23745039663SJohn Forte static void stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
23845039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
23945039663SJohn Forte static void stmf_ic_scsi_data_xfer_done_msg_free(
24045039663SJohn Forte     stmf_ic_scsi_data_xfer_done_msg_t *m,
24145039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
24245039663SJohn Forte static void stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
24345039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
24445039663SJohn Forte static void stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
24545039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
24645039663SJohn Forte static void stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
24745039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
24845039663SJohn Forte static void stmf_ic_session_create_destroy_msg_free(
24945039663SJohn Forte     stmf_ic_session_create_destroy_msg_t *m,
25045039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
25145039663SJohn Forte static void stmf_ic_echo_request_reply_msg_free(
25245039663SJohn Forte     stmf_ic_echo_request_reply_msg_t *m,
25345039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
25445039663SJohn Forte 
25545039663SJohn Forte /*
25645039663SJohn Forte  * Marshaling routines.
25745039663SJohn Forte  */
25845039663SJohn Forte static nvlist_t *stmf_ic_msg_marshal(stmf_ic_msg_t *msg);
25945039663SJohn Forte static int stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg);
26045039663SJohn Forte static int stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg);
26145039663SJohn Forte static int stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg);
26245039663SJohn Forte static int stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg);
26345039663SJohn Forte static int stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg);
26445039663SJohn Forte static int stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg);
26545039663SJohn Forte static int stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg);
26645039663SJohn Forte static int stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg);
26745039663SJohn Forte static int stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg);
26845039663SJohn Forte static int stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg);
26945039663SJohn Forte static int stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg);
27045039663SJohn Forte static int stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
27145039663SJohn Forte 	char *sdid_name, scsi_devid_desc_t *sdid);
272716c1805SNattuvetty Bhavyan static int stmf_ic_remote_port_marshal(nvlist_t *parent_nvl,
273716c1805SNattuvetty Bhavyan 	char *rport_name, stmf_remote_port_t *rport);
27445039663SJohn Forte 
27545039663SJohn Forte /*
27645039663SJohn Forte  * Unmarshaling routines.
27745039663SJohn Forte  */
27845039663SJohn Forte static stmf_ic_msg_t *stmf_ic_msg_unmarshal(nvlist_t *nvl);
27945039663SJohn Forte static void *stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl);
28045039663SJohn Forte static void *stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl);
28145039663SJohn Forte static void *stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl);
28245039663SJohn Forte static void *stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl);
28345039663SJohn Forte static void *stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl);
28445039663SJohn Forte static void *stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl);
28545039663SJohn Forte static void *stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl);
28645039663SJohn Forte static void *stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl);
28745039663SJohn Forte static void *stmf_ic_status_msg_unmarshal(nvlist_t *nvl);
28845039663SJohn Forte static void *stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl);
28945039663SJohn Forte static void *stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl);
29045039663SJohn Forte static scsi_devid_desc_t *stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
29145039663SJohn Forte     nvlist_t *nvl, char *field_name);
29245039663SJohn Forte static scsi_devid_desc_t *stmf_ic_scsi_devid_desc_unmarshal(
29345039663SJohn Forte     nvlist_t *nvl_devid);
29445039663SJohn Forte static uint8_t *stmf_ic_uint8_array_unmarshal(nvlist_t *nvl, char *field_name,
29591159e90SJohn Forte 	uint64_t len, uint8_t *buf);
29645039663SJohn Forte static char *stmf_ic_string_unmarshal(nvlist_t *nvl, char *field_name);
297716c1805SNattuvetty Bhavyan static stmf_remote_port_t *stmf_ic_lookup_remote_port_and_unmarshal(
298716c1805SNattuvetty Bhavyan 	nvlist_t *nvl, char *field_name);
299716c1805SNattuvetty Bhavyan static stmf_remote_port_t *stmf_ic_remote_port_unmarshal(nvlist_t *nvl);
30045039663SJohn Forte 
30145039663SJohn Forte /*
30245039663SJohn Forte  * Transmit and recieve routines.
30345039663SJohn Forte  */
30445039663SJohn Forte stmf_ic_msg_status_t stmf_ic_transmit(char *buf, size_t size);
30545039663SJohn Forte 
30645039663SJohn Forte /*
30745039663SJohn Forte  * Utilities.
30845039663SJohn Forte  */
30945039663SJohn Forte static stmf_ic_msg_t *stmf_ic_alloc_msg_header(stmf_ic_msg_type_t msg_type,
31045039663SJohn Forte 	stmf_ic_msgid_t msgid);
31145039663SJohn Forte static size_t sizeof_scsi_devid_desc(int ident_length);
31245039663SJohn Forte static char *stmf_ic_strdup(char *str);
31345039663SJohn Forte static scsi_devid_desc_t *scsi_devid_desc_dup(scsi_devid_desc_t *did);
314716c1805SNattuvetty Bhavyan static stmf_remote_port_t *remote_port_dup(stmf_remote_port_t *rport);
31545039663SJohn Forte static void scsi_devid_desc_free(scsi_devid_desc_t *did);
31645039663SJohn Forte static inline void stmf_ic_nvlookup_warn(const char *func, char *field);
31745039663SJohn Forte 
31845039663SJohn Forte /*
31945039663SJohn Forte  * Send a message out over the interconnect, in the process marshalling
32045039663SJohn Forte  * the arguments.
32145039663SJohn Forte  *
32245039663SJohn Forte  * After being sent, the message is freed.
32345039663SJohn Forte  */
32445039663SJohn Forte stmf_ic_msg_status_t
32545039663SJohn Forte stmf_ic_tx_msg(stmf_ic_msg_t *msg)
32645039663SJohn Forte {
32745039663SJohn Forte 	size_t size = 0;
32845039663SJohn Forte 	nvlist_t *nvl = NULL;
32945039663SJohn Forte 	char *buf = NULL;
33045039663SJohn Forte 	int err = 0;
33145039663SJohn Forte 	stmf_ic_msg_status_t status = STMF_IC_MSG_SUCCESS;
33245039663SJohn Forte 
33345039663SJohn Forte 	nvl = stmf_ic_msg_marshal(msg);
33445039663SJohn Forte 	if (!nvl) {
33545039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_tx_msg: marshal failed");
33645039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
33745039663SJohn Forte 		goto done;
33845039663SJohn Forte 	}
33945039663SJohn Forte 
34045039663SJohn Forte 	err = nvlist_size(nvl, &size, NV_ENCODE_XDR);
34145039663SJohn Forte 	if (err) {
34245039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
34345039663SJohn Forte 		goto done;
34445039663SJohn Forte 	}
34545039663SJohn Forte 
34645039663SJohn Forte 	buf = kmem_alloc(size, KM_SLEEP);
34745039663SJohn Forte 	err = nvlist_pack(nvl, &buf, &size, NV_ENCODE_XDR, 0);
34845039663SJohn Forte 	if (err) {
34945039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
35045039663SJohn Forte 		goto done;
35145039663SJohn Forte 	}
35245039663SJohn Forte 
35345039663SJohn Forte 	/* push the bits out on the wire */
35445039663SJohn Forte 
35545039663SJohn Forte 	status = stmf_ic_transmit(buf, size);
35645039663SJohn Forte 
35745039663SJohn Forte done:
35845039663SJohn Forte 	if (nvl)
35945039663SJohn Forte 		nvlist_free(nvl);
36045039663SJohn Forte 
36145039663SJohn Forte 	if (buf)
36245039663SJohn Forte 		kmem_free(buf, size);
36345039663SJohn Forte 
36445039663SJohn Forte 	stmf_ic_msg_free(msg);
36545039663SJohn Forte 
36645039663SJohn Forte 
36745039663SJohn Forte 	return (status);
36845039663SJohn Forte }
36945039663SJohn Forte 
37045039663SJohn Forte /*
37145039663SJohn Forte  * Pass the command to the daemon for transmission to the other node.
37245039663SJohn Forte  */
37345039663SJohn Forte stmf_ic_msg_status_t
37445039663SJohn Forte stmf_ic_transmit(char *buf, size_t size)
37545039663SJohn Forte {
37645039663SJohn Forte 	int i;
37745039663SJohn Forte 	int rc;
37845039663SJohn Forte 	door_arg_t arg;
37945039663SJohn Forte 	door_handle_t door;
38045039663SJohn Forte 	uint32_t result;
38145039663SJohn Forte 
38245039663SJohn Forte 	mutex_enter(&pppt_global.global_door_lock);
38345039663SJohn Forte 	if (pppt_global.global_door == NULL) {
38445039663SJohn Forte 		/* daemon not listening */
38545039663SJohn Forte 		mutex_exit(&pppt_global.global_door_lock);
38645039663SJohn Forte 		return (STMF_IC_MSG_INTERNAL_ERROR);
38745039663SJohn Forte 	}
38845039663SJohn Forte 	door = pppt_global.global_door;
38945039663SJohn Forte 	door_ki_hold(door);
39045039663SJohn Forte 	mutex_exit(&pppt_global.global_door_lock);
39145039663SJohn Forte 
39245039663SJohn Forte 	arg.data_ptr = buf;
39345039663SJohn Forte 	arg.data_size = size;
39445039663SJohn Forte 	arg.desc_ptr = NULL;
39545039663SJohn Forte 	arg.desc_num = 0;
39645039663SJohn Forte 	arg.rbuf = (char *)&result;
39745039663SJohn Forte 	arg.rsize = sizeof (result);
39845039663SJohn Forte 	/*
39945039663SJohn Forte 	 * Retry a few times if there is a shortage of threads to
40045039663SJohn Forte 	 * service the upcall. This shouldn't happen unless a large
40145039663SJohn Forte 	 * number of initiators issue commands at once.
40245039663SJohn Forte 	 */
40345039663SJohn Forte 	for (i = 0; i < STMF_MSG_TRANSMIT_RETRY; i++) {
40445039663SJohn Forte 		rc = door_ki_upcall(door, &arg);
40545039663SJohn Forte 		if (rc != EAGAIN)
40645039663SJohn Forte 			break;
40745039663SJohn Forte 		delay(hz);
40845039663SJohn Forte 	}
40945039663SJohn Forte 	door_ki_rele(door);
41045039663SJohn Forte 	if (rc != 0) {
41145039663SJohn Forte 		cmn_err(CE_WARN,
41245039663SJohn Forte 		    "stmf_ic_transmit door_ki_upcall failed %d", rc);
41345039663SJohn Forte 		return (STMF_IC_MSG_INTERNAL_ERROR);
41445039663SJohn Forte 	}
41545039663SJohn Forte 	if (result != 0) {
41645039663SJohn Forte 		/* XXX Just warn for now */
41745039663SJohn Forte 		cmn_err(CE_WARN,
41845039663SJohn Forte 		    "stmf_ic_transmit bad result from daemon %d", result);
41945039663SJohn Forte 	}
42045039663SJohn Forte 
42145039663SJohn Forte 	return (STMF_IC_MSG_SUCCESS);
42245039663SJohn Forte }
42345039663SJohn Forte 
42445039663SJohn Forte /*
42545039663SJohn Forte  * This is a low-level upcall which is called when a message has
42645039663SJohn Forte  * been received on the interconnect.
42745039663SJohn Forte  *
42845039663SJohn Forte  * The caller is responsible for freeing the buffer which is passed in.
42945039663SJohn Forte  */
43045039663SJohn Forte /*ARGSUSED*/
43145039663SJohn Forte void
43245039663SJohn Forte stmf_ic_rx_msg(char *buf, size_t len)
43345039663SJohn Forte {
43445039663SJohn Forte 	nvlist_t *nvl = NULL;
43545039663SJohn Forte 	stmf_ic_msg_t *m = NULL;
43645039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *icerr;
43745039663SJohn Forte 	stmf_ic_msg_t *echo_msg;
43845039663SJohn Forte 	int rc = 0;
43945039663SJohn Forte 
44045039663SJohn Forte 	rc = nvlist_unpack(buf, len, &nvl, 0);
44145039663SJohn Forte 	if (rc) {
44245039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unpack failed");
44345039663SJohn Forte 		return;
44445039663SJohn Forte 	}
44545039663SJohn Forte 
44645039663SJohn Forte 	m = stmf_ic_msg_unmarshal(nvl);
44745039663SJohn Forte 	if (m == NULL) {
44845039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unmarshal failed");
44945039663SJohn Forte 		nvlist_free(nvl);
45045039663SJohn Forte 		return;
45145039663SJohn Forte 	}
45245039663SJohn Forte 
45345039663SJohn Forte 	switch (m->icm_msg_type) {
45445039663SJohn Forte 
45545039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
45645039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
45745039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
45845039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
45945039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
46045039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
46145039663SJohn Forte 		/*
46245039663SJohn Forte 		 * These messages are all received by pppt.
46345039663SJohn Forte 		 * Currently, pppt will parse the message for type
46445039663SJohn Forte 		 */
46545039663SJohn Forte 		(void) pppt_msg_rx(m);
46645039663SJohn Forte 		break;
46745039663SJohn Forte 
46845039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
46945039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
47045039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
47145039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
47245039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
47345039663SJohn Forte 		/*
47445039663SJohn Forte 		 * These messages are all received by stmf.
47545039663SJohn Forte 		 * Currently, stmf will parse the message for type
47645039663SJohn Forte 		 */
47745039663SJohn Forte 		(void) stmf_msg_rx(m);
47845039663SJohn Forte 		break;
47945039663SJohn Forte 
48045039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
48145039663SJohn Forte 		icerr = m->icm_msg;
48245039663SJohn Forte 		echo_msg = stmf_ic_echo_reply_msg_alloc(icerr->icerr_datalen,
48345039663SJohn Forte 		    icerr->icerr_data, 0);
48445039663SJohn Forte 		if (echo_msg != NULL) {
48545039663SJohn Forte 			(void) stmf_ic_tx_msg(echo_msg);
48645039663SJohn Forte 		}
48745039663SJohn Forte 		stmf_ic_msg_free(m);
48845039663SJohn Forte 		break;
48945039663SJohn Forte 
49045039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
49145039663SJohn Forte 		stmf_ic_msg_free(m);
49245039663SJohn Forte 		break;
49345039663SJohn Forte 
49445039663SJohn Forte 	case STMF_ICM_R2T:
49545039663SJohn Forte 		/*
49645039663SJohn Forte 		 * XXX currently not supported
49745039663SJohn Forte 		 */
49845039663SJohn Forte 		stmf_ic_msg_free(m);
49945039663SJohn Forte 		break;
50045039663SJohn Forte 
50145039663SJohn Forte 	case STMF_ICM_STATUS:
50245039663SJohn Forte 		(void) stmf_msg_rx(m);
50345039663SJohn Forte 		break;
50445039663SJohn Forte 
50545039663SJohn Forte 	default:
50645039663SJohn Forte 		ASSERT(0);
50745039663SJohn Forte 	}
50845039663SJohn Forte }
50945039663SJohn Forte 
51045039663SJohn Forte /*
51145039663SJohn Forte  * IC message allocation routines.
51245039663SJohn Forte  */
51345039663SJohn Forte 
51445039663SJohn Forte stmf_ic_msg_t *
51545039663SJohn Forte stmf_ic_reg_port_msg_alloc(
51645039663SJohn Forte     scsi_devid_desc_t *port_id,
51745039663SJohn Forte     uint16_t relative_port_id,
51845039663SJohn Forte     uint16_t cb_arg_len,
51945039663SJohn Forte     uint8_t *cb_arg,
52045039663SJohn Forte     stmf_ic_msgid_t msgid)
52145039663SJohn Forte {
52245039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
52345039663SJohn Forte 	stmf_ic_reg_port_msg_t *icrp = NULL;
52445039663SJohn Forte 
52545039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_REGISTER_PROXY_PORT, msgid);
52645039663SJohn Forte 	icrp = (stmf_ic_reg_port_msg_t *)kmem_zalloc(sizeof (*icrp), KM_SLEEP);
52745039663SJohn Forte 	icm->icm_msg = (void *)icrp;
52845039663SJohn Forte 
52945039663SJohn Forte 	icrp->icrp_port_id = scsi_devid_desc_dup(port_id);
53045039663SJohn Forte 	icrp->icrp_relative_port_id = relative_port_id;
53145039663SJohn Forte 
53245039663SJohn Forte 	if (cb_arg_len) {
53345039663SJohn Forte 		icrp->icrp_cb_arg_len = cb_arg_len;
53445039663SJohn Forte 		icrp->icrp_cb_arg = cb_arg;
53545039663SJohn Forte 	}
53645039663SJohn Forte 
53745039663SJohn Forte 	return (icm);
53845039663SJohn Forte }
53945039663SJohn Forte 
54045039663SJohn Forte stmf_ic_msg_t *
54145039663SJohn Forte stmf_ic_dereg_port_msg_alloc(
54245039663SJohn Forte     scsi_devid_desc_t *port_id,
54345039663SJohn Forte     uint16_t cb_arg_len,
54445039663SJohn Forte     uint8_t *cb_arg,
54545039663SJohn Forte     stmf_ic_msgid_t msgid)
54645039663SJohn Forte {
54745039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
54845039663SJohn Forte 	stmf_ic_dereg_port_msg_t *icdp = NULL;
54945039663SJohn Forte 
55045039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_DEREGISTER_PROXY_PORT, msgid);
55145039663SJohn Forte 	icdp = (stmf_ic_dereg_port_msg_t *)kmem_zalloc(sizeof (*icdp),
55245039663SJohn Forte 	    KM_SLEEP);
55345039663SJohn Forte 	icm->icm_msg = (void *)icdp;
55445039663SJohn Forte 
55545039663SJohn Forte 	icdp->icdp_port_id = scsi_devid_desc_dup(port_id);
55645039663SJohn Forte 
55745039663SJohn Forte 	if (cb_arg_len) {
55845039663SJohn Forte 		icdp->icdp_cb_arg_len = cb_arg_len;
55945039663SJohn Forte 		icdp->icdp_cb_arg = cb_arg;
56045039663SJohn Forte 	}
56145039663SJohn Forte 
56245039663SJohn Forte 	return (icm);
56345039663SJohn Forte }
56445039663SJohn Forte 
56545039663SJohn Forte 
56645039663SJohn Forte stmf_ic_msg_t *
56745039663SJohn Forte stmf_ic_reg_lun_msg_alloc(
56845039663SJohn Forte     uint8_t *lun_id,
56945039663SJohn Forte     char *lu_provider_name,
57045039663SJohn Forte     uint16_t cb_arg_len,
57145039663SJohn Forte     uint8_t *cb_arg,
57245039663SJohn Forte     stmf_ic_msgid_t msgid)
57345039663SJohn Forte {
57445039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_REGISTER_LUN, lun_id,
57545039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
57645039663SJohn Forte }
57745039663SJohn Forte 
57845039663SJohn Forte stmf_ic_msg_t *
57945039663SJohn Forte stmf_ic_lun_active_msg_alloc(
58045039663SJohn Forte     uint8_t *lun_id,
58145039663SJohn Forte     char *lu_provider_name,
58245039663SJohn Forte     uint16_t cb_arg_len,
58345039663SJohn Forte     uint8_t *cb_arg,
58445039663SJohn Forte     stmf_ic_msgid_t msgid)
58545039663SJohn Forte {
58645039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_LUN_ACTIVE, lun_id,
58745039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
58845039663SJohn Forte }
58945039663SJohn Forte 
59045039663SJohn Forte stmf_ic_msg_t *
59145039663SJohn Forte stmf_ic_dereg_lun_msg_alloc(
59245039663SJohn Forte     uint8_t *lun_id,
59345039663SJohn Forte     char *lu_provider_name,
59445039663SJohn Forte     uint16_t cb_arg_len,
59545039663SJohn Forte     uint8_t *cb_arg,
59645039663SJohn Forte     stmf_ic_msgid_t msgid)
59745039663SJohn Forte {
59845039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_DEREGISTER_LUN, lun_id,
59945039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
60045039663SJohn Forte }
60145039663SJohn Forte 
60245039663SJohn Forte /*
60345039663SJohn Forte  * Guts of lun register/deregister/active alloc routines.
60445039663SJohn Forte  */
60545039663SJohn Forte static stmf_ic_msg_t *
60645039663SJohn Forte stmf_ic_reg_dereg_lun_msg_alloc(
60745039663SJohn Forte     stmf_ic_msg_type_t msg_type,
60845039663SJohn Forte     uint8_t *lun_id,
60945039663SJohn Forte     char *lu_provider_name,
61045039663SJohn Forte     uint16_t cb_arg_len,
61145039663SJohn Forte     uint8_t *cb_arg,
61245039663SJohn Forte     stmf_ic_msgid_t msgid)
61345039663SJohn Forte {
61445039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
61545039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *icrl = NULL;
61645039663SJohn Forte 
61745039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
61845039663SJohn Forte 	icrl = (stmf_ic_reg_dereg_lun_msg_t *)
61945039663SJohn Forte 	    kmem_zalloc(sizeof (*icrl), KM_SLEEP);
62045039663SJohn Forte 	icm->icm_msg = (void *)icrl;
62145039663SJohn Forte 
62245039663SJohn Forte 	icrl->icrl_lu_provider_name = stmf_ic_strdup(lu_provider_name);
62345039663SJohn Forte 
62445039663SJohn Forte 	bcopy(lun_id, icrl->icrl_lun_id, sizeof (icrl->icrl_lun_id));
62545039663SJohn Forte 
62645039663SJohn Forte 	if (cb_arg_len) {
62745039663SJohn Forte 		icrl->icrl_cb_arg_len = cb_arg_len;
62845039663SJohn Forte 		icrl->icrl_cb_arg = cb_arg;
62945039663SJohn Forte 	}
63045039663SJohn Forte 
63145039663SJohn Forte 	return (icm);
63245039663SJohn Forte }
63345039663SJohn Forte 
63445039663SJohn Forte stmf_ic_msg_t *
63545039663SJohn Forte stmf_ic_scsi_cmd_msg_alloc(
63645039663SJohn Forte     stmf_ic_msgid_t task_msgid,
63745039663SJohn Forte     scsi_task_t *task,
63845039663SJohn Forte     uint32_t immed_data_len,
63945039663SJohn Forte     uint8_t *immed_data,
64045039663SJohn Forte     stmf_ic_msgid_t msgid)
64145039663SJohn Forte {
64245039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
64345039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *icsc = NULL;
64445039663SJohn Forte 	scsi_devid_desc_t *ini_devid = task->task_session->ss_rport_id;
64545039663SJohn Forte 	scsi_devid_desc_t *tgt_devid = task->task_lport->lport_id;
646716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *rport = task->task_session->ss_rport;
64745039663SJohn Forte 
64845039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_CMD, msgid);
64945039663SJohn Forte 	icsc = (stmf_ic_scsi_cmd_msg_t *)kmem_zalloc(sizeof (*icsc), KM_SLEEP);
65045039663SJohn Forte 	icm->icm_msg = (void *)icsc;
65145039663SJohn Forte 
65245039663SJohn Forte 	icsc->icsc_task_msgid = task_msgid;
65345039663SJohn Forte 	icsc->icsc_ini_devid = scsi_devid_desc_dup(ini_devid);
65445039663SJohn Forte 	icsc->icsc_tgt_devid = scsi_devid_desc_dup(tgt_devid);
655716c1805SNattuvetty Bhavyan 	icsc->icsc_rport = remote_port_dup(rport);
65645039663SJohn Forte 	icsc->icsc_session_id = task->task_session->ss_session_id;
65745039663SJohn Forte 
658cbdc6dc7SJohn Forte 	if (!task->task_mgmt_function && task->task_lu->lu_id) {
659cbdc6dc7SJohn Forte 		bcopy(task->task_lu->lu_id->ident,
660cbdc6dc7SJohn Forte 		    icsc->icsc_lun_id, sizeof (icsc->icsc_lun_id));
661cbdc6dc7SJohn Forte 	}
66245039663SJohn Forte 
66345039663SJohn Forte 	bcopy(task->task_lun_no, icsc->icsc_task_lun_no,
66445039663SJohn Forte 	    sizeof (icsc->icsc_task_lun_no));
66545039663SJohn Forte 
66645039663SJohn Forte 	icsc->icsc_task_expected_xfer_length = task->task_expected_xfer_length;
667*8f641fa7SSue Gleeson 	if (task->task_cdb_length) {
668*8f641fa7SSue Gleeson 		ASSERT(task->task_mgmt_function == TM_NONE);
669*8f641fa7SSue Gleeson 		icsc->icsc_task_cdb_length = task->task_cdb_length;
670*8f641fa7SSue Gleeson 		icsc->icsc_task_cdb =
671*8f641fa7SSue Gleeson 		    (uint8_t *)kmem_zalloc(task->task_cdb_length, KM_SLEEP);
672*8f641fa7SSue Gleeson 		bcopy(task->task_cdb, icsc->icsc_task_cdb,
673*8f641fa7SSue Gleeson 		    task->task_cdb_length);
674*8f641fa7SSue Gleeson 	}
67545039663SJohn Forte 
67645039663SJohn Forte 	icsc->icsc_task_flags = task->task_flags;
67745039663SJohn Forte 	icsc->icsc_task_priority = task->task_priority;
67845039663SJohn Forte 	icsc->icsc_task_mgmt_function = task->task_mgmt_function;
67945039663SJohn Forte 
68045039663SJohn Forte 	icsc->icsc_immed_data_len = immed_data_len;
68145039663SJohn Forte 	icsc->icsc_immed_data = immed_data;
68245039663SJohn Forte 
68345039663SJohn Forte 	return (icm);
68445039663SJohn Forte }
68545039663SJohn Forte 
68645039663SJohn Forte stmf_ic_msg_t *
68745039663SJohn Forte stmf_ic_scsi_data_msg_alloc(
68845039663SJohn Forte     stmf_ic_msgid_t task_msgid,
68945039663SJohn Forte     uint64_t session_id,
69045039663SJohn Forte     uint8_t *lun_id,
69145039663SJohn Forte     uint64_t data_len,
69245039663SJohn Forte     uint8_t *data,
69345039663SJohn Forte     stmf_ic_msgid_t msgid)
69445039663SJohn Forte {
69545039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
69645039663SJohn Forte 	stmf_ic_scsi_data_msg_t *icsd = NULL;
69745039663SJohn Forte 
69845039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA, msgid);
69945039663SJohn Forte 	icsd = (stmf_ic_scsi_data_msg_t *)kmem_zalloc(sizeof (*icsd), KM_SLEEP);
70045039663SJohn Forte 	icm->icm_msg = (void *)icsd;
70145039663SJohn Forte 
70245039663SJohn Forte 	icsd->icsd_task_msgid = task_msgid;
70345039663SJohn Forte 	icsd->icsd_session_id = session_id;
70445039663SJohn Forte 	bcopy(lun_id, icsd->icsd_lun_id, sizeof (icsd->icsd_lun_id));
70545039663SJohn Forte 	icsd->icsd_data_len = data_len;
70645039663SJohn Forte 	icsd->icsd_data = data;
70745039663SJohn Forte 
70845039663SJohn Forte 	return (icm);
70945039663SJohn Forte }
71045039663SJohn Forte 
71145039663SJohn Forte stmf_ic_msg_t *
71245039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_alloc(
71345039663SJohn Forte     stmf_ic_msgid_t task_msgid,
71445039663SJohn Forte     uint64_t session_id,
71545039663SJohn Forte     stmf_status_t status,
71645039663SJohn Forte     stmf_ic_msgid_t msgid)
71745039663SJohn Forte {
71845039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
71945039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *icsx = NULL;
72045039663SJohn Forte 
72145039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA_XFER_DONE, msgid);
72245039663SJohn Forte 	icsx = (stmf_ic_scsi_data_xfer_done_msg_t *)kmem_zalloc(
72345039663SJohn Forte 	    sizeof (*icsx), KM_SLEEP);
72445039663SJohn Forte 	icm->icm_msg = (void *)icsx;
72545039663SJohn Forte 
72645039663SJohn Forte 	icsx->icsx_task_msgid = task_msgid;
72745039663SJohn Forte 	icsx->icsx_session_id = session_id;
72845039663SJohn Forte 	icsx->icsx_status = status;
72945039663SJohn Forte 
73045039663SJohn Forte 	return (icm);
73145039663SJohn Forte }
73245039663SJohn Forte 
73345039663SJohn Forte stmf_ic_msg_t *
73445039663SJohn Forte stmf_ic_scsi_status_msg_alloc(
73545039663SJohn Forte     stmf_ic_msgid_t task_msgid,
73645039663SJohn Forte     uint64_t session_id,
73745039663SJohn Forte     uint8_t *lun_id,
73845039663SJohn Forte     uint8_t response,
73945039663SJohn Forte     uint8_t status,
74045039663SJohn Forte     uint8_t flags,
74145039663SJohn Forte     uint32_t resid,
74245039663SJohn Forte     uint8_t sense_len,
74345039663SJohn Forte     uint8_t *sense,
74445039663SJohn Forte     stmf_ic_msgid_t msgid)
74545039663SJohn Forte {
74645039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
74745039663SJohn Forte 	stmf_ic_scsi_status_msg_t *icss = NULL;
74845039663SJohn Forte 
74945039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_STATUS, msgid);
75045039663SJohn Forte 	icss = (stmf_ic_scsi_status_msg_t *)kmem_zalloc(sizeof (*icss),
75145039663SJohn Forte 	    KM_SLEEP);
75245039663SJohn Forte 	icm->icm_msg = (void *)icss;
75345039663SJohn Forte 
75445039663SJohn Forte 	icss->icss_task_msgid = task_msgid;
75545039663SJohn Forte 	icss->icss_session_id = session_id;
75645039663SJohn Forte 	bcopy(lun_id, icss->icss_lun_id, sizeof (icss->icss_lun_id));
75745039663SJohn Forte 	icss->icss_response = response;
75845039663SJohn Forte 	icss->icss_status = status;
75945039663SJohn Forte 	icss->icss_flags = flags;
76045039663SJohn Forte 	icss->icss_resid = resid;
76145039663SJohn Forte 	icss->icss_sense_len = sense_len;
76245039663SJohn Forte 	icss->icss_sense = sense;
76345039663SJohn Forte 
76445039663SJohn Forte 	return (icm);
76545039663SJohn Forte }
76645039663SJohn Forte 
76745039663SJohn Forte stmf_ic_msg_t *
76845039663SJohn Forte stmf_ic_r2t_msg_alloc(
76945039663SJohn Forte     stmf_ic_msgid_t task_msgid,
77045039663SJohn Forte     uint64_t session_id,
77145039663SJohn Forte     uint32_t offset,
77245039663SJohn Forte     uint32_t length,
77345039663SJohn Forte     stmf_ic_msgid_t msgid)
77445039663SJohn Forte {
77545039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
77645039663SJohn Forte 	stmf_ic_r2t_msg_t *icrt = NULL;
77745039663SJohn Forte 
77845039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_R2T, msgid);
77945039663SJohn Forte 	icrt = (stmf_ic_r2t_msg_t *)kmem_zalloc(sizeof (*icrt), KM_SLEEP);
78045039663SJohn Forte 	icm->icm_msg = (void *)icrt;
78145039663SJohn Forte 
78245039663SJohn Forte 	icrt->icrt_task_msgid = task_msgid;
78345039663SJohn Forte 	icrt->icrt_session_id = session_id;
78445039663SJohn Forte 	icrt->icrt_offset = offset;
78545039663SJohn Forte 	icrt->icrt_length = length;
78645039663SJohn Forte 
78745039663SJohn Forte 	return (icm);
78845039663SJohn Forte }
78945039663SJohn Forte 
79045039663SJohn Forte stmf_ic_msg_t *
79145039663SJohn Forte stmf_ic_status_msg_alloc(
79245039663SJohn Forte     stmf_status_t status,
79345039663SJohn Forte     stmf_ic_msg_type_t msg_type,
79445039663SJohn Forte     stmf_ic_msgid_t msgid)
79545039663SJohn Forte {
79645039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
79745039663SJohn Forte 	stmf_ic_status_msg_t *ics = NULL;
79845039663SJohn Forte 
79945039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_STATUS, msgid);
80045039663SJohn Forte 	ics = (stmf_ic_status_msg_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
80145039663SJohn Forte 	icm->icm_msg = (void *)ics;
80245039663SJohn Forte 
80345039663SJohn Forte 	ics->ics_status = status;
80445039663SJohn Forte 	ics->ics_msg_type = msg_type;
80545039663SJohn Forte 	ics->ics_msgid = msgid;		/* XXX same as msgid in header */
80645039663SJohn Forte 
80745039663SJohn Forte 	return (icm);
80845039663SJohn Forte }
80945039663SJohn Forte 
81045039663SJohn Forte stmf_ic_msg_t *
81145039663SJohn Forte stmf_ic_session_create_msg_alloc(
81245039663SJohn Forte     stmf_scsi_session_t *session,
81345039663SJohn Forte     stmf_ic_msgid_t msgid)
81445039663SJohn Forte {
81545039663SJohn Forte 	return (stmf_ic_session_create_destroy_msg_alloc(
81645039663SJohn Forte 	    STMF_ICM_SESSION_CREATE, session, msgid));
81745039663SJohn Forte }
81845039663SJohn Forte 
81945039663SJohn Forte stmf_ic_msg_t *
82045039663SJohn Forte stmf_ic_session_destroy_msg_alloc(
82145039663SJohn Forte     stmf_scsi_session_t *session,
82245039663SJohn Forte     stmf_ic_msgid_t msgid)
82345039663SJohn Forte {
82445039663SJohn Forte 	return (stmf_ic_session_create_destroy_msg_alloc(
82545039663SJohn Forte 	    STMF_ICM_SESSION_DESTROY, session, msgid));
82645039663SJohn Forte }
82745039663SJohn Forte 
82845039663SJohn Forte /*
82945039663SJohn Forte  * Guts of session create/destroy routines.
83045039663SJohn Forte  */
83145039663SJohn Forte static stmf_ic_msg_t *
83245039663SJohn Forte stmf_ic_session_create_destroy_msg_alloc(
83345039663SJohn Forte     stmf_ic_msg_type_t msg_type,
83445039663SJohn Forte     stmf_scsi_session_t *session,
83545039663SJohn Forte     stmf_ic_msgid_t msgid)
83645039663SJohn Forte {
83745039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
83845039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *icscd = NULL;
83945039663SJohn Forte 	scsi_devid_desc_t *ini_devid = session->ss_rport_id;
84045039663SJohn Forte 	scsi_devid_desc_t *tgt_devid = session->ss_lport->lport_id;
84145039663SJohn Forte 
84245039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
84345039663SJohn Forte 	icscd = (stmf_ic_session_create_destroy_msg_t *)
84445039663SJohn Forte 	    kmem_zalloc(sizeof (*icscd), KM_SLEEP);
84545039663SJohn Forte 	icm->icm_msg = (void *)icscd;
84645039663SJohn Forte 
84745039663SJohn Forte 	icscd->icscd_session_id = session->ss_session_id;
84845039663SJohn Forte 	icscd->icscd_ini_devid = scsi_devid_desc_dup(ini_devid);
84945039663SJohn Forte 	icscd->icscd_tgt_devid = scsi_devid_desc_dup(tgt_devid);
850716c1805SNattuvetty Bhavyan 	icscd->icscd_rport = remote_port_dup(session->ss_rport);
85145039663SJohn Forte 
85245039663SJohn Forte 	return (icm);
85345039663SJohn Forte }
85445039663SJohn Forte 
85545039663SJohn Forte stmf_ic_msg_t *
85645039663SJohn Forte stmf_ic_echo_request_msg_alloc(
85745039663SJohn Forte     uint32_t data_len,
85845039663SJohn Forte     uint8_t *data,
85945039663SJohn Forte     stmf_ic_msgid_t msgid)
86045039663SJohn Forte {
86145039663SJohn Forte 	return (stmf_ic_echo_request_reply_msg_alloc(
86245039663SJohn Forte 	    STMF_ICM_ECHO_REQUEST, data_len, data, msgid));
86345039663SJohn Forte }
86445039663SJohn Forte 
86545039663SJohn Forte stmf_ic_msg_t *
86645039663SJohn Forte stmf_ic_echo_reply_msg_alloc(
86745039663SJohn Forte     uint32_t data_len,
86845039663SJohn Forte     uint8_t *data,
86945039663SJohn Forte     stmf_ic_msgid_t msgid)
87045039663SJohn Forte {
87145039663SJohn Forte 	return (stmf_ic_echo_request_reply_msg_alloc(
87245039663SJohn Forte 	    STMF_ICM_ECHO_REPLY, data_len, data, msgid));
87345039663SJohn Forte }
87445039663SJohn Forte 
87545039663SJohn Forte 
87645039663SJohn Forte static stmf_ic_msg_t *
87745039663SJohn Forte stmf_ic_echo_request_reply_msg_alloc(
87845039663SJohn Forte     stmf_ic_msg_type_t msg_type,
87945039663SJohn Forte     uint32_t data_len,
88045039663SJohn Forte     uint8_t *data,
88145039663SJohn Forte     stmf_ic_msgid_t msgid)
88245039663SJohn Forte {
88345039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
88445039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *icerr = NULL;
88545039663SJohn Forte 
88645039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
88745039663SJohn Forte 	icerr = kmem_zalloc(sizeof (*icerr), KM_SLEEP);
88845039663SJohn Forte 	icm->icm_msg = (void *)icerr;
88945039663SJohn Forte 
89045039663SJohn Forte 	icerr->icerr_data = data;
89145039663SJohn Forte 	icerr->icerr_datalen = data_len;
89245039663SJohn Forte 
89345039663SJohn Forte 	return (icm);
89445039663SJohn Forte }
89545039663SJohn Forte 
89645039663SJohn Forte /*
89745039663SJohn Forte  * msg free routines.
89845039663SJohn Forte  */
89945039663SJohn Forte void
90045039663SJohn Forte stmf_ic_msg_free(stmf_ic_msg_t *msg)
90145039663SJohn Forte {
90245039663SJohn Forte 	stmf_ic_msg_construction_method_t cmethod =
90345039663SJohn Forte 	    (msg->icm_nvlist ? STMF_UNMARSHAL : STMF_CONSTRUCTOR);
90445039663SJohn Forte 
90545039663SJohn Forte 	switch (msg->icm_msg_type) {
90645039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
90745039663SJohn Forte 		stmf_ic_reg_port_msg_free(
90845039663SJohn Forte 		    (stmf_ic_reg_port_msg_t *)msg->icm_msg, cmethod);
90945039663SJohn Forte 		break;
91045039663SJohn Forte 
91145039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
91245039663SJohn Forte 		stmf_ic_dereg_port_msg_free(
91345039663SJohn Forte 		    (stmf_ic_dereg_port_msg_t *)msg->icm_msg, cmethod);
91445039663SJohn Forte 		break;
91545039663SJohn Forte 
91645039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
91745039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
91845039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
91945039663SJohn Forte 		stmf_ic_reg_dereg_lun_msg_free(
92045039663SJohn Forte 		    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg, cmethod);
92145039663SJohn Forte 		break;
92245039663SJohn Forte 
92345039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
92445039663SJohn Forte 		stmf_ic_scsi_cmd_msg_free(
92545039663SJohn Forte 		    (stmf_ic_scsi_cmd_msg_t *)msg->icm_msg, cmethod);
92645039663SJohn Forte 		break;
92745039663SJohn Forte 
92845039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
92945039663SJohn Forte 		stmf_ic_scsi_data_msg_free(
93045039663SJohn Forte 		    (stmf_ic_scsi_data_msg_t *)msg->icm_msg, cmethod);
93145039663SJohn Forte 		break;
93245039663SJohn Forte 
93345039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
93445039663SJohn Forte 		stmf_ic_scsi_data_xfer_done_msg_free(
93545039663SJohn Forte 		    (stmf_ic_scsi_data_xfer_done_msg_t *)msg->icm_msg, cmethod);
93645039663SJohn Forte 		break;
93745039663SJohn Forte 
93845039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
93945039663SJohn Forte 		stmf_ic_scsi_status_msg_free(
94045039663SJohn Forte 		    (stmf_ic_scsi_status_msg_t *)msg->icm_msg, cmethod);
94145039663SJohn Forte 		break;
94245039663SJohn Forte 
94345039663SJohn Forte 	case STMF_ICM_R2T:
94445039663SJohn Forte 		stmf_ic_r2t_msg_free(
94545039663SJohn Forte 		    (stmf_ic_r2t_msg_t *)msg->icm_msg, cmethod);
94645039663SJohn Forte 		break;
94745039663SJohn Forte 
94845039663SJohn Forte 	case STMF_ICM_STATUS:
94945039663SJohn Forte 		stmf_ic_status_msg_free(
95045039663SJohn Forte 		    (stmf_ic_status_msg_t *)msg->icm_msg, cmethod);
95145039663SJohn Forte 		break;
95245039663SJohn Forte 
95345039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
95445039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
95545039663SJohn Forte 		stmf_ic_session_create_destroy_msg_free(
95645039663SJohn Forte 		    (stmf_ic_session_create_destroy_msg_t *)msg->icm_msg,
95745039663SJohn Forte 		    cmethod);
95845039663SJohn Forte 		break;
95945039663SJohn Forte 
96045039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
96145039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
96245039663SJohn Forte 		stmf_ic_echo_request_reply_msg_free(
96345039663SJohn Forte 		    (stmf_ic_echo_request_reply_msg_t *)msg->icm_msg, cmethod);
96445039663SJohn Forte 		break;
96545039663SJohn Forte 
96645039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
96745039663SJohn Forte 		ASSERT(0);
96845039663SJohn Forte 		break;
96945039663SJohn Forte 
97045039663SJohn Forte 	default:
97145039663SJohn Forte 		ASSERT(0);
97245039663SJohn Forte 	}
97345039663SJohn Forte 
97445039663SJohn Forte 	if (msg->icm_nvlist)
97545039663SJohn Forte 		nvlist_free(msg->icm_nvlist);
97645039663SJohn Forte 
97745039663SJohn Forte 	kmem_free(msg, sizeof (*msg));
97845039663SJohn Forte }
97945039663SJohn Forte 
98045039663SJohn Forte /*ARGSUSED*/
98145039663SJohn Forte static void
98245039663SJohn Forte stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
98345039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
98445039663SJohn Forte {
98545039663SJohn Forte 	scsi_devid_desc_free(m->icrp_port_id);
98645039663SJohn Forte 
98745039663SJohn Forte 	kmem_free(m, sizeof (*m));
98845039663SJohn Forte }
98945039663SJohn Forte 
99045039663SJohn Forte 
99145039663SJohn Forte /*ARGSUSED*/
99245039663SJohn Forte static void
99345039663SJohn Forte stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
99445039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
99545039663SJohn Forte {
99645039663SJohn Forte 	scsi_devid_desc_free(m->icdp_port_id);
99745039663SJohn Forte 
99845039663SJohn Forte 	kmem_free(m, sizeof (*m));
99945039663SJohn Forte }
100045039663SJohn Forte 
100145039663SJohn Forte 
100245039663SJohn Forte /*
100345039663SJohn Forte  * Works for both reg_lun_msg and dereg_lun_msg, since the message
100445039663SJohn Forte  * payload is the same.
100545039663SJohn Forte  */
100645039663SJohn Forte static void
100745039663SJohn Forte stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
100845039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
100945039663SJohn Forte {
101045039663SJohn Forte 	if (cmethod == STMF_CONSTRUCTOR) {
101145039663SJohn Forte 		kmem_free(m->icrl_lu_provider_name,
101245039663SJohn Forte 		    strlen(m->icrl_lu_provider_name) + 1);
101345039663SJohn Forte 	}
101445039663SJohn Forte 
101545039663SJohn Forte 	kmem_free(m, sizeof (*m));
101645039663SJohn Forte }
101745039663SJohn Forte 
101845039663SJohn Forte static void
101945039663SJohn Forte stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
102045039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
102145039663SJohn Forte {
102245039663SJohn Forte 	scsi_devid_desc_free(m->icsc_ini_devid);
102345039663SJohn Forte 	scsi_devid_desc_free(m->icsc_tgt_devid);
1024716c1805SNattuvetty Bhavyan 	stmf_remote_port_free(m->icsc_rport);
1025*8f641fa7SSue Gleeson 	if ((cmethod == STMF_CONSTRUCTOR) && m->icsc_task_cdb) {
102645039663SJohn Forte 		kmem_free(m->icsc_task_cdb, m->icsc_task_cdb_length);
102745039663SJohn Forte 	}
102845039663SJohn Forte 
102945039663SJohn Forte 	kmem_free(m, sizeof (*m));
103045039663SJohn Forte 
103145039663SJohn Forte }
103245039663SJohn Forte 
103345039663SJohn Forte /*ARGSUSED*/
103445039663SJohn Forte static void
103545039663SJohn Forte stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
103645039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
103745039663SJohn Forte {
103845039663SJohn Forte 	kmem_free(m, sizeof (*m));
103945039663SJohn Forte }
104045039663SJohn Forte 
104145039663SJohn Forte /*ARGSUSED*/
104245039663SJohn Forte static void
104345039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t *m,
104445039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
104545039663SJohn Forte {
104645039663SJohn Forte 	kmem_free(m, sizeof (*m));
104745039663SJohn Forte }
104845039663SJohn Forte 
104945039663SJohn Forte /*ARGSUSED*/
105045039663SJohn Forte static void
105145039663SJohn Forte stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
105245039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
105345039663SJohn Forte {
105445039663SJohn Forte 	kmem_free(m, sizeof (*m));
105545039663SJohn Forte }
105645039663SJohn Forte 
105745039663SJohn Forte /*ARGSUSED*/
105845039663SJohn Forte static void
105945039663SJohn Forte stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
106045039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
106145039663SJohn Forte {
106245039663SJohn Forte 	kmem_free(m, sizeof (*m));
106345039663SJohn Forte }
106445039663SJohn Forte 
106545039663SJohn Forte /*ARGSUSED*/
106645039663SJohn Forte static void
106745039663SJohn Forte stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
106845039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
106945039663SJohn Forte {
107045039663SJohn Forte 	kmem_free(m, sizeof (*m));
107145039663SJohn Forte }
107245039663SJohn Forte 
107345039663SJohn Forte /*
107445039663SJohn Forte  * Works for both session_create and session_destroy msgs, since the message
107545039663SJohn Forte  * payload is the same.
107645039663SJohn Forte  */
107745039663SJohn Forte /*ARGSUSED*/
107845039663SJohn Forte static void
107945039663SJohn Forte stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t *m,
108045039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
108145039663SJohn Forte {
108245039663SJohn Forte 	scsi_devid_desc_free(m->icscd_ini_devid);
108345039663SJohn Forte 	scsi_devid_desc_free(m->icscd_tgt_devid);
1084716c1805SNattuvetty Bhavyan 	stmf_remote_port_free(m->icscd_rport);
108545039663SJohn Forte 
108645039663SJohn Forte 	kmem_free(m, sizeof (*m));
108745039663SJohn Forte }
108845039663SJohn Forte 
108945039663SJohn Forte /*ARGSUSED*/
109045039663SJohn Forte static void
109145039663SJohn Forte stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t *m,
109245039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
109345039663SJohn Forte {
109445039663SJohn Forte 	kmem_free(m, sizeof (*m));
109545039663SJohn Forte }
109645039663SJohn Forte 
109745039663SJohn Forte 
109845039663SJohn Forte /*
109945039663SJohn Forte  * Marshaling routines.
110045039663SJohn Forte  */
110145039663SJohn Forte 
110245039663SJohn Forte static nvlist_t *
110345039663SJohn Forte stmf_ic_msg_marshal(stmf_ic_msg_t *msg)
110445039663SJohn Forte {
110545039663SJohn Forte 	nvlist_t *nvl = NULL;
110645039663SJohn Forte 	int rc = 0;
110745039663SJohn Forte 
110845039663SJohn Forte 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
110945039663SJohn Forte 	if (rc)
111045039663SJohn Forte 		goto done;
111145039663SJohn Forte 
111245039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, msg, icm_msg_type);
111345039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, msg, icm_msgid);
111445039663SJohn Forte 
111545039663SJohn Forte 	switch (msg->icm_msg_type) {
111645039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
111745039663SJohn Forte 		rc = stmf_ic_reg_port_msg_marshal(nvl, msg->icm_msg);
111845039663SJohn Forte 		break;
111945039663SJohn Forte 
112045039663SJohn Forte 
112145039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
112245039663SJohn Forte 		rc = stmf_ic_dereg_port_msg_marshal(nvl, msg->icm_msg);
112345039663SJohn Forte 		break;
112445039663SJohn Forte 
112545039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
112645039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
112745039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
112845039663SJohn Forte 		rc = stmf_ic_reg_dereg_lun_msg_marshal(nvl, msg->icm_msg);
112945039663SJohn Forte 		break;
113045039663SJohn Forte 
113145039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
113245039663SJohn Forte 		rc = stmf_ic_scsi_cmd_msg_marshal(nvl, msg->icm_msg);
113345039663SJohn Forte 		break;
113445039663SJohn Forte 
113545039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
113645039663SJohn Forte 		rc = stmf_ic_scsi_data_msg_marshal(nvl, msg->icm_msg);
113745039663SJohn Forte 		break;
113845039663SJohn Forte 
113945039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
114045039663SJohn Forte 		rc = stmf_ic_scsi_data_xfer_done_msg_marshal(nvl, msg->icm_msg);
114145039663SJohn Forte 		break;
114245039663SJohn Forte 
114345039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
114445039663SJohn Forte 		rc = stmf_ic_scsi_status_msg_marshal(nvl, msg->icm_msg);
114545039663SJohn Forte 		break;
114645039663SJohn Forte 
114745039663SJohn Forte 	case STMF_ICM_R2T:
114845039663SJohn Forte 		rc = stmf_ic_r2t_msg_marshal(nvl, msg->icm_msg);
114945039663SJohn Forte 		break;
115045039663SJohn Forte 
115145039663SJohn Forte 	case STMF_ICM_STATUS:
115245039663SJohn Forte 		rc = stmf_ic_status_msg_marshal(nvl, msg->icm_msg);
115345039663SJohn Forte 		break;
115445039663SJohn Forte 
115545039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
115645039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
115745039663SJohn Forte 		rc = stmf_ic_session_create_destroy_msg_marshal(nvl,
115845039663SJohn Forte 		    msg->icm_msg);
115945039663SJohn Forte 		break;
116045039663SJohn Forte 
116145039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
116245039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
116345039663SJohn Forte 		rc = stmf_ic_echo_request_reply_msg_marshal(nvl,
116445039663SJohn Forte 		    msg->icm_msg);
116545039663SJohn Forte 		break;
116645039663SJohn Forte 
116745039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
116845039663SJohn Forte 		ASSERT(0);
116945039663SJohn Forte 		break;
117045039663SJohn Forte 
117145039663SJohn Forte 	default:
117245039663SJohn Forte 		ASSERT(0);
117345039663SJohn Forte 	}
117445039663SJohn Forte 
117545039663SJohn Forte done:
117645039663SJohn Forte 	if (!rc)
117745039663SJohn Forte 		return (nvl);
117845039663SJohn Forte 
117945039663SJohn Forte 	if (nvl)
118045039663SJohn Forte 		nvlist_free(nvl);
118145039663SJohn Forte 
118245039663SJohn Forte 	return (NULL);
118345039663SJohn Forte }
118445039663SJohn Forte 
118545039663SJohn Forte 
118645039663SJohn Forte static int
118745039663SJohn Forte stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg)
118845039663SJohn Forte {
118945039663SJohn Forte 	stmf_ic_reg_port_msg_t *m = (stmf_ic_reg_port_msg_t *)msg;
119045039663SJohn Forte 	int rc = 0;
119145039663SJohn Forte 
119245039663SJohn Forte 	NVLIST_ADD_DEVID(m, icrp_port_id);
119345039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrp_relative_port_id);
119445039663SJohn Forte 
119545039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrp_cb_arg_len);
119645039663SJohn Forte 	/* only add the callback arg if necessary */
119745039663SJohn Forte 	if (m->icrp_cb_arg_len) {
119845039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrp_cb_arg, m->icrp_cb_arg_len);
119945039663SJohn Forte 	}
120045039663SJohn Forte 
120145039663SJohn Forte done:
120245039663SJohn Forte 	return (rc);
120345039663SJohn Forte }
120445039663SJohn Forte 
120545039663SJohn Forte static int
120645039663SJohn Forte stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg)
120745039663SJohn Forte {
120845039663SJohn Forte 	stmf_ic_dereg_port_msg_t *m = (stmf_ic_dereg_port_msg_t *)msg;
120945039663SJohn Forte 	int rc = 0;
121045039663SJohn Forte 
121145039663SJohn Forte 	NVLIST_ADD_DEVID(m, icdp_port_id);
121245039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icdp_cb_arg_len);
121345039663SJohn Forte 
121445039663SJohn Forte 	/* only add the callback arg if necessary */
121545039663SJohn Forte 	if (m->icdp_cb_arg_len) {
121645039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icdp_cb_arg, m->icdp_cb_arg_len);
121745039663SJohn Forte 	}
121845039663SJohn Forte 
121945039663SJohn Forte done:
122045039663SJohn Forte 	return (rc);
122145039663SJohn Forte }
122245039663SJohn Forte 
122345039663SJohn Forte /*
122445039663SJohn Forte  * Handles STMF_ICM_LUN_ACTIVE, STMF_ICM_REGISTER_LUN and
122545039663SJohn Forte  * STMF_ICM_DEREGISTER_LUN;
122645039663SJohn Forte  * msg payload is the same for all.
122745039663SJohn Forte  */
122845039663SJohn Forte static int
122945039663SJohn Forte stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg)
123045039663SJohn Forte {
123145039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *m = (stmf_ic_reg_dereg_lun_msg_t *)msg;
123245039663SJohn Forte 	int rc = 0;
123345039663SJohn Forte 
123445039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icrl_lun_id);
123545039663SJohn Forte 	NVLIST_ADD_FIELD(string, m, icrl_lu_provider_name);
123645039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrl_cb_arg_len);
123745039663SJohn Forte 
123845039663SJohn Forte 	/* only add the callback arg if necessary */
123945039663SJohn Forte 	if (m->icrl_cb_arg_len) {
124045039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrl_cb_arg, m->icrl_cb_arg_len);
124145039663SJohn Forte 	}
124245039663SJohn Forte 
124345039663SJohn Forte done:
124445039663SJohn Forte 	return (rc);
124545039663SJohn Forte }
124645039663SJohn Forte 
124745039663SJohn Forte static int
124845039663SJohn Forte stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg)
124945039663SJohn Forte {
125045039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *m = (stmf_ic_scsi_cmd_msg_t *)msg;
125145039663SJohn Forte 	int rc = 0;
125245039663SJohn Forte 
125345039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsc_task_msgid);
125445039663SJohn Forte 	NVLIST_ADD_DEVID(m, icsc_ini_devid);
125545039663SJohn Forte 	NVLIST_ADD_DEVID(m, icsc_tgt_devid);
1256716c1805SNattuvetty Bhavyan 	NVLIST_ADD_RPORT(m, icsc_rport);
125745039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icsc_lun_id);
125845039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsc_session_id);
125945039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_lun_no, 8);
126045039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icsc_task_expected_xfer_length);
126145039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icsc_task_cdb_length);
1262*8f641fa7SSue Gleeson 	/*
1263*8f641fa7SSue Gleeson 	 * icsc_task_cdb_length may be zero in the case of a task
1264*8f641fa7SSue Gleeson 	 * management function.
1265*8f641fa7SSue Gleeson 	 */
126645039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_cdb, m->icsc_task_cdb_length);
126745039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_flags);
126845039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_priority);
126945039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_mgmt_function);
127045039663SJohn Forte 
127145039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icsc_immed_data_len);
127245039663SJohn Forte 	/* only add immediate data if necessary */
127345039663SJohn Forte 	if (m->icsc_immed_data_len) {
127445039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_immed_data,
127545039663SJohn Forte 		    m->icsc_immed_data_len);
127645039663SJohn Forte 	}
127745039663SJohn Forte 
127845039663SJohn Forte done:
127945039663SJohn Forte 	return (rc);
128045039663SJohn Forte }
128145039663SJohn Forte 
128245039663SJohn Forte static int
128345039663SJohn Forte stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg)
128445039663SJohn Forte {
128545039663SJohn Forte 	stmf_ic_scsi_data_msg_t *m = (stmf_ic_scsi_data_msg_t *)msg;
128645039663SJohn Forte 	int rc = 0;
128745039663SJohn Forte 
128845039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_task_msgid);
128945039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_session_id);
129045039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icsd_lun_id);
129145039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_data_len);
129245039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsd_data, m->icsd_data_len);
129345039663SJohn Forte 
129445039663SJohn Forte done:
129545039663SJohn Forte 	return (rc);
129645039663SJohn Forte }
129745039663SJohn Forte 
129845039663SJohn Forte static int
129945039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg)
130045039663SJohn Forte {
130145039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *m =
130245039663SJohn Forte 	    (stmf_ic_scsi_data_xfer_done_msg_t *)msg;
130345039663SJohn Forte 	int rc = 0;
130445039663SJohn Forte 
130545039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_task_msgid);
130645039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_session_id);
130745039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_status);
130845039663SJohn Forte 
130945039663SJohn Forte done:
131045039663SJohn Forte 	return (rc);
131145039663SJohn Forte }
131245039663SJohn Forte 
131345039663SJohn Forte static int
131445039663SJohn Forte stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg)
131545039663SJohn Forte {
131645039663SJohn Forte 	stmf_ic_scsi_status_msg_t *m = (stmf_ic_scsi_status_msg_t *)msg;
131745039663SJohn Forte 	int rc = 0;
131845039663SJohn Forte 
131945039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icss_task_msgid);
132045039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icss_session_id);
132145039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icss_lun_id);
132245039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_response);
132345039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_status);
132445039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_flags);
132545039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icss_resid);
132645039663SJohn Forte 
132745039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_sense_len);
132845039663SJohn Forte 
132945039663SJohn Forte 	if (m->icss_sense_len)
133045039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icss_sense, m->icss_sense_len);
133145039663SJohn Forte 
133245039663SJohn Forte done:
133345039663SJohn Forte 	return (rc);
133445039663SJohn Forte }
133545039663SJohn Forte 
133645039663SJohn Forte static int
133745039663SJohn Forte stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg)
133845039663SJohn Forte {
133945039663SJohn Forte 	stmf_ic_r2t_msg_t *m = (stmf_ic_r2t_msg_t *)msg;
134045039663SJohn Forte 	int rc = 0;
134145039663SJohn Forte 
134245039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icrt_task_msgid);
134345039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icrt_session_id);
134445039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icrt_offset);
134545039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icrt_length);
134645039663SJohn Forte 
134745039663SJohn Forte done:
134845039663SJohn Forte 	return (rc);
134945039663SJohn Forte }
135045039663SJohn Forte 
135145039663SJohn Forte static int
135245039663SJohn Forte stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg)
135345039663SJohn Forte {
135445039663SJohn Forte 	stmf_ic_status_msg_t *m = (stmf_ic_status_msg_t *)msg;
135545039663SJohn Forte 	int rc = 0;
135645039663SJohn Forte 
135745039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, ics_msg_type);
135845039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, ics_msgid);
135945039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, ics_status);
136045039663SJohn Forte 
136145039663SJohn Forte done:
136245039663SJohn Forte 	return (rc);
136345039663SJohn Forte }
136445039663SJohn Forte 
136545039663SJohn Forte static int
136645039663SJohn Forte stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg)
136745039663SJohn Forte {
136845039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *m =
136945039663SJohn Forte 	    (stmf_ic_session_create_destroy_msg_t *)msg;
137045039663SJohn Forte 	int rc = 0;
137145039663SJohn Forte 
137245039663SJohn Forte 	NVLIST_ADD_DEVID(m, icscd_ini_devid);
137345039663SJohn Forte 	NVLIST_ADD_DEVID(m, icscd_tgt_devid);
1374716c1805SNattuvetty Bhavyan 	NVLIST_ADD_RPORT(m, icscd_rport);
137545039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icscd_session_id);
137645039663SJohn Forte 
137745039663SJohn Forte done:
137845039663SJohn Forte 	return (rc);
137945039663SJohn Forte }
138045039663SJohn Forte 
138145039663SJohn Forte static int
138245039663SJohn Forte stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg)
138345039663SJohn Forte {
138445039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *m = msg;
138545039663SJohn Forte 	int rc = 0;
138645039663SJohn Forte 
138745039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icerr_datalen);
138845039663SJohn Forte 	if (m->icerr_datalen)
138945039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icerr_data, m->icerr_datalen);
139045039663SJohn Forte 
139145039663SJohn Forte done:
139245039663SJohn Forte 	return (rc);
139345039663SJohn Forte }
139445039663SJohn Forte 
139545039663SJohn Forte /*
139645039663SJohn Forte  * Allocate a new nvlist representing the scsi_devid_desc and add it
139745039663SJohn Forte  * to the nvlist.
139845039663SJohn Forte  */
139945039663SJohn Forte static int
140045039663SJohn Forte stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
140145039663SJohn Forte 	char *sdid_name,
140245039663SJohn Forte 	scsi_devid_desc_t *sdid)
140345039663SJohn Forte {
140445039663SJohn Forte 	int rc = 0;
140545039663SJohn Forte 	nvlist_t *nvl = NULL;
140645039663SJohn Forte 
140745039663SJohn Forte 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
140845039663SJohn Forte 	if (rc)
140945039663SJohn Forte 		goto done;
141045039663SJohn Forte 
141145039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, protocol_id);
141245039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, code_set);
141345039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, piv);
141445039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, association);
141545039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, ident_type);
141645039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, ident_length);
141745039663SJohn Forte 
141845039663SJohn Forte 	rc = nvlist_add_uint8_array(nvl, "ident", sdid->ident,
141945039663SJohn Forte 	    sdid->ident_length);
142045039663SJohn Forte 	if (rc)
142145039663SJohn Forte 		goto done;
142245039663SJohn Forte 
142345039663SJohn Forte 	rc = nvlist_add_nvlist(parent_nvl, sdid_name, nvl);
1424716c1805SNattuvetty Bhavyan done:
1425716c1805SNattuvetty Bhavyan 	if (nvl) {
1426716c1805SNattuvetty Bhavyan 		nvlist_free(nvl);
1427716c1805SNattuvetty Bhavyan 	}
1428716c1805SNattuvetty Bhavyan 	return (rc);
1429716c1805SNattuvetty Bhavyan }
1430716c1805SNattuvetty Bhavyan 
1431716c1805SNattuvetty Bhavyan /*
1432716c1805SNattuvetty Bhavyan  * Allocate a new nvlist representing the stmf_remote_port and add it
1433716c1805SNattuvetty Bhavyan  * to the nvlist.
1434716c1805SNattuvetty Bhavyan  */
1435716c1805SNattuvetty Bhavyan static int
1436716c1805SNattuvetty Bhavyan stmf_ic_remote_port_marshal(nvlist_t *parent_nvl, char *rport_name,
1437716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *rport) {
1438716c1805SNattuvetty Bhavyan 
1439716c1805SNattuvetty Bhavyan 	int rc = 0;
1440716c1805SNattuvetty Bhavyan 	nvlist_t *nvl = NULL;
1441716c1805SNattuvetty Bhavyan 
1442716c1805SNattuvetty Bhavyan 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1443716c1805SNattuvetty Bhavyan 	if (rc)
1444716c1805SNattuvetty Bhavyan 		goto done;
144545039663SJohn Forte 
1446716c1805SNattuvetty Bhavyan 	NVLIST_ADD_FIELD(uint16, rport, rport_tptid_sz);
1447716c1805SNattuvetty Bhavyan 	rc = nvlist_add_uint8_array(nvl, "rport_tptid",
1448716c1805SNattuvetty Bhavyan 	    (uint8_t *)rport->rport_tptid, rport->rport_tptid_sz);
1449716c1805SNattuvetty Bhavyan 	if (rc)
1450716c1805SNattuvetty Bhavyan 		goto done;
1451716c1805SNattuvetty Bhavyan 
1452716c1805SNattuvetty Bhavyan 	rc = nvlist_add_nvlist(parent_nvl, rport_name, nvl);
145345039663SJohn Forte done:
145445039663SJohn Forte 	if (nvl) {
145545039663SJohn Forte 		nvlist_free(nvl);
145645039663SJohn Forte 	}
145745039663SJohn Forte 	return (rc);
145845039663SJohn Forte }
145945039663SJohn Forte 
146045039663SJohn Forte /*
146145039663SJohn Forte  * Unmarshaling routines.
146245039663SJohn Forte  */
146345039663SJohn Forte 
146445039663SJohn Forte static stmf_ic_msg_t *
146545039663SJohn Forte stmf_ic_msg_unmarshal(nvlist_t *nvl)
146645039663SJohn Forte {
146745039663SJohn Forte 	stmf_ic_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
146845039663SJohn Forte 	uint8_t msg_type;
146945039663SJohn Forte 	int rc = 0;
147045039663SJohn Forte 
147145039663SJohn Forte 	/*
147245039663SJohn Forte 	 * We'd like to do this:
147345039663SJohn Forte 	 *
147445039663SJohn Forte 	 *   NVLIST_LOOKUP_FIELD(uint8, m, icm_msg_type);
147545039663SJohn Forte 	 *
147645039663SJohn Forte 	 * but the fact that msg type is an enum causes type problems.
147745039663SJohn Forte 	 */
147845039663SJohn Forte 	rc = nvlist_lookup_uint8(nvl, "icm_msg_type", &msg_type);
147945039663SJohn Forte 	if (rc) {
148045039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icm_msg_type");
148145039663SJohn Forte 		goto done;
148245039663SJohn Forte 	}
148345039663SJohn Forte 
148445039663SJohn Forte 	m->icm_msg_type = msg_type;
148545039663SJohn Forte 	m->icm_nvlist = nvl;
148645039663SJohn Forte 
148745039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint64, m, icm_msgid);
148845039663SJohn Forte 
148945039663SJohn Forte 	switch (m->icm_msg_type) {
149045039663SJohn Forte 
149145039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
149245039663SJohn Forte 		m->icm_msg = stmf_ic_reg_port_msg_unmarshal(nvl);
149345039663SJohn Forte 		break;
149445039663SJohn Forte 
149545039663SJohn Forte 
149645039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
149745039663SJohn Forte 		m->icm_msg = stmf_ic_dereg_port_msg_unmarshal(nvl);
149845039663SJohn Forte 		break;
149945039663SJohn Forte 
150045039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
150145039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
150245039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
150345039663SJohn Forte 		m->icm_msg = stmf_ic_reg_dereg_lun_msg_unmarshal(nvl);
150445039663SJohn Forte 		break;
150545039663SJohn Forte 
150645039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
150745039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_cmd_msg_unmarshal(nvl);
150845039663SJohn Forte 		break;
150945039663SJohn Forte 
151045039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
151145039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_data_msg_unmarshal(nvl);
151245039663SJohn Forte 		break;
151345039663SJohn Forte 
151445039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
151545039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvl);
151645039663SJohn Forte 		break;
151745039663SJohn Forte 
151845039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
151945039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_status_msg_unmarshal(nvl);
152045039663SJohn Forte 		break;
152145039663SJohn Forte 
152245039663SJohn Forte 	case STMF_ICM_R2T:
152345039663SJohn Forte 		m->icm_msg = stmf_ic_r2t_msg_unmarshal(nvl);
152445039663SJohn Forte 		break;
152545039663SJohn Forte 
152645039663SJohn Forte 	case STMF_ICM_STATUS:
152745039663SJohn Forte 		m->icm_msg = stmf_ic_status_msg_unmarshal(nvl);
152845039663SJohn Forte 		break;
152945039663SJohn Forte 
153045039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
153145039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
153245039663SJohn Forte 		m->icm_msg = stmf_ic_session_create_destroy_msg_unmarshal(nvl);
153345039663SJohn Forte 		break;
153445039663SJohn Forte 
153545039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
153645039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
153745039663SJohn Forte 		m->icm_msg = stmf_ic_echo_request_reply_msg_unmarshal(nvl);
153845039663SJohn Forte 		break;
153945039663SJohn Forte 
154045039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
154145039663SJohn Forte 		ASSERT(0);
154245039663SJohn Forte 		break;
154345039663SJohn Forte 
154445039663SJohn Forte 	default:
154545039663SJohn Forte 		ASSERT(0);
154645039663SJohn Forte 	}
154745039663SJohn Forte 
154845039663SJohn Forte done:
154945039663SJohn Forte 
155045039663SJohn Forte 	if (!m->icm_msg) {
155145039663SJohn Forte 		kmem_free(m, sizeof (*m));
155245039663SJohn Forte 		return (NULL);
155345039663SJohn Forte 	}
155445039663SJohn Forte 
155545039663SJohn Forte 	return (m);
155645039663SJohn Forte }
155745039663SJohn Forte 
155845039663SJohn Forte static void *
155945039663SJohn Forte stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl)
156045039663SJohn Forte {
156145039663SJohn Forte 	nvlist_t *nvl_port_id = NULL;
156245039663SJohn Forte 	int rc = 0;
156345039663SJohn Forte 	stmf_ic_reg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
156445039663SJohn Forte 
156545039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, "icrp_port_id", &nvl_port_id);
156645039663SJohn Forte 	if (rc) {
156745039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id nvl");
156845039663SJohn Forte 		rc = ENOMEM; /* XXX */
156945039663SJohn Forte 		goto done;
157045039663SJohn Forte 	}
157145039663SJohn Forte 
157245039663SJohn Forte 	m->icrp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
157345039663SJohn Forte 	if (m->icrp_port_id == NULL) {
157445039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id");
157545039663SJohn Forte 		rc = ENOMEM; /* XXX */
157645039663SJohn Forte 		goto done;
157745039663SJohn Forte 	}
157845039663SJohn Forte 
157945039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_relative_port_id);
158045039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_cb_arg_len);
158145039663SJohn Forte 
158245039663SJohn Forte 	if (m->icrp_cb_arg_len) {
158345039663SJohn Forte 		m->icrp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
158445039663SJohn Forte 		    "icrp_cb_arg", m->icrp_cb_arg_len, NULL);
158545039663SJohn Forte 		if (m->icrp_cb_arg == NULL) {
158645039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icrp_cb_arg");
158745039663SJohn Forte 			rc = ENOMEM; /* XXX */
158845039663SJohn Forte 			goto done;
158945039663SJohn Forte 		}
159045039663SJohn Forte 	}
159145039663SJohn Forte 
159245039663SJohn Forte done:
159345039663SJohn Forte 	if (!rc)
159445039663SJohn Forte 		return (m);
159545039663SJohn Forte 
159645039663SJohn Forte 	stmf_ic_reg_port_msg_free(m, STMF_UNMARSHAL);
159745039663SJohn Forte 
159845039663SJohn Forte 	return (NULL);
159945039663SJohn Forte }
160045039663SJohn Forte 
160145039663SJohn Forte /*
160245039663SJohn Forte  * XXX largely the same as stmf_ic_reg_port_msg_unmarshal()
160345039663SJohn Forte  * Common stuff should be factored out.  Type issues may make this
160445039663SJohn Forte  * painful.
160545039663SJohn Forte  */
160645039663SJohn Forte static void *
160745039663SJohn Forte stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl)
160845039663SJohn Forte {
160945039663SJohn Forte 	nvlist_t *nvl_port_id = NULL;
161045039663SJohn Forte 	int rc = 0;
161145039663SJohn Forte 	stmf_ic_dereg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
161245039663SJohn Forte 
161345039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, "icdp_port_id", &nvl_port_id);
161445039663SJohn Forte 	if (rc) {
161545039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id nvl");
161645039663SJohn Forte 		goto done;
161745039663SJohn Forte 	}
161845039663SJohn Forte 
161945039663SJohn Forte 	m->icdp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
162045039663SJohn Forte 	if (m->icdp_port_id == NULL) {
162145039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id");
162245039663SJohn Forte 		rc = ENOMEM; /* XXX */
162345039663SJohn Forte 		goto done;
162445039663SJohn Forte 	}
162545039663SJohn Forte 
162645039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icdp_cb_arg_len);
162745039663SJohn Forte 
162845039663SJohn Forte 	if (m->icdp_cb_arg_len) {
162945039663SJohn Forte 		m->icdp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
163045039663SJohn Forte 		    "icdp_cb_arg", m->icdp_cb_arg_len, NULL);
163145039663SJohn Forte 		if (m->icdp_cb_arg == NULL) {
163245039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icdp_cb_arg");
163345039663SJohn Forte 			rc = ENOMEM; /* XXX */
163445039663SJohn Forte 			goto done;
163545039663SJohn Forte 		}
163645039663SJohn Forte 	}
163745039663SJohn Forte 
163845039663SJohn Forte done:
163945039663SJohn Forte 	if (!rc)
164045039663SJohn Forte 		return (m);
164145039663SJohn Forte 
164245039663SJohn Forte 	stmf_ic_dereg_port_msg_free(m, STMF_UNMARSHAL);
164345039663SJohn Forte 
164445039663SJohn Forte 	return (NULL);
164545039663SJohn Forte }
164645039663SJohn Forte 
164745039663SJohn Forte static void *
164845039663SJohn Forte stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl)
164945039663SJohn Forte {
165045039663SJohn Forte 	int rc = 0;
165145039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
165245039663SJohn Forte 
165345039663SJohn Forte 	if (! stmf_ic_uint8_array_unmarshal(nvl, "icrl_lun_id",
165445039663SJohn Forte 	    sizeof (m->icrl_lun_id), m->icrl_lun_id)) {
165545039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrl_lun_id");
165645039663SJohn Forte 		rc = ENOMEM; /* XXX */
165745039663SJohn Forte 		goto done;
165845039663SJohn Forte 	}
165945039663SJohn Forte 
166045039663SJohn Forte 	m->icrl_lu_provider_name = stmf_ic_string_unmarshal(nvl,
166145039663SJohn Forte 	    "icrl_lu_provider_name");
166245039663SJohn Forte 
166345039663SJohn Forte 	if (!m->icrl_lu_provider_name) {
166445039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrl_lu_provider_name");
166545039663SJohn Forte 		rc = ENOMEM; /* XXX */
166645039663SJohn Forte 		goto done;
166745039663SJohn Forte 	}
166845039663SJohn Forte 
166945039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrl_cb_arg_len);
167045039663SJohn Forte 
167145039663SJohn Forte 	if (m->icrl_cb_arg_len) {
167245039663SJohn Forte 		m->icrl_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
167345039663SJohn Forte 		    "icrl_cb_arg", m->icrl_cb_arg_len, NULL);
167445039663SJohn Forte 		if (m->icrl_cb_arg == NULL) {
167545039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icrl_cb_arg");
167645039663SJohn Forte 			rc = ENOMEM; /* XXX */
167745039663SJohn Forte 			goto done;
167845039663SJohn Forte 		}
167945039663SJohn Forte 	}
168045039663SJohn Forte 
168145039663SJohn Forte done:
168245039663SJohn Forte 	if (!rc)
168345039663SJohn Forte 		return (m);
168445039663SJohn Forte 
168545039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_free(m, STMF_UNMARSHAL);
168645039663SJohn Forte 
168745039663SJohn Forte 	return (NULL);
168845039663SJohn Forte }
168945039663SJohn Forte 
169045039663SJohn Forte static void *
169145039663SJohn Forte stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl)
169245039663SJohn Forte {
169345039663SJohn Forte 	int rc = 0;
169445039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
169545039663SJohn Forte 
169645039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
169745039663SJohn Forte 	    NV_PAIR(UINT64, m, icsc_task_msgid),
169845039663SJohn Forte 	    NV_PAIR(UINT64, m, icsc_session_id),
169945039663SJohn Forte 	    NV_PAIR(UINT32, m, icsc_task_expected_xfer_length),
170045039663SJohn Forte 	    NV_PAIR(UINT16, m, icsc_task_cdb_length),
170145039663SJohn Forte 	    NV_PAIR(UINT8, m, icsc_task_flags),
170245039663SJohn Forte 	    NV_PAIR(UINT8, m, icsc_task_mgmt_function),
170345039663SJohn Forte 	    NV_PAIR(UINT32, m, icsc_immed_data_len),
170445039663SJohn Forte 	    NULL) != 0) {
170545039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_task_msgid and friends");
170645039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
170745039663SJohn Forte 		goto done;
170845039663SJohn Forte 	}
170945039663SJohn Forte 
171045039663SJohn Forte 	m->icsc_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
171145039663SJohn Forte 	    nvl, "icsc_ini_devid");
171245039663SJohn Forte 	if (m->icsc_ini_devid == NULL) {
171345039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_ini_devid");
171445039663SJohn Forte 		rc = ENOMEM;
171545039663SJohn Forte 		goto done;
171645039663SJohn Forte 	}
171745039663SJohn Forte 
171845039663SJohn Forte 	m->icsc_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
171945039663SJohn Forte 	    nvl, "icsc_tgt_devid");
172045039663SJohn Forte 	if (m->icsc_tgt_devid == NULL) {
172145039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_tgt_devid");
172245039663SJohn Forte 		rc = ENOMEM;
172345039663SJohn Forte 		goto done;
172445039663SJohn Forte 	}
172545039663SJohn Forte 
1726716c1805SNattuvetty Bhavyan 	m->icsc_rport = stmf_ic_lookup_remote_port_and_unmarshal(
1727716c1805SNattuvetty Bhavyan 	    nvl, "icsc_rport");
1728716c1805SNattuvetty Bhavyan 	if (m->icsc_rport == NULL) {
1729716c1805SNattuvetty Bhavyan 		stmf_ic_nvlookup_warn(__func__, "icsc_rport");
1730716c1805SNattuvetty Bhavyan 		rc = ENOMEM;
1731716c1805SNattuvetty Bhavyan 		goto done;
1732716c1805SNattuvetty Bhavyan 	}
1733716c1805SNattuvetty Bhavyan 
173445039663SJohn Forte 	/* icsc_lun_id */
173545039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_lun_id",
173645039663SJohn Forte 	    sizeof (m->icsc_lun_id), m->icsc_lun_id)) {
173745039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_lun_id");
173845039663SJohn Forte 		rc = ENOMEM;
173945039663SJohn Forte 		goto done;
174045039663SJohn Forte 	}
174145039663SJohn Forte 
174245039663SJohn Forte 	/* icsc_task_lun_no */
174345039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_lun_no",
174445039663SJohn Forte 	    sizeof (m->icsc_task_lun_no), m->icsc_task_lun_no)) {
174545039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_task_lun_no");
174645039663SJohn Forte 		rc = ENOMEM;
174745039663SJohn Forte 		goto done;
174845039663SJohn Forte 	}
174945039663SJohn Forte 
175045039663SJohn Forte 	/* icsc_task_cdb */
1751*8f641fa7SSue Gleeson 	if (m->icsc_task_cdb_length) {
1752*8f641fa7SSue Gleeson 		m->icsc_task_cdb = stmf_ic_uint8_array_unmarshal(nvl,
1753*8f641fa7SSue Gleeson 		    "icsc_task_cdb", m->icsc_task_cdb_length, NULL);
1754*8f641fa7SSue Gleeson 		if (!m->icsc_task_cdb) {
1755*8f641fa7SSue Gleeson 			stmf_ic_nvlookup_warn(__func__, "icsc_task_cdb");
1756*8f641fa7SSue Gleeson 			rc = ENOMEM;
1757*8f641fa7SSue Gleeson 			goto done;
1758*8f641fa7SSue Gleeson 		}
175945039663SJohn Forte 	}
176045039663SJohn Forte 
176145039663SJohn Forte 	/* immediate data, if there is any */
176245039663SJohn Forte 	if (m->icsc_immed_data_len) {
176345039663SJohn Forte 		m->icsc_immed_data = stmf_ic_uint8_array_unmarshal(nvl,
176445039663SJohn Forte 		    "icsc_immed_data", m->icsc_immed_data_len, NULL);
176545039663SJohn Forte 		if (!m->icsc_immed_data) {
176645039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icsc_immed_data");
176745039663SJohn Forte 			rc = ENOMEM;
176845039663SJohn Forte 			goto done;
176945039663SJohn Forte 		}
177045039663SJohn Forte 	}
177145039663SJohn Forte 
177245039663SJohn Forte done:
177345039663SJohn Forte 	if (!rc)
177445039663SJohn Forte 		return (m);
177545039663SJohn Forte 
177645039663SJohn Forte 	stmf_ic_scsi_cmd_msg_free(m, STMF_UNMARSHAL);
177745039663SJohn Forte 
177845039663SJohn Forte 	return (NULL);
177945039663SJohn Forte }
178045039663SJohn Forte 
178145039663SJohn Forte static void *
178245039663SJohn Forte stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl)
178345039663SJohn Forte {
178445039663SJohn Forte 	int rc = 0;
178545039663SJohn Forte 	stmf_ic_scsi_data_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
178645039663SJohn Forte 
178745039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
178845039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_task_msgid),
178945039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_session_id),
179045039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_data_len),
179145039663SJohn Forte 	    NULL) != 0) {
179245039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_task_msgid and friends");
179345039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
179445039663SJohn Forte 		goto done;
179545039663SJohn Forte 	}
179645039663SJohn Forte 
179745039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsd_lun_id",
179845039663SJohn Forte 	    sizeof (m->icsd_lun_id), m->icsd_lun_id)) {
179945039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_lun_id");
180045039663SJohn Forte 		rc = ENOMEM;
180145039663SJohn Forte 		goto done;
180245039663SJohn Forte 	}
180345039663SJohn Forte 
180445039663SJohn Forte 	m->icsd_data = stmf_ic_uint8_array_unmarshal(nvl, "icsd_data",
180545039663SJohn Forte 	    m->icsd_data_len, NULL);
180645039663SJohn Forte 	if (!m->icsd_data) {
180745039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_data");
180845039663SJohn Forte 		rc = ENOMEM;
180945039663SJohn Forte 		goto done;
181045039663SJohn Forte 	}
181145039663SJohn Forte 
181245039663SJohn Forte done:
181345039663SJohn Forte 	if (!rc)
181445039663SJohn Forte 		return (m);
181545039663SJohn Forte 
181645039663SJohn Forte 	stmf_ic_scsi_data_msg_free(m, STMF_UNMARSHAL);
181745039663SJohn Forte 
181845039663SJohn Forte 	return (NULL);
181945039663SJohn Forte }
182045039663SJohn Forte 
182145039663SJohn Forte static void *
182245039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl)
182345039663SJohn Forte {
182445039663SJohn Forte 	int rc = 0;
182545039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *m =
182645039663SJohn Forte 	    kmem_zalloc(sizeof (*m), KM_SLEEP);
182745039663SJohn Forte 
182845039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
182945039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_task_msgid),
183045039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_session_id),
183145039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_status),
183245039663SJohn Forte 	    NULL) != 0) {
183345039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsx_task_msgid and friends");
183445039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
183545039663SJohn Forte 		goto done;
183645039663SJohn Forte 	}
183745039663SJohn Forte 
183845039663SJohn Forte done:
183945039663SJohn Forte 	if (!rc)
184045039663SJohn Forte 		return (m);
184145039663SJohn Forte 
184245039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_free(m, STMF_UNMARSHAL);
184345039663SJohn Forte 
184445039663SJohn Forte 	return (NULL);
184545039663SJohn Forte }
184645039663SJohn Forte 
184745039663SJohn Forte static void *
184845039663SJohn Forte stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl)
184945039663SJohn Forte {
185045039663SJohn Forte 	int rc = 0;
185145039663SJohn Forte 	stmf_ic_scsi_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
185245039663SJohn Forte 
185345039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
185445039663SJohn Forte 	    NV_PAIR(UINT64, m, icss_task_msgid),
185545039663SJohn Forte 	    NV_PAIR(UINT64, m, icss_session_id),
185645039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_response),
185745039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_status),
185845039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_flags),
185945039663SJohn Forte 	    NV_PAIR(UINT32, m, icss_resid),
186045039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_sense_len),
186145039663SJohn Forte 	    NULL) != 0) {
186245039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icss_task_msgid and friends");
186345039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
186445039663SJohn Forte 		goto done;
186545039663SJohn Forte 	}
186645039663SJohn Forte 
186745039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icss_lun_id",
186845039663SJohn Forte 	    sizeof (m->icss_lun_id), m->icss_lun_id)) {
186945039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icss_lun_id");
187045039663SJohn Forte 		rc = ENOMEM;
187145039663SJohn Forte 		goto done;
187245039663SJohn Forte 	}
187345039663SJohn Forte 
187445039663SJohn Forte 	if (m->icss_sense_len) {
187545039663SJohn Forte 		m->icss_sense = stmf_ic_uint8_array_unmarshal(nvl, "icss_sense",
187645039663SJohn Forte 		    m->icss_sense_len, NULL);
187745039663SJohn Forte 		if (!m->icss_sense) {
187845039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icss_sense");
187945039663SJohn Forte 			rc = ENOMEM;
188045039663SJohn Forte 			goto done;
188145039663SJohn Forte 		}
188245039663SJohn Forte 	}
188345039663SJohn Forte done:
188445039663SJohn Forte 	if (!rc)
188545039663SJohn Forte 		return (m);
188645039663SJohn Forte 
188745039663SJohn Forte 	stmf_ic_scsi_status_msg_free(m, STMF_UNMARSHAL);
188845039663SJohn Forte 
188945039663SJohn Forte 	return (NULL);
189045039663SJohn Forte }
189145039663SJohn Forte 
189245039663SJohn Forte static void *
189345039663SJohn Forte stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl)
189445039663SJohn Forte {
189545039663SJohn Forte 	int rc = 0;
189645039663SJohn Forte 	stmf_ic_r2t_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
189745039663SJohn Forte 
189845039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
189945039663SJohn Forte 	    NV_PAIR(UINT64, m, icrt_task_msgid),
190045039663SJohn Forte 	    NV_PAIR(UINT64, m, icrt_session_id),
190145039663SJohn Forte 	    NV_PAIR(UINT32, m, icrt_offset),
190245039663SJohn Forte 	    NV_PAIR(UINT32, m, icrt_length),
190345039663SJohn Forte 	    NULL) != 0) {
190445039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrt_task_msgid and friends");
190545039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
190645039663SJohn Forte 		goto done;
190745039663SJohn Forte 	}
190845039663SJohn Forte 
190945039663SJohn Forte done:
191045039663SJohn Forte 	if (!rc)
191145039663SJohn Forte 		return (m);
191245039663SJohn Forte 
191345039663SJohn Forte 	stmf_ic_r2t_msg_free(m, STMF_UNMARSHAL);
191445039663SJohn Forte 
191545039663SJohn Forte 	return (NULL);
191645039663SJohn Forte }
191745039663SJohn Forte 
191845039663SJohn Forte static void *
191945039663SJohn Forte stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl)
192045039663SJohn Forte {
192145039663SJohn Forte 	int rc = 0;
192245039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *m = kmem_zalloc(sizeof (*m),
192345039663SJohn Forte 	    KM_SLEEP);
192445039663SJohn Forte 
192545039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
192645039663SJohn Forte 	    NV_PAIR(UINT64, m, icscd_session_id),
192745039663SJohn Forte 	    NULL) != 0) {
192845039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_session_id");
192945039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
193045039663SJohn Forte 		goto done;
193145039663SJohn Forte 	}
193245039663SJohn Forte 
193345039663SJohn Forte 	m->icscd_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
193445039663SJohn Forte 	    nvl, "icscd_ini_devid");
193545039663SJohn Forte 	if (m->icscd_ini_devid == NULL) {
193645039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_ini_devid");
193745039663SJohn Forte 		rc = ENOMEM;
193845039663SJohn Forte 		goto done;
193945039663SJohn Forte 	}
194045039663SJohn Forte 
194145039663SJohn Forte 	m->icscd_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
194245039663SJohn Forte 	    nvl, "icscd_tgt_devid");
194345039663SJohn Forte 	if (m->icscd_tgt_devid == NULL) {
194445039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_tgt_devid");
194545039663SJohn Forte 		rc = ENOMEM;
194645039663SJohn Forte 		goto done;
194745039663SJohn Forte 	}
194845039663SJohn Forte 
1949716c1805SNattuvetty Bhavyan 	m->icscd_rport = stmf_ic_lookup_remote_port_and_unmarshal(
1950716c1805SNattuvetty Bhavyan 	    nvl, "icscd_rport");
1951716c1805SNattuvetty Bhavyan 	if (m->icscd_rport == NULL) {
1952716c1805SNattuvetty Bhavyan 		stmf_ic_nvlookup_warn(__func__, "icscd_rport");
1953716c1805SNattuvetty Bhavyan 		rc = ENOMEM;
1954716c1805SNattuvetty Bhavyan 		goto done;
1955716c1805SNattuvetty Bhavyan 	}
1956716c1805SNattuvetty Bhavyan 
195745039663SJohn Forte done:
195845039663SJohn Forte 	if (!rc)
195945039663SJohn Forte 		return (m);
196045039663SJohn Forte 
196145039663SJohn Forte 	stmf_ic_session_create_destroy_msg_free(m, STMF_UNMARSHAL);
196245039663SJohn Forte 
196345039663SJohn Forte 	return (NULL);
196445039663SJohn Forte }
196545039663SJohn Forte 
196645039663SJohn Forte static void *
196745039663SJohn Forte stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl)
196845039663SJohn Forte {
196945039663SJohn Forte 	int rc = 0;
197045039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *m = kmem_zalloc(sizeof (*m),
197145039663SJohn Forte 	    KM_SLEEP);
197245039663SJohn Forte 
197345039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
197445039663SJohn Forte 	    NV_PAIR(UINT32, m, icerr_datalen),
197545039663SJohn Forte 	    NULL) != 0) {
197645039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icerr_datalen");
197745039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
197845039663SJohn Forte 		goto done;
197945039663SJohn Forte 	}
198045039663SJohn Forte 
198145039663SJohn Forte 	/* immediate data, if there is any */
198245039663SJohn Forte 	if (m->icerr_datalen) {
198345039663SJohn Forte 		m->icerr_data = stmf_ic_uint8_array_unmarshal(nvl,
198445039663SJohn Forte 		    "icerr_data", m->icerr_datalen, NULL);
198545039663SJohn Forte 		if (!m->icerr_data) {
198645039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icerr_data");
198745039663SJohn Forte 			rc = ENOMEM;
198845039663SJohn Forte 			goto done;
198945039663SJohn Forte 		}
199045039663SJohn Forte 	}
199145039663SJohn Forte 
199245039663SJohn Forte done:
199345039663SJohn Forte 	if (!rc)
199445039663SJohn Forte 		return (m);
199545039663SJohn Forte 
199645039663SJohn Forte 	stmf_ic_echo_request_reply_msg_free(m, STMF_UNMARSHAL);
199745039663SJohn Forte 
199845039663SJohn Forte 	return (NULL);
199945039663SJohn Forte }
200045039663SJohn Forte 
200145039663SJohn Forte static void *
200245039663SJohn Forte stmf_ic_status_msg_unmarshal(nvlist_t *nvl)
200345039663SJohn Forte {
200445039663SJohn Forte 	int rc = 0;
200545039663SJohn Forte 	stmf_ic_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
200645039663SJohn Forte 
200745039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
200845039663SJohn Forte 	    NV_PAIR(UINT8, m, ics_msg_type),
200945039663SJohn Forte 	    NV_PAIR(UINT64, m, ics_msgid),
201045039663SJohn Forte 	    NV_PAIR(UINT8, m, ics_status),
201145039663SJohn Forte 	    NULL) != 0) {
201245039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "ics_msg_type and friends");
201345039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
201445039663SJohn Forte 		goto done;
201545039663SJohn Forte 	}
201645039663SJohn Forte 
201745039663SJohn Forte done:
201845039663SJohn Forte 	if (!rc)
201945039663SJohn Forte 		return (m);
202045039663SJohn Forte 
202145039663SJohn Forte 	kmem_free(m, sizeof (*m));
202245039663SJohn Forte 	return (NULL);
202345039663SJohn Forte }
202445039663SJohn Forte 
202545039663SJohn Forte 
202645039663SJohn Forte static scsi_devid_desc_t *
202745039663SJohn Forte stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t *nvl, char *field_name)
202845039663SJohn Forte {
202945039663SJohn Forte 	nvlist_t *nvl_devid = NULL;
203045039663SJohn Forte 	scsi_devid_desc_t *did = NULL;
203145039663SJohn Forte 	int rc;
203245039663SJohn Forte 
203345039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, field_name, &nvl_devid);
203445039663SJohn Forte 	if (rc) {
203545039663SJohn Forte 		goto done;
203645039663SJohn Forte 	}
203745039663SJohn Forte 
203845039663SJohn Forte 	did = stmf_ic_scsi_devid_desc_unmarshal(nvl_devid);
203945039663SJohn Forte 
204045039663SJohn Forte done:
204145039663SJohn Forte 	return (did);
204245039663SJohn Forte }
204345039663SJohn Forte 
204445039663SJohn Forte 
204545039663SJohn Forte static scsi_devid_desc_t *
204645039663SJohn Forte stmf_ic_scsi_devid_desc_unmarshal(nvlist_t *nvl)
204745039663SJohn Forte {
204845039663SJohn Forte 	scsi_devid_desc_t *sdid = NULL;
204945039663SJohn Forte 	uint8_t ident_length = 0;
205045039663SJohn Forte 	size_t sdid_size;
205145039663SJohn Forte 	int rc = 0;
205245039663SJohn Forte 
205345039663SJohn Forte 	/*
205445039663SJohn Forte 	 * we get the ident_length first, since that's the only
205545039663SJohn Forte 	 * variable-sized field in the struct.
205645039663SJohn Forte 	 */
205745039663SJohn Forte 	rc = nvlist_lookup_uint8(nvl, "ident_length", &ident_length);
205845039663SJohn Forte 	if (rc)
205945039663SJohn Forte 		goto done;
206045039663SJohn Forte 
206145039663SJohn Forte 	sdid_size = sizeof_scsi_devid_desc(ident_length);
206245039663SJohn Forte 	sdid = kmem_zalloc(sdid_size, KM_SLEEP);
206345039663SJohn Forte 
206445039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, protocol_id);
206545039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, code_set);
206645039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, piv);
206745039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, association);
206845039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, ident_type);
206945039663SJohn Forte 
207045039663SJohn Forte 	sdid->ident_length = ident_length;
207145039663SJohn Forte 
207245039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "ident",
207345039663SJohn Forte 	    sdid->ident_length, sdid->ident)) {
207445039663SJohn Forte 		rc = ENOMEM; /* XXX */
207545039663SJohn Forte 		goto done;
207645039663SJohn Forte 	}
207745039663SJohn Forte 
207845039663SJohn Forte done:
207945039663SJohn Forte 	if (!rc)
208045039663SJohn Forte 		return (sdid);
208145039663SJohn Forte 
208245039663SJohn Forte 	kmem_free(sdid, sdid_size);
208345039663SJohn Forte 
208445039663SJohn Forte 	return (NULL);
208545039663SJohn Forte }
208645039663SJohn Forte 
2087716c1805SNattuvetty Bhavyan static stmf_remote_port_t *
2088716c1805SNattuvetty Bhavyan stmf_ic_lookup_remote_port_and_unmarshal(nvlist_t *nvl, char *field_name)
2089716c1805SNattuvetty Bhavyan {
2090716c1805SNattuvetty Bhavyan 	nvlist_t *nvl_rport = NULL;
2091716c1805SNattuvetty Bhavyan 
2092716c1805SNattuvetty Bhavyan 	if (nvlist_lookup_nvlist(nvl, field_name, &nvl_rport) != 0)
2093716c1805SNattuvetty Bhavyan 		return (NULL);
2094716c1805SNattuvetty Bhavyan 
2095716c1805SNattuvetty Bhavyan 	return (stmf_ic_remote_port_unmarshal(nvl_rport));
2096716c1805SNattuvetty Bhavyan }
2097716c1805SNattuvetty Bhavyan 
2098716c1805SNattuvetty Bhavyan static stmf_remote_port_t *
2099716c1805SNattuvetty Bhavyan stmf_ic_remote_port_unmarshal(nvlist_t *nvl)
2100716c1805SNattuvetty Bhavyan {
2101716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *rport = NULL;
2102716c1805SNattuvetty Bhavyan 	uint16_t rport_tptid_sz = 0;
2103716c1805SNattuvetty Bhavyan 	int rc = 0;
2104716c1805SNattuvetty Bhavyan 
2105716c1805SNattuvetty Bhavyan 	rc = nvlist_lookup_uint16(nvl, "rport_tptid_sz", &rport_tptid_sz);
2106716c1805SNattuvetty Bhavyan 	if (rc || rport_tptid_sz < sizeof (scsi_transport_id_t))
2107716c1805SNattuvetty Bhavyan 		return (NULL);
2108716c1805SNattuvetty Bhavyan 
2109716c1805SNattuvetty Bhavyan 	rport = stmf_remote_port_alloc(rport_tptid_sz);
2110716c1805SNattuvetty Bhavyan 	if (!stmf_ic_uint8_array_unmarshal(nvl, "rport_tptid", rport_tptid_sz,
2111716c1805SNattuvetty Bhavyan 	    (uint8_t *)rport->rport_tptid)) {
2112716c1805SNattuvetty Bhavyan 		stmf_remote_port_free(rport);
2113716c1805SNattuvetty Bhavyan 		rport = NULL;
2114716c1805SNattuvetty Bhavyan 	}
2115716c1805SNattuvetty Bhavyan 	return (rport);
2116716c1805SNattuvetty Bhavyan }
2117716c1805SNattuvetty Bhavyan 
211845039663SJohn Forte /*
211945039663SJohn Forte  * Unmarshal a uint8_t array.
212045039663SJohn Forte  *
212145039663SJohn Forte  * Takes a buf argument:
212245039663SJohn Forte  *
212345039663SJohn Forte  * - if non-null, the array contents are copied into the buf,
212445039663SJohn Forte  *   and we return a pointer to the buffer.
212545039663SJohn Forte  *
212645039663SJohn Forte  * - if null, we return a pointer to the unmarshaled data, which
212745039663SJohn Forte  *   resides in the nvlist.
212845039663SJohn Forte  *
212945039663SJohn Forte  * Returns NULL on failure.
213045039663SJohn Forte  */
213145039663SJohn Forte static uint8_t *
213245039663SJohn Forte stmf_ic_uint8_array_unmarshal(
213345039663SJohn Forte     nvlist_t *nvl,
213445039663SJohn Forte     char *field_name,
213591159e90SJohn Forte     uint64_t len,
213645039663SJohn Forte     uint8_t *buf)	/* non-NULL: copy array into buf */
213745039663SJohn Forte {
213845039663SJohn Forte 	uint8_t *array = NULL;
213945039663SJohn Forte 	uint_t actual_len;
214045039663SJohn Forte 	int rc = 0;
214145039663SJohn Forte 
214245039663SJohn Forte 	rc = nvlist_lookup_uint8_array(nvl, field_name, &array, &actual_len);
214345039663SJohn Forte 	if (rc) {
214445039663SJohn Forte 		return (NULL);
214545039663SJohn Forte 	}
214645039663SJohn Forte 
214745039663SJohn Forte 	if (len != actual_len) {
214845039663SJohn Forte 		cmn_err(CE_WARN,
214945039663SJohn Forte 		    "stmf_ic_uint8_array_unmarshal: wrong len (%d != %d)",
215091159e90SJohn Forte 		    (int)len, actual_len);
215145039663SJohn Forte 		return (NULL);
215245039663SJohn Forte 	}
215345039663SJohn Forte 
215445039663SJohn Forte 	if (buf) {
215545039663SJohn Forte 		/* preallocated buf, copy in */
215645039663SJohn Forte 		bcopy(array, buf, len);
215745039663SJohn Forte 	} else {
215845039663SJohn Forte 		/* return a pointer to the underlying array in the nvlist */
215945039663SJohn Forte 		buf = array;
216045039663SJohn Forte 	}
216145039663SJohn Forte 
216245039663SJohn Forte 	return (buf);
216345039663SJohn Forte }
216445039663SJohn Forte 
216545039663SJohn Forte /*
216645039663SJohn Forte  * Unmarshal a string.
216745039663SJohn Forte  *
216845039663SJohn Forte  * Returns NULL on failure.
216945039663SJohn Forte  */
217045039663SJohn Forte static char *
217145039663SJohn Forte stmf_ic_string_unmarshal(
217245039663SJohn Forte     nvlist_t *nvl,
217345039663SJohn Forte     char *field_name)
217445039663SJohn Forte {
217545039663SJohn Forte 	char *s = NULL;
217645039663SJohn Forte 	int rc = 0;
217745039663SJohn Forte 
217845039663SJohn Forte 	rc = nvlist_lookup_string(nvl, field_name, &s);
217945039663SJohn Forte 	if (rc) {
218045039663SJohn Forte 		return (NULL);
218145039663SJohn Forte 	}
218245039663SJohn Forte 
218345039663SJohn Forte 	return (s);
218445039663SJohn Forte }
218545039663SJohn Forte 
218645039663SJohn Forte /*
218745039663SJohn Forte  * Utility routines.
218845039663SJohn Forte  */
218945039663SJohn Forte 
219045039663SJohn Forte static stmf_ic_msg_t *
219145039663SJohn Forte stmf_ic_alloc_msg_header(
219245039663SJohn Forte     stmf_ic_msg_type_t msg_type,
219345039663SJohn Forte     stmf_ic_msgid_t msgid)
219445039663SJohn Forte {
219545039663SJohn Forte 	stmf_ic_msg_t *icm;
219645039663SJohn Forte 
219745039663SJohn Forte 	icm = (stmf_ic_msg_t *)kmem_zalloc(sizeof (*icm), KM_SLEEP);
219845039663SJohn Forte 	icm->icm_msg_type = msg_type;
219945039663SJohn Forte 	icm->icm_msgid = msgid;
220045039663SJohn Forte 
220145039663SJohn Forte 	return (icm);
220245039663SJohn Forte }
220345039663SJohn Forte 
220445039663SJohn Forte static size_t
220545039663SJohn Forte sizeof_scsi_devid_desc(int ident_length)
220645039663SJohn Forte {
220745039663SJohn Forte 	int num_ident_elems;
220845039663SJohn Forte 	size_t size;
220945039663SJohn Forte 
221045039663SJohn Forte 	ASSERT(ident_length > 0);
221145039663SJohn Forte 
221245039663SJohn Forte 	/*
221345039663SJohn Forte 	 * Need to account for the fact that there's
221445039663SJohn Forte 	 * already a single element in scsi_devid_desc_t.
221545039663SJohn Forte 	 *
221645039663SJohn Forte 	 * XXX would really like to have a way to determine the
221745039663SJohn Forte 	 * sizeof (struct scsi_devid_desc.ident[0]), but
221845039663SJohn Forte 	 * it's not clear that can be done.
221945039663SJohn Forte 	 * Thus, this code relies on the knowledge of the type of
222045039663SJohn Forte 	 * that field.
222145039663SJohn Forte 	 */
222245039663SJohn Forte 	num_ident_elems = ident_length - 1;
222345039663SJohn Forte 	size = sizeof (scsi_devid_desc_t) +
222445039663SJohn Forte 	    (num_ident_elems * sizeof (uint8_t));
222545039663SJohn Forte 
222645039663SJohn Forte 	return (size);
222745039663SJohn Forte }
222845039663SJohn Forte 
222945039663SJohn Forte 
223045039663SJohn Forte /*
223145039663SJohn Forte  * Duplicate the scsi_devid_desc_t.
223245039663SJohn Forte  */
223345039663SJohn Forte static scsi_devid_desc_t *
223445039663SJohn Forte scsi_devid_desc_dup(scsi_devid_desc_t *did)
223545039663SJohn Forte {
223645039663SJohn Forte 	scsi_devid_desc_t *dup;
223745039663SJohn Forte 	size_t dup_size;
223845039663SJohn Forte 
223945039663SJohn Forte 	ASSERT(did->ident_length > 0);
224045039663SJohn Forte 
224145039663SJohn Forte 	dup_size = sizeof_scsi_devid_desc(did->ident_length);
224245039663SJohn Forte 	dup = (scsi_devid_desc_t *)kmem_zalloc(dup_size, KM_SLEEP);
224345039663SJohn Forte 	bcopy(did, dup, dup_size);
224445039663SJohn Forte 	return (dup);
224545039663SJohn Forte }
224645039663SJohn Forte 
224745039663SJohn Forte /*
224845039663SJohn Forte  * May be called with a null pointer.
224945039663SJohn Forte  */
225045039663SJohn Forte static void
225145039663SJohn Forte scsi_devid_desc_free(scsi_devid_desc_t *did)
225245039663SJohn Forte {
225345039663SJohn Forte 	if (!did)
225445039663SJohn Forte 		return;
225545039663SJohn Forte 
225645039663SJohn Forte 	kmem_free(did, sizeof_scsi_devid_desc(did->ident_length));
225745039663SJohn Forte }
225845039663SJohn Forte 
2259716c1805SNattuvetty Bhavyan /*
2260716c1805SNattuvetty Bhavyan  * Duplicate the stmf_remote_port_t.
2261716c1805SNattuvetty Bhavyan  */
2262716c1805SNattuvetty Bhavyan static stmf_remote_port_t *
2263716c1805SNattuvetty Bhavyan remote_port_dup(stmf_remote_port_t *rport)
2264716c1805SNattuvetty Bhavyan {
2265716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *dup = NULL;
2266716c1805SNattuvetty Bhavyan 	if (rport) {
2267716c1805SNattuvetty Bhavyan 		dup = stmf_remote_port_alloc(rport->rport_tptid_sz);
2268716c1805SNattuvetty Bhavyan 		bcopy(rport->rport_tptid, dup->rport_tptid,
2269716c1805SNattuvetty Bhavyan 		    rport->rport_tptid_sz);
2270716c1805SNattuvetty Bhavyan 	}
2271716c1805SNattuvetty Bhavyan 	return (dup);
2272716c1805SNattuvetty Bhavyan }
2273716c1805SNattuvetty Bhavyan 
227445039663SJohn Forte /*
227545039663SJohn Forte  * Helper functions, returns NULL if no memory.
227645039663SJohn Forte  */
227745039663SJohn Forte static char *
227845039663SJohn Forte stmf_ic_strdup(char *str)
227945039663SJohn Forte {
228045039663SJohn Forte 	char *copy;
228145039663SJohn Forte 
228245039663SJohn Forte 	ASSERT(str);
228345039663SJohn Forte 
228445039663SJohn Forte 	copy = kmem_zalloc(strlen(str) + 1, KM_SLEEP);
228545039663SJohn Forte 	(void) strcpy(copy, str);
228645039663SJohn Forte 	return (copy);
228745039663SJohn Forte }
228845039663SJohn Forte 
228945039663SJohn Forte static inline void
229045039663SJohn Forte stmf_ic_nvlookup_warn(const char *func, char *field)
229145039663SJohn Forte {
229245039663SJohn Forte 	cmn_err(CE_WARN, "%s: nvlist lookup of %s failed", func, field);
229345039663SJohn Forte }
2294