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