1*45039663SJohn Forte /*
2*45039663SJohn Forte  * CDDL HEADER START
3*45039663SJohn Forte  *
4*45039663SJohn Forte  * The contents of this file are subject to the terms of the
5*45039663SJohn Forte  * Common Development and Distribution License (the "License").
6*45039663SJohn Forte  * You may not use this file except in compliance with the License.
7*45039663SJohn Forte  *
8*45039663SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*45039663SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*45039663SJohn Forte  * See the License for the specific language governing permissions
11*45039663SJohn Forte  * and limitations under the License.
12*45039663SJohn Forte  *
13*45039663SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*45039663SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*45039663SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*45039663SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*45039663SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*45039663SJohn Forte  *
19*45039663SJohn Forte  * CDDL HEADER END
20*45039663SJohn Forte  */
21*45039663SJohn Forte /*
22*45039663SJohn Forte  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*45039663SJohn Forte  * Use is subject to license terms.
24*45039663SJohn Forte  */
25*45039663SJohn Forte 
26*45039663SJohn Forte /*
27*45039663SJohn Forte  * XXX TODO
28*45039663SJohn Forte  * #includes cribbed from stmf.c -- undoubtedly only a small subset of these
29*45039663SJohn Forte  * are actually needed.
30*45039663SJohn Forte  */
31*45039663SJohn Forte #include <sys/conf.h>
32*45039663SJohn Forte #include <sys/file.h>
33*45039663SJohn Forte #include <sys/ddi.h>
34*45039663SJohn Forte #include <sys/sunddi.h>
35*45039663SJohn Forte #include <sys/scsi/scsi.h>
36*45039663SJohn Forte #include <sys/byteorder.h>
37*45039663SJohn Forte #include <sys/nvpair.h>
38*45039663SJohn Forte #include <sys/door.h>
39*45039663SJohn Forte 
40*45039663SJohn Forte #include <sys/stmf.h>
41*45039663SJohn Forte #include <sys/lpif.h>
42*45039663SJohn Forte #include <sys/stmf_ioctl.h>
43*45039663SJohn Forte #include <sys/portif.h>
44*45039663SJohn Forte #include <pppt.h>
45*45039663SJohn Forte #include <sys/pppt_ic_if.h>
46*45039663SJohn Forte 
47*45039663SJohn Forte 
48*45039663SJohn Forte /*
49*45039663SJohn Forte  * Macros
50*45039663SJohn Forte  */
51*45039663SJohn Forte 
52*45039663SJohn Forte /* Free a struct if it was allocated */
53*45039663SJohn Forte #define	FREE_IF_ALLOC(m)					\
54*45039663SJohn Forte 	do {							\
55*45039663SJohn Forte 		if ((m)) kmem_free((m), sizeof (*(m)));		\
56*45039663SJohn Forte 		_NOTE(CONSTCOND)				\
57*45039663SJohn Forte 	} while (0)
58*45039663SJohn Forte 
59*45039663SJohn Forte /*
60*45039663SJohn Forte  * Macros to simplify the addition of struct fields to an nvlist.
61*45039663SJohn Forte  * The name of the fields in the nvlist is the same as the name
62*45039663SJohn Forte  * of the struct field.
63*45039663SJohn Forte  *
64*45039663SJohn Forte  * These macros require an int rc and a "done:" return retval label;
65*45039663SJohn Forte  * they assume that the nvlist is named "nvl".
66*45039663SJohn Forte  */
67*45039663SJohn Forte #define	NVLIST_ADD_FIELD(type, structure, field)			\
68*45039663SJohn Forte 	do {								\
69*45039663SJohn Forte 		rc = nvlist_add_##type(nvl, #field, structure->field);  \
70*45039663SJohn Forte 		if (rc) goto done;					\
71*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
72*45039663SJohn Forte 	} while (0)
73*45039663SJohn Forte 
74*45039663SJohn Forte /* use this macro when the array is defined as part of the struct */
75*45039663SJohn Forte #define	NVLIST_ADD_ARRAY(type, structure, field)			\
76*45039663SJohn Forte 	do {								\
77*45039663SJohn Forte 		rc = nvlist_add_##type##_array(nvl, #field,		\
78*45039663SJohn Forte 		    structure->field, sizeof (structure->field));	\
79*45039663SJohn Forte 		if (rc) goto done;					\
80*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
81*45039663SJohn Forte 	} while (0)
82*45039663SJohn Forte 
83*45039663SJohn Forte /*
84*45039663SJohn Forte  * use this macro when the array field is a ptr or you need to explictly
85*45039663SJohn Forte  * call out the size.
86*45039663SJohn Forte  */
87*45039663SJohn Forte #define	NVLIST_ADD_ARRAY_LEN(type, structure, field, len)		\
88*45039663SJohn Forte 	do {								\
89*45039663SJohn Forte 		rc = nvlist_add_##type##_array(nvl, #field,		\
90*45039663SJohn Forte 		    structure->field, len);				\
91*45039663SJohn Forte 		if (rc) goto done;					\
92*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
93*45039663SJohn Forte 	} while (0)
94*45039663SJohn Forte 
95*45039663SJohn Forte #define	NVLIST_ADD_DEVID(structure, field)				\
96*45039663SJohn Forte 	do {								\
97*45039663SJohn Forte 		rc = stmf_ic_scsi_devid_desc_marshal(nvl, #field,	\
98*45039663SJohn Forte 		    structure->field);					\
99*45039663SJohn Forte 		if (rc) goto done;					\
100*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
101*45039663SJohn Forte 	} while (0)
102*45039663SJohn Forte 
103*45039663SJohn Forte #define	NVLIST_ADD_FIELD_UINT8(structure, field)			\
104*45039663SJohn Forte 	NVLIST_ADD_FIELD(structure, field, uint8)
105*45039663SJohn Forte 
106*45039663SJohn Forte /*
107*45039663SJohn Forte  * Macros to simplify the extraction of struct fields from an nvlist.
108*45039663SJohn Forte  * The name of the fields in the nvlist is the same as the name
109*45039663SJohn Forte  * of the struct field.
110*45039663SJohn Forte  *
111*45039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
112*45039663SJohn Forte  * Assumes that the nvlist is named "nvl".
113*45039663SJohn Forte  *
114*45039663SJohn Forte  * Sample usage: NVLIST_LOOKUP_FIELD(uint8, structname, fieldname);
115*45039663SJohn Forte  */
116*45039663SJohn Forte #define	NVLIST_LOOKUP_FIELD(type, structure, field)			\
117*45039663SJohn Forte 	do {								\
118*45039663SJohn Forte 		rc = nvlist_lookup_##type(nvl, #field,			\
119*45039663SJohn Forte 		    &(structure->field));				\
120*45039663SJohn Forte 		if (rc) { 						\
121*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
122*45039663SJohn Forte 			goto done;					\
123*45039663SJohn Forte 		}							\
124*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
125*45039663SJohn Forte 	} while (0)
126*45039663SJohn Forte 
127*45039663SJohn Forte /*
128*45039663SJohn Forte  * Look up a field which gets stored into a structure bit field.
129*45039663SJohn Forte  * The type passed is a uint type which can hold the largest value
130*45039663SJohn Forte  * in the bit field.
131*45039663SJohn Forte  *
132*45039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
133*45039663SJohn Forte  * Assumes that the nvlist is named "nvl".
134*45039663SJohn Forte  *
135*45039663SJohn Forte  * Sample usage: NVLIST_LOOKUP_BIT_FIELD(uint8, structname, fieldname);
136*45039663SJohn Forte  */
137*45039663SJohn Forte #define	NVLIST_LOOKUP_BIT_FIELD(type, structure, field)			\
138*45039663SJohn Forte 	do {								\
139*45039663SJohn Forte 		type##_t tmp;						\
140*45039663SJohn Forte 		rc = nvlist_lookup_##type(nvl, #field, &tmp);		\
141*45039663SJohn Forte 		if (rc) { 						\
142*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
143*45039663SJohn Forte 			goto done;					\
144*45039663SJohn Forte 		}							\
145*45039663SJohn Forte 		structure->field = tmp;					\
146*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
147*45039663SJohn Forte 	} while (0)
148*45039663SJohn Forte 
149*45039663SJohn Forte /*
150*45039663SJohn Forte  * Look up a boolean field which gets stored into a structure bit field.
151*45039663SJohn Forte  *
152*45039663SJohn Forte  * Requires an int rc and a "done:" return retval label.
153*45039663SJohn Forte  * Assumes that the nvlist is named "nvl".
154*45039663SJohn Forte  */
155*45039663SJohn Forte #define	NVLIST_LOOKUP_BIT_FIELD_BOOLEAN(structure, field)		\
156*45039663SJohn Forte 	do {								\
157*45039663SJohn Forte 		boolean_t tmp;						\
158*45039663SJohn Forte 		rc = nvlist_lookup_boolean_value(nvl, #field, &tmp);	\
159*45039663SJohn Forte 		if (rc) { 						\
160*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, #field);	\
161*45039663SJohn Forte 			goto done;					\
162*45039663SJohn Forte 		}							\
163*45039663SJohn Forte 		structure->field = (tmp ?  1 : 0);			\
164*45039663SJohn Forte 		_NOTE(CONSTCOND)					\
165*45039663SJohn Forte 	} while (0)
166*45039663SJohn Forte 
167*45039663SJohn Forte /* shorthand  for nvlist_lookup_pairs() args */
168*45039663SJohn Forte #define	NV_PAIR(type, strct, field) #field, DATA_TYPE_##type, &(strct->field)
169*45039663SJohn Forte 
170*45039663SJohn Forte /* number of times to retry the upcall to transmit */
171*45039663SJohn Forte #define	STMF_MSG_TRANSMIT_RETRY	    3
172*45039663SJohn Forte 
173*45039663SJohn Forte /*
174*45039663SJohn Forte  * How was the message constructed?
175*45039663SJohn Forte  *
176*45039663SJohn Forte  * We need to know this when we free the message in order to
177*45039663SJohn Forte  * determine what to do with pointers in the message:
178*45039663SJohn Forte  *
179*45039663SJohn Forte  * - messages which were unmarshaled from an nvlist may point to
180*45039663SJohn Forte  *   memory within that nvlist; this memory should not be freed since
181*45039663SJohn Forte  *   it will be deallocated when we free the nvlist.
182*45039663SJohn Forte  *
183*45039663SJohn Forte  * - messages which built using a constructor (alloc) function may
184*45039663SJohn Forte  *   point to memory which was explicitly allocated by the constructor;
185*45039663SJohn Forte  *   it should be freed when the message is freed.
186*45039663SJohn Forte  *
187*45039663SJohn Forte  */
188*45039663SJohn Forte typedef enum {
189*45039663SJohn Forte 	STMF_CONSTRUCTOR = 0,
190*45039663SJohn Forte 	STMF_UNMARSHAL
191*45039663SJohn Forte } stmf_ic_msg_construction_method_t;
192*45039663SJohn Forte 
193*45039663SJohn Forte 
194*45039663SJohn Forte /*
195*45039663SJohn Forte  * Function prototypes.
196*45039663SJohn Forte  */
197*45039663SJohn Forte 
198*45039663SJohn Forte /*
199*45039663SJohn Forte  * Helpers for msg_alloc routines, used when the msg payload is
200*45039663SJohn Forte  * the same for multiple types of messages.
201*45039663SJohn Forte  */
202*45039663SJohn Forte static stmf_ic_msg_t *stmf_ic_reg_dereg_lun_msg_alloc(
203*45039663SJohn Forte     stmf_ic_msg_type_t msg_type, uint8_t *lun_id,
204*45039663SJohn Forte     char *lu_provider_name, uint16_t cb_arg_len,
205*45039663SJohn Forte     uint8_t *cb_arg, stmf_ic_msgid_t msgid);
206*45039663SJohn Forte 
207*45039663SJohn Forte static stmf_ic_msg_t *stmf_ic_session_create_destroy_msg_alloc(
208*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
209*45039663SJohn Forte     stmf_scsi_session_t *session,
210*45039663SJohn Forte     stmf_ic_msgid_t msgid);
211*45039663SJohn Forte 
212*45039663SJohn Forte static stmf_ic_msg_t *stmf_ic_echo_request_reply_msg_alloc(
213*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
214*45039663SJohn Forte     uint32_t data_len,
215*45039663SJohn Forte     uint8_t *data,
216*45039663SJohn Forte     stmf_ic_msgid_t msgid);
217*45039663SJohn Forte 
218*45039663SJohn Forte /*
219*45039663SJohn Forte  * Msg free routines.
220*45039663SJohn Forte  */
221*45039663SJohn Forte static void stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
222*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
223*45039663SJohn Forte static void stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
224*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
225*45039663SJohn Forte static void stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
226*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
227*45039663SJohn Forte static void stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
228*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
229*45039663SJohn Forte static void stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
230*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
231*45039663SJohn Forte static void stmf_ic_scsi_data_xfer_done_msg_free(
232*45039663SJohn Forte     stmf_ic_scsi_data_xfer_done_msg_t *m,
233*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
234*45039663SJohn Forte static void stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
235*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
236*45039663SJohn Forte static void stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
237*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
238*45039663SJohn Forte static void stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
239*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
240*45039663SJohn Forte static void stmf_ic_session_create_destroy_msg_free(
241*45039663SJohn Forte     stmf_ic_session_create_destroy_msg_t *m,
242*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
243*45039663SJohn Forte static void stmf_ic_echo_request_reply_msg_free(
244*45039663SJohn Forte     stmf_ic_echo_request_reply_msg_t *m,
245*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod);
246*45039663SJohn Forte 
247*45039663SJohn Forte /*
248*45039663SJohn Forte  * Marshaling routines.
249*45039663SJohn Forte  */
250*45039663SJohn Forte static nvlist_t *stmf_ic_msg_marshal(stmf_ic_msg_t *msg);
251*45039663SJohn Forte static int stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg);
252*45039663SJohn Forte static int stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg);
253*45039663SJohn Forte static int stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg);
254*45039663SJohn Forte static int stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg);
255*45039663SJohn Forte static int stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg);
256*45039663SJohn Forte static int stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg);
257*45039663SJohn Forte static int stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg);
258*45039663SJohn Forte static int stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg);
259*45039663SJohn Forte static int stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg);
260*45039663SJohn Forte static int stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg);
261*45039663SJohn Forte static int stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg);
262*45039663SJohn Forte static int stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
263*45039663SJohn Forte 	char *sdid_name, scsi_devid_desc_t *sdid);
264*45039663SJohn Forte 
265*45039663SJohn Forte /*
266*45039663SJohn Forte  * Unmarshaling routines.
267*45039663SJohn Forte  */
268*45039663SJohn Forte static stmf_ic_msg_t *stmf_ic_msg_unmarshal(nvlist_t *nvl);
269*45039663SJohn Forte static void *stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl);
270*45039663SJohn Forte static void *stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl);
271*45039663SJohn Forte static void *stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl);
272*45039663SJohn Forte static void *stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl);
273*45039663SJohn Forte static void *stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl);
274*45039663SJohn Forte static void *stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl);
275*45039663SJohn Forte static void *stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl);
276*45039663SJohn Forte static void *stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl);
277*45039663SJohn Forte static void *stmf_ic_status_msg_unmarshal(nvlist_t *nvl);
278*45039663SJohn Forte static void *stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl);
279*45039663SJohn Forte static void *stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl);
280*45039663SJohn Forte static scsi_devid_desc_t *stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
281*45039663SJohn Forte     nvlist_t *nvl, char *field_name);
282*45039663SJohn Forte static scsi_devid_desc_t *stmf_ic_scsi_devid_desc_unmarshal(
283*45039663SJohn Forte     nvlist_t *nvl_devid);
284*45039663SJohn Forte static uint8_t *stmf_ic_uint8_array_unmarshal(nvlist_t *nvl, char *field_name,
285*45039663SJohn Forte 	uint16_t len, uint8_t *buf);
286*45039663SJohn Forte static char *stmf_ic_string_unmarshal(nvlist_t *nvl, char *field_name);
287*45039663SJohn Forte 
288*45039663SJohn Forte /*
289*45039663SJohn Forte  * Transmit and recieve routines.
290*45039663SJohn Forte  */
291*45039663SJohn Forte stmf_ic_msg_status_t stmf_ic_transmit(char *buf, size_t size);
292*45039663SJohn Forte 
293*45039663SJohn Forte /*
294*45039663SJohn Forte  * Utilities.
295*45039663SJohn Forte  */
296*45039663SJohn Forte static stmf_ic_msg_t *stmf_ic_alloc_msg_header(stmf_ic_msg_type_t msg_type,
297*45039663SJohn Forte 	stmf_ic_msgid_t msgid);
298*45039663SJohn Forte static size_t sizeof_scsi_devid_desc(int ident_length);
299*45039663SJohn Forte static char *stmf_ic_strdup(char *str);
300*45039663SJohn Forte static scsi_devid_desc_t *scsi_devid_desc_dup(scsi_devid_desc_t *did);
301*45039663SJohn Forte static void scsi_devid_desc_free(scsi_devid_desc_t *did);
302*45039663SJohn Forte static inline void stmf_ic_nvlookup_warn(const char *func, char *field);
303*45039663SJohn Forte 
304*45039663SJohn Forte /*
305*45039663SJohn Forte  * Send a message out over the interconnect, in the process marshalling
306*45039663SJohn Forte  * the arguments.
307*45039663SJohn Forte  *
308*45039663SJohn Forte  * After being sent, the message is freed.
309*45039663SJohn Forte  */
310*45039663SJohn Forte stmf_ic_msg_status_t
311*45039663SJohn Forte stmf_ic_tx_msg(stmf_ic_msg_t *msg)
312*45039663SJohn Forte {
313*45039663SJohn Forte 	size_t size = 0;
314*45039663SJohn Forte 	nvlist_t *nvl = NULL;
315*45039663SJohn Forte 	char *buf = NULL;
316*45039663SJohn Forte 	int err = 0;
317*45039663SJohn Forte 	stmf_ic_msg_status_t status = STMF_IC_MSG_SUCCESS;
318*45039663SJohn Forte 
319*45039663SJohn Forte 	nvl = stmf_ic_msg_marshal(msg);
320*45039663SJohn Forte 	if (!nvl) {
321*45039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_tx_msg: marshal failed");
322*45039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
323*45039663SJohn Forte 		goto done;
324*45039663SJohn Forte 	}
325*45039663SJohn Forte 
326*45039663SJohn Forte 	err = nvlist_size(nvl, &size, NV_ENCODE_XDR);
327*45039663SJohn Forte 	if (err) {
328*45039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
329*45039663SJohn Forte 		goto done;
330*45039663SJohn Forte 	}
331*45039663SJohn Forte 
332*45039663SJohn Forte 	buf = kmem_alloc(size, KM_SLEEP);
333*45039663SJohn Forte 	err = nvlist_pack(nvl, &buf, &size, NV_ENCODE_XDR, 0);
334*45039663SJohn Forte 	if (err) {
335*45039663SJohn Forte 		status = STMF_IC_MSG_INTERNAL_ERROR;
336*45039663SJohn Forte 		goto done;
337*45039663SJohn Forte 	}
338*45039663SJohn Forte 
339*45039663SJohn Forte 	/* push the bits out on the wire */
340*45039663SJohn Forte 
341*45039663SJohn Forte 	status = stmf_ic_transmit(buf, size);
342*45039663SJohn Forte 
343*45039663SJohn Forte done:
344*45039663SJohn Forte 	if (nvl)
345*45039663SJohn Forte 		nvlist_free(nvl);
346*45039663SJohn Forte 
347*45039663SJohn Forte 	if (buf)
348*45039663SJohn Forte 		kmem_free(buf, size);
349*45039663SJohn Forte 
350*45039663SJohn Forte 	stmf_ic_msg_free(msg);
351*45039663SJohn Forte 
352*45039663SJohn Forte 
353*45039663SJohn Forte 	return (status);
354*45039663SJohn Forte }
355*45039663SJohn Forte 
356*45039663SJohn Forte /*
357*45039663SJohn Forte  * Pass the command to the daemon for transmission to the other node.
358*45039663SJohn Forte  */
359*45039663SJohn Forte stmf_ic_msg_status_t
360*45039663SJohn Forte stmf_ic_transmit(char *buf, size_t size)
361*45039663SJohn Forte {
362*45039663SJohn Forte 	int i;
363*45039663SJohn Forte 	int rc;
364*45039663SJohn Forte 	door_arg_t arg;
365*45039663SJohn Forte 	door_handle_t door;
366*45039663SJohn Forte 	uint32_t result;
367*45039663SJohn Forte 
368*45039663SJohn Forte 	mutex_enter(&pppt_global.global_door_lock);
369*45039663SJohn Forte 	if (pppt_global.global_door == NULL) {
370*45039663SJohn Forte 		/* daemon not listening */
371*45039663SJohn Forte 		mutex_exit(&pppt_global.global_door_lock);
372*45039663SJohn Forte 		return (STMF_IC_MSG_INTERNAL_ERROR);
373*45039663SJohn Forte 	}
374*45039663SJohn Forte 	door = pppt_global.global_door;
375*45039663SJohn Forte 	door_ki_hold(door);
376*45039663SJohn Forte 	mutex_exit(&pppt_global.global_door_lock);
377*45039663SJohn Forte 
378*45039663SJohn Forte 	arg.data_ptr = buf;
379*45039663SJohn Forte 	arg.data_size = size;
380*45039663SJohn Forte 	arg.desc_ptr = NULL;
381*45039663SJohn Forte 	arg.desc_num = 0;
382*45039663SJohn Forte 	arg.rbuf = (char *)&result;
383*45039663SJohn Forte 	arg.rsize = sizeof (result);
384*45039663SJohn Forte 	/*
385*45039663SJohn Forte 	 * Retry a few times if there is a shortage of threads to
386*45039663SJohn Forte 	 * service the upcall. This shouldn't happen unless a large
387*45039663SJohn Forte 	 * number of initiators issue commands at once.
388*45039663SJohn Forte 	 */
389*45039663SJohn Forte 	for (i = 0; i < STMF_MSG_TRANSMIT_RETRY; i++) {
390*45039663SJohn Forte 		rc = door_ki_upcall(door, &arg);
391*45039663SJohn Forte 		if (rc != EAGAIN)
392*45039663SJohn Forte 			break;
393*45039663SJohn Forte 		delay(hz);
394*45039663SJohn Forte 	}
395*45039663SJohn Forte 	door_ki_rele(door);
396*45039663SJohn Forte 	if (rc != 0) {
397*45039663SJohn Forte 		cmn_err(CE_WARN,
398*45039663SJohn Forte 		    "stmf_ic_transmit door_ki_upcall failed %d", rc);
399*45039663SJohn Forte 		return (STMF_IC_MSG_INTERNAL_ERROR);
400*45039663SJohn Forte 	}
401*45039663SJohn Forte 	if (result != 0) {
402*45039663SJohn Forte 		/* XXX Just warn for now */
403*45039663SJohn Forte 		cmn_err(CE_WARN,
404*45039663SJohn Forte 		    "stmf_ic_transmit bad result from daemon %d", result);
405*45039663SJohn Forte 	}
406*45039663SJohn Forte 
407*45039663SJohn Forte 	return (STMF_IC_MSG_SUCCESS);
408*45039663SJohn Forte }
409*45039663SJohn Forte 
410*45039663SJohn Forte /*
411*45039663SJohn Forte  * This is a low-level upcall which is called when a message has
412*45039663SJohn Forte  * been received on the interconnect.
413*45039663SJohn Forte  *
414*45039663SJohn Forte  * The caller is responsible for freeing the buffer which is passed in.
415*45039663SJohn Forte  */
416*45039663SJohn Forte /*ARGSUSED*/
417*45039663SJohn Forte void
418*45039663SJohn Forte stmf_ic_rx_msg(char *buf, size_t len)
419*45039663SJohn Forte {
420*45039663SJohn Forte 	nvlist_t *nvl = NULL;
421*45039663SJohn Forte 	stmf_ic_msg_t *m = NULL;
422*45039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *icerr;
423*45039663SJohn Forte 	stmf_ic_msg_t *echo_msg;
424*45039663SJohn Forte 	int rc = 0;
425*45039663SJohn Forte 
426*45039663SJohn Forte 	rc = nvlist_unpack(buf, len, &nvl, 0);
427*45039663SJohn Forte 	if (rc) {
428*45039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unpack failed");
429*45039663SJohn Forte 		return;
430*45039663SJohn Forte 	}
431*45039663SJohn Forte 
432*45039663SJohn Forte 	m = stmf_ic_msg_unmarshal(nvl);
433*45039663SJohn Forte 	if (m == NULL) {
434*45039663SJohn Forte 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unmarshal failed");
435*45039663SJohn Forte 		nvlist_free(nvl);
436*45039663SJohn Forte 		return;
437*45039663SJohn Forte 	}
438*45039663SJohn Forte 
439*45039663SJohn Forte 	switch (m->icm_msg_type) {
440*45039663SJohn Forte 
441*45039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
442*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
443*45039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
444*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
445*45039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
446*45039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
447*45039663SJohn Forte 		/*
448*45039663SJohn Forte 		 * These messages are all received by pppt.
449*45039663SJohn Forte 		 * Currently, pppt will parse the message for type
450*45039663SJohn Forte 		 */
451*45039663SJohn Forte 		(void) pppt_msg_rx(m);
452*45039663SJohn Forte 		break;
453*45039663SJohn Forte 
454*45039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
455*45039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
456*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
457*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
458*45039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
459*45039663SJohn Forte 		/*
460*45039663SJohn Forte 		 * These messages are all received by stmf.
461*45039663SJohn Forte 		 * Currently, stmf will parse the message for type
462*45039663SJohn Forte 		 */
463*45039663SJohn Forte 		(void) stmf_msg_rx(m);
464*45039663SJohn Forte 		break;
465*45039663SJohn Forte 
466*45039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
467*45039663SJohn Forte 		icerr = m->icm_msg;
468*45039663SJohn Forte 		echo_msg = stmf_ic_echo_reply_msg_alloc(icerr->icerr_datalen,
469*45039663SJohn Forte 		    icerr->icerr_data, 0);
470*45039663SJohn Forte 		if (echo_msg != NULL) {
471*45039663SJohn Forte 			(void) stmf_ic_tx_msg(echo_msg);
472*45039663SJohn Forte 		}
473*45039663SJohn Forte 		stmf_ic_msg_free(m);
474*45039663SJohn Forte 		break;
475*45039663SJohn Forte 
476*45039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
477*45039663SJohn Forte 		stmf_ic_msg_free(m);
478*45039663SJohn Forte 		break;
479*45039663SJohn Forte 
480*45039663SJohn Forte 	case STMF_ICM_R2T:
481*45039663SJohn Forte 		/*
482*45039663SJohn Forte 		 * XXX currently not supported
483*45039663SJohn Forte 		 */
484*45039663SJohn Forte 		stmf_ic_msg_free(m);
485*45039663SJohn Forte 		break;
486*45039663SJohn Forte 
487*45039663SJohn Forte 	case STMF_ICM_STATUS:
488*45039663SJohn Forte 		(void) stmf_msg_rx(m);
489*45039663SJohn Forte 		break;
490*45039663SJohn Forte 
491*45039663SJohn Forte 	default:
492*45039663SJohn Forte 		ASSERT(0);
493*45039663SJohn Forte 	}
494*45039663SJohn Forte }
495*45039663SJohn Forte 
496*45039663SJohn Forte /*
497*45039663SJohn Forte  * IC message allocation routines.
498*45039663SJohn Forte  */
499*45039663SJohn Forte 
500*45039663SJohn Forte stmf_ic_msg_t *
501*45039663SJohn Forte stmf_ic_reg_port_msg_alloc(
502*45039663SJohn Forte     scsi_devid_desc_t *port_id,
503*45039663SJohn Forte     uint16_t relative_port_id,
504*45039663SJohn Forte     uint16_t cb_arg_len,
505*45039663SJohn Forte     uint8_t *cb_arg,
506*45039663SJohn Forte     stmf_ic_msgid_t msgid)
507*45039663SJohn Forte {
508*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
509*45039663SJohn Forte 	stmf_ic_reg_port_msg_t *icrp = NULL;
510*45039663SJohn Forte 
511*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_REGISTER_PROXY_PORT, msgid);
512*45039663SJohn Forte 	icrp = (stmf_ic_reg_port_msg_t *)kmem_zalloc(sizeof (*icrp), KM_SLEEP);
513*45039663SJohn Forte 	icm->icm_msg = (void *)icrp;
514*45039663SJohn Forte 
515*45039663SJohn Forte 	icrp->icrp_port_id = scsi_devid_desc_dup(port_id);
516*45039663SJohn Forte 	icrp->icrp_relative_port_id = relative_port_id;
517*45039663SJohn Forte 
518*45039663SJohn Forte 	if (cb_arg_len) {
519*45039663SJohn Forte 		icrp->icrp_cb_arg_len = cb_arg_len;
520*45039663SJohn Forte 		icrp->icrp_cb_arg = cb_arg;
521*45039663SJohn Forte 	}
522*45039663SJohn Forte 
523*45039663SJohn Forte 	return (icm);
524*45039663SJohn Forte }
525*45039663SJohn Forte 
526*45039663SJohn Forte stmf_ic_msg_t *
527*45039663SJohn Forte stmf_ic_dereg_port_msg_alloc(
528*45039663SJohn Forte     scsi_devid_desc_t *port_id,
529*45039663SJohn Forte     uint16_t cb_arg_len,
530*45039663SJohn Forte     uint8_t *cb_arg,
531*45039663SJohn Forte     stmf_ic_msgid_t msgid)
532*45039663SJohn Forte {
533*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
534*45039663SJohn Forte 	stmf_ic_dereg_port_msg_t *icdp = NULL;
535*45039663SJohn Forte 
536*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_DEREGISTER_PROXY_PORT, msgid);
537*45039663SJohn Forte 	icdp = (stmf_ic_dereg_port_msg_t *)kmem_zalloc(sizeof (*icdp),
538*45039663SJohn Forte 	    KM_SLEEP);
539*45039663SJohn Forte 	icm->icm_msg = (void *)icdp;
540*45039663SJohn Forte 
541*45039663SJohn Forte 	icdp->icdp_port_id = scsi_devid_desc_dup(port_id);
542*45039663SJohn Forte 
543*45039663SJohn Forte 	if (cb_arg_len) {
544*45039663SJohn Forte 		icdp->icdp_cb_arg_len = cb_arg_len;
545*45039663SJohn Forte 		icdp->icdp_cb_arg = cb_arg;
546*45039663SJohn Forte 	}
547*45039663SJohn Forte 
548*45039663SJohn Forte 	return (icm);
549*45039663SJohn Forte }
550*45039663SJohn Forte 
551*45039663SJohn Forte 
552*45039663SJohn Forte stmf_ic_msg_t *
553*45039663SJohn Forte stmf_ic_reg_lun_msg_alloc(
554*45039663SJohn Forte     uint8_t *lun_id,
555*45039663SJohn Forte     char *lu_provider_name,
556*45039663SJohn Forte     uint16_t cb_arg_len,
557*45039663SJohn Forte     uint8_t *cb_arg,
558*45039663SJohn Forte     stmf_ic_msgid_t msgid)
559*45039663SJohn Forte {
560*45039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_REGISTER_LUN, lun_id,
561*45039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
562*45039663SJohn Forte }
563*45039663SJohn Forte 
564*45039663SJohn Forte stmf_ic_msg_t *
565*45039663SJohn Forte stmf_ic_lun_active_msg_alloc(
566*45039663SJohn Forte     uint8_t *lun_id,
567*45039663SJohn Forte     char *lu_provider_name,
568*45039663SJohn Forte     uint16_t cb_arg_len,
569*45039663SJohn Forte     uint8_t *cb_arg,
570*45039663SJohn Forte     stmf_ic_msgid_t msgid)
571*45039663SJohn Forte {
572*45039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_LUN_ACTIVE, lun_id,
573*45039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
574*45039663SJohn Forte }
575*45039663SJohn Forte 
576*45039663SJohn Forte stmf_ic_msg_t *
577*45039663SJohn Forte stmf_ic_dereg_lun_msg_alloc(
578*45039663SJohn Forte     uint8_t *lun_id,
579*45039663SJohn Forte     char *lu_provider_name,
580*45039663SJohn Forte     uint16_t cb_arg_len,
581*45039663SJohn Forte     uint8_t *cb_arg,
582*45039663SJohn Forte     stmf_ic_msgid_t msgid)
583*45039663SJohn Forte {
584*45039663SJohn Forte 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_DEREGISTER_LUN, lun_id,
585*45039663SJohn Forte 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
586*45039663SJohn Forte }
587*45039663SJohn Forte 
588*45039663SJohn Forte /*
589*45039663SJohn Forte  * Guts of lun register/deregister/active alloc routines.
590*45039663SJohn Forte  */
591*45039663SJohn Forte static stmf_ic_msg_t *
592*45039663SJohn Forte stmf_ic_reg_dereg_lun_msg_alloc(
593*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
594*45039663SJohn Forte     uint8_t *lun_id,
595*45039663SJohn Forte     char *lu_provider_name,
596*45039663SJohn Forte     uint16_t cb_arg_len,
597*45039663SJohn Forte     uint8_t *cb_arg,
598*45039663SJohn Forte     stmf_ic_msgid_t msgid)
599*45039663SJohn Forte {
600*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
601*45039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *icrl = NULL;
602*45039663SJohn Forte 
603*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
604*45039663SJohn Forte 	icrl = (stmf_ic_reg_dereg_lun_msg_t *)
605*45039663SJohn Forte 	    kmem_zalloc(sizeof (*icrl), KM_SLEEP);
606*45039663SJohn Forte 	icm->icm_msg = (void *)icrl;
607*45039663SJohn Forte 
608*45039663SJohn Forte 	icrl->icrl_lu_provider_name = stmf_ic_strdup(lu_provider_name);
609*45039663SJohn Forte 
610*45039663SJohn Forte 	bcopy(lun_id, icrl->icrl_lun_id, sizeof (icrl->icrl_lun_id));
611*45039663SJohn Forte 
612*45039663SJohn Forte 	if (cb_arg_len) {
613*45039663SJohn Forte 		icrl->icrl_cb_arg_len = cb_arg_len;
614*45039663SJohn Forte 		icrl->icrl_cb_arg = cb_arg;
615*45039663SJohn Forte 	}
616*45039663SJohn Forte 
617*45039663SJohn Forte 	return (icm);
618*45039663SJohn Forte }
619*45039663SJohn Forte 
620*45039663SJohn Forte stmf_ic_msg_t *
621*45039663SJohn Forte stmf_ic_scsi_cmd_msg_alloc(
622*45039663SJohn Forte     stmf_ic_msgid_t task_msgid,
623*45039663SJohn Forte     scsi_task_t *task,
624*45039663SJohn Forte     uint32_t immed_data_len,
625*45039663SJohn Forte     uint8_t *immed_data,
626*45039663SJohn Forte     stmf_ic_msgid_t msgid)
627*45039663SJohn Forte {
628*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
629*45039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *icsc = NULL;
630*45039663SJohn Forte 	scsi_devid_desc_t *ini_devid = task->task_session->ss_rport_id;
631*45039663SJohn Forte 	scsi_devid_desc_t *tgt_devid = task->task_lport->lport_id;
632*45039663SJohn Forte 	uint8_t *lun_id = task->task_lu->lu_id->ident;
633*45039663SJohn Forte 
634*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_CMD, msgid);
635*45039663SJohn Forte 	icsc = (stmf_ic_scsi_cmd_msg_t *)kmem_zalloc(sizeof (*icsc), KM_SLEEP);
636*45039663SJohn Forte 	icm->icm_msg = (void *)icsc;
637*45039663SJohn Forte 
638*45039663SJohn Forte 	icsc->icsc_task_msgid = task_msgid;
639*45039663SJohn Forte 	icsc->icsc_ini_devid = scsi_devid_desc_dup(ini_devid);
640*45039663SJohn Forte 	icsc->icsc_tgt_devid = scsi_devid_desc_dup(tgt_devid);
641*45039663SJohn Forte 	icsc->icsc_session_id = task->task_session->ss_session_id;
642*45039663SJohn Forte 
643*45039663SJohn Forte 	bcopy(lun_id, icsc->icsc_lun_id, sizeof (icsc->icsc_lun_id));
644*45039663SJohn Forte 
645*45039663SJohn Forte 	bcopy(task->task_lun_no, icsc->icsc_task_lun_no,
646*45039663SJohn Forte 	    sizeof (icsc->icsc_task_lun_no));
647*45039663SJohn Forte 
648*45039663SJohn Forte 	icsc->icsc_task_expected_xfer_length = task->task_expected_xfer_length;
649*45039663SJohn Forte 	icsc->icsc_task_cdb_length = task->task_cdb_length;
650*45039663SJohn Forte 
651*45039663SJohn Forte 	icsc->icsc_task_cdb = (uint8_t *)kmem_zalloc(task->task_cdb_length,
652*45039663SJohn Forte 	    KM_SLEEP);
653*45039663SJohn Forte 	bcopy(task->task_cdb, icsc->icsc_task_cdb, task->task_cdb_length);
654*45039663SJohn Forte 
655*45039663SJohn Forte 	icsc->icsc_task_flags = task->task_flags;
656*45039663SJohn Forte 	icsc->icsc_task_priority = task->task_priority;
657*45039663SJohn Forte 	icsc->icsc_task_mgmt_function = task->task_mgmt_function;
658*45039663SJohn Forte 
659*45039663SJohn Forte 	icsc->icsc_immed_data_len = immed_data_len;
660*45039663SJohn Forte 	icsc->icsc_immed_data = immed_data;
661*45039663SJohn Forte 
662*45039663SJohn Forte 	return (icm);
663*45039663SJohn Forte }
664*45039663SJohn Forte 
665*45039663SJohn Forte stmf_ic_msg_t *
666*45039663SJohn Forte stmf_ic_scsi_data_msg_alloc(
667*45039663SJohn Forte     stmf_ic_msgid_t task_msgid,
668*45039663SJohn Forte     uint64_t session_id,
669*45039663SJohn Forte     uint8_t *lun_id,
670*45039663SJohn Forte     uint64_t data_len,
671*45039663SJohn Forte     uint8_t *data,
672*45039663SJohn Forte     stmf_ic_msgid_t msgid)
673*45039663SJohn Forte {
674*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
675*45039663SJohn Forte 	stmf_ic_scsi_data_msg_t *icsd = NULL;
676*45039663SJohn Forte 
677*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA, msgid);
678*45039663SJohn Forte 	icsd = (stmf_ic_scsi_data_msg_t *)kmem_zalloc(sizeof (*icsd), KM_SLEEP);
679*45039663SJohn Forte 	icm->icm_msg = (void *)icsd;
680*45039663SJohn Forte 
681*45039663SJohn Forte 	icsd->icsd_task_msgid = task_msgid;
682*45039663SJohn Forte 	icsd->icsd_session_id = session_id;
683*45039663SJohn Forte 	bcopy(lun_id, icsd->icsd_lun_id, sizeof (icsd->icsd_lun_id));
684*45039663SJohn Forte 	icsd->icsd_data_len = data_len;
685*45039663SJohn Forte 	icsd->icsd_data = data;
686*45039663SJohn Forte 
687*45039663SJohn Forte 	return (icm);
688*45039663SJohn Forte }
689*45039663SJohn Forte 
690*45039663SJohn Forte stmf_ic_msg_t *
691*45039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_alloc(
692*45039663SJohn Forte     stmf_ic_msgid_t task_msgid,
693*45039663SJohn Forte     uint64_t session_id,
694*45039663SJohn Forte     stmf_status_t status,
695*45039663SJohn Forte     stmf_ic_msgid_t msgid)
696*45039663SJohn Forte {
697*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
698*45039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *icsx = NULL;
699*45039663SJohn Forte 
700*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA_XFER_DONE, msgid);
701*45039663SJohn Forte 	icsx = (stmf_ic_scsi_data_xfer_done_msg_t *)kmem_zalloc(
702*45039663SJohn Forte 	    sizeof (*icsx), KM_SLEEP);
703*45039663SJohn Forte 	icm->icm_msg = (void *)icsx;
704*45039663SJohn Forte 
705*45039663SJohn Forte 	icsx->icsx_task_msgid = task_msgid;
706*45039663SJohn Forte 	icsx->icsx_session_id = session_id;
707*45039663SJohn Forte 	icsx->icsx_status = status;
708*45039663SJohn Forte 
709*45039663SJohn Forte 	return (icm);
710*45039663SJohn Forte }
711*45039663SJohn Forte 
712*45039663SJohn Forte stmf_ic_msg_t *
713*45039663SJohn Forte stmf_ic_scsi_status_msg_alloc(
714*45039663SJohn Forte     stmf_ic_msgid_t task_msgid,
715*45039663SJohn Forte     uint64_t session_id,
716*45039663SJohn Forte     uint8_t *lun_id,
717*45039663SJohn Forte     uint8_t response,
718*45039663SJohn Forte     uint8_t status,
719*45039663SJohn Forte     uint8_t flags,
720*45039663SJohn Forte     uint32_t resid,
721*45039663SJohn Forte     uint8_t sense_len,
722*45039663SJohn Forte     uint8_t *sense,
723*45039663SJohn Forte     stmf_ic_msgid_t msgid)
724*45039663SJohn Forte {
725*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
726*45039663SJohn Forte 	stmf_ic_scsi_status_msg_t *icss = NULL;
727*45039663SJohn Forte 
728*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_STATUS, msgid);
729*45039663SJohn Forte 	icss = (stmf_ic_scsi_status_msg_t *)kmem_zalloc(sizeof (*icss),
730*45039663SJohn Forte 	    KM_SLEEP);
731*45039663SJohn Forte 	icm->icm_msg = (void *)icss;
732*45039663SJohn Forte 
733*45039663SJohn Forte 	icss->icss_task_msgid = task_msgid;
734*45039663SJohn Forte 	icss->icss_session_id = session_id;
735*45039663SJohn Forte 	bcopy(lun_id, icss->icss_lun_id, sizeof (icss->icss_lun_id));
736*45039663SJohn Forte 	icss->icss_response = response;
737*45039663SJohn Forte 	icss->icss_status = status;
738*45039663SJohn Forte 	icss->icss_flags = flags;
739*45039663SJohn Forte 	icss->icss_resid = resid;
740*45039663SJohn Forte 	icss->icss_sense_len = sense_len;
741*45039663SJohn Forte 	icss->icss_sense = sense;
742*45039663SJohn Forte 
743*45039663SJohn Forte 	return (icm);
744*45039663SJohn Forte }
745*45039663SJohn Forte 
746*45039663SJohn Forte stmf_ic_msg_t *
747*45039663SJohn Forte stmf_ic_r2t_msg_alloc(
748*45039663SJohn Forte     stmf_ic_msgid_t task_msgid,
749*45039663SJohn Forte     uint64_t session_id,
750*45039663SJohn Forte     uint32_t offset,
751*45039663SJohn Forte     uint32_t length,
752*45039663SJohn Forte     stmf_ic_msgid_t msgid)
753*45039663SJohn Forte {
754*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
755*45039663SJohn Forte 	stmf_ic_r2t_msg_t *icrt = NULL;
756*45039663SJohn Forte 
757*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_R2T, msgid);
758*45039663SJohn Forte 	icrt = (stmf_ic_r2t_msg_t *)kmem_zalloc(sizeof (*icrt), KM_SLEEP);
759*45039663SJohn Forte 	icm->icm_msg = (void *)icrt;
760*45039663SJohn Forte 
761*45039663SJohn Forte 	icrt->icrt_task_msgid = task_msgid;
762*45039663SJohn Forte 	icrt->icrt_session_id = session_id;
763*45039663SJohn Forte 	icrt->icrt_offset = offset;
764*45039663SJohn Forte 	icrt->icrt_length = length;
765*45039663SJohn Forte 
766*45039663SJohn Forte 	return (icm);
767*45039663SJohn Forte }
768*45039663SJohn Forte 
769*45039663SJohn Forte stmf_ic_msg_t *
770*45039663SJohn Forte stmf_ic_status_msg_alloc(
771*45039663SJohn Forte     stmf_status_t status,
772*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
773*45039663SJohn Forte     stmf_ic_msgid_t msgid)
774*45039663SJohn Forte {
775*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
776*45039663SJohn Forte 	stmf_ic_status_msg_t *ics = NULL;
777*45039663SJohn Forte 
778*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(STMF_ICM_STATUS, msgid);
779*45039663SJohn Forte 	ics = (stmf_ic_status_msg_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
780*45039663SJohn Forte 	icm->icm_msg = (void *)ics;
781*45039663SJohn Forte 
782*45039663SJohn Forte 	ics->ics_status = status;
783*45039663SJohn Forte 	ics->ics_msg_type = msg_type;
784*45039663SJohn Forte 	ics->ics_msgid = msgid;		/* XXX same as msgid in header */
785*45039663SJohn Forte 
786*45039663SJohn Forte 	return (icm);
787*45039663SJohn Forte }
788*45039663SJohn Forte 
789*45039663SJohn Forte stmf_ic_msg_t *
790*45039663SJohn Forte stmf_ic_session_create_msg_alloc(
791*45039663SJohn Forte     stmf_scsi_session_t *session,
792*45039663SJohn Forte     stmf_ic_msgid_t msgid)
793*45039663SJohn Forte {
794*45039663SJohn Forte 	return (stmf_ic_session_create_destroy_msg_alloc(
795*45039663SJohn Forte 	    STMF_ICM_SESSION_CREATE, session, msgid));
796*45039663SJohn Forte }
797*45039663SJohn Forte 
798*45039663SJohn Forte stmf_ic_msg_t *
799*45039663SJohn Forte stmf_ic_session_destroy_msg_alloc(
800*45039663SJohn Forte     stmf_scsi_session_t *session,
801*45039663SJohn Forte     stmf_ic_msgid_t msgid)
802*45039663SJohn Forte {
803*45039663SJohn Forte 	return (stmf_ic_session_create_destroy_msg_alloc(
804*45039663SJohn Forte 	    STMF_ICM_SESSION_DESTROY, session, msgid));
805*45039663SJohn Forte }
806*45039663SJohn Forte 
807*45039663SJohn Forte /*
808*45039663SJohn Forte  * Guts of session create/destroy routines.
809*45039663SJohn Forte  */
810*45039663SJohn Forte static stmf_ic_msg_t *
811*45039663SJohn Forte stmf_ic_session_create_destroy_msg_alloc(
812*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
813*45039663SJohn Forte     stmf_scsi_session_t *session,
814*45039663SJohn Forte     stmf_ic_msgid_t msgid)
815*45039663SJohn Forte {
816*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
817*45039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *icscd = NULL;
818*45039663SJohn Forte 	scsi_devid_desc_t *ini_devid = session->ss_rport_id;
819*45039663SJohn Forte 	scsi_devid_desc_t *tgt_devid = session->ss_lport->lport_id;
820*45039663SJohn Forte 
821*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
822*45039663SJohn Forte 	icscd = (stmf_ic_session_create_destroy_msg_t *)
823*45039663SJohn Forte 	    kmem_zalloc(sizeof (*icscd), KM_SLEEP);
824*45039663SJohn Forte 	icm->icm_msg = (void *)icscd;
825*45039663SJohn Forte 
826*45039663SJohn Forte 	icscd->icscd_session_id = session->ss_session_id;
827*45039663SJohn Forte 	icscd->icscd_ini_devid = scsi_devid_desc_dup(ini_devid);
828*45039663SJohn Forte 	icscd->icscd_tgt_devid = scsi_devid_desc_dup(tgt_devid);
829*45039663SJohn Forte 
830*45039663SJohn Forte 	return (icm);
831*45039663SJohn Forte }
832*45039663SJohn Forte 
833*45039663SJohn Forte stmf_ic_msg_t *
834*45039663SJohn Forte stmf_ic_echo_request_msg_alloc(
835*45039663SJohn Forte     uint32_t data_len,
836*45039663SJohn Forte     uint8_t *data,
837*45039663SJohn Forte     stmf_ic_msgid_t msgid)
838*45039663SJohn Forte {
839*45039663SJohn Forte 	return (stmf_ic_echo_request_reply_msg_alloc(
840*45039663SJohn Forte 	    STMF_ICM_ECHO_REQUEST, data_len, data, msgid));
841*45039663SJohn Forte }
842*45039663SJohn Forte 
843*45039663SJohn Forte stmf_ic_msg_t *
844*45039663SJohn Forte stmf_ic_echo_reply_msg_alloc(
845*45039663SJohn Forte     uint32_t data_len,
846*45039663SJohn Forte     uint8_t *data,
847*45039663SJohn Forte     stmf_ic_msgid_t msgid)
848*45039663SJohn Forte {
849*45039663SJohn Forte 	return (stmf_ic_echo_request_reply_msg_alloc(
850*45039663SJohn Forte 	    STMF_ICM_ECHO_REPLY, data_len, data, msgid));
851*45039663SJohn Forte }
852*45039663SJohn Forte 
853*45039663SJohn Forte 
854*45039663SJohn Forte static stmf_ic_msg_t *
855*45039663SJohn Forte stmf_ic_echo_request_reply_msg_alloc(
856*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
857*45039663SJohn Forte     uint32_t data_len,
858*45039663SJohn Forte     uint8_t *data,
859*45039663SJohn Forte     stmf_ic_msgid_t msgid)
860*45039663SJohn Forte {
861*45039663SJohn Forte 	stmf_ic_msg_t *icm = NULL;
862*45039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *icerr = NULL;
863*45039663SJohn Forte 
864*45039663SJohn Forte 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
865*45039663SJohn Forte 	icerr = kmem_zalloc(sizeof (*icerr), KM_SLEEP);
866*45039663SJohn Forte 	icm->icm_msg = (void *)icerr;
867*45039663SJohn Forte 
868*45039663SJohn Forte 	icerr->icerr_data = data;
869*45039663SJohn Forte 	icerr->icerr_datalen = data_len;
870*45039663SJohn Forte 
871*45039663SJohn Forte 	return (icm);
872*45039663SJohn Forte }
873*45039663SJohn Forte 
874*45039663SJohn Forte /*
875*45039663SJohn Forte  * msg free routines.
876*45039663SJohn Forte  */
877*45039663SJohn Forte void
878*45039663SJohn Forte stmf_ic_msg_free(stmf_ic_msg_t *msg)
879*45039663SJohn Forte {
880*45039663SJohn Forte 	stmf_ic_msg_construction_method_t cmethod =
881*45039663SJohn Forte 	    (msg->icm_nvlist ? STMF_UNMARSHAL : STMF_CONSTRUCTOR);
882*45039663SJohn Forte 
883*45039663SJohn Forte 	switch (msg->icm_msg_type) {
884*45039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
885*45039663SJohn Forte 		stmf_ic_reg_port_msg_free(
886*45039663SJohn Forte 		    (stmf_ic_reg_port_msg_t *)msg->icm_msg, cmethod);
887*45039663SJohn Forte 		break;
888*45039663SJohn Forte 
889*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
890*45039663SJohn Forte 		stmf_ic_dereg_port_msg_free(
891*45039663SJohn Forte 		    (stmf_ic_dereg_port_msg_t *)msg->icm_msg, cmethod);
892*45039663SJohn Forte 		break;
893*45039663SJohn Forte 
894*45039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
895*45039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
896*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
897*45039663SJohn Forte 		stmf_ic_reg_dereg_lun_msg_free(
898*45039663SJohn Forte 		    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg, cmethod);
899*45039663SJohn Forte 		break;
900*45039663SJohn Forte 
901*45039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
902*45039663SJohn Forte 		stmf_ic_scsi_cmd_msg_free(
903*45039663SJohn Forte 		    (stmf_ic_scsi_cmd_msg_t *)msg->icm_msg, cmethod);
904*45039663SJohn Forte 		break;
905*45039663SJohn Forte 
906*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
907*45039663SJohn Forte 		stmf_ic_scsi_data_msg_free(
908*45039663SJohn Forte 		    (stmf_ic_scsi_data_msg_t *)msg->icm_msg, cmethod);
909*45039663SJohn Forte 		break;
910*45039663SJohn Forte 
911*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
912*45039663SJohn Forte 		stmf_ic_scsi_data_xfer_done_msg_free(
913*45039663SJohn Forte 		    (stmf_ic_scsi_data_xfer_done_msg_t *)msg->icm_msg, cmethod);
914*45039663SJohn Forte 		break;
915*45039663SJohn Forte 
916*45039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
917*45039663SJohn Forte 		stmf_ic_scsi_status_msg_free(
918*45039663SJohn Forte 		    (stmf_ic_scsi_status_msg_t *)msg->icm_msg, cmethod);
919*45039663SJohn Forte 		break;
920*45039663SJohn Forte 
921*45039663SJohn Forte 	case STMF_ICM_R2T:
922*45039663SJohn Forte 		stmf_ic_r2t_msg_free(
923*45039663SJohn Forte 		    (stmf_ic_r2t_msg_t *)msg->icm_msg, cmethod);
924*45039663SJohn Forte 		break;
925*45039663SJohn Forte 
926*45039663SJohn Forte 	case STMF_ICM_STATUS:
927*45039663SJohn Forte 		stmf_ic_status_msg_free(
928*45039663SJohn Forte 		    (stmf_ic_status_msg_t *)msg->icm_msg, cmethod);
929*45039663SJohn Forte 		break;
930*45039663SJohn Forte 
931*45039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
932*45039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
933*45039663SJohn Forte 		stmf_ic_session_create_destroy_msg_free(
934*45039663SJohn Forte 		    (stmf_ic_session_create_destroy_msg_t *)msg->icm_msg,
935*45039663SJohn Forte 		    cmethod);
936*45039663SJohn Forte 		break;
937*45039663SJohn Forte 
938*45039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
939*45039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
940*45039663SJohn Forte 		stmf_ic_echo_request_reply_msg_free(
941*45039663SJohn Forte 		    (stmf_ic_echo_request_reply_msg_t *)msg->icm_msg, cmethod);
942*45039663SJohn Forte 		break;
943*45039663SJohn Forte 
944*45039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
945*45039663SJohn Forte 		ASSERT(0);
946*45039663SJohn Forte 		break;
947*45039663SJohn Forte 
948*45039663SJohn Forte 	default:
949*45039663SJohn Forte 		ASSERT(0);
950*45039663SJohn Forte 	}
951*45039663SJohn Forte 
952*45039663SJohn Forte 	if (msg->icm_nvlist)
953*45039663SJohn Forte 		nvlist_free(msg->icm_nvlist);
954*45039663SJohn Forte 
955*45039663SJohn Forte 	kmem_free(msg, sizeof (*msg));
956*45039663SJohn Forte }
957*45039663SJohn Forte 
958*45039663SJohn Forte /*ARGSUSED*/
959*45039663SJohn Forte static void
960*45039663SJohn Forte stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
961*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
962*45039663SJohn Forte {
963*45039663SJohn Forte 	scsi_devid_desc_free(m->icrp_port_id);
964*45039663SJohn Forte 
965*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
966*45039663SJohn Forte }
967*45039663SJohn Forte 
968*45039663SJohn Forte 
969*45039663SJohn Forte /*ARGSUSED*/
970*45039663SJohn Forte static void
971*45039663SJohn Forte stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
972*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
973*45039663SJohn Forte {
974*45039663SJohn Forte 	scsi_devid_desc_free(m->icdp_port_id);
975*45039663SJohn Forte 
976*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
977*45039663SJohn Forte }
978*45039663SJohn Forte 
979*45039663SJohn Forte 
980*45039663SJohn Forte /*
981*45039663SJohn Forte  * Works for both reg_lun_msg and dereg_lun_msg, since the message
982*45039663SJohn Forte  * payload is the same.
983*45039663SJohn Forte  */
984*45039663SJohn Forte static void
985*45039663SJohn Forte stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
986*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
987*45039663SJohn Forte {
988*45039663SJohn Forte 	if (cmethod == STMF_CONSTRUCTOR) {
989*45039663SJohn Forte 		kmem_free(m->icrl_lu_provider_name,
990*45039663SJohn Forte 		    strlen(m->icrl_lu_provider_name) + 1);
991*45039663SJohn Forte 	}
992*45039663SJohn Forte 
993*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
994*45039663SJohn Forte }
995*45039663SJohn Forte 
996*45039663SJohn Forte static void
997*45039663SJohn Forte stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
998*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
999*45039663SJohn Forte {
1000*45039663SJohn Forte 	scsi_devid_desc_free(m->icsc_ini_devid);
1001*45039663SJohn Forte 	scsi_devid_desc_free(m->icsc_tgt_devid);
1002*45039663SJohn Forte 	if (cmethod == STMF_CONSTRUCTOR) {
1003*45039663SJohn Forte 		kmem_free(m->icsc_task_cdb, m->icsc_task_cdb_length);
1004*45039663SJohn Forte 	}
1005*45039663SJohn Forte 
1006*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1007*45039663SJohn Forte 
1008*45039663SJohn Forte }
1009*45039663SJohn Forte 
1010*45039663SJohn Forte /*ARGSUSED*/
1011*45039663SJohn Forte static void
1012*45039663SJohn Forte stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
1013*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1014*45039663SJohn Forte {
1015*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1016*45039663SJohn Forte }
1017*45039663SJohn Forte 
1018*45039663SJohn Forte /*ARGSUSED*/
1019*45039663SJohn Forte static void
1020*45039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t *m,
1021*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1022*45039663SJohn Forte {
1023*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1024*45039663SJohn Forte }
1025*45039663SJohn Forte 
1026*45039663SJohn Forte /*ARGSUSED*/
1027*45039663SJohn Forte static void
1028*45039663SJohn Forte stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
1029*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1030*45039663SJohn Forte {
1031*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1032*45039663SJohn Forte }
1033*45039663SJohn Forte 
1034*45039663SJohn Forte /*ARGSUSED*/
1035*45039663SJohn Forte static void
1036*45039663SJohn Forte stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
1037*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1038*45039663SJohn Forte {
1039*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1040*45039663SJohn Forte }
1041*45039663SJohn Forte 
1042*45039663SJohn Forte /*ARGSUSED*/
1043*45039663SJohn Forte static void
1044*45039663SJohn Forte stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
1045*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1046*45039663SJohn Forte {
1047*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1048*45039663SJohn Forte }
1049*45039663SJohn Forte 
1050*45039663SJohn Forte /*
1051*45039663SJohn Forte  * Works for both session_create and session_destroy msgs, since the message
1052*45039663SJohn Forte  * payload is the same.
1053*45039663SJohn Forte  */
1054*45039663SJohn Forte /*ARGSUSED*/
1055*45039663SJohn Forte static void
1056*45039663SJohn Forte stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t *m,
1057*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1058*45039663SJohn Forte {
1059*45039663SJohn Forte 	scsi_devid_desc_free(m->icscd_ini_devid);
1060*45039663SJohn Forte 	scsi_devid_desc_free(m->icscd_tgt_devid);
1061*45039663SJohn Forte 
1062*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1063*45039663SJohn Forte }
1064*45039663SJohn Forte 
1065*45039663SJohn Forte /*ARGSUSED*/
1066*45039663SJohn Forte static void
1067*45039663SJohn Forte stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t *m,
1068*45039663SJohn Forte     stmf_ic_msg_construction_method_t cmethod)
1069*45039663SJohn Forte {
1070*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1071*45039663SJohn Forte }
1072*45039663SJohn Forte 
1073*45039663SJohn Forte 
1074*45039663SJohn Forte /*
1075*45039663SJohn Forte  * Marshaling routines.
1076*45039663SJohn Forte  */
1077*45039663SJohn Forte 
1078*45039663SJohn Forte static nvlist_t *
1079*45039663SJohn Forte stmf_ic_msg_marshal(stmf_ic_msg_t *msg)
1080*45039663SJohn Forte {
1081*45039663SJohn Forte 	nvlist_t *nvl = NULL;
1082*45039663SJohn Forte 	int rc = 0;
1083*45039663SJohn Forte 
1084*45039663SJohn Forte 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1085*45039663SJohn Forte 	if (rc)
1086*45039663SJohn Forte 		goto done;
1087*45039663SJohn Forte 
1088*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, msg, icm_msg_type);
1089*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, msg, icm_msgid);
1090*45039663SJohn Forte 
1091*45039663SJohn Forte 	switch (msg->icm_msg_type) {
1092*45039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
1093*45039663SJohn Forte 		rc = stmf_ic_reg_port_msg_marshal(nvl, msg->icm_msg);
1094*45039663SJohn Forte 		break;
1095*45039663SJohn Forte 
1096*45039663SJohn Forte 
1097*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
1098*45039663SJohn Forte 		rc = stmf_ic_dereg_port_msg_marshal(nvl, msg->icm_msg);
1099*45039663SJohn Forte 		break;
1100*45039663SJohn Forte 
1101*45039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
1102*45039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
1103*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
1104*45039663SJohn Forte 		rc = stmf_ic_reg_dereg_lun_msg_marshal(nvl, msg->icm_msg);
1105*45039663SJohn Forte 		break;
1106*45039663SJohn Forte 
1107*45039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
1108*45039663SJohn Forte 		rc = stmf_ic_scsi_cmd_msg_marshal(nvl, msg->icm_msg);
1109*45039663SJohn Forte 		break;
1110*45039663SJohn Forte 
1111*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
1112*45039663SJohn Forte 		rc = stmf_ic_scsi_data_msg_marshal(nvl, msg->icm_msg);
1113*45039663SJohn Forte 		break;
1114*45039663SJohn Forte 
1115*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
1116*45039663SJohn Forte 		rc = stmf_ic_scsi_data_xfer_done_msg_marshal(nvl, msg->icm_msg);
1117*45039663SJohn Forte 		break;
1118*45039663SJohn Forte 
1119*45039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
1120*45039663SJohn Forte 		rc = stmf_ic_scsi_status_msg_marshal(nvl, msg->icm_msg);
1121*45039663SJohn Forte 		break;
1122*45039663SJohn Forte 
1123*45039663SJohn Forte 	case STMF_ICM_R2T:
1124*45039663SJohn Forte 		rc = stmf_ic_r2t_msg_marshal(nvl, msg->icm_msg);
1125*45039663SJohn Forte 		break;
1126*45039663SJohn Forte 
1127*45039663SJohn Forte 	case STMF_ICM_STATUS:
1128*45039663SJohn Forte 		rc = stmf_ic_status_msg_marshal(nvl, msg->icm_msg);
1129*45039663SJohn Forte 		break;
1130*45039663SJohn Forte 
1131*45039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
1132*45039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
1133*45039663SJohn Forte 		rc = stmf_ic_session_create_destroy_msg_marshal(nvl,
1134*45039663SJohn Forte 		    msg->icm_msg);
1135*45039663SJohn Forte 		break;
1136*45039663SJohn Forte 
1137*45039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
1138*45039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
1139*45039663SJohn Forte 		rc = stmf_ic_echo_request_reply_msg_marshal(nvl,
1140*45039663SJohn Forte 		    msg->icm_msg);
1141*45039663SJohn Forte 		break;
1142*45039663SJohn Forte 
1143*45039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
1144*45039663SJohn Forte 		ASSERT(0);
1145*45039663SJohn Forte 		break;
1146*45039663SJohn Forte 
1147*45039663SJohn Forte 	default:
1148*45039663SJohn Forte 		ASSERT(0);
1149*45039663SJohn Forte 	}
1150*45039663SJohn Forte 
1151*45039663SJohn Forte done:
1152*45039663SJohn Forte 	if (!rc)
1153*45039663SJohn Forte 		return (nvl);
1154*45039663SJohn Forte 
1155*45039663SJohn Forte 	if (nvl)
1156*45039663SJohn Forte 		nvlist_free(nvl);
1157*45039663SJohn Forte 
1158*45039663SJohn Forte 	return (NULL);
1159*45039663SJohn Forte }
1160*45039663SJohn Forte 
1161*45039663SJohn Forte 
1162*45039663SJohn Forte static int
1163*45039663SJohn Forte stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg)
1164*45039663SJohn Forte {
1165*45039663SJohn Forte 	stmf_ic_reg_port_msg_t *m = (stmf_ic_reg_port_msg_t *)msg;
1166*45039663SJohn Forte 	int rc = 0;
1167*45039663SJohn Forte 
1168*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icrp_port_id);
1169*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrp_relative_port_id);
1170*45039663SJohn Forte 
1171*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrp_cb_arg_len);
1172*45039663SJohn Forte 	/* only add the callback arg if necessary */
1173*45039663SJohn Forte 	if (m->icrp_cb_arg_len) {
1174*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrp_cb_arg, m->icrp_cb_arg_len);
1175*45039663SJohn Forte 	}
1176*45039663SJohn Forte 
1177*45039663SJohn Forte done:
1178*45039663SJohn Forte 	return (rc);
1179*45039663SJohn Forte }
1180*45039663SJohn Forte 
1181*45039663SJohn Forte static int
1182*45039663SJohn Forte stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg)
1183*45039663SJohn Forte {
1184*45039663SJohn Forte 	stmf_ic_dereg_port_msg_t *m = (stmf_ic_dereg_port_msg_t *)msg;
1185*45039663SJohn Forte 	int rc = 0;
1186*45039663SJohn Forte 
1187*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icdp_port_id);
1188*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icdp_cb_arg_len);
1189*45039663SJohn Forte 
1190*45039663SJohn Forte 	/* only add the callback arg if necessary */
1191*45039663SJohn Forte 	if (m->icdp_cb_arg_len) {
1192*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icdp_cb_arg, m->icdp_cb_arg_len);
1193*45039663SJohn Forte 	}
1194*45039663SJohn Forte 
1195*45039663SJohn Forte done:
1196*45039663SJohn Forte 	return (rc);
1197*45039663SJohn Forte }
1198*45039663SJohn Forte 
1199*45039663SJohn Forte /*
1200*45039663SJohn Forte  * Handles STMF_ICM_LUN_ACTIVE, STMF_ICM_REGISTER_LUN and
1201*45039663SJohn Forte  * STMF_ICM_DEREGISTER_LUN;
1202*45039663SJohn Forte  * msg payload is the same for all.
1203*45039663SJohn Forte  */
1204*45039663SJohn Forte static int
1205*45039663SJohn Forte stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg)
1206*45039663SJohn Forte {
1207*45039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *m = (stmf_ic_reg_dereg_lun_msg_t *)msg;
1208*45039663SJohn Forte 	int rc = 0;
1209*45039663SJohn Forte 
1210*45039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icrl_lun_id);
1211*45039663SJohn Forte 	NVLIST_ADD_FIELD(string, m, icrl_lu_provider_name);
1212*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icrl_cb_arg_len);
1213*45039663SJohn Forte 
1214*45039663SJohn Forte 	/* only add the callback arg if necessary */
1215*45039663SJohn Forte 	if (m->icrl_cb_arg_len) {
1216*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrl_cb_arg, m->icrl_cb_arg_len);
1217*45039663SJohn Forte 	}
1218*45039663SJohn Forte 
1219*45039663SJohn Forte done:
1220*45039663SJohn Forte 	return (rc);
1221*45039663SJohn Forte }
1222*45039663SJohn Forte 
1223*45039663SJohn Forte static int
1224*45039663SJohn Forte stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg)
1225*45039663SJohn Forte {
1226*45039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *m = (stmf_ic_scsi_cmd_msg_t *)msg;
1227*45039663SJohn Forte 	int rc = 0;
1228*45039663SJohn Forte 
1229*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsc_task_msgid);
1230*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icsc_ini_devid);
1231*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icsc_tgt_devid);
1232*45039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icsc_lun_id);
1233*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsc_session_id);
1234*45039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_lun_no, 8);
1235*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icsc_task_expected_xfer_length);
1236*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint16, m, icsc_task_cdb_length);
1237*45039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_cdb, m->icsc_task_cdb_length);
1238*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_flags);
1239*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_priority);
1240*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icsc_task_mgmt_function);
1241*45039663SJohn Forte 
1242*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icsc_immed_data_len);
1243*45039663SJohn Forte 	/* only add immediate data if necessary */
1244*45039663SJohn Forte 	if (m->icsc_immed_data_len) {
1245*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_immed_data,
1246*45039663SJohn Forte 		    m->icsc_immed_data_len);
1247*45039663SJohn Forte 	}
1248*45039663SJohn Forte 
1249*45039663SJohn Forte done:
1250*45039663SJohn Forte 	return (rc);
1251*45039663SJohn Forte }
1252*45039663SJohn Forte 
1253*45039663SJohn Forte static int
1254*45039663SJohn Forte stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg)
1255*45039663SJohn Forte {
1256*45039663SJohn Forte 	stmf_ic_scsi_data_msg_t *m = (stmf_ic_scsi_data_msg_t *)msg;
1257*45039663SJohn Forte 	int rc = 0;
1258*45039663SJohn Forte 
1259*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_task_msgid);
1260*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_session_id);
1261*45039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icsd_lun_id);
1262*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsd_data_len);
1263*45039663SJohn Forte 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsd_data, m->icsd_data_len);
1264*45039663SJohn Forte 
1265*45039663SJohn Forte done:
1266*45039663SJohn Forte 	return (rc);
1267*45039663SJohn Forte }
1268*45039663SJohn Forte 
1269*45039663SJohn Forte static int
1270*45039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg)
1271*45039663SJohn Forte {
1272*45039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *m =
1273*45039663SJohn Forte 	    (stmf_ic_scsi_data_xfer_done_msg_t *)msg;
1274*45039663SJohn Forte 	int rc = 0;
1275*45039663SJohn Forte 
1276*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_task_msgid);
1277*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_session_id);
1278*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icsx_status);
1279*45039663SJohn Forte 
1280*45039663SJohn Forte done:
1281*45039663SJohn Forte 	return (rc);
1282*45039663SJohn Forte }
1283*45039663SJohn Forte 
1284*45039663SJohn Forte static int
1285*45039663SJohn Forte stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg)
1286*45039663SJohn Forte {
1287*45039663SJohn Forte 	stmf_ic_scsi_status_msg_t *m = (stmf_ic_scsi_status_msg_t *)msg;
1288*45039663SJohn Forte 	int rc = 0;
1289*45039663SJohn Forte 
1290*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icss_task_msgid);
1291*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icss_session_id);
1292*45039663SJohn Forte 	NVLIST_ADD_ARRAY(uint8, m, icss_lun_id);
1293*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_response);
1294*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_status);
1295*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_flags);
1296*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icss_resid);
1297*45039663SJohn Forte 
1298*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, icss_sense_len);
1299*45039663SJohn Forte 
1300*45039663SJohn Forte 	if (m->icss_sense_len)
1301*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icss_sense, m->icss_sense_len);
1302*45039663SJohn Forte 
1303*45039663SJohn Forte done:
1304*45039663SJohn Forte 	return (rc);
1305*45039663SJohn Forte }
1306*45039663SJohn Forte 
1307*45039663SJohn Forte static int
1308*45039663SJohn Forte stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg)
1309*45039663SJohn Forte {
1310*45039663SJohn Forte 	stmf_ic_r2t_msg_t *m = (stmf_ic_r2t_msg_t *)msg;
1311*45039663SJohn Forte 	int rc = 0;
1312*45039663SJohn Forte 
1313*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icrt_task_msgid);
1314*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icrt_session_id);
1315*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icrt_offset);
1316*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icrt_length);
1317*45039663SJohn Forte 
1318*45039663SJohn Forte done:
1319*45039663SJohn Forte 	return (rc);
1320*45039663SJohn Forte }
1321*45039663SJohn Forte 
1322*45039663SJohn Forte static int
1323*45039663SJohn Forte stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg)
1324*45039663SJohn Forte {
1325*45039663SJohn Forte 	stmf_ic_status_msg_t *m = (stmf_ic_status_msg_t *)msg;
1326*45039663SJohn Forte 	int rc = 0;
1327*45039663SJohn Forte 
1328*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, ics_msg_type);
1329*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, ics_msgid);
1330*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, m, ics_status);
1331*45039663SJohn Forte 
1332*45039663SJohn Forte done:
1333*45039663SJohn Forte 	return (rc);
1334*45039663SJohn Forte }
1335*45039663SJohn Forte 
1336*45039663SJohn Forte static int
1337*45039663SJohn Forte stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg)
1338*45039663SJohn Forte {
1339*45039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *m =
1340*45039663SJohn Forte 	    (stmf_ic_session_create_destroy_msg_t *)msg;
1341*45039663SJohn Forte 	int rc = 0;
1342*45039663SJohn Forte 
1343*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icscd_ini_devid);
1344*45039663SJohn Forte 	NVLIST_ADD_DEVID(m, icscd_tgt_devid);
1345*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint64, m, icscd_session_id);
1346*45039663SJohn Forte 
1347*45039663SJohn Forte done:
1348*45039663SJohn Forte 	return (rc);
1349*45039663SJohn Forte }
1350*45039663SJohn Forte 
1351*45039663SJohn Forte static int
1352*45039663SJohn Forte stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg)
1353*45039663SJohn Forte {
1354*45039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *m = msg;
1355*45039663SJohn Forte 	int rc = 0;
1356*45039663SJohn Forte 
1357*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint32, m, icerr_datalen);
1358*45039663SJohn Forte 	if (m->icerr_datalen)
1359*45039663SJohn Forte 		NVLIST_ADD_ARRAY_LEN(uint8, m, icerr_data, m->icerr_datalen);
1360*45039663SJohn Forte 
1361*45039663SJohn Forte done:
1362*45039663SJohn Forte 	return (rc);
1363*45039663SJohn Forte }
1364*45039663SJohn Forte 
1365*45039663SJohn Forte /*
1366*45039663SJohn Forte  * Allocate a new nvlist representing the scsi_devid_desc and add it
1367*45039663SJohn Forte  * to the nvlist.
1368*45039663SJohn Forte  */
1369*45039663SJohn Forte static int
1370*45039663SJohn Forte stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
1371*45039663SJohn Forte 	char *sdid_name,
1372*45039663SJohn Forte 	scsi_devid_desc_t *sdid)
1373*45039663SJohn Forte {
1374*45039663SJohn Forte 	int rc = 0;
1375*45039663SJohn Forte 	nvlist_t *nvl = NULL;
1376*45039663SJohn Forte 
1377*45039663SJohn Forte 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1378*45039663SJohn Forte 	if (rc)
1379*45039663SJohn Forte 		goto done;
1380*45039663SJohn Forte 
1381*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, protocol_id);
1382*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, code_set);
1383*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, piv);
1384*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, association);
1385*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, ident_type);
1386*45039663SJohn Forte 	NVLIST_ADD_FIELD(uint8, sdid, ident_length);
1387*45039663SJohn Forte 
1388*45039663SJohn Forte 	rc = nvlist_add_uint8_array(nvl, "ident", sdid->ident,
1389*45039663SJohn Forte 	    sdid->ident_length);
1390*45039663SJohn Forte 	if (rc)
1391*45039663SJohn Forte 		goto done;
1392*45039663SJohn Forte 
1393*45039663SJohn Forte 	rc = nvlist_add_nvlist(parent_nvl, sdid_name, nvl);
1394*45039663SJohn Forte 
1395*45039663SJohn Forte done:
1396*45039663SJohn Forte 	if (nvl) {
1397*45039663SJohn Forte 		nvlist_free(nvl);
1398*45039663SJohn Forte 	}
1399*45039663SJohn Forte 	return (rc);
1400*45039663SJohn Forte }
1401*45039663SJohn Forte 
1402*45039663SJohn Forte /*
1403*45039663SJohn Forte  * Unmarshaling routines.
1404*45039663SJohn Forte  */
1405*45039663SJohn Forte 
1406*45039663SJohn Forte static stmf_ic_msg_t *
1407*45039663SJohn Forte stmf_ic_msg_unmarshal(nvlist_t *nvl)
1408*45039663SJohn Forte {
1409*45039663SJohn Forte 	stmf_ic_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1410*45039663SJohn Forte 	uint8_t msg_type;
1411*45039663SJohn Forte 	int rc = 0;
1412*45039663SJohn Forte 
1413*45039663SJohn Forte 	/*
1414*45039663SJohn Forte 	 * We'd like to do this:
1415*45039663SJohn Forte 	 *
1416*45039663SJohn Forte 	 *   NVLIST_LOOKUP_FIELD(uint8, m, icm_msg_type);
1417*45039663SJohn Forte 	 *
1418*45039663SJohn Forte 	 * but the fact that msg type is an enum causes type problems.
1419*45039663SJohn Forte 	 */
1420*45039663SJohn Forte 	rc = nvlist_lookup_uint8(nvl, "icm_msg_type", &msg_type);
1421*45039663SJohn Forte 	if (rc) {
1422*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icm_msg_type");
1423*45039663SJohn Forte 		goto done;
1424*45039663SJohn Forte 	}
1425*45039663SJohn Forte 
1426*45039663SJohn Forte 	m->icm_msg_type = msg_type;
1427*45039663SJohn Forte 	m->icm_nvlist = nvl;
1428*45039663SJohn Forte 
1429*45039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint64, m, icm_msgid);
1430*45039663SJohn Forte 
1431*45039663SJohn Forte 	switch (m->icm_msg_type) {
1432*45039663SJohn Forte 
1433*45039663SJohn Forte 	case STMF_ICM_REGISTER_PROXY_PORT:
1434*45039663SJohn Forte 		m->icm_msg = stmf_ic_reg_port_msg_unmarshal(nvl);
1435*45039663SJohn Forte 		break;
1436*45039663SJohn Forte 
1437*45039663SJohn Forte 
1438*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_PROXY_PORT:
1439*45039663SJohn Forte 		m->icm_msg = stmf_ic_dereg_port_msg_unmarshal(nvl);
1440*45039663SJohn Forte 		break;
1441*45039663SJohn Forte 
1442*45039663SJohn Forte 	case STMF_ICM_LUN_ACTIVE:
1443*45039663SJohn Forte 	case STMF_ICM_REGISTER_LUN:
1444*45039663SJohn Forte 	case STMF_ICM_DEREGISTER_LUN:
1445*45039663SJohn Forte 		m->icm_msg = stmf_ic_reg_dereg_lun_msg_unmarshal(nvl);
1446*45039663SJohn Forte 		break;
1447*45039663SJohn Forte 
1448*45039663SJohn Forte 	case STMF_ICM_SCSI_CMD:
1449*45039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_cmd_msg_unmarshal(nvl);
1450*45039663SJohn Forte 		break;
1451*45039663SJohn Forte 
1452*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA:
1453*45039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_data_msg_unmarshal(nvl);
1454*45039663SJohn Forte 		break;
1455*45039663SJohn Forte 
1456*45039663SJohn Forte 	case STMF_ICM_SCSI_DATA_XFER_DONE:
1457*45039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvl);
1458*45039663SJohn Forte 		break;
1459*45039663SJohn Forte 
1460*45039663SJohn Forte 	case STMF_ICM_SCSI_STATUS:
1461*45039663SJohn Forte 		m->icm_msg = stmf_ic_scsi_status_msg_unmarshal(nvl);
1462*45039663SJohn Forte 		break;
1463*45039663SJohn Forte 
1464*45039663SJohn Forte 	case STMF_ICM_R2T:
1465*45039663SJohn Forte 		m->icm_msg = stmf_ic_r2t_msg_unmarshal(nvl);
1466*45039663SJohn Forte 		break;
1467*45039663SJohn Forte 
1468*45039663SJohn Forte 	case STMF_ICM_STATUS:
1469*45039663SJohn Forte 		m->icm_msg = stmf_ic_status_msg_unmarshal(nvl);
1470*45039663SJohn Forte 		break;
1471*45039663SJohn Forte 
1472*45039663SJohn Forte 	case STMF_ICM_SESSION_CREATE:
1473*45039663SJohn Forte 	case STMF_ICM_SESSION_DESTROY:
1474*45039663SJohn Forte 		m->icm_msg = stmf_ic_session_create_destroy_msg_unmarshal(nvl);
1475*45039663SJohn Forte 		break;
1476*45039663SJohn Forte 
1477*45039663SJohn Forte 	case STMF_ICM_ECHO_REQUEST:
1478*45039663SJohn Forte 	case STMF_ICM_ECHO_REPLY:
1479*45039663SJohn Forte 		m->icm_msg = stmf_ic_echo_request_reply_msg_unmarshal(nvl);
1480*45039663SJohn Forte 		break;
1481*45039663SJohn Forte 
1482*45039663SJohn Forte 	case STMF_ICM_MAX_MSG_TYPE:
1483*45039663SJohn Forte 		ASSERT(0);
1484*45039663SJohn Forte 		break;
1485*45039663SJohn Forte 
1486*45039663SJohn Forte 	default:
1487*45039663SJohn Forte 		ASSERT(0);
1488*45039663SJohn Forte 	}
1489*45039663SJohn Forte 
1490*45039663SJohn Forte done:
1491*45039663SJohn Forte 
1492*45039663SJohn Forte 	if (!m->icm_msg) {
1493*45039663SJohn Forte 		kmem_free(m, sizeof (*m));
1494*45039663SJohn Forte 		return (NULL);
1495*45039663SJohn Forte 	}
1496*45039663SJohn Forte 
1497*45039663SJohn Forte 	return (m);
1498*45039663SJohn Forte }
1499*45039663SJohn Forte 
1500*45039663SJohn Forte static void *
1501*45039663SJohn Forte stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl)
1502*45039663SJohn Forte {
1503*45039663SJohn Forte 	nvlist_t *nvl_port_id = NULL;
1504*45039663SJohn Forte 	int rc = 0;
1505*45039663SJohn Forte 	stmf_ic_reg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1506*45039663SJohn Forte 
1507*45039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, "icrp_port_id", &nvl_port_id);
1508*45039663SJohn Forte 	if (rc) {
1509*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id nvl");
1510*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1511*45039663SJohn Forte 		goto done;
1512*45039663SJohn Forte 	}
1513*45039663SJohn Forte 
1514*45039663SJohn Forte 	m->icrp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
1515*45039663SJohn Forte 	if (m->icrp_port_id == NULL) {
1516*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id");
1517*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1518*45039663SJohn Forte 		goto done;
1519*45039663SJohn Forte 	}
1520*45039663SJohn Forte 
1521*45039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_relative_port_id);
1522*45039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_cb_arg_len);
1523*45039663SJohn Forte 
1524*45039663SJohn Forte 	if (m->icrp_cb_arg_len) {
1525*45039663SJohn Forte 		m->icrp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1526*45039663SJohn Forte 		    "icrp_cb_arg", m->icrp_cb_arg_len, NULL);
1527*45039663SJohn Forte 		if (m->icrp_cb_arg == NULL) {
1528*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icrp_cb_arg");
1529*45039663SJohn Forte 			rc = ENOMEM; /* XXX */
1530*45039663SJohn Forte 			goto done;
1531*45039663SJohn Forte 		}
1532*45039663SJohn Forte 	}
1533*45039663SJohn Forte 
1534*45039663SJohn Forte done:
1535*45039663SJohn Forte 	if (!rc)
1536*45039663SJohn Forte 		return (m);
1537*45039663SJohn Forte 
1538*45039663SJohn Forte 	stmf_ic_reg_port_msg_free(m, STMF_UNMARSHAL);
1539*45039663SJohn Forte 
1540*45039663SJohn Forte 	return (NULL);
1541*45039663SJohn Forte }
1542*45039663SJohn Forte 
1543*45039663SJohn Forte /*
1544*45039663SJohn Forte  * XXX largely the same as stmf_ic_reg_port_msg_unmarshal()
1545*45039663SJohn Forte  * Common stuff should be factored out.  Type issues may make this
1546*45039663SJohn Forte  * painful.
1547*45039663SJohn Forte  */
1548*45039663SJohn Forte static void *
1549*45039663SJohn Forte stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl)
1550*45039663SJohn Forte {
1551*45039663SJohn Forte 	nvlist_t *nvl_port_id = NULL;
1552*45039663SJohn Forte 	int rc = 0;
1553*45039663SJohn Forte 	stmf_ic_dereg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1554*45039663SJohn Forte 
1555*45039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, "icdp_port_id", &nvl_port_id);
1556*45039663SJohn Forte 	if (rc) {
1557*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id nvl");
1558*45039663SJohn Forte 		goto done;
1559*45039663SJohn Forte 	}
1560*45039663SJohn Forte 
1561*45039663SJohn Forte 	m->icdp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
1562*45039663SJohn Forte 	if (m->icdp_port_id == NULL) {
1563*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id");
1564*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1565*45039663SJohn Forte 		goto done;
1566*45039663SJohn Forte 	}
1567*45039663SJohn Forte 
1568*45039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icdp_cb_arg_len);
1569*45039663SJohn Forte 
1570*45039663SJohn Forte 	if (m->icdp_cb_arg_len) {
1571*45039663SJohn Forte 		m->icdp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1572*45039663SJohn Forte 		    "icdp_cb_arg", m->icdp_cb_arg_len, NULL);
1573*45039663SJohn Forte 		if (m->icdp_cb_arg == NULL) {
1574*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icdp_cb_arg");
1575*45039663SJohn Forte 			rc = ENOMEM; /* XXX */
1576*45039663SJohn Forte 			goto done;
1577*45039663SJohn Forte 		}
1578*45039663SJohn Forte 	}
1579*45039663SJohn Forte 
1580*45039663SJohn Forte done:
1581*45039663SJohn Forte 	if (!rc)
1582*45039663SJohn Forte 		return (m);
1583*45039663SJohn Forte 
1584*45039663SJohn Forte 	stmf_ic_dereg_port_msg_free(m, STMF_UNMARSHAL);
1585*45039663SJohn Forte 
1586*45039663SJohn Forte 	return (NULL);
1587*45039663SJohn Forte }
1588*45039663SJohn Forte 
1589*45039663SJohn Forte static void *
1590*45039663SJohn Forte stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl)
1591*45039663SJohn Forte {
1592*45039663SJohn Forte 	int rc = 0;
1593*45039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1594*45039663SJohn Forte 
1595*45039663SJohn Forte 	if (! stmf_ic_uint8_array_unmarshal(nvl, "icrl_lun_id",
1596*45039663SJohn Forte 	    sizeof (m->icrl_lun_id), m->icrl_lun_id)) {
1597*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrl_lun_id");
1598*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1599*45039663SJohn Forte 		goto done;
1600*45039663SJohn Forte 	}
1601*45039663SJohn Forte 
1602*45039663SJohn Forte 	m->icrl_lu_provider_name = stmf_ic_string_unmarshal(nvl,
1603*45039663SJohn Forte 	    "icrl_lu_provider_name");
1604*45039663SJohn Forte 
1605*45039663SJohn Forte 	if (!m->icrl_lu_provider_name) {
1606*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrl_lu_provider_name");
1607*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1608*45039663SJohn Forte 		goto done;
1609*45039663SJohn Forte 	}
1610*45039663SJohn Forte 
1611*45039663SJohn Forte 	NVLIST_LOOKUP_FIELD(uint16, m, icrl_cb_arg_len);
1612*45039663SJohn Forte 
1613*45039663SJohn Forte 	if (m->icrl_cb_arg_len) {
1614*45039663SJohn Forte 		m->icrl_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1615*45039663SJohn Forte 		    "icrl_cb_arg", m->icrl_cb_arg_len, NULL);
1616*45039663SJohn Forte 		if (m->icrl_cb_arg == NULL) {
1617*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icrl_cb_arg");
1618*45039663SJohn Forte 			rc = ENOMEM; /* XXX */
1619*45039663SJohn Forte 			goto done;
1620*45039663SJohn Forte 		}
1621*45039663SJohn Forte 	}
1622*45039663SJohn Forte 
1623*45039663SJohn Forte done:
1624*45039663SJohn Forte 	if (!rc)
1625*45039663SJohn Forte 		return (m);
1626*45039663SJohn Forte 
1627*45039663SJohn Forte 	stmf_ic_reg_dereg_lun_msg_free(m, STMF_UNMARSHAL);
1628*45039663SJohn Forte 
1629*45039663SJohn Forte 	return (NULL);
1630*45039663SJohn Forte }
1631*45039663SJohn Forte 
1632*45039663SJohn Forte static void *
1633*45039663SJohn Forte stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl)
1634*45039663SJohn Forte {
1635*45039663SJohn Forte 	int rc = 0;
1636*45039663SJohn Forte 	stmf_ic_scsi_cmd_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1637*45039663SJohn Forte 
1638*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1639*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsc_task_msgid),
1640*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsc_session_id),
1641*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icsc_task_expected_xfer_length),
1642*45039663SJohn Forte 	    NV_PAIR(UINT16, m, icsc_task_cdb_length),
1643*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icsc_task_flags),
1644*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icsc_task_mgmt_function),
1645*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icsc_immed_data_len),
1646*45039663SJohn Forte 	    NULL) != 0) {
1647*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_task_msgid and friends");
1648*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1649*45039663SJohn Forte 		goto done;
1650*45039663SJohn Forte 	}
1651*45039663SJohn Forte 
1652*45039663SJohn Forte 	m->icsc_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1653*45039663SJohn Forte 	    nvl, "icsc_ini_devid");
1654*45039663SJohn Forte 	if (m->icsc_ini_devid == NULL) {
1655*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_ini_devid");
1656*45039663SJohn Forte 		rc = ENOMEM;
1657*45039663SJohn Forte 		goto done;
1658*45039663SJohn Forte 	}
1659*45039663SJohn Forte 
1660*45039663SJohn Forte 	m->icsc_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1661*45039663SJohn Forte 	    nvl, "icsc_tgt_devid");
1662*45039663SJohn Forte 	if (m->icsc_tgt_devid == NULL) {
1663*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_tgt_devid");
1664*45039663SJohn Forte 		rc = ENOMEM;
1665*45039663SJohn Forte 		goto done;
1666*45039663SJohn Forte 	}
1667*45039663SJohn Forte 
1668*45039663SJohn Forte 	/* icsc_lun_id */
1669*45039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_lun_id",
1670*45039663SJohn Forte 	    sizeof (m->icsc_lun_id), m->icsc_lun_id)) {
1671*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_lun_id");
1672*45039663SJohn Forte 		rc = ENOMEM;
1673*45039663SJohn Forte 		goto done;
1674*45039663SJohn Forte 	}
1675*45039663SJohn Forte 
1676*45039663SJohn Forte 	/* icsc_task_lun_no */
1677*45039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_lun_no",
1678*45039663SJohn Forte 	    sizeof (m->icsc_task_lun_no), m->icsc_task_lun_no)) {
1679*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_task_lun_no");
1680*45039663SJohn Forte 		rc = ENOMEM;
1681*45039663SJohn Forte 		goto done;
1682*45039663SJohn Forte 	}
1683*45039663SJohn Forte 
1684*45039663SJohn Forte 	/* icsc_task_cdb */
1685*45039663SJohn Forte 	m->icsc_task_cdb = stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_cdb",
1686*45039663SJohn Forte 	    m->icsc_task_cdb_length, NULL);
1687*45039663SJohn Forte 	if (!m->icsc_task_cdb) {
1688*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsc_task_cdb");
1689*45039663SJohn Forte 		rc = ENOMEM;
1690*45039663SJohn Forte 		goto done;
1691*45039663SJohn Forte 	}
1692*45039663SJohn Forte 
1693*45039663SJohn Forte 	/* immediate data, if there is any */
1694*45039663SJohn Forte 	if (m->icsc_immed_data_len) {
1695*45039663SJohn Forte 		m->icsc_immed_data = stmf_ic_uint8_array_unmarshal(nvl,
1696*45039663SJohn Forte 		    "icsc_immed_data", m->icsc_immed_data_len, NULL);
1697*45039663SJohn Forte 		if (!m->icsc_immed_data) {
1698*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icsc_immed_data");
1699*45039663SJohn Forte 			rc = ENOMEM;
1700*45039663SJohn Forte 			goto done;
1701*45039663SJohn Forte 		}
1702*45039663SJohn Forte 	}
1703*45039663SJohn Forte 
1704*45039663SJohn Forte done:
1705*45039663SJohn Forte 	if (!rc)
1706*45039663SJohn Forte 		return (m);
1707*45039663SJohn Forte 
1708*45039663SJohn Forte 	stmf_ic_scsi_cmd_msg_free(m, STMF_UNMARSHAL);
1709*45039663SJohn Forte 
1710*45039663SJohn Forte 	return (NULL);
1711*45039663SJohn Forte }
1712*45039663SJohn Forte 
1713*45039663SJohn Forte static void *
1714*45039663SJohn Forte stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl)
1715*45039663SJohn Forte {
1716*45039663SJohn Forte 	int rc = 0;
1717*45039663SJohn Forte 	stmf_ic_scsi_data_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1718*45039663SJohn Forte 
1719*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1720*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_task_msgid),
1721*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_session_id),
1722*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsd_data_len),
1723*45039663SJohn Forte 	    NULL) != 0) {
1724*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_task_msgid and friends");
1725*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1726*45039663SJohn Forte 		goto done;
1727*45039663SJohn Forte 	}
1728*45039663SJohn Forte 
1729*45039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsd_lun_id",
1730*45039663SJohn Forte 	    sizeof (m->icsd_lun_id), m->icsd_lun_id)) {
1731*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_lun_id");
1732*45039663SJohn Forte 		rc = ENOMEM;
1733*45039663SJohn Forte 		goto done;
1734*45039663SJohn Forte 	}
1735*45039663SJohn Forte 
1736*45039663SJohn Forte 	m->icsd_data = stmf_ic_uint8_array_unmarshal(nvl, "icsd_data",
1737*45039663SJohn Forte 	    m->icsd_data_len, NULL);
1738*45039663SJohn Forte 	if (!m->icsd_data) {
1739*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_data");
1740*45039663SJohn Forte 		rc = ENOMEM;
1741*45039663SJohn Forte 		goto done;
1742*45039663SJohn Forte 	}
1743*45039663SJohn Forte 
1744*45039663SJohn Forte done:
1745*45039663SJohn Forte 	if (!rc)
1746*45039663SJohn Forte 		return (m);
1747*45039663SJohn Forte 
1748*45039663SJohn Forte 	stmf_ic_scsi_data_msg_free(m, STMF_UNMARSHAL);
1749*45039663SJohn Forte 
1750*45039663SJohn Forte 	return (NULL);
1751*45039663SJohn Forte }
1752*45039663SJohn Forte 
1753*45039663SJohn Forte static void *
1754*45039663SJohn Forte stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl)
1755*45039663SJohn Forte {
1756*45039663SJohn Forte 	int rc = 0;
1757*45039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_t *m =
1758*45039663SJohn Forte 	    kmem_zalloc(sizeof (*m), KM_SLEEP);
1759*45039663SJohn Forte 
1760*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1761*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_task_msgid),
1762*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_session_id),
1763*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icsx_status),
1764*45039663SJohn Forte 	    NULL) != 0) {
1765*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsx_task_msgid and friends");
1766*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1767*45039663SJohn Forte 		goto done;
1768*45039663SJohn Forte 	}
1769*45039663SJohn Forte 
1770*45039663SJohn Forte done:
1771*45039663SJohn Forte 	if (!rc)
1772*45039663SJohn Forte 		return (m);
1773*45039663SJohn Forte 
1774*45039663SJohn Forte 	stmf_ic_scsi_data_xfer_done_msg_free(m, STMF_UNMARSHAL);
1775*45039663SJohn Forte 
1776*45039663SJohn Forte 	return (NULL);
1777*45039663SJohn Forte }
1778*45039663SJohn Forte 
1779*45039663SJohn Forte static void *
1780*45039663SJohn Forte stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl)
1781*45039663SJohn Forte {
1782*45039663SJohn Forte 	int rc = 0;
1783*45039663SJohn Forte 	stmf_ic_scsi_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1784*45039663SJohn Forte 
1785*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1786*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icss_task_msgid),
1787*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icss_session_id),
1788*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_response),
1789*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_status),
1790*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_flags),
1791*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icss_resid),
1792*45039663SJohn Forte 	    NV_PAIR(UINT8, m, icss_sense_len),
1793*45039663SJohn Forte 	    NULL) != 0) {
1794*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icss_task_msgid and friends");
1795*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1796*45039663SJohn Forte 		goto done;
1797*45039663SJohn Forte 	}
1798*45039663SJohn Forte 
1799*45039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icss_lun_id",
1800*45039663SJohn Forte 	    sizeof (m->icss_lun_id), m->icss_lun_id)) {
1801*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icss_lun_id");
1802*45039663SJohn Forte 		rc = ENOMEM;
1803*45039663SJohn Forte 		goto done;
1804*45039663SJohn Forte 	}
1805*45039663SJohn Forte 
1806*45039663SJohn Forte 	if (m->icss_sense_len) {
1807*45039663SJohn Forte 		m->icss_sense = stmf_ic_uint8_array_unmarshal(nvl, "icss_sense",
1808*45039663SJohn Forte 		    m->icss_sense_len, NULL);
1809*45039663SJohn Forte 		if (!m->icss_sense) {
1810*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icss_sense");
1811*45039663SJohn Forte 			rc = ENOMEM;
1812*45039663SJohn Forte 			goto done;
1813*45039663SJohn Forte 		}
1814*45039663SJohn Forte 	}
1815*45039663SJohn Forte done:
1816*45039663SJohn Forte 	if (!rc)
1817*45039663SJohn Forte 		return (m);
1818*45039663SJohn Forte 
1819*45039663SJohn Forte 	stmf_ic_scsi_status_msg_free(m, STMF_UNMARSHAL);
1820*45039663SJohn Forte 
1821*45039663SJohn Forte 	return (NULL);
1822*45039663SJohn Forte }
1823*45039663SJohn Forte 
1824*45039663SJohn Forte static void *
1825*45039663SJohn Forte stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl)
1826*45039663SJohn Forte {
1827*45039663SJohn Forte 	int rc = 0;
1828*45039663SJohn Forte 	stmf_ic_r2t_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1829*45039663SJohn Forte 
1830*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1831*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icrt_task_msgid),
1832*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icrt_session_id),
1833*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icrt_offset),
1834*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icrt_length),
1835*45039663SJohn Forte 	    NULL) != 0) {
1836*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icrt_task_msgid and friends");
1837*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1838*45039663SJohn Forte 		goto done;
1839*45039663SJohn Forte 	}
1840*45039663SJohn Forte 
1841*45039663SJohn Forte done:
1842*45039663SJohn Forte 	if (!rc)
1843*45039663SJohn Forte 		return (m);
1844*45039663SJohn Forte 
1845*45039663SJohn Forte 	stmf_ic_r2t_msg_free(m, STMF_UNMARSHAL);
1846*45039663SJohn Forte 
1847*45039663SJohn Forte 	return (NULL);
1848*45039663SJohn Forte }
1849*45039663SJohn Forte 
1850*45039663SJohn Forte static void *
1851*45039663SJohn Forte stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl)
1852*45039663SJohn Forte {
1853*45039663SJohn Forte 	int rc = 0;
1854*45039663SJohn Forte 	stmf_ic_session_create_destroy_msg_t *m = kmem_zalloc(sizeof (*m),
1855*45039663SJohn Forte 	    KM_SLEEP);
1856*45039663SJohn Forte 
1857*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1858*45039663SJohn Forte 	    NV_PAIR(UINT64, m, icscd_session_id),
1859*45039663SJohn Forte 	    NULL) != 0) {
1860*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_session_id");
1861*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1862*45039663SJohn Forte 		goto done;
1863*45039663SJohn Forte 	}
1864*45039663SJohn Forte 
1865*45039663SJohn Forte 	m->icscd_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1866*45039663SJohn Forte 	    nvl, "icscd_ini_devid");
1867*45039663SJohn Forte 	if (m->icscd_ini_devid == NULL) {
1868*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_ini_devid");
1869*45039663SJohn Forte 		rc = ENOMEM;
1870*45039663SJohn Forte 		goto done;
1871*45039663SJohn Forte 	}
1872*45039663SJohn Forte 
1873*45039663SJohn Forte 	m->icscd_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1874*45039663SJohn Forte 	    nvl, "icscd_tgt_devid");
1875*45039663SJohn Forte 	if (m->icscd_tgt_devid == NULL) {
1876*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icsd_tgt_devid");
1877*45039663SJohn Forte 		rc = ENOMEM;
1878*45039663SJohn Forte 		goto done;
1879*45039663SJohn Forte 	}
1880*45039663SJohn Forte 
1881*45039663SJohn Forte done:
1882*45039663SJohn Forte 	if (!rc)
1883*45039663SJohn Forte 		return (m);
1884*45039663SJohn Forte 
1885*45039663SJohn Forte 	stmf_ic_session_create_destroy_msg_free(m, STMF_UNMARSHAL);
1886*45039663SJohn Forte 
1887*45039663SJohn Forte 	return (NULL);
1888*45039663SJohn Forte }
1889*45039663SJohn Forte 
1890*45039663SJohn Forte static void *
1891*45039663SJohn Forte stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl)
1892*45039663SJohn Forte {
1893*45039663SJohn Forte 	int rc = 0;
1894*45039663SJohn Forte 	stmf_ic_echo_request_reply_msg_t *m = kmem_zalloc(sizeof (*m),
1895*45039663SJohn Forte 	    KM_SLEEP);
1896*45039663SJohn Forte 
1897*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1898*45039663SJohn Forte 	    NV_PAIR(UINT32, m, icerr_datalen),
1899*45039663SJohn Forte 	    NULL) != 0) {
1900*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "icerr_datalen");
1901*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1902*45039663SJohn Forte 		goto done;
1903*45039663SJohn Forte 	}
1904*45039663SJohn Forte 
1905*45039663SJohn Forte 	/* immediate data, if there is any */
1906*45039663SJohn Forte 	if (m->icerr_datalen) {
1907*45039663SJohn Forte 		m->icerr_data = stmf_ic_uint8_array_unmarshal(nvl,
1908*45039663SJohn Forte 		    "icerr_data", m->icerr_datalen, NULL);
1909*45039663SJohn Forte 		if (!m->icerr_data) {
1910*45039663SJohn Forte 			stmf_ic_nvlookup_warn(__func__, "icerr_data");
1911*45039663SJohn Forte 			rc = ENOMEM;
1912*45039663SJohn Forte 			goto done;
1913*45039663SJohn Forte 		}
1914*45039663SJohn Forte 	}
1915*45039663SJohn Forte 
1916*45039663SJohn Forte done:
1917*45039663SJohn Forte 	if (!rc)
1918*45039663SJohn Forte 		return (m);
1919*45039663SJohn Forte 
1920*45039663SJohn Forte 	stmf_ic_echo_request_reply_msg_free(m, STMF_UNMARSHAL);
1921*45039663SJohn Forte 
1922*45039663SJohn Forte 	return (NULL);
1923*45039663SJohn Forte }
1924*45039663SJohn Forte 
1925*45039663SJohn Forte static void *
1926*45039663SJohn Forte stmf_ic_status_msg_unmarshal(nvlist_t *nvl)
1927*45039663SJohn Forte {
1928*45039663SJohn Forte 	int rc = 0;
1929*45039663SJohn Forte 	stmf_ic_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1930*45039663SJohn Forte 
1931*45039663SJohn Forte 	if (nvlist_lookup_pairs(nvl, 0,
1932*45039663SJohn Forte 	    NV_PAIR(UINT8, m, ics_msg_type),
1933*45039663SJohn Forte 	    NV_PAIR(UINT64, m, ics_msgid),
1934*45039663SJohn Forte 	    NV_PAIR(UINT8, m, ics_status),
1935*45039663SJohn Forte 	    NULL) != 0) {
1936*45039663SJohn Forte 		stmf_ic_nvlookup_warn(__func__, "ics_msg_type and friends");
1937*45039663SJohn Forte 		rc = ENOMEM; /* XXX need something better */
1938*45039663SJohn Forte 		goto done;
1939*45039663SJohn Forte 	}
1940*45039663SJohn Forte 
1941*45039663SJohn Forte done:
1942*45039663SJohn Forte 	if (!rc)
1943*45039663SJohn Forte 		return (m);
1944*45039663SJohn Forte 
1945*45039663SJohn Forte 	kmem_free(m, sizeof (*m));
1946*45039663SJohn Forte 	return (NULL);
1947*45039663SJohn Forte }
1948*45039663SJohn Forte 
1949*45039663SJohn Forte 
1950*45039663SJohn Forte static scsi_devid_desc_t *
1951*45039663SJohn Forte stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t *nvl, char *field_name)
1952*45039663SJohn Forte {
1953*45039663SJohn Forte 	nvlist_t *nvl_devid = NULL;
1954*45039663SJohn Forte 	scsi_devid_desc_t *did = NULL;
1955*45039663SJohn Forte 	int rc;
1956*45039663SJohn Forte 
1957*45039663SJohn Forte 	rc = nvlist_lookup_nvlist(nvl, field_name, &nvl_devid);
1958*45039663SJohn Forte 	if (rc) {
1959*45039663SJohn Forte 		goto done;
1960*45039663SJohn Forte 	}
1961*45039663SJohn Forte 
1962*45039663SJohn Forte 	did = stmf_ic_scsi_devid_desc_unmarshal(nvl_devid);
1963*45039663SJohn Forte 
1964*45039663SJohn Forte done:
1965*45039663SJohn Forte 	return (did);
1966*45039663SJohn Forte }
1967*45039663SJohn Forte 
1968*45039663SJohn Forte 
1969*45039663SJohn Forte static scsi_devid_desc_t *
1970*45039663SJohn Forte stmf_ic_scsi_devid_desc_unmarshal(nvlist_t *nvl)
1971*45039663SJohn Forte {
1972*45039663SJohn Forte 	scsi_devid_desc_t *sdid = NULL;
1973*45039663SJohn Forte 	uint8_t ident_length = 0;
1974*45039663SJohn Forte 	size_t sdid_size;
1975*45039663SJohn Forte 	int rc = 0;
1976*45039663SJohn Forte 
1977*45039663SJohn Forte 	/*
1978*45039663SJohn Forte 	 * we get the ident_length first, since that's the only
1979*45039663SJohn Forte 	 * variable-sized field in the struct.
1980*45039663SJohn Forte 	 */
1981*45039663SJohn Forte 	rc = nvlist_lookup_uint8(nvl, "ident_length", &ident_length);
1982*45039663SJohn Forte 	if (rc)
1983*45039663SJohn Forte 		goto done;
1984*45039663SJohn Forte 
1985*45039663SJohn Forte 	sdid_size = sizeof_scsi_devid_desc(ident_length);
1986*45039663SJohn Forte 	sdid = kmem_zalloc(sdid_size, KM_SLEEP);
1987*45039663SJohn Forte 
1988*45039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, protocol_id);
1989*45039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, code_set);
1990*45039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, piv);
1991*45039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, association);
1992*45039663SJohn Forte 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, ident_type);
1993*45039663SJohn Forte 
1994*45039663SJohn Forte 	sdid->ident_length = ident_length;
1995*45039663SJohn Forte 
1996*45039663SJohn Forte 	if (!stmf_ic_uint8_array_unmarshal(nvl, "ident",
1997*45039663SJohn Forte 	    sdid->ident_length, sdid->ident)) {
1998*45039663SJohn Forte 		rc = ENOMEM; /* XXX */
1999*45039663SJohn Forte 		goto done;
2000*45039663SJohn Forte 	}
2001*45039663SJohn Forte 
2002*45039663SJohn Forte done:
2003*45039663SJohn Forte 	if (!rc)
2004*45039663SJohn Forte 		return (sdid);
2005*45039663SJohn Forte 
2006*45039663SJohn Forte 	kmem_free(sdid, sdid_size);
2007*45039663SJohn Forte 
2008*45039663SJohn Forte 	return (NULL);
2009*45039663SJohn Forte }
2010*45039663SJohn Forte 
2011*45039663SJohn Forte /*
2012*45039663SJohn Forte  * Unmarshal a uint8_t array.
2013*45039663SJohn Forte  *
2014*45039663SJohn Forte  * Takes a buf argument:
2015*45039663SJohn Forte  *
2016*45039663SJohn Forte  * - if non-null, the array contents are copied into the buf,
2017*45039663SJohn Forte  *   and we return a pointer to the buffer.
2018*45039663SJohn Forte  *
2019*45039663SJohn Forte  * - if null, we return a pointer to the unmarshaled data, which
2020*45039663SJohn Forte  *   resides in the nvlist.
2021*45039663SJohn Forte  *
2022*45039663SJohn Forte  * Returns NULL on failure.
2023*45039663SJohn Forte  */
2024*45039663SJohn Forte static uint8_t *
2025*45039663SJohn Forte stmf_ic_uint8_array_unmarshal(
2026*45039663SJohn Forte     nvlist_t *nvl,
2027*45039663SJohn Forte     char *field_name,
2028*45039663SJohn Forte     uint16_t len,
2029*45039663SJohn Forte     uint8_t *buf)	/* non-NULL: copy array into buf */
2030*45039663SJohn Forte {
2031*45039663SJohn Forte 	uint8_t *array = NULL;
2032*45039663SJohn Forte 	uint_t actual_len;
2033*45039663SJohn Forte 	int rc = 0;
2034*45039663SJohn Forte 
2035*45039663SJohn Forte 	rc = nvlist_lookup_uint8_array(nvl, field_name, &array, &actual_len);
2036*45039663SJohn Forte 	if (rc) {
2037*45039663SJohn Forte 		return (NULL);
2038*45039663SJohn Forte 	}
2039*45039663SJohn Forte 
2040*45039663SJohn Forte 	if (len != actual_len) {
2041*45039663SJohn Forte 		cmn_err(CE_WARN,
2042*45039663SJohn Forte 		    "stmf_ic_uint8_array_unmarshal: wrong len (%d != %d)",
2043*45039663SJohn Forte 		    len, actual_len);
2044*45039663SJohn Forte 		return (NULL);
2045*45039663SJohn Forte 	}
2046*45039663SJohn Forte 
2047*45039663SJohn Forte 	if (buf) {
2048*45039663SJohn Forte 		/* preallocated buf, copy in */
2049*45039663SJohn Forte 		bcopy(array, buf, len);
2050*45039663SJohn Forte 	} else {
2051*45039663SJohn Forte 		/* return a pointer to the underlying array in the nvlist */
2052*45039663SJohn Forte 		buf = array;
2053*45039663SJohn Forte 	}
2054*45039663SJohn Forte 
2055*45039663SJohn Forte 	return (buf);
2056*45039663SJohn Forte }
2057*45039663SJohn Forte 
2058*45039663SJohn Forte /*
2059*45039663SJohn Forte  * Unmarshal a string.
2060*45039663SJohn Forte  *
2061*45039663SJohn Forte  * Returns NULL on failure.
2062*45039663SJohn Forte  */
2063*45039663SJohn Forte static char *
2064*45039663SJohn Forte stmf_ic_string_unmarshal(
2065*45039663SJohn Forte     nvlist_t *nvl,
2066*45039663SJohn Forte     char *field_name)
2067*45039663SJohn Forte {
2068*45039663SJohn Forte 	char *s = NULL;
2069*45039663SJohn Forte 	int rc = 0;
2070*45039663SJohn Forte 
2071*45039663SJohn Forte 	rc = nvlist_lookup_string(nvl, field_name, &s);
2072*45039663SJohn Forte 	if (rc) {
2073*45039663SJohn Forte 		return (NULL);
2074*45039663SJohn Forte 	}
2075*45039663SJohn Forte 
2076*45039663SJohn Forte 	return (s);
2077*45039663SJohn Forte }
2078*45039663SJohn Forte 
2079*45039663SJohn Forte /*
2080*45039663SJohn Forte  * Utility routines.
2081*45039663SJohn Forte  */
2082*45039663SJohn Forte 
2083*45039663SJohn Forte static stmf_ic_msg_t *
2084*45039663SJohn Forte stmf_ic_alloc_msg_header(
2085*45039663SJohn Forte     stmf_ic_msg_type_t msg_type,
2086*45039663SJohn Forte     stmf_ic_msgid_t msgid)
2087*45039663SJohn Forte {
2088*45039663SJohn Forte 	stmf_ic_msg_t *icm;
2089*45039663SJohn Forte 
2090*45039663SJohn Forte 	icm = (stmf_ic_msg_t *)kmem_zalloc(sizeof (*icm), KM_SLEEP);
2091*45039663SJohn Forte 	icm->icm_msg_type = msg_type;
2092*45039663SJohn Forte 	icm->icm_msgid = msgid;
2093*45039663SJohn Forte 
2094*45039663SJohn Forte 	return (icm);
2095*45039663SJohn Forte }
2096*45039663SJohn Forte 
2097*45039663SJohn Forte static size_t
2098*45039663SJohn Forte sizeof_scsi_devid_desc(int ident_length)
2099*45039663SJohn Forte {
2100*45039663SJohn Forte 	int num_ident_elems;
2101*45039663SJohn Forte 	size_t size;
2102*45039663SJohn Forte 
2103*45039663SJohn Forte 	ASSERT(ident_length > 0);
2104*45039663SJohn Forte 
2105*45039663SJohn Forte 	/*
2106*45039663SJohn Forte 	 * Need to account for the fact that there's
2107*45039663SJohn Forte 	 * already a single element in scsi_devid_desc_t.
2108*45039663SJohn Forte 	 *
2109*45039663SJohn Forte 	 * XXX would really like to have a way to determine the
2110*45039663SJohn Forte 	 * sizeof (struct scsi_devid_desc.ident[0]), but
2111*45039663SJohn Forte 	 * it's not clear that can be done.
2112*45039663SJohn Forte 	 * Thus, this code relies on the knowledge of the type of
2113*45039663SJohn Forte 	 * that field.
2114*45039663SJohn Forte 	 */
2115*45039663SJohn Forte 	num_ident_elems = ident_length - 1;
2116*45039663SJohn Forte 	size = sizeof (scsi_devid_desc_t) +
2117*45039663SJohn Forte 	    (num_ident_elems * sizeof (uint8_t));
2118*45039663SJohn Forte 
2119*45039663SJohn Forte 	return (size);
2120*45039663SJohn Forte }
2121*45039663SJohn Forte 
2122*45039663SJohn Forte 
2123*45039663SJohn Forte /*
2124*45039663SJohn Forte  * Duplicate the scsi_devid_desc_t.
2125*45039663SJohn Forte  */
2126*45039663SJohn Forte static scsi_devid_desc_t *
2127*45039663SJohn Forte scsi_devid_desc_dup(scsi_devid_desc_t *did)
2128*45039663SJohn Forte {
2129*45039663SJohn Forte 	scsi_devid_desc_t *dup;
2130*45039663SJohn Forte 	size_t dup_size;
2131*45039663SJohn Forte 
2132*45039663SJohn Forte 	ASSERT(did->ident_length > 0);
2133*45039663SJohn Forte 
2134*45039663SJohn Forte 	dup_size = sizeof_scsi_devid_desc(did->ident_length);
2135*45039663SJohn Forte 	dup = (scsi_devid_desc_t *)kmem_zalloc(dup_size, KM_SLEEP);
2136*45039663SJohn Forte 	bcopy(did, dup, dup_size);
2137*45039663SJohn Forte 	return (dup);
2138*45039663SJohn Forte }
2139*45039663SJohn Forte 
2140*45039663SJohn Forte /*
2141*45039663SJohn Forte  * May be called with a null pointer.
2142*45039663SJohn Forte  */
2143*45039663SJohn Forte static void
2144*45039663SJohn Forte scsi_devid_desc_free(scsi_devid_desc_t *did)
2145*45039663SJohn Forte {
2146*45039663SJohn Forte 	if (!did)
2147*45039663SJohn Forte 		return;
2148*45039663SJohn Forte 
2149*45039663SJohn Forte 	kmem_free(did, sizeof_scsi_devid_desc(did->ident_length));
2150*45039663SJohn Forte }
2151*45039663SJohn Forte 
2152*45039663SJohn Forte /*
2153*45039663SJohn Forte  * Helper functions, returns NULL if no memory.
2154*45039663SJohn Forte  */
2155*45039663SJohn Forte static char *
2156*45039663SJohn Forte stmf_ic_strdup(char *str)
2157*45039663SJohn Forte {
2158*45039663SJohn Forte 	char *copy;
2159*45039663SJohn Forte 
2160*45039663SJohn Forte 	ASSERT(str);
2161*45039663SJohn Forte 
2162*45039663SJohn Forte 	copy = kmem_zalloc(strlen(str) + 1, KM_SLEEP);
2163*45039663SJohn Forte 	(void) strcpy(copy, str);
2164*45039663SJohn Forte 	return (copy);
2165*45039663SJohn Forte }
2166*45039663SJohn Forte 
2167*45039663SJohn Forte static inline void
2168*45039663SJohn Forte stmf_ic_nvlookup_warn(const char *func, char *field)
2169*45039663SJohn Forte {
2170*45039663SJohn Forte 	cmn_err(CE_WARN, "%s: nvlist lookup of %s failed", func, field);
2171*45039663SJohn Forte }
2172