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