xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/ulp/fcp.c (revision bde334a8dbd66dfa70ce4d7fc9dcad6e1ae45fe4)
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) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23  *
24  * Fibre Channel SCSI ULP Mapping driver
25  */
26 
27 #include <sys/scsi/scsi.h>
28 #include <sys/types.h>
29 #include <sys/varargs.h>
30 #include <sys/devctl.h>
31 #include <sys/thread.h>
32 #include <sys/thread.h>
33 #include <sys/open.h>
34 #include <sys/file.h>
35 #include <sys/sunndi.h>
36 #include <sys/console.h>
37 #include <sys/proc.h>
38 #include <sys/time.h>
39 #include <sys/utsname.h>
40 #include <sys/scsi/impl/scsi_reset_notify.h>
41 #include <sys/ndi_impldefs.h>
42 #include <sys/byteorder.h>
43 #include <sys/fs/dv_node.h>
44 #include <sys/ctype.h>
45 #include <sys/sunmdi.h>
46 
47 #include <sys/fibre-channel/fc.h>
48 #include <sys/fibre-channel/impl/fc_ulpif.h>
49 #include <sys/fibre-channel/ulp/fcpvar.h>
50 
51 /*
52  * Discovery Process
53  * =================
54  *
55  *    The discovery process is a major function of FCP.	 In order to help
56  * understand that function a flow diagram is given here.  This diagram
57  * doesn't claim to cover all the cases and the events that can occur during
58  * the discovery process nor the subtleties of the code.  The code paths shown
59  * are simplified.  Its purpose is to help the reader (and potentially bug
60  * fixer) have an overall view of the logic of the code.  For that reason the
61  * diagram covers the simple case of the line coming up cleanly or of a new
62  * port attaching to FCP the link being up.  The reader must keep in mind
63  * that:
64  *
65  *	- There are special cases where bringing devices online and offline
66  *	  is driven by Ioctl.
67  *
68  *	- The behavior of the discovery process can be modified through the
69  *	  .conf file.
70  *
71  *	- The line can go down and come back up at any time during the
72  *	  discovery process which explains some of the complexity of the code.
73  *
74  * ............................................................................
75  *
76  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
77  *
78  *
79  *			+-------------------------+
80  *   fp/fctl module --->|    fcp_port_attach	  |
81  *			+-------------------------+
82  *	   |			     |
83  *	   |			     |
84  *	   |			     v
85  *	   |		+-------------------------+
86  *	   |		| fcp_handle_port_attach  |
87  *	   |		+-------------------------+
88  *	   |				|
89  *	   |				|
90  *	   +--------------------+	|
91  *				|	|
92  *				v	v
93  *			+-------------------------+
94  *			|   fcp_statec_callback	  |
95  *			+-------------------------+
96  *				    |
97  *				    |
98  *				    v
99  *			+-------------------------+
100  *			|    fcp_handle_devices	  |
101  *			+-------------------------+
102  *				    |
103  *				    |
104  *				    v
105  *			+-------------------------+
106  *			|   fcp_handle_mapflags	  |
107  *			+-------------------------+
108  *				    |
109  *				    |
110  *				    v
111  *			+-------------------------+
112  *			|     fcp_send_els	  |
113  *			|			  |
114  *			| PLOGI or PRLI To all the|
115  *			| reachable devices.	  |
116  *			+-------------------------+
117  *
118  *
119  * ............................................................................
120  *
121  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
122  *	   STEP 1 are called (it is actually the same function).
123  *
124  *
125  *			+-------------------------+
126  *			|    fcp_icmd_callback	  |
127  *   fp/fctl module --->|			  |
128  *			| callback for PLOGI and  |
129  *			| PRLI.			  |
130  *			+-------------------------+
131  *				     |
132  *				     |
133  *	    Received PLOGI Accept   /-\	  Received PRLI Accept
134  *		       _ _ _ _ _ _ /   \_ _ _ _ _ _
135  *		      |		   \   /	   |
136  *		      |		    \-/		   |
137  *		      |				   |
138  *		      v				   v
139  *	+-------------------------+	+-------------------------+
140  *	|     fcp_send_els	  |	|     fcp_send_scsi	  |
141  *	|			  |	|			  |
142  *	|	  PRLI		  |	|	REPORT_LUN	  |
143  *	+-------------------------+	+-------------------------+
144  *
145  * ............................................................................
146  *
147  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
148  *	   (It is actually the same function).
149  *
150  *
151  *			    +-------------------------+
152  *   fp/fctl module ------->|	 fcp_scsi_callback    |
153  *			    +-------------------------+
154  *					|
155  *					|
156  *					|
157  *	Receive REPORT_LUN reply       /-\	Receive INQUIRY PAGE83 reply
158  *		  _ _ _ _ _ _ _ _ _ _ /	  \_ _ _ _ _ _ _ _ _ _ _ _
159  *		 |		      \	  /			  |
160  *		 |		       \-/			  |
161  *		 |			|			  |
162  *		 | Receive INQUIRY reply|			  |
163  *		 |			|			  |
164  *		 v			v			  v
165  * +------------------------+ +----------------------+ +----------------------+
166  * |  fcp_handle_reportlun  | |	 fcp_handle_inquiry  | |  fcp_handle_page83   |
167  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
168  * +------------------------+ +----------------------+ +----------------------+
169  *		 |			|			  |
170  *		 |			|			  |
171  *		 |			|			  |
172  *		 v			v			  |
173  *     +-----------------+	+-----------------+		  |
174  *     |  fcp_send_scsi	 |	|  fcp_send_scsi  |		  |
175  *     |		 |	|		  |		  |
176  *     |     INQUIRY	 |	| INQUIRY PAGE83  |		  |
177  *     |  (To each LUN)	 |	+-----------------+		  |
178  *     +-----------------+					  |
179  *								  |
180  *								  v
181  *						      +------------------------+
182  *						      |	 fcp_call_finish_init  |
183  *						      +------------------------+
184  *								  |
185  *								  v
186  *						 +-----------------------------+
187  *						 |  fcp_call_finish_init_held  |
188  *						 +-----------------------------+
189  *								  |
190  *								  |
191  *			   All LUNs scanned			 /-\
192  *			       _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
193  *			      |					\   /
194  *			      |					 \-/
195  *			      v					  |
196  *		     +------------------+			  |
197  *		     |	fcp_finish_tgt	|			  |
198  *		     +------------------+			  |
199  *			      |	  Target Not Offline and	  |
200  *  Target Not Offline and    |	  not marked and tgt_node_state	  |
201  *  marked		     /-\  not FCP_TGT_NODE_ON_DEMAND	  |
202  *		_ _ _ _ _ _ /	\_ _ _ _ _ _ _ _		  |
203  *	       |	    \	/		|		  |
204  *	       |	     \-/		|		  |
205  *	       v				v		  |
206  * +----------------------------+     +-------------------+	  |
207  * |	 fcp_offline_target	|     |	 fcp_create_luns  |	  |
208  * |				|     +-------------------+	  |
209  * | A structure fcp_tgt_elem	|		|		  |
210  * | is created and queued in	|		v		  |
211  * | the FCP port list		|     +-------------------+	  |
212  * | port_offline_tgts.	 It	|     |	 fcp_pass_to_hp	  |	  |
213  * | will be unqueued by the	|     |			  |	  |
214  * | watchdog timer.		|     | Called for each	  |	  |
215  * +----------------------------+     | LUN. Dispatches	  |	  |
216  *		  |		      | fcp_hp_task	  |	  |
217  *		  |		      +-------------------+	  |
218  *		  |				|		  |
219  *		  |				|		  |
220  *		  |				|		  |
221  *		  |				+---------------->|
222  *		  |						  |
223  *		  +---------------------------------------------->|
224  *								  |
225  *								  |
226  *		All the targets (devices) have been scanned	 /-\
227  *				_ _ _ _	_ _ _ _	_ _ _ _ _ _ _ _ /   \
228  *			       |				\   /
229  *			       |				 \-/
230  *	    +-------------------------------------+		  |
231  *	    |		fcp_finish_init		  |		  |
232  *	    |					  |		  |
233  *	    | Signal broadcasts the condition	  |		  |
234  *	    | variable port_config_cv of the FCP  |		  |
235  *	    | port.  One potential code sequence  |		  |
236  *	    | waiting on the condition variable	  |		  |
237  *	    | the code sequence handling	  |		  |
238  *	    | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|		  |
239  *	    | The other is in the function	  |		  |
240  *	    | fcp_reconfig_wait which is called	  |		  |
241  *	    | in the transmit path preventing IOs |		  |
242  *	    | from going through till the disco-  |		  |
243  *	    | very process is over.		  |		  |
244  *	    +-------------------------------------+		  |
245  *			       |				  |
246  *			       |				  |
247  *			       +--------------------------------->|
248  *								  |
249  *								  v
250  *								Return
251  *
252  * ............................................................................
253  *
254  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
255  *
256  *
257  *			+-------------------------+
258  *			|      fcp_hp_task	  |
259  *			+-------------------------+
260  *				     |
261  *				     |
262  *				     v
263  *			+-------------------------+
264  *			|     fcp_trigger_lun	  |
265  *			+-------------------------+
266  *				     |
267  *				     |
268  *				     v
269  *		   Bring offline    /-\	 Bring online
270  *		  _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
271  *		 |		   \   /		   |
272  *		 |		    \-/			   |
273  *		 v					   v
274  *    +---------------------+			+-----------------------+
275  *    |	 fcp_offline_child  |			|      fcp_get_cip	|
276  *    +---------------------+			|			|
277  *						| Creates a dev_info_t	|
278  *						| or a mdi_pathinfo_t	|
279  *						| depending on whether	|
280  *						| mpxio is on or off.	|
281  *						+-----------------------+
282  *							   |
283  *							   |
284  *							   v
285  *						+-----------------------+
286  *						|  fcp_online_child	|
287  *						|			|
288  *						| Set device online	|
289  *						| using NDI or MDI.	|
290  *						+-----------------------+
291  *
292  * ............................................................................
293  *
294  * STEP 5: The watchdog timer expires.	The watch dog timer does much more that
295  *	   what is described here.  We only show the target offline path.
296  *
297  *
298  *			 +--------------------------+
299  *			 |	  fcp_watch	    |
300  *			 +--------------------------+
301  *				       |
302  *				       |
303  *				       v
304  *			 +--------------------------+
305  *			 |  fcp_scan_offline_tgts   |
306  *			 +--------------------------+
307  *				       |
308  *				       |
309  *				       v
310  *			 +--------------------------+
311  *			 |  fcp_offline_target_now  |
312  *			 +--------------------------+
313  *				       |
314  *				       |
315  *				       v
316  *			 +--------------------------+
317  *			 |   fcp_offline_tgt_luns   |
318  *			 +--------------------------+
319  *				       |
320  *				       |
321  *				       v
322  *			 +--------------------------+
323  *			 |     fcp_offline_lun	    |
324  *			 +--------------------------+
325  *				       |
326  *				       |
327  *				       v
328  *		     +----------------------------------+
329  *		     |	     fcp_offline_lun_now	|
330  *		     |					|
331  *		     | A request (or two if mpxio) is	|
332  *		     | sent to the hot plug task using	|
333  *		     | a fcp_hp_elem structure.		|
334  *		     +----------------------------------+
335  */
336 
337 /*
338  * Functions registered with DDI framework
339  */
340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
345     cred_t *credp, int *rval);
346 
347 /*
348  * Functions registered with FC Transport framework
349  */
350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
351     fc_attach_cmd_t cmd,  uint32_t s_id);
352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
353     fc_detach_cmd_t cmd);
354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
355     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
356     uint32_t claimed);
357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
358     fc_unsol_buf_t *buf, uint32_t claimed);
359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
360     fc_unsol_buf_t *buf, uint32_t claimed);
361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
362     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
363     uint32_t  dev_cnt, uint32_t port_sid);
364 
365 /*
366  * Functions registered with SCSA framework
367  */
368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
369     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
371     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
373     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
376 static int fcp_scsi_reset(struct scsi_address *ap, int level);
377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
379     int whom);
380 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
382     void (*callback)(caddr_t), caddr_t arg);
383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
384     char *name, ddi_eventcookie_t *event_cookiep);
385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
386     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
387     ddi_callback_id_t *cb_id);
388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
389     ddi_callback_id_t cb_id);
390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
391     ddi_eventcookie_t eventid, void *impldata);
392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
393     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
395     ddi_bus_config_op_t op, void *arg);
396 
397 /*
398  * Internal functions
399  */
400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
401     int mode, int *rval);
402 
403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
404     int mode, int *rval);
405 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
406     struct fcp_scsi_cmd *fscsi, int mode);
407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
408     caddr_t base_addr, int mode);
409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
410 
411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
412     la_wwn_t *pwwn, int	*ret_val, int *fc_status, int *fc_pkt_state,
413     int *fc_pkt_reason, int *fc_pkt_action);
414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
415     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
416 static int fcp_tgt_send_prli(struct fcp_tgt	*ptgt, int *fc_status,
417     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
422 
423 static void fcp_handle_devices(struct fcp_port *pptr,
424     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
425     fcp_map_tag_t *map_tag, int cause);
426 static int fcp_handle_mapflags(struct fcp_port *pptr,
427     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
428     int tgt_cnt, int cause);
429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
431     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
433     int cause);
434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
435     uint32_t state);
436 static struct fcp_port *fcp_get_port(opaque_t port_handle);
437 static void fcp_unsol_callback(fc_packet_t *fpkt);
438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
439     uchar_t r_ctl, uchar_t type);
440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
442     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
443     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
446     int nodma, int flags);
447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
449     uchar_t *wwn);
450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
451     uint32_t d_id);
452 static void fcp_icmd_callback(fc_packet_t *fpkt);
453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
454     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
456 static void fcp_scsi_callback(fc_packet_t *fpkt);
457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
461     uint16_t lun_num);
462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
463     int link_cnt, int tgt_cnt, int cause);
464 static void fcp_finish_init(struct fcp_port *pptr);
465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
466     int tgt_cnt, int cause);
467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
468     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
470     int link_cnt, int tgt_cnt, int nowait, int flags);
471 static void fcp_offline_target_now(struct fcp_port *pptr,
472     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
474     int tgt_cnt, int flags);
475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
476     int nowait, int flags);
477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
478     int tgt_cnt);
479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
480     int tgt_cnt, int flags);
481 static void fcp_scan_offline_luns(struct fcp_port *pptr);
482 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
483 static void fcp_update_offline_flags(struct fcp_lun *plun);
484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
485 static void fcp_abort_commands(struct fcp_pkt *head, struct
486     fcp_port *pptr);
487 static void fcp_cmd_callback(fc_packet_t *fpkt);
488 static void fcp_complete_pkt(fc_packet_t *fpkt);
489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
490     struct fcp_port *pptr);
491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
492     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
494 static void fcp_dealloc_lun(struct fcp_lun *plun);
495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
496     fc_portmap_t *map_entry, int link_cnt);
497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
500     int internal);
501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
503     uint32_t s_id, int instance);
504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
505     int instance);
506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
508     int);
509 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
512     int flags);
513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
514 static int fcp_reset_target(struct scsi_address *ap, int level);
515 static int fcp_commoncap(struct scsi_address *ap, char *cap,
516     int val, int tgtonly, int doset);
517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
520     int sleep);
521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
522     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
526     int lcount, int tcount);
527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
530     int tgt_cnt);
531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
532     dev_info_t *pdip, caddr_t name);
533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
534     int lcount, int tcount, int flags, int *circ);
535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
536     int lcount, int tcount, int flags, int *circ);
537 static void fcp_remove_child(struct fcp_lun *plun);
538 static void fcp_watch(void *arg);
539 static void fcp_check_reset_delay(struct fcp_port *pptr);
540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
541     struct fcp_lun *rlun, int tgt_cnt);
542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
544     uchar_t *wwn, uint16_t lun);
545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
546     struct fcp_lun *plun);
547 static void fcp_post_callback(struct fcp_pkt *cmd);
548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
549 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
551     child_info_t *cip);
552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
553     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
554     int tgt_cnt, int flags);
555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
556     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
557     int tgt_cnt, int flags, int wait);
558 static void fcp_retransport_cmd(struct fcp_port *pptr,
559     struct fcp_pkt *cmd);
560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
561     uint_t statistics);
562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
563 static void fcp_update_targets(struct fcp_port *pptr,
564     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
565 static int fcp_call_finish_init(struct fcp_port *pptr,
566     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
567 static int fcp_call_finish_init_held(struct fcp_port *pptr,
568     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
569 static void fcp_reconfigure_luns(void * tgt_handle);
570 static void fcp_free_targets(struct fcp_port *pptr);
571 static void fcp_free_target(struct fcp_tgt *ptgt);
572 static int fcp_is_retryable(struct fcp_ipkt *icmd);
573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
576 static void fcp_print_error(fc_packet_t *fpkt);
577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
578     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
581     uint32_t *dev_cnt);
582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
585     struct fcp_ioctl *, struct fcp_port **);
586 static char *fcp_get_lun_path(struct fcp_lun *plun);
587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
588     int *rval);
589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
591 static char *fcp_get_lun_path(struct fcp_lun *plun);
592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
593     int *rval);
594 static void fcp_reconfig_wait(struct fcp_port *pptr);
595 
596 /*
597  * New functions added for mpxio support
598  */
599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
600     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
602     int tcount);
603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
604     dev_info_t *pdip);
605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
610     int what);
611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
612     fc_packet_t *fpkt);
613 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
614 
615 /*
616  * New functions added for lun masking support
617  */
618 static void fcp_read_blacklist(dev_info_t *dip,
619     struct fcp_black_list_entry **pplun_blacklist);
620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
621     struct fcp_black_list_entry **pplun_blacklist);
622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
623     struct fcp_black_list_entry **pplun_blacklist);
624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
626 
627 /*
628  * New functions to support software FCA (like fcoei)
629  */
630 static struct scsi_pkt *fcp_pseudo_init_pkt(
631 	struct scsi_address *ap, struct scsi_pkt *pkt,
632 	struct buf *bp, int cmdlen, int statuslen,
633 	int tgtlen, int flags, int (*callback)(), caddr_t arg);
634 static void fcp_pseudo_destroy_pkt(
635 	struct scsi_address *ap, struct scsi_pkt *pkt);
636 static void fcp_pseudo_sync_pkt(
637 	struct scsi_address *ap, struct scsi_pkt *pkt);
638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
639 static void fcp_pseudo_dmafree(
640 	struct scsi_address *ap, struct scsi_pkt *pkt);
641 
642 extern struct mod_ops	mod_driverops;
643 /*
644  * This variable is defined in modctl.c and set to '1' after the root driver
645  * and fs are loaded.  It serves as an indication that the root filesystem can
646  * be used.
647  */
648 extern int		modrootloaded;
649 /*
650  * This table contains strings associated with the SCSI sense key codes.  It
651  * is used by FCP to print a clear explanation of the code returned in the
652  * sense information by a device.
653  */
654 extern char		*sense_keys[];
655 /*
656  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
657  * under this device that the paths to a physical device are created when
658  * MPxIO is used.
659  */
660 extern dev_info_t	*scsi_vhci_dip;
661 
662 /*
663  * Report lun processing
664  */
665 #define	FCP_LUN_ADDRESSING		0x80
666 #define	FCP_PD_ADDRESSING		0x00
667 #define	FCP_VOLUME_ADDRESSING		0x40
668 
669 #define	FCP_SVE_THROTTLE		0x28 /* Vicom */
670 #define	MAX_INT_DMA			0x7fffffff
671 /*
672  * Property definitions
673  */
674 #define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
675 #define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
676 #define	TARGET_PROP	(char *)fcp_target_prop
677 #define	LUN_PROP	(char *)fcp_lun_prop
678 #define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
679 #define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
680 #define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
681 #define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
682 #define	INIT_PORT_PROP	(char *)fcp_init_port_prop
683 #define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
684 #define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
685 /*
686  * Short hand macros.
687  */
688 #define	LUN_PORT	(plun->lun_tgt->tgt_port)
689 #define	LUN_TGT		(plun->lun_tgt)
690 
691 /*
692  * Driver private macros
693  */
694 #define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
695 			((x) >= 'a' && (x) <= 'f') ?			\
696 			((x) - 'a' + 10) : ((x) - 'A' + 10))
697 
698 #define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
699 
700 #define	FCP_N_NDI_EVENTS						\
701 	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
702 
703 #define	FCP_LINK_STATE_CHANGED(p, c)			\
704 	((p)->port_link_cnt != (c)->ipkt_link_cnt)
705 
706 #define	FCP_TGT_STATE_CHANGED(t, c)			\
707 	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
708 
709 #define	FCP_STATE_CHANGED(p, t, c)		\
710 	(FCP_TGT_STATE_CHANGED(t, c))
711 
712 #define	FCP_MUST_RETRY(fpkt)				\
713 	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
714 	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
715 	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
716 	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
717 	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
718 	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
719 	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
720 	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
721 
722 #define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
723 	((es)->es_key == KEY_UNIT_ATTENTION &&	\
724 	(es)->es_add_code == 0x3f &&		\
725 	(es)->es_qual_code == 0x0e)
726 
727 #define	FCP_SENSE_NO_LUN(es)			\
728 	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
729 	(es)->es_add_code == 0x25 &&		\
730 	(es)->es_qual_code == 0x0)
731 
732 #define	FCP_VERSION		"20091208-1.192"
733 #define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
734 
735 #define	FCP_NUM_ELEMENTS(array)			\
736 	(sizeof (array) / sizeof ((array)[0]))
737 
738 /*
739  * Debugging, Error reporting, and tracing
740  */
741 #define	FCP_LOG_SIZE		1024 * 1024
742 
743 #define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
744 #define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
745 #define	FCP_LEVEL_3		0x00004		/* state change, discovery */
746 #define	FCP_LEVEL_4		0x00008		/* ULP messages */
747 #define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
748 #define	FCP_LEVEL_6		0x00020		/* Transport failures */
749 #define	FCP_LEVEL_7		0x00040
750 #define	FCP_LEVEL_8		0x00080		/* I/O tracing */
751 #define	FCP_LEVEL_9		0x00100		/* I/O tracing */
752 
753 
754 
755 /*
756  * Log contents to system messages file
757  */
758 #define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
759 #define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
760 #define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
761 #define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
762 #define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
763 #define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
764 #define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
765 #define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
766 #define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
767 
768 
769 /*
770  * Log contents to trace buffer
771  */
772 #define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
773 #define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
774 #define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
775 #define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
776 #define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
777 #define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
778 #define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
779 #define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
780 #define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
781 
782 
783 /*
784  * Log contents to both system messages file and trace buffer
785  */
786 #define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
787 				FC_TRACE_LOG_MSG)
788 #define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
789 				FC_TRACE_LOG_MSG)
790 #define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
791 				FC_TRACE_LOG_MSG)
792 #define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
793 				FC_TRACE_LOG_MSG)
794 #define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
795 				FC_TRACE_LOG_MSG)
796 #define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
797 				FC_TRACE_LOG_MSG)
798 #define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
799 				FC_TRACE_LOG_MSG)
800 #define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
801 				FC_TRACE_LOG_MSG)
802 #define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
803 				FC_TRACE_LOG_MSG)
804 #ifdef DEBUG
805 #define	FCP_DTRACE	fc_trace_debug
806 #else
807 #define	FCP_DTRACE
808 #endif
809 
810 #define	FCP_TRACE	fc_trace_debug
811 
812 static struct cb_ops fcp_cb_ops = {
813 	fcp_open,			/* open */
814 	fcp_close,			/* close */
815 	nodev,				/* strategy */
816 	nodev,				/* print */
817 	nodev,				/* dump */
818 	nodev,				/* read */
819 	nodev,				/* write */
820 	fcp_ioctl,			/* ioctl */
821 	nodev,				/* devmap */
822 	nodev,				/* mmap */
823 	nodev,				/* segmap */
824 	nochpoll,			/* chpoll */
825 	ddi_prop_op,			/* cb_prop_op */
826 	0,				/* streamtab */
827 	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
828 	CB_REV,				/* rev */
829 	nodev,				/* aread */
830 	nodev				/* awrite */
831 };
832 
833 
834 static struct dev_ops fcp_ops = {
835 	DEVO_REV,
836 	0,
837 	ddi_getinfo_1to1,
838 	nulldev,		/* identify */
839 	nulldev,		/* probe */
840 	fcp_attach,		/* attach and detach are mandatory */
841 	fcp_detach,
842 	nodev,			/* reset */
843 	&fcp_cb_ops,		/* cb_ops */
844 	NULL,			/* bus_ops */
845 	NULL,			/* power */
846 };
847 
848 
849 char *fcp_version = FCP_NAME_VERSION;
850 
851 static struct modldrv modldrv = {
852 	&mod_driverops,
853 	FCP_NAME_VERSION,
854 	&fcp_ops
855 };
856 
857 
858 static struct modlinkage modlinkage = {
859 	MODREV_1,
860 	&modldrv,
861 	NULL
862 };
863 
864 
865 static fc_ulp_modinfo_t fcp_modinfo = {
866 	&fcp_modinfo,			/* ulp_handle */
867 	FCTL_ULP_MODREV_4,		/* ulp_rev */
868 	FC4_SCSI_FCP,			/* ulp_type */
869 	"fcp",				/* ulp_name */
870 	FCP_STATEC_MASK,		/* ulp_statec_mask */
871 	fcp_port_attach,		/* ulp_port_attach */
872 	fcp_port_detach,		/* ulp_port_detach */
873 	fcp_port_ioctl,			/* ulp_port_ioctl */
874 	fcp_els_callback,		/* ulp_els_callback */
875 	fcp_data_callback,		/* ulp_data_callback */
876 	fcp_statec_callback		/* ulp_statec_callback */
877 };
878 
879 #ifdef	DEBUG
880 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
881 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
882 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
883 				FCP_LEVEL_6 | FCP_LEVEL_7)
884 #else
885 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
886 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
887 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
888 				FCP_LEVEL_6 | FCP_LEVEL_7)
889 #endif
890 
891 /* FCP global variables */
892 int			fcp_bus_config_debug = 0;
893 static int		fcp_log_size = FCP_LOG_SIZE;
894 static int		fcp_trace = FCP_TRACE_DEFAULT;
895 static fc_trace_logq_t	*fcp_logq = NULL;
896 static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
897 /*
898  * The auto-configuration is set by default.  The only way of disabling it is
899  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
900  */
901 static int		fcp_enable_auto_configuration = 1;
902 static int		fcp_max_bus_config_retries	= 4;
903 static int		fcp_lun_ready_retry = 300;
904 /*
905  * The value assigned to the following variable has changed several times due
906  * to a problem with the data underruns reporting of some firmware(s).	The
907  * current value of 50 gives a timeout value of 25 seconds for a max number
908  * of 256 LUNs.
909  */
910 static int		fcp_max_target_retries = 50;
911 /*
912  * Watchdog variables
913  * ------------------
914  *
915  * fcp_watchdog_init
916  *
917  *	Indicates if the watchdog timer is running or not.  This is actually
918  *	a counter of the number of Fibre Channel ports that attached.  When
919  *	the first port attaches the watchdog is started.  When the last port
920  *	detaches the watchdog timer is stopped.
921  *
922  * fcp_watchdog_time
923  *
924  *	This is the watchdog clock counter.  It is incremented by
925  *	fcp_watchdog_time each time the watchdog timer expires.
926  *
927  * fcp_watchdog_timeout
928  *
929  *	Increment value of the variable fcp_watchdog_time as well as the
930  *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
931  *	is strange that this is not a #define	but a variable since the code
932  *	never changes this value.  The reason why it can be said that the
933  *	unit is 1 second is because the number of ticks for the watchdog
934  *	timer is determined like this:
935  *
936  *	    fcp_watchdog_tick = fcp_watchdog_timeout *
937  *				  drv_usectohz(1000000);
938  *
939  *	The value 1000000 is hard coded in the code.
940  *
941  * fcp_watchdog_tick
942  *
943  *	Watchdog timer value in ticks.
944  */
945 static int		fcp_watchdog_init = 0;
946 static int		fcp_watchdog_time = 0;
947 static int		fcp_watchdog_timeout = 1;
948 static int		fcp_watchdog_tick;
949 
950 /*
951  * fcp_offline_delay is a global variable to enable customisation of
952  * the timeout on link offlines or RSCNs. The default value is set
953  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
954  * specified in FCP4 Chapter 11 (see www.t10.org).
955  *
956  * The variable fcp_offline_delay is specified in SECONDS.
957  *
958  * If we made this a static var then the user would not be able to
959  * change it. This variable is set in fcp_attach().
960  */
961 unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
962 
963 static void		*fcp_softstate = NULL; /* for soft state */
964 static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
965 static kmutex_t		fcp_global_mutex;
966 static kmutex_t		fcp_ioctl_mutex;
967 static dev_info_t	*fcp_global_dip = NULL;
968 static timeout_id_t	fcp_watchdog_id;
969 const char		*fcp_lun_prop = "lun";
970 const char		*fcp_sam_lun_prop = "sam-lun";
971 const char		*fcp_target_prop = "target";
972 /*
973  * NOTE: consumers of "node-wwn" property include stmsboot in ON
974  * consolidation.
975  */
976 const char		*fcp_node_wwn_prop = "node-wwn";
977 const char		*fcp_port_wwn_prop = "port-wwn";
978 const char		*fcp_conf_wwn_prop = "fc-port-wwn";
979 const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
980 const char		*fcp_manual_config_only = "manual_configuration_only";
981 const char		*fcp_init_port_prop = "initiator-port";
982 const char		*fcp_tgt_port_prop = "target-port";
983 const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
984 
985 static struct fcp_port	*fcp_port_head = NULL;
986 static ddi_eventcookie_t	fcp_insert_eid;
987 static ddi_eventcookie_t	fcp_remove_eid;
988 
989 static ndi_event_definition_t	fcp_ndi_event_defs[] = {
990 	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
991 	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
992 };
993 
994 /*
995  * List of valid commands for the scsi_ioctl call
996  */
997 static uint8_t scsi_ioctl_list[] = {
998 	SCMD_INQUIRY,
999 	SCMD_REPORT_LUN,
1000 	SCMD_READ_CAPACITY
1001 };
1002 
1003 /*
1004  * this is used to dummy up a report lun response for cases
1005  * where the target doesn't support it
1006  */
1007 static uchar_t fcp_dummy_lun[] = {
1008 	0x00,		/* MSB length (length = no of luns * 8) */
1009 	0x00,
1010 	0x00,
1011 	0x08,		/* LSB length */
1012 	0x00,		/* MSB reserved */
1013 	0x00,
1014 	0x00,
1015 	0x00,		/* LSB reserved */
1016 	FCP_PD_ADDRESSING,
1017 	0x00,		/* LUN is ZERO at the first level */
1018 	0x00,
1019 	0x00,		/* second level is zero */
1020 	0x00,
1021 	0x00,		/* third level is zero */
1022 	0x00,
1023 	0x00		/* fourth level is zero */
1024 };
1025 
1026 static uchar_t fcp_alpa_to_switch[] = {
1027 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1028 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1029 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1030 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1031 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1032 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1033 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1034 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1035 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1036 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1037 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1038 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1039 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1040 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1041 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1043 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1044 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1045 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1046 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1047 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1048 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1049 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1050 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051 };
1052 
1053 static caddr_t pid = "SESS01	      ";
1054 
1055 #if	!defined(lint)
1056 
1057 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1058     fcp_port::fcp_next fcp_watchdog_id))
1059 
1060 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1061 
1062 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1063     fcp_insert_eid
1064     fcp_remove_eid
1065     fcp_watchdog_time))
1066 
1067 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1068     fcp_cb_ops
1069     fcp_ops
1070     callb_cpr))
1071 
1072 #endif /* lint */
1073 
1074 /*
1075  * This table is used to determine whether or not it's safe to copy in
1076  * the target node name for a lun.  Since all luns behind the same target
1077  * have the same wwnn, only tagets that do not support multiple luns are
1078  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1079  */
1080 
1081 char *fcp_symmetric_disk_table[] = {
1082 	"SEAGATE ST",
1083 	"IBM	 DDYFT",
1084 	"SUNW	 SUNWGS",	/* Daktari enclosure */
1085 	"SUN	 SENA",		/* SES device */
1086 	"SUN	 SESS01"	/* VICOM SVE box */
1087 };
1088 
1089 int fcp_symmetric_disk_table_size =
1090 	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1091 
1092 /*
1093  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1094  * will panic if you don't pass this in to the routine, this information.
1095  * Need to determine what the actual impact to the system is by providing
1096  * this information if any. Since dma allocation is done in pkt_init it may
1097  * not have any impact. These values are straight from the Writing Device
1098  * Driver manual.
1099  */
1100 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1101 	DMA_ATTR_V0,	/* ddi_dma_attr version */
1102 	0,		/* low address */
1103 	0xffffffff,	/* high address */
1104 	0x00ffffff,	/* counter upper bound */
1105 	1,		/* alignment requirements */
1106 	0x3f,		/* burst sizes */
1107 	1,		/* minimum DMA access */
1108 	0xffffffff,	/* maximum DMA access */
1109 	(1 << 24) - 1,	/* segment boundary restrictions */
1110 	1,		/* scater/gather list length */
1111 	512,		/* device granularity */
1112 	0		/* DMA flags */
1113 };
1114 
1115 /*
1116  * The _init(9e) return value should be that of mod_install(9f). Under
1117  * some circumstances, a failure may not be related mod_install(9f) and
1118  * one would then require a return value to indicate the failure. Looking
1119  * at mod_install(9f), it is expected to return 0 for success and non-zero
1120  * for failure. mod_install(9f) for device drivers, further goes down the
1121  * calling chain and ends up in ddi_installdrv(), whose return values are
1122  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1123  * calling chain of mod_install(9f) which return values like EINVAL and
1124  * in some even return -1.
1125  *
1126  * To work around the vagaries of the mod_install() calling chain, return
1127  * either 0 or ENODEV depending on the success or failure of mod_install()
1128  */
1129 int
1130 _init(void)
1131 {
1132 	int rval;
1133 
1134 	/*
1135 	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1136 	 * before registering with the transport first.
1137 	 */
1138 	if (ddi_soft_state_init(&fcp_softstate,
1139 	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1140 		return (EINVAL);
1141 	}
1142 
1143 	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1144 	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1145 
1146 	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1147 		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1148 		mutex_destroy(&fcp_global_mutex);
1149 		mutex_destroy(&fcp_ioctl_mutex);
1150 		ddi_soft_state_fini(&fcp_softstate);
1151 		return (ENODEV);
1152 	}
1153 
1154 	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1155 
1156 	if ((rval = mod_install(&modlinkage)) != 0) {
1157 		fc_trace_free_logq(fcp_logq);
1158 		(void) fc_ulp_remove(&fcp_modinfo);
1159 		mutex_destroy(&fcp_global_mutex);
1160 		mutex_destroy(&fcp_ioctl_mutex);
1161 		ddi_soft_state_fini(&fcp_softstate);
1162 		rval = ENODEV;
1163 	}
1164 
1165 	return (rval);
1166 }
1167 
1168 
1169 /*
1170  * the system is done with us as a driver, so clean up
1171  */
1172 int
1173 _fini(void)
1174 {
1175 	int rval;
1176 
1177 	/*
1178 	 * don't start cleaning up until we know that the module remove
1179 	 * has worked  -- if this works, then we know that each instance
1180 	 * has successfully been DDI_DETACHed
1181 	 */
1182 	if ((rval = mod_remove(&modlinkage)) != 0) {
1183 		return (rval);
1184 	}
1185 
1186 	(void) fc_ulp_remove(&fcp_modinfo);
1187 
1188 	ddi_soft_state_fini(&fcp_softstate);
1189 	mutex_destroy(&fcp_global_mutex);
1190 	mutex_destroy(&fcp_ioctl_mutex);
1191 	fc_trace_free_logq(fcp_logq);
1192 
1193 	return (rval);
1194 }
1195 
1196 
1197 int
1198 _info(struct modinfo *modinfop)
1199 {
1200 	return (mod_info(&modlinkage, modinfop));
1201 }
1202 
1203 
1204 /*
1205  * attach the module
1206  */
1207 static int
1208 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1209 {
1210 	int rval = DDI_SUCCESS;
1211 
1212 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1213 	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1214 
1215 	if (cmd == DDI_ATTACH) {
1216 		/* The FCP pseudo device is created here. */
1217 		mutex_enter(&fcp_global_mutex);
1218 		fcp_global_dip = devi;
1219 		mutex_exit(&fcp_global_mutex);
1220 
1221 		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1222 		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1223 			ddi_report_dev(fcp_global_dip);
1224 		} else {
1225 			cmn_err(CE_WARN, "FCP: Cannot create minor node");
1226 			mutex_enter(&fcp_global_mutex);
1227 			fcp_global_dip = NULL;
1228 			mutex_exit(&fcp_global_mutex);
1229 
1230 			rval = DDI_FAILURE;
1231 		}
1232 		/*
1233 		 * We check the fcp_offline_delay property at this
1234 		 * point. This variable is global for the driver,
1235 		 * not specific to an instance.
1236 		 *
1237 		 * We do not recommend setting the value to less
1238 		 * than 10 seconds (RA_TOV_els), or greater than
1239 		 * 60 seconds.
1240 		 */
1241 		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1242 		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1243 		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
1244 		if ((fcp_offline_delay < 10) ||
1245 		    (fcp_offline_delay > 60)) {
1246 			cmn_err(CE_WARN, "Setting fcp_offline_delay "
1247 			    "to %d second(s). This is outside the "
1248 			    "recommended range of 10..60 seconds.",
1249 			    fcp_offline_delay);
1250 		}
1251 	}
1252 
1253 	return (rval);
1254 }
1255 
1256 
1257 /*ARGSUSED*/
1258 static int
1259 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1260 {
1261 	int	res = DDI_SUCCESS;
1262 
1263 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1264 	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
1265 
1266 	if (cmd == DDI_DETACH) {
1267 		/*
1268 		 * Check if there are active ports/threads. If there
1269 		 * are any, we will fail, else we will succeed (there
1270 		 * should not be much to clean up)
1271 		 */
1272 		mutex_enter(&fcp_global_mutex);
1273 		FCP_DTRACE(fcp_logq, "fcp",
1274 		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1275 		    (void *) fcp_port_head);
1276 
1277 		if (fcp_port_head == NULL) {
1278 			ddi_remove_minor_node(fcp_global_dip, NULL);
1279 			fcp_global_dip = NULL;
1280 			mutex_exit(&fcp_global_mutex);
1281 		} else {
1282 			mutex_exit(&fcp_global_mutex);
1283 			res = DDI_FAILURE;
1284 		}
1285 	}
1286 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1287 	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
1288 
1289 	return (res);
1290 }
1291 
1292 
1293 /* ARGSUSED */
1294 static int
1295 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1296 {
1297 	if (otype != OTYP_CHR) {
1298 		return (EINVAL);
1299 	}
1300 
1301 	/*
1302 	 * Allow only root to talk;
1303 	 */
1304 	if (drv_priv(credp)) {
1305 		return (EPERM);
1306 	}
1307 
1308 	mutex_enter(&fcp_global_mutex);
1309 	if (fcp_oflag & FCP_EXCL) {
1310 		mutex_exit(&fcp_global_mutex);
1311 		return (EBUSY);
1312 	}
1313 
1314 	if (flag & FEXCL) {
1315 		if (fcp_oflag & FCP_OPEN) {
1316 			mutex_exit(&fcp_global_mutex);
1317 			return (EBUSY);
1318 		}
1319 		fcp_oflag |= FCP_EXCL;
1320 	}
1321 	fcp_oflag |= FCP_OPEN;
1322 	mutex_exit(&fcp_global_mutex);
1323 
1324 	return (0);
1325 }
1326 
1327 
1328 /* ARGSUSED */
1329 static int
1330 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1331 {
1332 	if (otype != OTYP_CHR) {
1333 		return (EINVAL);
1334 	}
1335 
1336 	mutex_enter(&fcp_global_mutex);
1337 	if (!(fcp_oflag & FCP_OPEN)) {
1338 		mutex_exit(&fcp_global_mutex);
1339 		return (ENODEV);
1340 	}
1341 	fcp_oflag = FCP_IDLE;
1342 	mutex_exit(&fcp_global_mutex);
1343 
1344 	return (0);
1345 }
1346 
1347 
1348 /*
1349  * fcp_ioctl
1350  *	Entry point for the FCP ioctls
1351  *
1352  * Input:
1353  *	See ioctl(9E)
1354  *
1355  * Output:
1356  *	See ioctl(9E)
1357  *
1358  * Returns:
1359  *	See ioctl(9E)
1360  *
1361  * Context:
1362  *	Kernel context.
1363  */
1364 /* ARGSUSED */
1365 static int
1366 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1367     int *rval)
1368 {
1369 	int			ret = 0;
1370 
1371 	mutex_enter(&fcp_global_mutex);
1372 	if (!(fcp_oflag & FCP_OPEN)) {
1373 		mutex_exit(&fcp_global_mutex);
1374 		return (ENXIO);
1375 	}
1376 	mutex_exit(&fcp_global_mutex);
1377 
1378 	switch (cmd) {
1379 	case FCP_TGT_INQUIRY:
1380 	case FCP_TGT_CREATE:
1381 	case FCP_TGT_DELETE:
1382 		ret = fcp_setup_device_data_ioctl(cmd,
1383 		    (struct fcp_ioctl *)data, mode, rval);
1384 		break;
1385 
1386 	case FCP_TGT_SEND_SCSI:
1387 		mutex_enter(&fcp_ioctl_mutex);
1388 		ret = fcp_setup_scsi_ioctl(
1389 		    (struct fcp_scsi_cmd *)data, mode, rval);
1390 		mutex_exit(&fcp_ioctl_mutex);
1391 		break;
1392 
1393 	case FCP_STATE_COUNT:
1394 		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1395 		    mode, rval);
1396 		break;
1397 	case FCP_GET_TARGET_MAPPINGS:
1398 		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1399 		    mode, rval);
1400 		break;
1401 	default:
1402 		fcp_log(CE_WARN, NULL,
1403 		    "!Invalid ioctl opcode = 0x%x", cmd);
1404 		ret	= EINVAL;
1405 	}
1406 
1407 	return (ret);
1408 }
1409 
1410 
1411 /*
1412  * fcp_setup_device_data_ioctl
1413  *	Setup handler for the "device data" style of
1414  *	ioctl for FCP.	See "fcp_util.h" for data structure
1415  *	definition.
1416  *
1417  * Input:
1418  *	cmd	= FCP ioctl command
1419  *	data	= ioctl data
1420  *	mode	= See ioctl(9E)
1421  *
1422  * Output:
1423  *	data	= ioctl data
1424  *	rval	= return value - see ioctl(9E)
1425  *
1426  * Returns:
1427  *	See ioctl(9E)
1428  *
1429  * Context:
1430  *	Kernel context.
1431  */
1432 /* ARGSUSED */
1433 static int
1434 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1435     int *rval)
1436 {
1437 	struct fcp_port	*pptr;
1438 	struct	device_data	*dev_data;
1439 	uint32_t		link_cnt;
1440 	la_wwn_t		*wwn_ptr = NULL;
1441 	struct fcp_tgt		*ptgt = NULL;
1442 	struct fcp_lun		*plun = NULL;
1443 	int			i, error;
1444 	struct fcp_ioctl	fioctl;
1445 
1446 #ifdef	_MULTI_DATAMODEL
1447 	switch (ddi_model_convert_from(mode & FMODELS)) {
1448 	case DDI_MODEL_ILP32: {
1449 		struct fcp32_ioctl f32_ioctl;
1450 
1451 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1452 		    sizeof (struct fcp32_ioctl), mode)) {
1453 			return (EFAULT);
1454 		}
1455 		fioctl.fp_minor = f32_ioctl.fp_minor;
1456 		fioctl.listlen = f32_ioctl.listlen;
1457 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1458 		break;
1459 	}
1460 	case DDI_MODEL_NONE:
1461 		if (ddi_copyin((void *)data, (void *)&fioctl,
1462 		    sizeof (struct fcp_ioctl), mode)) {
1463 			return (EFAULT);
1464 		}
1465 		break;
1466 	}
1467 
1468 #else	/* _MULTI_DATAMODEL */
1469 	if (ddi_copyin((void *)data, (void *)&fioctl,
1470 	    sizeof (struct fcp_ioctl), mode)) {
1471 		return (EFAULT);
1472 	}
1473 #endif	/* _MULTI_DATAMODEL */
1474 
1475 	/*
1476 	 * Right now we can assume that the minor number matches with
1477 	 * this instance of fp. If this changes we will need to
1478 	 * revisit this logic.
1479 	 */
1480 	mutex_enter(&fcp_global_mutex);
1481 	pptr = fcp_port_head;
1482 	while (pptr) {
1483 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1484 			break;
1485 		} else {
1486 			pptr = pptr->port_next;
1487 		}
1488 	}
1489 	mutex_exit(&fcp_global_mutex);
1490 	if (pptr == NULL) {
1491 		return (ENXIO);
1492 	}
1493 	mutex_enter(&pptr->port_mutex);
1494 
1495 
1496 	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1497 	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
1498 		mutex_exit(&pptr->port_mutex);
1499 		return (ENOMEM);
1500 	}
1501 
1502 	if (ddi_copyin(fioctl.list, dev_data,
1503 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1504 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1505 		mutex_exit(&pptr->port_mutex);
1506 		return (EFAULT);
1507 	}
1508 	link_cnt = pptr->port_link_cnt;
1509 
1510 	if (cmd == FCP_TGT_INQUIRY) {
1511 		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1512 		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1513 		    sizeof (wwn_ptr->raw_wwn)) == 0) {
1514 			/* This ioctl is requesting INQ info of local HBA */
1515 			mutex_exit(&pptr->port_mutex);
1516 			dev_data[0].dev0_type = DTYPE_UNKNOWN;
1517 			dev_data[0].dev_status = 0;
1518 			if (ddi_copyout(dev_data, fioctl.list,
1519 			    (sizeof (struct device_data)) * fioctl.listlen,
1520 			    mode)) {
1521 				kmem_free(dev_data,
1522 				    sizeof (*dev_data) * fioctl.listlen);
1523 				return (EFAULT);
1524 			}
1525 			kmem_free(dev_data,
1526 			    sizeof (*dev_data) * fioctl.listlen);
1527 #ifdef	_MULTI_DATAMODEL
1528 			switch (ddi_model_convert_from(mode & FMODELS)) {
1529 			case DDI_MODEL_ILP32: {
1530 				struct fcp32_ioctl f32_ioctl;
1531 				f32_ioctl.fp_minor = fioctl.fp_minor;
1532 				f32_ioctl.listlen = fioctl.listlen;
1533 				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1534 				if (ddi_copyout((void *)&f32_ioctl,
1535 				    (void *)data,
1536 				    sizeof (struct fcp32_ioctl), mode)) {
1537 					return (EFAULT);
1538 				}
1539 				break;
1540 			}
1541 			case DDI_MODEL_NONE:
1542 				if (ddi_copyout((void *)&fioctl, (void *)data,
1543 				    sizeof (struct fcp_ioctl), mode)) {
1544 					return (EFAULT);
1545 				}
1546 				break;
1547 			}
1548 #else	/* _MULTI_DATAMODEL */
1549 			if (ddi_copyout((void *)&fioctl, (void *)data,
1550 			    sizeof (struct fcp_ioctl), mode)) {
1551 				return (EFAULT);
1552 			}
1553 #endif	/* _MULTI_DATAMODEL */
1554 			return (0);
1555 		}
1556 	}
1557 
1558 	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1559 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1560 		mutex_exit(&pptr->port_mutex);
1561 		return (ENXIO);
1562 	}
1563 
1564 	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1565 	    i++) {
1566 		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1567 
1568 		dev_data[i].dev0_type = DTYPE_UNKNOWN;
1569 
1570 
1571 		dev_data[i].dev_status = ENXIO;
1572 
1573 		if ((ptgt = fcp_lookup_target(pptr,
1574 		    (uchar_t *)wwn_ptr)) == NULL) {
1575 			mutex_exit(&pptr->port_mutex);
1576 			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1577 			    wwn_ptr, &error, 0) == NULL) {
1578 				dev_data[i].dev_status = ENODEV;
1579 				mutex_enter(&pptr->port_mutex);
1580 				continue;
1581 			} else {
1582 
1583 				dev_data[i].dev_status = EAGAIN;
1584 
1585 				mutex_enter(&pptr->port_mutex);
1586 				continue;
1587 			}
1588 		} else {
1589 			mutex_enter(&ptgt->tgt_mutex);
1590 			if (ptgt->tgt_state & (FCP_TGT_MARK |
1591 			    FCP_TGT_BUSY)) {
1592 				dev_data[i].dev_status = EAGAIN;
1593 				mutex_exit(&ptgt->tgt_mutex);
1594 				continue;
1595 			}
1596 
1597 			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1598 				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1599 					dev_data[i].dev_status = ENOTSUP;
1600 				} else {
1601 					dev_data[i].dev_status = ENXIO;
1602 				}
1603 				mutex_exit(&ptgt->tgt_mutex);
1604 				continue;
1605 			}
1606 
1607 			switch (cmd) {
1608 			case FCP_TGT_INQUIRY:
1609 				/*
1610 				 * The reason we give device type of
1611 				 * lun 0 only even though in some
1612 				 * cases(like maxstrat) lun 0 device
1613 				 * type may be 0x3f(invalid) is that
1614 				 * for bridge boxes target will appear
1615 				 * as luns and the first lun could be
1616 				 * a device that utility may not care
1617 				 * about (like a tape device).
1618 				 */
1619 				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1620 				dev_data[i].dev_status = 0;
1621 				mutex_exit(&ptgt->tgt_mutex);
1622 
1623 				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1624 					dev_data[i].dev0_type = DTYPE_UNKNOWN;
1625 				} else {
1626 					dev_data[i].dev0_type = plun->lun_type;
1627 				}
1628 				mutex_enter(&ptgt->tgt_mutex);
1629 				break;
1630 
1631 			case FCP_TGT_CREATE:
1632 				mutex_exit(&ptgt->tgt_mutex);
1633 				mutex_exit(&pptr->port_mutex);
1634 
1635 				/*
1636 				 * serialize state change call backs.
1637 				 * only one call back will be handled
1638 				 * at a time.
1639 				 */
1640 				mutex_enter(&fcp_global_mutex);
1641 				if (fcp_oflag & FCP_BUSY) {
1642 					mutex_exit(&fcp_global_mutex);
1643 					if (dev_data) {
1644 						kmem_free(dev_data,
1645 						    sizeof (*dev_data) *
1646 						    fioctl.listlen);
1647 					}
1648 					return (EBUSY);
1649 				}
1650 				fcp_oflag |= FCP_BUSY;
1651 				mutex_exit(&fcp_global_mutex);
1652 
1653 				dev_data[i].dev_status =
1654 				    fcp_create_on_demand(pptr,
1655 				    wwn_ptr->raw_wwn);
1656 
1657 				if (dev_data[i].dev_status != 0) {
1658 					char	buf[25];
1659 
1660 					for (i = 0; i < FC_WWN_SIZE; i++) {
1661 						(void) sprintf(&buf[i << 1],
1662 						    "%02x",
1663 						    wwn_ptr->raw_wwn[i]);
1664 					}
1665 
1666 					fcp_log(CE_WARN, pptr->port_dip,
1667 					    "!Failed to create nodes for"
1668 					    " pwwn=%s; error=%x", buf,
1669 					    dev_data[i].dev_status);
1670 				}
1671 
1672 				/* allow state change call backs again */
1673 				mutex_enter(&fcp_global_mutex);
1674 				fcp_oflag &= ~FCP_BUSY;
1675 				mutex_exit(&fcp_global_mutex);
1676 
1677 				mutex_enter(&pptr->port_mutex);
1678 				mutex_enter(&ptgt->tgt_mutex);
1679 
1680 				break;
1681 
1682 			case FCP_TGT_DELETE:
1683 				break;
1684 
1685 			default:
1686 				fcp_log(CE_WARN, pptr->port_dip,
1687 				    "!Invalid device data ioctl "
1688 				    "opcode = 0x%x", cmd);
1689 			}
1690 			mutex_exit(&ptgt->tgt_mutex);
1691 		}
1692 	}
1693 	mutex_exit(&pptr->port_mutex);
1694 
1695 	if (ddi_copyout(dev_data, fioctl.list,
1696 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1697 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1698 		return (EFAULT);
1699 	}
1700 	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1701 
1702 #ifdef	_MULTI_DATAMODEL
1703 	switch (ddi_model_convert_from(mode & FMODELS)) {
1704 	case DDI_MODEL_ILP32: {
1705 		struct fcp32_ioctl f32_ioctl;
1706 
1707 		f32_ioctl.fp_minor = fioctl.fp_minor;
1708 		f32_ioctl.listlen = fioctl.listlen;
1709 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1710 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1711 		    sizeof (struct fcp32_ioctl), mode)) {
1712 			return (EFAULT);
1713 		}
1714 		break;
1715 	}
1716 	case DDI_MODEL_NONE:
1717 		if (ddi_copyout((void *)&fioctl, (void *)data,
1718 		    sizeof (struct fcp_ioctl), mode)) {
1719 			return (EFAULT);
1720 		}
1721 		break;
1722 	}
1723 #else	/* _MULTI_DATAMODEL */
1724 
1725 	if (ddi_copyout((void *)&fioctl, (void *)data,
1726 	    sizeof (struct fcp_ioctl), mode)) {
1727 		return (EFAULT);
1728 	}
1729 #endif	/* _MULTI_DATAMODEL */
1730 
1731 	return (0);
1732 }
1733 
1734 /*
1735  * Fetch the target mappings (path, etc.) for all LUNs
1736  * on this port.
1737  */
1738 /* ARGSUSED */
1739 static int
1740 fcp_get_target_mappings(struct fcp_ioctl *data,
1741     int mode, int *rval)
1742 {
1743 	struct fcp_port	    *pptr;
1744 	fc_hba_target_mappings_t    *mappings;
1745 	fc_hba_mapping_entry_t	    *map;
1746 	struct fcp_tgt	    *ptgt = NULL;
1747 	struct fcp_lun	    *plun = NULL;
1748 	int			    i, mapIndex, mappingSize;
1749 	int			    listlen;
1750 	struct fcp_ioctl	    fioctl;
1751 	char			    *path;
1752 	fcp_ent_addr_t		    sam_lun_addr;
1753 
1754 #ifdef	_MULTI_DATAMODEL
1755 	switch (ddi_model_convert_from(mode & FMODELS)) {
1756 	case DDI_MODEL_ILP32: {
1757 		struct fcp32_ioctl f32_ioctl;
1758 
1759 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1760 		    sizeof (struct fcp32_ioctl), mode)) {
1761 			return (EFAULT);
1762 		}
1763 		fioctl.fp_minor = f32_ioctl.fp_minor;
1764 		fioctl.listlen = f32_ioctl.listlen;
1765 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1766 		break;
1767 	}
1768 	case DDI_MODEL_NONE:
1769 		if (ddi_copyin((void *)data, (void *)&fioctl,
1770 		    sizeof (struct fcp_ioctl), mode)) {
1771 			return (EFAULT);
1772 		}
1773 		break;
1774 	}
1775 
1776 #else	/* _MULTI_DATAMODEL */
1777 	if (ddi_copyin((void *)data, (void *)&fioctl,
1778 	    sizeof (struct fcp_ioctl), mode)) {
1779 		return (EFAULT);
1780 	}
1781 #endif	/* _MULTI_DATAMODEL */
1782 
1783 	/*
1784 	 * Right now we can assume that the minor number matches with
1785 	 * this instance of fp. If this changes we will need to
1786 	 * revisit this logic.
1787 	 */
1788 	mutex_enter(&fcp_global_mutex);
1789 	pptr = fcp_port_head;
1790 	while (pptr) {
1791 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1792 			break;
1793 		} else {
1794 			pptr = pptr->port_next;
1795 		}
1796 	}
1797 	mutex_exit(&fcp_global_mutex);
1798 	if (pptr == NULL) {
1799 		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1800 		    fioctl.fp_minor);
1801 		return (ENXIO);
1802 	}
1803 
1804 
1805 	/* We use listlen to show the total buffer size */
1806 	mappingSize = fioctl.listlen;
1807 
1808 	/* Now calculate how many mapping entries will fit */
1809 	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1810 	    - sizeof (fc_hba_target_mappings_t);
1811 	if (listlen <= 0) {
1812 		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1813 		return (ENXIO);
1814 	}
1815 	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1816 
1817 	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1818 		return (ENOMEM);
1819 	}
1820 	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1821 
1822 	/* Now get to work */
1823 	mapIndex = 0;
1824 
1825 	mutex_enter(&pptr->port_mutex);
1826 	/* Loop through all targets on this port */
1827 	for (i = 0; i < FCP_NUM_HASH; i++) {
1828 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1829 		    ptgt = ptgt->tgt_next) {
1830 
1831 			mutex_enter(&ptgt->tgt_mutex);
1832 
1833 			/* Loop through all LUNs on this target */
1834 			for (plun = ptgt->tgt_lun; plun != NULL;
1835 			    plun = plun->lun_next) {
1836 				if (plun->lun_state & FCP_LUN_OFFLINE) {
1837 					continue;
1838 				}
1839 
1840 				path = fcp_get_lun_path(plun);
1841 				if (path == NULL) {
1842 					continue;
1843 				}
1844 
1845 				if (mapIndex >= listlen) {
1846 					mapIndex ++;
1847 					kmem_free(path, MAXPATHLEN);
1848 					continue;
1849 				}
1850 				map = &mappings->entries[mapIndex++];
1851 				bcopy(path, map->targetDriver,
1852 				    sizeof (map->targetDriver));
1853 				map->d_id = ptgt->tgt_d_id;
1854 				map->busNumber = 0;
1855 				map->targetNumber = ptgt->tgt_d_id;
1856 				map->osLUN = plun->lun_num;
1857 
1858 				/*
1859 				 * We had swapped lun when we stored it in
1860 				 * lun_addr. We need to swap it back before
1861 				 * returning it to user land
1862 				 */
1863 
1864 				sam_lun_addr.ent_addr_0 =
1865 				    BE_16(plun->lun_addr.ent_addr_0);
1866 				sam_lun_addr.ent_addr_1 =
1867 				    BE_16(plun->lun_addr.ent_addr_1);
1868 				sam_lun_addr.ent_addr_2 =
1869 				    BE_16(plun->lun_addr.ent_addr_2);
1870 				sam_lun_addr.ent_addr_3 =
1871 				    BE_16(plun->lun_addr.ent_addr_3);
1872 
1873 				bcopy(&sam_lun_addr, &map->samLUN,
1874 				    FCP_LUN_SIZE);
1875 				bcopy(ptgt->tgt_node_wwn.raw_wwn,
1876 				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1877 				bcopy(ptgt->tgt_port_wwn.raw_wwn,
1878 				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1879 
1880 				if (plun->lun_guid) {
1881 
1882 					/* convert ascii wwn to bytes */
1883 					fcp_ascii_to_wwn(plun->lun_guid,
1884 					    map->guid, sizeof (map->guid));
1885 
1886 					if ((sizeof (map->guid)) <
1887 					    plun->lun_guid_size / 2) {
1888 						cmn_err(CE_WARN,
1889 						    "fcp_get_target_mappings:"
1890 						    "guid copy space "
1891 						    "insufficient."
1892 						    "Copy Truncation - "
1893 						    "available %d; need %d",
1894 						    (int)sizeof (map->guid),
1895 						    (int)
1896 						    plun->lun_guid_size / 2);
1897 					}
1898 				}
1899 				kmem_free(path, MAXPATHLEN);
1900 			}
1901 			mutex_exit(&ptgt->tgt_mutex);
1902 		}
1903 	}
1904 	mutex_exit(&pptr->port_mutex);
1905 	mappings->numLuns = mapIndex;
1906 
1907 	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1908 		kmem_free(mappings, mappingSize);
1909 		return (EFAULT);
1910 	}
1911 	kmem_free(mappings, mappingSize);
1912 
1913 #ifdef	_MULTI_DATAMODEL
1914 	switch (ddi_model_convert_from(mode & FMODELS)) {
1915 	case DDI_MODEL_ILP32: {
1916 		struct fcp32_ioctl f32_ioctl;
1917 
1918 		f32_ioctl.fp_minor = fioctl.fp_minor;
1919 		f32_ioctl.listlen = fioctl.listlen;
1920 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1921 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1922 		    sizeof (struct fcp32_ioctl), mode)) {
1923 			return (EFAULT);
1924 		}
1925 		break;
1926 	}
1927 	case DDI_MODEL_NONE:
1928 		if (ddi_copyout((void *)&fioctl, (void *)data,
1929 		    sizeof (struct fcp_ioctl), mode)) {
1930 			return (EFAULT);
1931 		}
1932 		break;
1933 	}
1934 #else	/* _MULTI_DATAMODEL */
1935 
1936 	if (ddi_copyout((void *)&fioctl, (void *)data,
1937 	    sizeof (struct fcp_ioctl), mode)) {
1938 		return (EFAULT);
1939 	}
1940 #endif	/* _MULTI_DATAMODEL */
1941 
1942 	return (0);
1943 }
1944 
1945 /*
1946  * fcp_setup_scsi_ioctl
1947  *	Setup handler for the "scsi passthru" style of
1948  *	ioctl for FCP.	See "fcp_util.h" for data structure
1949  *	definition.
1950  *
1951  * Input:
1952  *	u_fscsi	= ioctl data (user address space)
1953  *	mode	= See ioctl(9E)
1954  *
1955  * Output:
1956  *	u_fscsi	= ioctl data (user address space)
1957  *	rval	= return value - see ioctl(9E)
1958  *
1959  * Returns:
1960  *	0	= OK
1961  *	EAGAIN	= See errno.h
1962  *	EBUSY	= See errno.h
1963  *	EFAULT	= See errno.h
1964  *	EINTR	= See errno.h
1965  *	EINVAL	= See errno.h
1966  *	EIO	= See errno.h
1967  *	ENOMEM	= See errno.h
1968  *	ENXIO	= See errno.h
1969  *
1970  * Context:
1971  *	Kernel context.
1972  */
1973 /* ARGSUSED */
1974 static int
1975 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1976     int mode, int *rval)
1977 {
1978 	int			ret		= 0;
1979 	int			temp_ret;
1980 	caddr_t			k_cdbbufaddr	= NULL;
1981 	caddr_t			k_bufaddr	= NULL;
1982 	caddr_t			k_rqbufaddr	= NULL;
1983 	caddr_t			u_cdbbufaddr;
1984 	caddr_t			u_bufaddr;
1985 	caddr_t			u_rqbufaddr;
1986 	struct fcp_scsi_cmd	k_fscsi;
1987 
1988 	/*
1989 	 * Get fcp_scsi_cmd array element from user address space
1990 	 */
1991 	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1992 	    != 0) {
1993 		return (ret);
1994 	}
1995 
1996 
1997 	/*
1998 	 * Even though kmem_alloc() checks the validity of the
1999 	 * buffer length, this check is needed when the
2000 	 * kmem_flags set and the zero buffer length is passed.
2001 	 */
2002 	if ((k_fscsi.scsi_cdblen <= 0) ||
2003 	    (k_fscsi.scsi_buflen <= 0) ||
2004 	    (k_fscsi.scsi_rqlen <= 0)) {
2005 		return (EINVAL);
2006 	}
2007 
2008 	/*
2009 	 * Allocate data for fcp_scsi_cmd pointer fields
2010 	 */
2011 	if (ret == 0) {
2012 		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2013 		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2014 		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2015 
2016 		if (k_cdbbufaddr == NULL ||
2017 		    k_bufaddr	 == NULL ||
2018 		    k_rqbufaddr	 == NULL) {
2019 			ret = ENOMEM;
2020 		}
2021 	}
2022 
2023 	/*
2024 	 * Get fcp_scsi_cmd pointer fields from user
2025 	 * address space
2026 	 */
2027 	if (ret == 0) {
2028 		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2029 		u_bufaddr    = k_fscsi.scsi_bufaddr;
2030 		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2031 
2032 		if (ddi_copyin(u_cdbbufaddr,
2033 		    k_cdbbufaddr,
2034 		    k_fscsi.scsi_cdblen,
2035 		    mode)) {
2036 			ret = EFAULT;
2037 		} else if (ddi_copyin(u_bufaddr,
2038 		    k_bufaddr,
2039 		    k_fscsi.scsi_buflen,
2040 		    mode)) {
2041 			ret = EFAULT;
2042 		} else if (ddi_copyin(u_rqbufaddr,
2043 		    k_rqbufaddr,
2044 		    k_fscsi.scsi_rqlen,
2045 		    mode)) {
2046 			ret = EFAULT;
2047 		}
2048 	}
2049 
2050 	/*
2051 	 * Send scsi command (blocking)
2052 	 */
2053 	if (ret == 0) {
2054 		/*
2055 		 * Prior to sending the scsi command, the
2056 		 * fcp_scsi_cmd data structure must contain kernel,
2057 		 * not user, addresses.
2058 		 */
2059 		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
2060 		k_fscsi.scsi_bufaddr	= k_bufaddr;
2061 		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
2062 
2063 		ret = fcp_send_scsi_ioctl(&k_fscsi);
2064 
2065 		/*
2066 		 * After sending the scsi command, the
2067 		 * fcp_scsi_cmd data structure must contain user,
2068 		 * not kernel, addresses.
2069 		 */
2070 		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
2071 		k_fscsi.scsi_bufaddr	= u_bufaddr;
2072 		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
2073 	}
2074 
2075 	/*
2076 	 * Put fcp_scsi_cmd pointer fields to user address space
2077 	 */
2078 	if (ret == 0) {
2079 		if (ddi_copyout(k_cdbbufaddr,
2080 		    u_cdbbufaddr,
2081 		    k_fscsi.scsi_cdblen,
2082 		    mode)) {
2083 			ret = EFAULT;
2084 		} else if (ddi_copyout(k_bufaddr,
2085 		    u_bufaddr,
2086 		    k_fscsi.scsi_buflen,
2087 		    mode)) {
2088 			ret = EFAULT;
2089 		} else if (ddi_copyout(k_rqbufaddr,
2090 		    u_rqbufaddr,
2091 		    k_fscsi.scsi_rqlen,
2092 		    mode)) {
2093 			ret = EFAULT;
2094 		}
2095 	}
2096 
2097 	/*
2098 	 * Free data for fcp_scsi_cmd pointer fields
2099 	 */
2100 	if (k_cdbbufaddr != NULL) {
2101 		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2102 	}
2103 	if (k_bufaddr != NULL) {
2104 		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2105 	}
2106 	if (k_rqbufaddr != NULL) {
2107 		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2108 	}
2109 
2110 	/*
2111 	 * Put fcp_scsi_cmd array element to user address space
2112 	 */
2113 	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2114 	if (temp_ret != 0) {
2115 		ret = temp_ret;
2116 	}
2117 
2118 	/*
2119 	 * Return status
2120 	 */
2121 	return (ret);
2122 }
2123 
2124 
2125 /*
2126  * fcp_copyin_scsi_cmd
2127  *	Copy in fcp_scsi_cmd data structure from user address space.
2128  *	The data may be in 32 bit or 64 bit modes.
2129  *
2130  * Input:
2131  *	base_addr	= from address (user address space)
2132  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2133  *
2134  * Output:
2135  *	fscsi		= to address (kernel address space)
2136  *
2137  * Returns:
2138  *	0	= OK
2139  *	EFAULT	= Error
2140  *
2141  * Context:
2142  *	Kernel context.
2143  */
2144 static int
2145 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2146 {
2147 #ifdef	_MULTI_DATAMODEL
2148 	struct fcp32_scsi_cmd	f32scsi;
2149 
2150 	switch (ddi_model_convert_from(mode & FMODELS)) {
2151 	case DDI_MODEL_ILP32:
2152 		/*
2153 		 * Copy data from user address space
2154 		 */
2155 		if (ddi_copyin((void *)base_addr,
2156 		    &f32scsi,
2157 		    sizeof (struct fcp32_scsi_cmd),
2158 		    mode)) {
2159 			return (EFAULT);
2160 		}
2161 		/*
2162 		 * Convert from 32 bit to 64 bit
2163 		 */
2164 		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2165 		break;
2166 	case DDI_MODEL_NONE:
2167 		/*
2168 		 * Copy data from user address space
2169 		 */
2170 		if (ddi_copyin((void *)base_addr,
2171 		    fscsi,
2172 		    sizeof (struct fcp_scsi_cmd),
2173 		    mode)) {
2174 			return (EFAULT);
2175 		}
2176 		break;
2177 	}
2178 #else	/* _MULTI_DATAMODEL */
2179 	/*
2180 	 * Copy data from user address space
2181 	 */
2182 	if (ddi_copyin((void *)base_addr,
2183 	    fscsi,
2184 	    sizeof (struct fcp_scsi_cmd),
2185 	    mode)) {
2186 		return (EFAULT);
2187 	}
2188 #endif	/* _MULTI_DATAMODEL */
2189 
2190 	return (0);
2191 }
2192 
2193 
2194 /*
2195  * fcp_copyout_scsi_cmd
2196  *	Copy out fcp_scsi_cmd data structure to user address space.
2197  *	The data may be in 32 bit or 64 bit modes.
2198  *
2199  * Input:
2200  *	fscsi		= to address (kernel address space)
2201  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2202  *
2203  * Output:
2204  *	base_addr	= from address (user address space)
2205  *
2206  * Returns:
2207  *	0	= OK
2208  *	EFAULT	= Error
2209  *
2210  * Context:
2211  *	Kernel context.
2212  */
2213 static int
2214 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2215 {
2216 #ifdef	_MULTI_DATAMODEL
2217 	struct fcp32_scsi_cmd	f32scsi;
2218 
2219 	switch (ddi_model_convert_from(mode & FMODELS)) {
2220 	case DDI_MODEL_ILP32:
2221 		/*
2222 		 * Convert from 64 bit to 32 bit
2223 		 */
2224 		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2225 		/*
2226 		 * Copy data to user address space
2227 		 */
2228 		if (ddi_copyout(&f32scsi,
2229 		    (void *)base_addr,
2230 		    sizeof (struct fcp32_scsi_cmd),
2231 		    mode)) {
2232 			return (EFAULT);
2233 		}
2234 		break;
2235 	case DDI_MODEL_NONE:
2236 		/*
2237 		 * Copy data to user address space
2238 		 */
2239 		if (ddi_copyout(fscsi,
2240 		    (void *)base_addr,
2241 		    sizeof (struct fcp_scsi_cmd),
2242 		    mode)) {
2243 			return (EFAULT);
2244 		}
2245 		break;
2246 	}
2247 #else	/* _MULTI_DATAMODEL */
2248 	/*
2249 	 * Copy data to user address space
2250 	 */
2251 	if (ddi_copyout(fscsi,
2252 	    (void *)base_addr,
2253 	    sizeof (struct fcp_scsi_cmd),
2254 	    mode)) {
2255 		return (EFAULT);
2256 	}
2257 #endif	/* _MULTI_DATAMODEL */
2258 
2259 	return (0);
2260 }
2261 
2262 
2263 /*
2264  * fcp_send_scsi_ioctl
2265  *	Sends the SCSI command in blocking mode.
2266  *
2267  * Input:
2268  *	fscsi		= SCSI command data structure
2269  *
2270  * Output:
2271  *	fscsi		= SCSI command data structure
2272  *
2273  * Returns:
2274  *	0	= OK
2275  *	EAGAIN	= See errno.h
2276  *	EBUSY	= See errno.h
2277  *	EINTR	= See errno.h
2278  *	EINVAL	= See errno.h
2279  *	EIO	= See errno.h
2280  *	ENOMEM	= See errno.h
2281  *	ENXIO	= See errno.h
2282  *
2283  * Context:
2284  *	Kernel context.
2285  */
2286 static int
2287 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2288 {
2289 	struct fcp_lun	*plun		= NULL;
2290 	struct fcp_port	*pptr		= NULL;
2291 	struct fcp_tgt	*ptgt		= NULL;
2292 	fc_packet_t		*fpkt		= NULL;
2293 	struct fcp_ipkt	*icmd		= NULL;
2294 	int			target_created	= FALSE;
2295 	fc_frame_hdr_t		*hp;
2296 	struct fcp_cmd		fcp_cmd;
2297 	struct fcp_cmd		*fcmd;
2298 	union scsi_cdb		*scsi_cdb;
2299 	la_wwn_t		*wwn_ptr;
2300 	int			nodma;
2301 	struct fcp_rsp		*rsp;
2302 	struct fcp_rsp_info	*rsp_info;
2303 	caddr_t			rsp_sense;
2304 	int			buf_len;
2305 	int			info_len;
2306 	int			sense_len;
2307 	struct scsi_extended_sense	*sense_to = NULL;
2308 	timeout_id_t		tid;
2309 	uint8_t			reconfig_lun = FALSE;
2310 	uint8_t			reconfig_pending = FALSE;
2311 	uint8_t			scsi_cmd;
2312 	int			rsp_len;
2313 	int			cmd_index;
2314 	int			fc_status;
2315 	int			pkt_state;
2316 	int			pkt_action;
2317 	int			pkt_reason;
2318 	int			ret, xport_retval = ~FC_SUCCESS;
2319 	int			lcount;
2320 	int			tcount;
2321 	int			reconfig_status;
2322 	int			port_busy = FALSE;
2323 	uchar_t			*lun_string;
2324 
2325 	/*
2326 	 * Check valid SCSI command
2327 	 */
2328 	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2329 	ret = EINVAL;
2330 	for (cmd_index = 0;
2331 	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2332 	    ret != 0;
2333 	    cmd_index++) {
2334 		/*
2335 		 * First byte of CDB is the SCSI command
2336 		 */
2337 		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2338 			ret = 0;
2339 		}
2340 	}
2341 
2342 	/*
2343 	 * Check inputs
2344 	 */
2345 	if (fscsi->scsi_flags != FCP_SCSI_READ) {
2346 		ret = EINVAL;
2347 	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2348 		/* no larger than */
2349 		ret = EINVAL;
2350 	}
2351 
2352 
2353 	/*
2354 	 * Find FC port
2355 	 */
2356 	if (ret == 0) {
2357 		/*
2358 		 * Acquire global mutex
2359 		 */
2360 		mutex_enter(&fcp_global_mutex);
2361 
2362 		pptr = fcp_port_head;
2363 		while (pptr) {
2364 			if (pptr->port_instance ==
2365 			    (uint32_t)fscsi->scsi_fc_port_num) {
2366 				break;
2367 			} else {
2368 				pptr = pptr->port_next;
2369 			}
2370 		}
2371 
2372 		if (pptr == NULL) {
2373 			ret = ENXIO;
2374 		} else {
2375 			/*
2376 			 * fc_ulp_busy_port can raise power
2377 			 *  so, we must not hold any mutexes involved in PM
2378 			 */
2379 			mutex_exit(&fcp_global_mutex);
2380 			ret = fc_ulp_busy_port(pptr->port_fp_handle);
2381 		}
2382 
2383 		if (ret == 0) {
2384 
2385 			/* remember port is busy, so we will release later */
2386 			port_busy = TRUE;
2387 
2388 			/*
2389 			 * If there is a reconfiguration in progress, wait
2390 			 * for it to complete.
2391 			 */
2392 
2393 			fcp_reconfig_wait(pptr);
2394 
2395 			/* reacquire mutexes in order */
2396 			mutex_enter(&fcp_global_mutex);
2397 			mutex_enter(&pptr->port_mutex);
2398 
2399 			/*
2400 			 * Will port accept DMA?
2401 			 */
2402 			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2403 			    ? 1 : 0;
2404 
2405 			/*
2406 			 * If init or offline, device not known
2407 			 *
2408 			 * If we are discovering (onlining), we can
2409 			 * NOT obviously provide reliable data about
2410 			 * devices until it is complete
2411 			 */
2412 			if (pptr->port_state &	  (FCP_STATE_INIT |
2413 			    FCP_STATE_OFFLINE)) {
2414 				ret = ENXIO;
2415 			} else if (pptr->port_state & FCP_STATE_ONLINING) {
2416 				ret = EBUSY;
2417 			} else {
2418 				/*
2419 				 * Find target from pwwn
2420 				 *
2421 				 * The wwn must be put into a local
2422 				 * variable to ensure alignment.
2423 				 */
2424 				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2425 				ptgt = fcp_lookup_target(pptr,
2426 				    (uchar_t *)wwn_ptr);
2427 
2428 				/*
2429 				 * If target not found,
2430 				 */
2431 				if (ptgt == NULL) {
2432 					/*
2433 					 * Note: Still have global &
2434 					 * port mutexes
2435 					 */
2436 					mutex_exit(&pptr->port_mutex);
2437 					ptgt = fcp_port_create_tgt(pptr,
2438 					    wwn_ptr, &ret, &fc_status,
2439 					    &pkt_state, &pkt_action,
2440 					    &pkt_reason);
2441 					mutex_enter(&pptr->port_mutex);
2442 
2443 					fscsi->scsi_fc_status  = fc_status;
2444 					fscsi->scsi_pkt_state  =
2445 					    (uchar_t)pkt_state;
2446 					fscsi->scsi_pkt_reason = pkt_reason;
2447 					fscsi->scsi_pkt_action =
2448 					    (uchar_t)pkt_action;
2449 
2450 					if (ptgt != NULL) {
2451 						target_created = TRUE;
2452 					} else if (ret == 0) {
2453 						ret = ENOMEM;
2454 					}
2455 				}
2456 
2457 				if (ret == 0) {
2458 					/*
2459 					 * Acquire target
2460 					 */
2461 					mutex_enter(&ptgt->tgt_mutex);
2462 
2463 					/*
2464 					 * If target is mark or busy,
2465 					 * then target can not be used
2466 					 */
2467 					if (ptgt->tgt_state &
2468 					    (FCP_TGT_MARK |
2469 					    FCP_TGT_BUSY)) {
2470 						ret = EBUSY;
2471 					} else {
2472 						/*
2473 						 * Mark target as busy
2474 						 */
2475 						ptgt->tgt_state |=
2476 						    FCP_TGT_BUSY;
2477 					}
2478 
2479 					/*
2480 					 * Release target
2481 					 */
2482 					lcount = pptr->port_link_cnt;
2483 					tcount = ptgt->tgt_change_cnt;
2484 					mutex_exit(&ptgt->tgt_mutex);
2485 				}
2486 			}
2487 
2488 			/*
2489 			 * Release port
2490 			 */
2491 			mutex_exit(&pptr->port_mutex);
2492 		}
2493 
2494 		/*
2495 		 * Release global mutex
2496 		 */
2497 		mutex_exit(&fcp_global_mutex);
2498 	}
2499 
2500 	if (ret == 0) {
2501 		uint64_t belun = BE_64(fscsi->scsi_lun);
2502 
2503 		/*
2504 		 * If it's a target device, find lun from pwwn
2505 		 * The wwn must be put into a local
2506 		 * variable to ensure alignment.
2507 		 */
2508 		mutex_enter(&pptr->port_mutex);
2509 		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2510 		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2511 			/* this is not a target */
2512 			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2513 			ret = ENXIO;
2514 		} else if ((belun << 16) != 0) {
2515 			/*
2516 			 * Since fcp only support PD and LU addressing method
2517 			 * so far, the last 6 bytes of a valid LUN are expected
2518 			 * to be filled with 00h.
2519 			 */
2520 			fscsi->scsi_fc_status = FC_INVALID_LUN;
2521 			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2522 			    " method 0x%02x with LUN number 0x%016" PRIx64,
2523 			    (uint8_t)(belun >> 62), belun);
2524 			ret = ENXIO;
2525 		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2526 		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2527 			/*
2528 			 * This is a SCSI target, but no LUN at this
2529 			 * address.
2530 			 *
2531 			 * In the future, we may want to send this to
2532 			 * the target, and let it respond
2533 			 * appropriately
2534 			 */
2535 			ret = ENXIO;
2536 		}
2537 		mutex_exit(&pptr->port_mutex);
2538 	}
2539 
2540 	/*
2541 	 * Finished grabbing external resources
2542 	 * Allocate internal packet (icmd)
2543 	 */
2544 	if (ret == 0) {
2545 		/*
2546 		 * Calc rsp len assuming rsp info included
2547 		 */
2548 		rsp_len = sizeof (struct fcp_rsp) +
2549 		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2550 
2551 		icmd = fcp_icmd_alloc(pptr, ptgt,
2552 		    sizeof (struct fcp_cmd),
2553 		    rsp_len,
2554 		    fscsi->scsi_buflen,
2555 		    nodma,
2556 		    lcount,			/* ipkt_link_cnt */
2557 		    tcount,			/* ipkt_change_cnt */
2558 		    0,				/* cause */
2559 		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
2560 
2561 		if (icmd == NULL) {
2562 			ret = ENOMEM;
2563 		} else {
2564 			/*
2565 			 * Setup internal packet as sema sync
2566 			 */
2567 			fcp_ipkt_sema_init(icmd);
2568 		}
2569 	}
2570 
2571 	if (ret == 0) {
2572 		/*
2573 		 * Init fpkt pointer for use.
2574 		 */
2575 
2576 		fpkt = icmd->ipkt_fpkt;
2577 
2578 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
2579 		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
2580 		fpkt->pkt_timeout	= fscsi->scsi_timeout;
2581 
2582 		/*
2583 		 * Init fcmd pointer for use by SCSI command
2584 		 */
2585 
2586 		if (nodma) {
2587 			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2588 		} else {
2589 			fcmd = &fcp_cmd;
2590 		}
2591 		bzero(fcmd, sizeof (struct fcp_cmd));
2592 		ptgt = plun->lun_tgt;
2593 
2594 		lun_string = (uchar_t *)&fscsi->scsi_lun;
2595 
2596 		fcmd->fcp_ent_addr.ent_addr_0 =
2597 		    BE_16(*(uint16_t *)&(lun_string[0]));
2598 		fcmd->fcp_ent_addr.ent_addr_1 =
2599 		    BE_16(*(uint16_t *)&(lun_string[2]));
2600 		fcmd->fcp_ent_addr.ent_addr_2 =
2601 		    BE_16(*(uint16_t *)&(lun_string[4]));
2602 		fcmd->fcp_ent_addr.ent_addr_3 =
2603 		    BE_16(*(uint16_t *)&(lun_string[6]));
2604 
2605 		/*
2606 		 * Setup internal packet(icmd)
2607 		 */
2608 		icmd->ipkt_lun		= plun;
2609 		icmd->ipkt_restart	= 0;
2610 		icmd->ipkt_retries	= 0;
2611 		icmd->ipkt_opcode	= 0;
2612 
2613 		/*
2614 		 * Init the frame HEADER Pointer for use
2615 		 */
2616 		hp = &fpkt->pkt_cmd_fhdr;
2617 
2618 		hp->s_id	= pptr->port_id;
2619 		hp->d_id	= ptgt->tgt_d_id;
2620 		hp->r_ctl	= R_CTL_COMMAND;
2621 		hp->type	= FC_TYPE_SCSI_FCP;
2622 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2623 		hp->rsvd	= 0;
2624 		hp->seq_id	= 0;
2625 		hp->seq_cnt	= 0;
2626 		hp->ox_id	= 0xffff;
2627 		hp->rx_id	= 0xffff;
2628 		hp->ro		= 0;
2629 
2630 		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
2631 		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
2632 		fcmd->fcp_cntl.cntl_write_data	= 0;
2633 		fcmd->fcp_data_len	= fscsi->scsi_buflen;
2634 
2635 		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2636 		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2637 		    fscsi->scsi_cdblen);
2638 
2639 		if (!nodma) {
2640 			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2641 			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2642 		}
2643 
2644 		/*
2645 		 * Send SCSI command to FC transport
2646 		 */
2647 
2648 		if (ret == 0) {
2649 			mutex_enter(&ptgt->tgt_mutex);
2650 
2651 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2652 				mutex_exit(&ptgt->tgt_mutex);
2653 				fscsi->scsi_fc_status = xport_retval =
2654 				    fc_ulp_transport(pptr->port_fp_handle,
2655 				    fpkt);
2656 				if (fscsi->scsi_fc_status != FC_SUCCESS) {
2657 					ret = EIO;
2658 				}
2659 			} else {
2660 				mutex_exit(&ptgt->tgt_mutex);
2661 				ret = EBUSY;
2662 			}
2663 		}
2664 	}
2665 
2666 	/*
2667 	 * Wait for completion only if fc_ulp_transport was called and it
2668 	 * returned a success. This is the only time callback will happen.
2669 	 * Otherwise, there is no point in waiting
2670 	 */
2671 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2672 		ret = fcp_ipkt_sema_wait(icmd);
2673 	}
2674 
2675 	/*
2676 	 * Copy data to IOCTL data structures
2677 	 */
2678 	rsp = NULL;
2679 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2680 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2681 
2682 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2683 			fcp_log(CE_WARN, pptr->port_dip,
2684 			    "!SCSI command to d_id=0x%x lun=0x%x"
2685 			    " failed, Bad FCP response values:"
2686 			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2687 			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2688 			    ptgt->tgt_d_id, plun->lun_num,
2689 			    rsp->reserved_0, rsp->reserved_1,
2690 			    rsp->fcp_u.fcp_status.reserved_0,
2691 			    rsp->fcp_u.fcp_status.reserved_1,
2692 			    rsp->fcp_response_len, rsp->fcp_sense_len);
2693 
2694 			ret = EIO;
2695 		}
2696 	}
2697 
2698 	if ((ret == 0) && (rsp != NULL)) {
2699 		/*
2700 		 * Calc response lengths
2701 		 */
2702 		sense_len = 0;
2703 		info_len = 0;
2704 
2705 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
2706 			info_len = rsp->fcp_response_len;
2707 		}
2708 
2709 		rsp_info   = (struct fcp_rsp_info *)
2710 		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2711 
2712 		/*
2713 		 * Get SCSI status
2714 		 */
2715 		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2716 		/*
2717 		 * If a lun was just added or removed and the next command
2718 		 * comes through this interface, we need to capture the check
2719 		 * condition so we can discover the new topology.
2720 		 */
2721 		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2722 		    rsp->fcp_u.fcp_status.sense_len_set) {
2723 			sense_len = rsp->fcp_sense_len;
2724 			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2725 			sense_to = (struct scsi_extended_sense *)rsp_sense;
2726 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2727 			    (FCP_SENSE_NO_LUN(sense_to))) {
2728 				reconfig_lun = TRUE;
2729 			}
2730 		}
2731 
2732 		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2733 		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2734 			if (reconfig_lun == FALSE) {
2735 				reconfig_status =
2736 				    fcp_is_reconfig_needed(ptgt, fpkt);
2737 			}
2738 
2739 			if ((reconfig_lun == TRUE) ||
2740 			    (reconfig_status == TRUE)) {
2741 				mutex_enter(&ptgt->tgt_mutex);
2742 				if (ptgt->tgt_tid == NULL) {
2743 					/*
2744 					 * Either we've been notified the
2745 					 * REPORT_LUN data has changed, or
2746 					 * we've determined on our own that
2747 					 * we're out of date.  Kick off
2748 					 * rediscovery.
2749 					 */
2750 					tid = timeout(fcp_reconfigure_luns,
2751 					    (caddr_t)ptgt, drv_usectohz(1));
2752 
2753 					ptgt->tgt_tid = tid;
2754 					ptgt->tgt_state |= FCP_TGT_BUSY;
2755 					ret = EBUSY;
2756 					reconfig_pending = TRUE;
2757 				}
2758 				mutex_exit(&ptgt->tgt_mutex);
2759 			}
2760 		}
2761 
2762 		/*
2763 		 * Calc residuals and buffer lengths
2764 		 */
2765 
2766 		if (ret == 0) {
2767 			buf_len = fscsi->scsi_buflen;
2768 			fscsi->scsi_bufresid	= 0;
2769 			if (rsp->fcp_u.fcp_status.resid_under) {
2770 				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2771 					fscsi->scsi_bufresid = rsp->fcp_resid;
2772 				} else {
2773 					cmn_err(CE_WARN, "fcp: bad residue %x "
2774 					    "for txfer len %x", rsp->fcp_resid,
2775 					    fscsi->scsi_buflen);
2776 					fscsi->scsi_bufresid =
2777 					    fscsi->scsi_buflen;
2778 				}
2779 				buf_len -= fscsi->scsi_bufresid;
2780 			}
2781 			if (rsp->fcp_u.fcp_status.resid_over) {
2782 				fscsi->scsi_bufresid = -rsp->fcp_resid;
2783 			}
2784 
2785 			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
2786 			if (fscsi->scsi_rqlen < sense_len) {
2787 				sense_len = fscsi->scsi_rqlen;
2788 			}
2789 
2790 			fscsi->scsi_fc_rspcode	= 0;
2791 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
2792 				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
2793 			}
2794 			fscsi->scsi_pkt_state	= fpkt->pkt_state;
2795 			fscsi->scsi_pkt_action	= fpkt->pkt_action;
2796 			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
2797 
2798 			/*
2799 			 * Copy data and request sense
2800 			 *
2801 			 * Data must be copied by using the FCP_CP_IN macro.
2802 			 * This will ensure the proper byte order since the data
2803 			 * is being copied directly from the memory mapped
2804 			 * device register.
2805 			 *
2806 			 * The response (and request sense) will be in the
2807 			 * correct byte order.	No special copy is necessary.
2808 			 */
2809 
2810 			if (buf_len) {
2811 				FCP_CP_IN(fpkt->pkt_data,
2812 				    fscsi->scsi_bufaddr,
2813 				    fpkt->pkt_data_acc,
2814 				    buf_len);
2815 			}
2816 			bcopy((void *)rsp_sense,
2817 			    (void *)fscsi->scsi_rqbufaddr,
2818 			    sense_len);
2819 		}
2820 	}
2821 
2822 	/*
2823 	 * Cleanup transport data structures if icmd was alloc-ed
2824 	 * So, cleanup happens in the same thread that icmd was alloc-ed
2825 	 */
2826 	if (icmd != NULL) {
2827 		fcp_ipkt_sema_cleanup(icmd);
2828 	}
2829 
2830 	/* restore pm busy/idle status */
2831 	if (port_busy) {
2832 		fc_ulp_idle_port(pptr->port_fp_handle);
2833 	}
2834 
2835 	/*
2836 	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2837 	 * flag, it'll be cleared when the reconfig is complete.
2838 	 */
2839 	if ((ptgt != NULL) && !reconfig_pending) {
2840 		/*
2841 		 * If target was created,
2842 		 */
2843 		if (target_created) {
2844 			mutex_enter(&ptgt->tgt_mutex);
2845 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2846 			mutex_exit(&ptgt->tgt_mutex);
2847 		} else {
2848 			/*
2849 			 * De-mark target as busy
2850 			 */
2851 			mutex_enter(&ptgt->tgt_mutex);
2852 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2853 			mutex_exit(&ptgt->tgt_mutex);
2854 		}
2855 	}
2856 	return (ret);
2857 }
2858 
2859 
2860 static int
2861 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2862     fc_packet_t	*fpkt)
2863 {
2864 	uchar_t			*lun_string;
2865 	uint16_t		lun_num, i;
2866 	int			num_luns;
2867 	int			actual_luns;
2868 	int			num_masked_luns;
2869 	int			lun_buflen;
2870 	struct fcp_lun	*plun	= NULL;
2871 	struct fcp_reportlun_resp	*report_lun;
2872 	uint8_t			reconfig_needed = FALSE;
2873 	uint8_t			lun_exists = FALSE;
2874 	fcp_port_t			*pptr		 = ptgt->tgt_port;
2875 
2876 	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2877 
2878 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2879 	    fpkt->pkt_datalen);
2880 
2881 	/* get number of luns (which is supplied as LUNS * 8) */
2882 	num_luns = BE_32(report_lun->num_lun) >> 3;
2883 
2884 	/*
2885 	 * Figure out exactly how many lun strings our response buffer
2886 	 * can hold.
2887 	 */
2888 	lun_buflen = (fpkt->pkt_datalen -
2889 	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
2890 
2891 	/*
2892 	 * Is our response buffer full or not? We don't want to
2893 	 * potentially walk beyond the number of luns we have.
2894 	 */
2895 	if (num_luns <= lun_buflen) {
2896 		actual_luns = num_luns;
2897 	} else {
2898 		actual_luns = lun_buflen;
2899 	}
2900 
2901 	mutex_enter(&ptgt->tgt_mutex);
2902 
2903 	/* Scan each lun to see if we have masked it. */
2904 	num_masked_luns = 0;
2905 	if (fcp_lun_blacklist != NULL) {
2906 		for (i = 0; i < actual_luns; i++) {
2907 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2908 			switch (lun_string[0] & 0xC0) {
2909 			case FCP_LUN_ADDRESSING:
2910 			case FCP_PD_ADDRESSING:
2911 			case FCP_VOLUME_ADDRESSING:
2912 				lun_num = ((lun_string[0] & 0x3F) << 8)
2913 				    | lun_string[1];
2914 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
2915 				    lun_num) == TRUE) {
2916 					num_masked_luns++;
2917 				}
2918 				break;
2919 			default:
2920 				break;
2921 			}
2922 		}
2923 	}
2924 
2925 	/*
2926 	 * The quick and easy check.  If the number of LUNs reported
2927 	 * doesn't match the number we currently know about, we need
2928 	 * to reconfigure.
2929 	 */
2930 	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2931 		mutex_exit(&ptgt->tgt_mutex);
2932 		kmem_free(report_lun, fpkt->pkt_datalen);
2933 		return (TRUE);
2934 	}
2935 
2936 	/*
2937 	 * If the quick and easy check doesn't turn up anything, we walk
2938 	 * the list of luns from the REPORT_LUN response and look for
2939 	 * any luns we don't know about.  If we find one, we know we need
2940 	 * to reconfigure. We will skip LUNs that are masked because of the
2941 	 * blacklist.
2942 	 */
2943 	for (i = 0; i < actual_luns; i++) {
2944 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2945 		lun_exists = FALSE;
2946 		switch (lun_string[0] & 0xC0) {
2947 		case FCP_LUN_ADDRESSING:
2948 		case FCP_PD_ADDRESSING:
2949 		case FCP_VOLUME_ADDRESSING:
2950 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2951 
2952 			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2953 			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2954 				lun_exists = TRUE;
2955 				break;
2956 			}
2957 
2958 			for (plun = ptgt->tgt_lun; plun;
2959 			    plun = plun->lun_next) {
2960 				if (plun->lun_num == lun_num) {
2961 					lun_exists = TRUE;
2962 					break;
2963 				}
2964 			}
2965 			break;
2966 		default:
2967 			break;
2968 		}
2969 
2970 		if (lun_exists == FALSE) {
2971 			reconfig_needed = TRUE;
2972 			break;
2973 		}
2974 	}
2975 
2976 	mutex_exit(&ptgt->tgt_mutex);
2977 	kmem_free(report_lun, fpkt->pkt_datalen);
2978 
2979 	return (reconfig_needed);
2980 }
2981 
2982 /*
2983  * This function is called by fcp_handle_page83 and uses inquiry response data
2984  * stored in plun->lun_inq to determine whether or not a device is a member of
2985  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2986  * otherwise 1.
2987  */
2988 static int
2989 fcp_symmetric_device_probe(struct fcp_lun *plun)
2990 {
2991 	struct scsi_inquiry	*stdinq = &plun->lun_inq;
2992 	char			*devidptr;
2993 	int			i, len;
2994 
2995 	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2996 		devidptr = fcp_symmetric_disk_table[i];
2997 		len = (int)strlen(devidptr);
2998 
2999 		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3000 			return (0);
3001 		}
3002 	}
3003 	return (1);
3004 }
3005 
3006 
3007 /*
3008  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3009  * It basically returns the current count of # of state change callbacks
3010  * i.e the value of tgt_change_cnt.
3011  *
3012  * INPUT:
3013  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3014  *   fcp_ioctl.listlen	-> 1
3015  *   fcp_ioctl.list	-> Pointer to a 32 bit integer
3016  */
3017 /*ARGSUSED2*/
3018 static int
3019 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3020 {
3021 	int			ret;
3022 	uint32_t		link_cnt;
3023 	struct fcp_ioctl	fioctl;
3024 	struct fcp_port	*pptr = NULL;
3025 
3026 	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3027 	    &pptr)) != 0) {
3028 		return (ret);
3029 	}
3030 
3031 	ASSERT(pptr != NULL);
3032 
3033 	if (fioctl.listlen != 1) {
3034 		return (EINVAL);
3035 	}
3036 
3037 	mutex_enter(&pptr->port_mutex);
3038 	if (pptr->port_state & FCP_STATE_OFFLINE) {
3039 		mutex_exit(&pptr->port_mutex);
3040 		return (ENXIO);
3041 	}
3042 
3043 	/*
3044 	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3045 	 * When the fcp initially attaches to the port and there are nothing
3046 	 * hanging out of the port or if there was a repeat offline state change
3047 	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3048 	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3049 	 * will differentiate the 2 cases.
3050 	 */
3051 	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3052 		mutex_exit(&pptr->port_mutex);
3053 		return (ENXIO);
3054 	}
3055 
3056 	link_cnt = pptr->port_link_cnt;
3057 	mutex_exit(&pptr->port_mutex);
3058 
3059 	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3060 		return (EFAULT);
3061 	}
3062 
3063 #ifdef	_MULTI_DATAMODEL
3064 	switch (ddi_model_convert_from(mode & FMODELS)) {
3065 	case DDI_MODEL_ILP32: {
3066 		struct fcp32_ioctl f32_ioctl;
3067 
3068 		f32_ioctl.fp_minor = fioctl.fp_minor;
3069 		f32_ioctl.listlen = fioctl.listlen;
3070 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3071 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3072 		    sizeof (struct fcp32_ioctl), mode)) {
3073 			return (EFAULT);
3074 		}
3075 		break;
3076 	}
3077 	case DDI_MODEL_NONE:
3078 		if (ddi_copyout((void *)&fioctl, (void *)data,
3079 		    sizeof (struct fcp_ioctl), mode)) {
3080 			return (EFAULT);
3081 		}
3082 		break;
3083 	}
3084 #else	/* _MULTI_DATAMODEL */
3085 
3086 	if (ddi_copyout((void *)&fioctl, (void *)data,
3087 	    sizeof (struct fcp_ioctl), mode)) {
3088 		return (EFAULT);
3089 	}
3090 #endif	/* _MULTI_DATAMODEL */
3091 
3092 	return (0);
3093 }
3094 
3095 /*
3096  * This function copies the fcp_ioctl structure passed in from user land
3097  * into kernel land. Handles 32 bit applications.
3098  */
3099 /*ARGSUSED*/
3100 static int
3101 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3102     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3103 {
3104 	struct fcp_port	*t_pptr;
3105 
3106 #ifdef	_MULTI_DATAMODEL
3107 	switch (ddi_model_convert_from(mode & FMODELS)) {
3108 	case DDI_MODEL_ILP32: {
3109 		struct fcp32_ioctl f32_ioctl;
3110 
3111 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3112 		    sizeof (struct fcp32_ioctl), mode)) {
3113 			return (EFAULT);
3114 		}
3115 		fioctl->fp_minor = f32_ioctl.fp_minor;
3116 		fioctl->listlen = f32_ioctl.listlen;
3117 		fioctl->list = (caddr_t)(long)f32_ioctl.list;
3118 		break;
3119 	}
3120 	case DDI_MODEL_NONE:
3121 		if (ddi_copyin((void *)data, (void *)fioctl,
3122 		    sizeof (struct fcp_ioctl), mode)) {
3123 			return (EFAULT);
3124 		}
3125 		break;
3126 	}
3127 
3128 #else	/* _MULTI_DATAMODEL */
3129 	if (ddi_copyin((void *)data, (void *)fioctl,
3130 	    sizeof (struct fcp_ioctl), mode)) {
3131 		return (EFAULT);
3132 	}
3133 #endif	/* _MULTI_DATAMODEL */
3134 
3135 	/*
3136 	 * Right now we can assume that the minor number matches with
3137 	 * this instance of fp. If this changes we will need to
3138 	 * revisit this logic.
3139 	 */
3140 	mutex_enter(&fcp_global_mutex);
3141 	t_pptr = fcp_port_head;
3142 	while (t_pptr) {
3143 		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3144 			break;
3145 		} else {
3146 			t_pptr = t_pptr->port_next;
3147 		}
3148 	}
3149 	*pptr = t_pptr;
3150 	mutex_exit(&fcp_global_mutex);
3151 	if (t_pptr == NULL) {
3152 		return (ENXIO);
3153 	}
3154 
3155 	return (0);
3156 }
3157 
3158 /*
3159  *     Function: fcp_port_create_tgt
3160  *
3161  *  Description: As the name suggest this function creates the target context
3162  *		 specified by the the WWN provided by the caller.  If the
3163  *		 creation goes well and the target is known by fp/fctl a PLOGI
3164  *		 followed by a PRLI are issued.
3165  *
3166  *     Argument: pptr		fcp port structure
3167  *		 pwwn		WWN of the target
3168  *		 ret_val	Address of the return code.  It could be:
3169  *				EIO, ENOMEM or 0.
3170  *		 fc_status	PLOGI or PRLI status completion
3171  *		 fc_pkt_state	PLOGI or PRLI state completion
3172  *		 fc_pkt_reason	PLOGI or PRLI reason completion
3173  *		 fc_pkt_action	PLOGI or PRLI action completion
3174  *
3175  * Return Value: NULL if it failed
3176  *		 Target structure address if it succeeds
3177  */
3178 static struct fcp_tgt *
3179 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3180     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3181 {
3182 	struct fcp_tgt	*ptgt = NULL;
3183 	fc_portmap_t		devlist;
3184 	int			lcount;
3185 	int			error;
3186 
3187 	*ret_val = 0;
3188 
3189 	/*
3190 	 * Check FC port device & get port map
3191 	 */
3192 	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3193 	    &error, 1) == NULL) {
3194 		*ret_val = EIO;
3195 	} else {
3196 		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3197 		    &devlist) != FC_SUCCESS) {
3198 			*ret_val = EIO;
3199 		}
3200 	}
3201 
3202 	/* Set port map flags */
3203 	devlist.map_type = PORT_DEVICE_USER_CREATE;
3204 
3205 	/* Allocate target */
3206 	if (*ret_val == 0) {
3207 		lcount = pptr->port_link_cnt;
3208 		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3209 		if (ptgt == NULL) {
3210 			fcp_log(CE_WARN, pptr->port_dip,
3211 			    "!FC target allocation failed");
3212 			*ret_val = ENOMEM;
3213 		} else {
3214 			/* Setup target */
3215 			mutex_enter(&ptgt->tgt_mutex);
3216 
3217 			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
3218 			ptgt->tgt_tmp_cnt	= 1;
3219 			ptgt->tgt_d_id		= devlist.map_did.port_id;
3220 			ptgt->tgt_hard_addr	=
3221 			    devlist.map_hard_addr.hard_addr;
3222 			ptgt->tgt_pd_handle	= devlist.map_pd;
3223 			ptgt->tgt_fca_dev	= NULL;
3224 
3225 			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3226 			    FC_WWN_SIZE);
3227 			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3228 			    FC_WWN_SIZE);
3229 
3230 			mutex_exit(&ptgt->tgt_mutex);
3231 		}
3232 	}
3233 
3234 	/* Release global mutex for PLOGI and PRLI */
3235 	mutex_exit(&fcp_global_mutex);
3236 
3237 	/* Send PLOGI (If necessary) */
3238 	if (*ret_val == 0) {
3239 		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3240 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3241 	}
3242 
3243 	/* Send PRLI (If necessary) */
3244 	if (*ret_val == 0) {
3245 		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3246 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3247 	}
3248 
3249 	mutex_enter(&fcp_global_mutex);
3250 
3251 	return (ptgt);
3252 }
3253 
3254 /*
3255  *     Function: fcp_tgt_send_plogi
3256  *
3257  *  Description: This function sends a PLOGI to the target specified by the
3258  *		 caller and waits till it completes.
3259  *
3260  *     Argument: ptgt		Target to send the plogi to.
3261  *		 fc_status	Status returned by fp/fctl in the PLOGI request.
3262  *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
3263  *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
3264  *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
3265  *
3266  * Return Value: 0
3267  *		 ENOMEM
3268  *		 EIO
3269  *
3270  *	Context: User context.
3271  */
3272 static int
3273 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3274     int *fc_pkt_reason, int *fc_pkt_action)
3275 {
3276 	struct fcp_port	*pptr;
3277 	struct fcp_ipkt	*icmd;
3278 	struct fc_packet	*fpkt;
3279 	fc_frame_hdr_t		*hp;
3280 	struct la_els_logi	logi;
3281 	int			tcount;
3282 	int			lcount;
3283 	int			ret, login_retval = ~FC_SUCCESS;
3284 
3285 	ret = 0;
3286 
3287 	pptr = ptgt->tgt_port;
3288 
3289 	lcount = pptr->port_link_cnt;
3290 	tcount = ptgt->tgt_change_cnt;
3291 
3292 	/* Alloc internal packet */
3293 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3294 	    sizeof (la_els_logi_t), 0,
3295 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3296 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3297 
3298 	if (icmd == NULL) {
3299 		ret = ENOMEM;
3300 	} else {
3301 		/*
3302 		 * Setup internal packet as sema sync
3303 		 */
3304 		fcp_ipkt_sema_init(icmd);
3305 
3306 		/*
3307 		 * Setup internal packet (icmd)
3308 		 */
3309 		icmd->ipkt_lun		= NULL;
3310 		icmd->ipkt_restart	= 0;
3311 		icmd->ipkt_retries	= 0;
3312 		icmd->ipkt_opcode	= LA_ELS_PLOGI;
3313 
3314 		/*
3315 		 * Setup fc_packet
3316 		 */
3317 		fpkt = icmd->ipkt_fpkt;
3318 
3319 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
3320 		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
3321 		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
3322 
3323 		/*
3324 		 * Setup FC frame header
3325 		 */
3326 		hp = &fpkt->pkt_cmd_fhdr;
3327 
3328 		hp->s_id	= pptr->port_id;	/* source ID */
3329 		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
3330 		hp->r_ctl	= R_CTL_ELS_REQ;
3331 		hp->type	= FC_TYPE_EXTENDED_LS;
3332 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3333 		hp->seq_id	= 0;
3334 		hp->rsvd	= 0;
3335 		hp->df_ctl	= 0;
3336 		hp->seq_cnt	= 0;
3337 		hp->ox_id	= 0xffff;		/* i.e. none */
3338 		hp->rx_id	= 0xffff;		/* i.e. none */
3339 		hp->ro		= 0;
3340 
3341 		/*
3342 		 * Setup PLOGI
3343 		 */
3344 		bzero(&logi, sizeof (struct la_els_logi));
3345 		logi.ls_code.ls_code = LA_ELS_PLOGI;
3346 
3347 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3348 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3349 
3350 		/*
3351 		 * Send PLOGI
3352 		 */
3353 		*fc_status = login_retval =
3354 		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3355 		if (*fc_status != FC_SUCCESS) {
3356 			ret = EIO;
3357 		}
3358 	}
3359 
3360 	/*
3361 	 * Wait for completion
3362 	 */
3363 	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3364 		ret = fcp_ipkt_sema_wait(icmd);
3365 
3366 		*fc_pkt_state	= fpkt->pkt_state;
3367 		*fc_pkt_reason	= fpkt->pkt_reason;
3368 		*fc_pkt_action	= fpkt->pkt_action;
3369 	}
3370 
3371 	/*
3372 	 * Cleanup transport data structures if icmd was alloc-ed AND if there
3373 	 * is going to be no callback (i.e if fc_ulp_login() failed).
3374 	 * Otherwise, cleanup happens in callback routine.
3375 	 */
3376 	if (icmd != NULL) {
3377 		fcp_ipkt_sema_cleanup(icmd);
3378 	}
3379 
3380 	return (ret);
3381 }
3382 
3383 /*
3384  *     Function: fcp_tgt_send_prli
3385  *
3386  *  Description: Does nothing as of today.
3387  *
3388  *     Argument: ptgt		Target to send the prli to.
3389  *		 fc_status	Status returned by fp/fctl in the PRLI request.
3390  *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
3391  *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
3392  *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
3393  *
3394  * Return Value: 0
3395  */
3396 /*ARGSUSED*/
3397 static int
3398 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3399     int *fc_pkt_reason, int *fc_pkt_action)
3400 {
3401 	return (0);
3402 }
3403 
3404 /*
3405  *     Function: fcp_ipkt_sema_init
3406  *
3407  *  Description: Initializes the semaphore contained in the internal packet.
3408  *
3409  *     Argument: icmd	Internal packet the semaphore of which must be
3410  *			initialized.
3411  *
3412  * Return Value: None
3413  *
3414  *	Context: User context only.
3415  */
3416 static void
3417 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3418 {
3419 	struct fc_packet	*fpkt;
3420 
3421 	fpkt = icmd->ipkt_fpkt;
3422 
3423 	/* Create semaphore for sync */
3424 	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3425 
3426 	/* Setup the completion callback */
3427 	fpkt->pkt_comp = fcp_ipkt_sema_callback;
3428 }
3429 
3430 /*
3431  *     Function: fcp_ipkt_sema_wait
3432  *
3433  *  Description: Wait on the semaphore embedded in the internal packet.	 The
3434  *		 semaphore is released in the callback.
3435  *
3436  *     Argument: icmd	Internal packet to wait on for completion.
3437  *
3438  * Return Value: 0
3439  *		 EIO
3440  *		 EBUSY
3441  *		 EAGAIN
3442  *
3443  *	Context: User context only.
3444  *
3445  * This function does a conversion between the field pkt_state of the fc_packet
3446  * embedded in the internal packet (icmd) and the code it returns.
3447  */
3448 static int
3449 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3450 {
3451 	struct fc_packet	*fpkt;
3452 	int	ret;
3453 
3454 	ret = EIO;
3455 	fpkt = icmd->ipkt_fpkt;
3456 
3457 	/*
3458 	 * Wait on semaphore
3459 	 */
3460 	sema_p(&(icmd->ipkt_sema));
3461 
3462 	/*
3463 	 * Check the status of the FC packet
3464 	 */
3465 	switch (fpkt->pkt_state) {
3466 	case FC_PKT_SUCCESS:
3467 		ret = 0;
3468 		break;
3469 	case FC_PKT_LOCAL_RJT:
3470 		switch (fpkt->pkt_reason) {
3471 		case FC_REASON_SEQ_TIMEOUT:
3472 		case FC_REASON_RX_BUF_TIMEOUT:
3473 			ret = EAGAIN;
3474 			break;
3475 		case FC_REASON_PKT_BUSY:
3476 			ret = EBUSY;
3477 			break;
3478 		}
3479 		break;
3480 	case FC_PKT_TIMEOUT:
3481 		ret = EAGAIN;
3482 		break;
3483 	case FC_PKT_LOCAL_BSY:
3484 	case FC_PKT_TRAN_BSY:
3485 	case FC_PKT_NPORT_BSY:
3486 	case FC_PKT_FABRIC_BSY:
3487 		ret = EBUSY;
3488 		break;
3489 	case FC_PKT_LS_RJT:
3490 	case FC_PKT_BA_RJT:
3491 		switch (fpkt->pkt_reason) {
3492 		case FC_REASON_LOGICAL_BSY:
3493 			ret = EBUSY;
3494 			break;
3495 		}
3496 		break;
3497 	case FC_PKT_FS_RJT:
3498 		switch (fpkt->pkt_reason) {
3499 		case FC_REASON_FS_LOGICAL_BUSY:
3500 			ret = EBUSY;
3501 			break;
3502 		}
3503 		break;
3504 	}
3505 
3506 	return (ret);
3507 }
3508 
3509 /*
3510  *     Function: fcp_ipkt_sema_callback
3511  *
3512  *  Description: Registered as the completion callback function for the FC
3513  *		 transport when the ipkt semaphore is used for sync. This will
3514  *		 cleanup the used data structures, if necessary and wake up
3515  *		 the user thread to complete the transaction.
3516  *
3517  *     Argument: fpkt	FC packet (points to the icmd)
3518  *
3519  * Return Value: None
3520  *
3521  *	Context: User context only
3522  */
3523 static void
3524 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3525 {
3526 	struct fcp_ipkt	*icmd;
3527 
3528 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3529 
3530 	/*
3531 	 * Wake up user thread
3532 	 */
3533 	sema_v(&(icmd->ipkt_sema));
3534 }
3535 
3536 /*
3537  *     Function: fcp_ipkt_sema_cleanup
3538  *
3539  *  Description: Called to cleanup (if necessary) the data structures used
3540  *		 when ipkt sema is used for sync.  This function will detect
3541  *		 whether the caller is the last thread (via counter) and
3542  *		 cleanup only if necessary.
3543  *
3544  *     Argument: icmd	Internal command packet
3545  *
3546  * Return Value: None
3547  *
3548  *	Context: User context only
3549  */
3550 static void
3551 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3552 {
3553 	struct fcp_tgt	*ptgt;
3554 	struct fcp_port	*pptr;
3555 
3556 	ptgt = icmd->ipkt_tgt;
3557 	pptr = icmd->ipkt_port;
3558 
3559 	/*
3560 	 * Acquire data structure
3561 	 */
3562 	mutex_enter(&ptgt->tgt_mutex);
3563 
3564 	/*
3565 	 * Destroy semaphore
3566 	 */
3567 	sema_destroy(&(icmd->ipkt_sema));
3568 
3569 	/*
3570 	 * Cleanup internal packet
3571 	 */
3572 	mutex_exit(&ptgt->tgt_mutex);
3573 	fcp_icmd_free(pptr, icmd);
3574 }
3575 
3576 /*
3577  *     Function: fcp_port_attach
3578  *
3579  *  Description: Called by the transport framework to resume, suspend or
3580  *		 attach a new port.
3581  *
3582  *     Argument: ulph		Port handle
3583  *		 *pinfo		Port information
3584  *		 cmd		Command
3585  *		 s_id		Port ID
3586  *
3587  * Return Value: FC_FAILURE or FC_SUCCESS
3588  */
3589 /*ARGSUSED*/
3590 static int
3591 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3592     fc_attach_cmd_t cmd, uint32_t s_id)
3593 {
3594 	int	instance;
3595 	int	res = FC_FAILURE; /* default result */
3596 
3597 	ASSERT(pinfo != NULL);
3598 
3599 	instance = ddi_get_instance(pinfo->port_dip);
3600 
3601 	switch (cmd) {
3602 	case FC_CMD_ATTACH:
3603 		/*
3604 		 * this port instance attaching for the first time (or after
3605 		 * being detached before)
3606 		 */
3607 		if (fcp_handle_port_attach(ulph, pinfo, s_id,
3608 		    instance) == DDI_SUCCESS) {
3609 			res = FC_SUCCESS;
3610 		} else {
3611 			ASSERT(ddi_get_soft_state(fcp_softstate,
3612 			    instance) == NULL);
3613 		}
3614 		break;
3615 
3616 	case FC_CMD_RESUME:
3617 	case FC_CMD_POWER_UP:
3618 		/*
3619 		 * this port instance was attached and the suspended and
3620 		 * will now be resumed
3621 		 */
3622 		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3623 		    instance) == DDI_SUCCESS) {
3624 			res = FC_SUCCESS;
3625 		}
3626 		break;
3627 
3628 	default:
3629 		/* shouldn't happen */
3630 		FCP_TRACE(fcp_logq, "fcp",
3631 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
3632 		    "port_attach: unknown cmdcommand: %d", cmd);
3633 		break;
3634 	}
3635 
3636 	/* return result */
3637 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3638 	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3639 
3640 	return (res);
3641 }
3642 
3643 
3644 /*
3645  * detach or suspend this port instance
3646  *
3647  * acquires and releases the global mutex
3648  *
3649  * acquires and releases the mutex for this port
3650  *
3651  * acquires and releases the hotplug mutex for this port
3652  */
3653 /*ARGSUSED*/
3654 static int
3655 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3656     fc_detach_cmd_t cmd)
3657 {
3658 	int			flag;
3659 	int			instance;
3660 	struct fcp_port		*pptr;
3661 
3662 	instance = ddi_get_instance(info->port_dip);
3663 	pptr = ddi_get_soft_state(fcp_softstate, instance);
3664 
3665 	switch (cmd) {
3666 	case FC_CMD_SUSPEND:
3667 		FCP_DTRACE(fcp_logq, "fcp",
3668 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3669 		    "port suspend called for port %d", instance);
3670 		flag = FCP_STATE_SUSPENDED;
3671 		break;
3672 
3673 	case FC_CMD_POWER_DOWN:
3674 		FCP_DTRACE(fcp_logq, "fcp",
3675 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3676 		    "port power down called for port %d", instance);
3677 		flag = FCP_STATE_POWER_DOWN;
3678 		break;
3679 
3680 	case FC_CMD_DETACH:
3681 		FCP_DTRACE(fcp_logq, "fcp",
3682 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3683 		    "port detach called for port %d", instance);
3684 		flag = FCP_STATE_DETACHING;
3685 		break;
3686 
3687 	default:
3688 		/* shouldn't happen */
3689 		return (FC_FAILURE);
3690 	}
3691 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3692 	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3693 
3694 	return (fcp_handle_port_detach(pptr, flag, instance));
3695 }
3696 
3697 
3698 /*
3699  * called for ioctls on the transport's devctl interface, and the transport
3700  * has passed it to us
3701  *
3702  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3703  *
3704  * return FC_SUCCESS if we decide to claim the ioctl,
3705  * else return FC_UNCLAIMED
3706  *
3707  * *rval is set iff we decide to claim the ioctl
3708  */
3709 /*ARGSUSED*/
3710 static int
3711 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3712     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3713 {
3714 	int			retval = FC_UNCLAIMED;	/* return value */
3715 	struct fcp_port		*pptr = NULL;		/* our soft state */
3716 	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
3717 	dev_info_t		*cdip;
3718 	mdi_pathinfo_t		*pip = NULL;
3719 	char			*ndi_nm;		/* NDI name */
3720 	char			*ndi_addr;		/* NDI addr */
3721 	int			is_mpxio, circ;
3722 	int			devi_entered = 0;
3723 	clock_t			end_time;
3724 
3725 	ASSERT(rval != NULL);
3726 
3727 	FCP_DTRACE(fcp_logq, "fcp",
3728 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3729 	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3730 
3731 	/* if already claimed then forget it */
3732 	if (claimed) {
3733 		/*
3734 		 * for now, if this ioctl has already been claimed, then
3735 		 * we just ignore it
3736 		 */
3737 		return (retval);
3738 	}
3739 
3740 	/* get our port info */
3741 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
3742 		fcp_log(CE_WARN, NULL,
3743 		    "!fcp:Invalid port handle handle in ioctl");
3744 		*rval = ENXIO;
3745 		return (retval);
3746 	}
3747 	is_mpxio = pptr->port_mpxio;
3748 
3749 	switch (cmd) {
3750 	case DEVCTL_BUS_GETSTATE:
3751 	case DEVCTL_BUS_QUIESCE:
3752 	case DEVCTL_BUS_UNQUIESCE:
3753 	case DEVCTL_BUS_RESET:
3754 	case DEVCTL_BUS_RESETALL:
3755 
3756 	case DEVCTL_BUS_DEV_CREATE:
3757 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3758 			return (retval);
3759 		}
3760 		break;
3761 
3762 	case DEVCTL_DEVICE_GETSTATE:
3763 	case DEVCTL_DEVICE_OFFLINE:
3764 	case DEVCTL_DEVICE_ONLINE:
3765 	case DEVCTL_DEVICE_REMOVE:
3766 	case DEVCTL_DEVICE_RESET:
3767 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3768 			return (retval);
3769 		}
3770 
3771 		ASSERT(dcp != NULL);
3772 
3773 		/* ensure we have a name and address */
3774 		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3775 		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3776 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
3777 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
3778 			    "ioctl: can't get name (%s) or addr (%s)",
3779 			    ndi_nm ? ndi_nm : "<null ptr>",
3780 			    ndi_addr ? ndi_addr : "<null ptr>");
3781 			ndi_dc_freehdl(dcp);
3782 			return (retval);
3783 		}
3784 
3785 
3786 		/* get our child's DIP */
3787 		ASSERT(pptr != NULL);
3788 		if (is_mpxio) {
3789 			mdi_devi_enter(pptr->port_dip, &circ);
3790 		} else {
3791 			ndi_devi_enter(pptr->port_dip, &circ);
3792 		}
3793 		devi_entered = 1;
3794 
3795 		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3796 		    ndi_addr)) == NULL) {
3797 			/* Look for virtually enumerated devices. */
3798 			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3799 			if (pip == NULL ||
3800 			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3801 				*rval = ENXIO;
3802 				goto out;
3803 			}
3804 		}
3805 		break;
3806 
3807 	default:
3808 		*rval = ENOTTY;
3809 		return (retval);
3810 	}
3811 
3812 	/* this ioctl is ours -- process it */
3813 
3814 	retval = FC_SUCCESS;		/* just means we claim the ioctl */
3815 
3816 	/* we assume it will be a success; else we'll set error value */
3817 	*rval = 0;
3818 
3819 
3820 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3821 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3822 	    "ioctl: claiming this one");
3823 
3824 	/* handle ioctls now */
3825 	switch (cmd) {
3826 	case DEVCTL_DEVICE_GETSTATE:
3827 		ASSERT(cdip != NULL);
3828 		ASSERT(dcp != NULL);
3829 		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3830 			*rval = EFAULT;
3831 		}
3832 		break;
3833 
3834 	case DEVCTL_DEVICE_REMOVE:
3835 	case DEVCTL_DEVICE_OFFLINE: {
3836 		int			flag = 0;
3837 		int			lcount;
3838 		int			tcount;
3839 		struct fcp_pkt	*head = NULL;
3840 		struct fcp_lun	*plun;
3841 		child_info_t		*cip = CIP(cdip);
3842 		int			all = 1;
3843 		struct fcp_lun	*tplun;
3844 		struct fcp_tgt	*ptgt;
3845 
3846 		ASSERT(pptr != NULL);
3847 		ASSERT(cdip != NULL);
3848 
3849 		mutex_enter(&pptr->port_mutex);
3850 		if (pip != NULL) {
3851 			cip = CIP(pip);
3852 		}
3853 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3854 			mutex_exit(&pptr->port_mutex);
3855 			*rval = ENXIO;
3856 			break;
3857 		}
3858 
3859 		head = fcp_scan_commands(plun);
3860 		if (head != NULL) {
3861 			fcp_abort_commands(head, LUN_PORT);
3862 		}
3863 		lcount = pptr->port_link_cnt;
3864 		tcount = plun->lun_tgt->tgt_change_cnt;
3865 		mutex_exit(&pptr->port_mutex);
3866 
3867 		if (cmd == DEVCTL_DEVICE_REMOVE) {
3868 			flag = NDI_DEVI_REMOVE;
3869 		}
3870 
3871 		if (is_mpxio) {
3872 			mdi_devi_exit(pptr->port_dip, circ);
3873 		} else {
3874 			ndi_devi_exit(pptr->port_dip, circ);
3875 		}
3876 		devi_entered = 0;
3877 
3878 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3879 		    FCP_OFFLINE, lcount, tcount, flag);
3880 
3881 		if (*rval != NDI_SUCCESS) {
3882 			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3883 			break;
3884 		}
3885 
3886 		fcp_update_offline_flags(plun);
3887 
3888 		ptgt = plun->lun_tgt;
3889 		mutex_enter(&ptgt->tgt_mutex);
3890 		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3891 		    tplun->lun_next) {
3892 			mutex_enter(&tplun->lun_mutex);
3893 			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3894 				all = 0;
3895 			}
3896 			mutex_exit(&tplun->lun_mutex);
3897 		}
3898 
3899 		if (all) {
3900 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3901 			/*
3902 			 * The user is unconfiguring/offlining the device.
3903 			 * If fabric and the auto configuration is set
3904 			 * then make sure the user is the only one who
3905 			 * can reconfigure the device.
3906 			 */
3907 			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3908 			    fcp_enable_auto_configuration) {
3909 				ptgt->tgt_manual_config_only = 1;
3910 			}
3911 		}
3912 		mutex_exit(&ptgt->tgt_mutex);
3913 		break;
3914 	}
3915 
3916 	case DEVCTL_DEVICE_ONLINE: {
3917 		int			lcount;
3918 		int			tcount;
3919 		struct fcp_lun	*plun;
3920 		child_info_t		*cip = CIP(cdip);
3921 
3922 		ASSERT(cdip != NULL);
3923 		ASSERT(pptr != NULL);
3924 
3925 		mutex_enter(&pptr->port_mutex);
3926 		if (pip != NULL) {
3927 			cip = CIP(pip);
3928 		}
3929 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3930 			mutex_exit(&pptr->port_mutex);
3931 			*rval = ENXIO;
3932 			break;
3933 		}
3934 		lcount = pptr->port_link_cnt;
3935 		tcount = plun->lun_tgt->tgt_change_cnt;
3936 		mutex_exit(&pptr->port_mutex);
3937 
3938 		/*
3939 		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3940 		 * to allow the device attach to occur when the device is
3941 		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3942 		 * from the scsi_probe()).
3943 		 */
3944 		mutex_enter(&LUN_TGT->tgt_mutex);
3945 		plun->lun_state |= FCP_LUN_ONLINING;
3946 		mutex_exit(&LUN_TGT->tgt_mutex);
3947 
3948 		if (is_mpxio) {
3949 			mdi_devi_exit(pptr->port_dip, circ);
3950 		} else {
3951 			ndi_devi_exit(pptr->port_dip, circ);
3952 		}
3953 		devi_entered = 0;
3954 
3955 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3956 		    FCP_ONLINE, lcount, tcount, 0);
3957 
3958 		if (*rval != NDI_SUCCESS) {
3959 			/* Reset the FCP_LUN_ONLINING bit */
3960 			mutex_enter(&LUN_TGT->tgt_mutex);
3961 			plun->lun_state &= ~FCP_LUN_ONLINING;
3962 			mutex_exit(&LUN_TGT->tgt_mutex);
3963 			*rval = EIO;
3964 			break;
3965 		}
3966 		mutex_enter(&LUN_TGT->tgt_mutex);
3967 		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3968 		    FCP_LUN_ONLINING);
3969 		mutex_exit(&LUN_TGT->tgt_mutex);
3970 		break;
3971 	}
3972 
3973 	case DEVCTL_BUS_DEV_CREATE: {
3974 		uchar_t			*bytes = NULL;
3975 		uint_t			nbytes;
3976 		struct fcp_tgt		*ptgt = NULL;
3977 		struct fcp_lun		*plun = NULL;
3978 		dev_info_t		*useless_dip = NULL;
3979 
3980 		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3981 		    DEVCTL_CONSTRUCT, &useless_dip);
3982 		if (*rval != 0 || useless_dip == NULL) {
3983 			break;
3984 		}
3985 
3986 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3987 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3988 		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3989 			*rval = EINVAL;
3990 			(void) ndi_devi_free(useless_dip);
3991 			if (bytes != NULL) {
3992 				ddi_prop_free(bytes);
3993 			}
3994 			break;
3995 		}
3996 
3997 		*rval = fcp_create_on_demand(pptr, bytes);
3998 		if (*rval == 0) {
3999 			mutex_enter(&pptr->port_mutex);
4000 			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4001 			if (ptgt) {
4002 				/*
4003 				 * We now have a pointer to the target that
4004 				 * was created. Lets point to the first LUN on
4005 				 * this new target.
4006 				 */
4007 				mutex_enter(&ptgt->tgt_mutex);
4008 
4009 				plun = ptgt->tgt_lun;
4010 				/*
4011 				 * There may be stale/offline LUN entries on
4012 				 * this list (this is by design) and so we have
4013 				 * to make sure we point to the first online
4014 				 * LUN
4015 				 */
4016 				while (plun &&
4017 				    plun->lun_state & FCP_LUN_OFFLINE) {
4018 					plun = plun->lun_next;
4019 				}
4020 
4021 				mutex_exit(&ptgt->tgt_mutex);
4022 			}
4023 			mutex_exit(&pptr->port_mutex);
4024 		}
4025 
4026 		if (*rval == 0 && ptgt && plun) {
4027 			mutex_enter(&plun->lun_mutex);
4028 			/*
4029 			 * Allow up to fcp_lun_ready_retry seconds to
4030 			 * configure all the luns behind the target.
4031 			 *
4032 			 * The intent here is to allow targets with long
4033 			 * reboot/reset-recovery times to become available
4034 			 * while limiting the maximum wait time for an
4035 			 * unresponsive target.
4036 			 */
4037 			end_time = ddi_get_lbolt() +
4038 			    SEC_TO_TICK(fcp_lun_ready_retry);
4039 
4040 			while (ddi_get_lbolt() < end_time) {
4041 				retval = FC_SUCCESS;
4042 
4043 				/*
4044 				 * The new ndi interfaces for on-demand creation
4045 				 * are inflexible, Do some more work to pass on
4046 				 * a path name of some LUN (design is broken !)
4047 				 */
4048 				if (plun->lun_cip) {
4049 					if (plun->lun_mpxio == 0) {
4050 						cdip = DIP(plun->lun_cip);
4051 					} else {
4052 						cdip = mdi_pi_get_client(
4053 						    PIP(plun->lun_cip));
4054 					}
4055 					if (cdip == NULL) {
4056 						*rval = ENXIO;
4057 						break;
4058 					}
4059 
4060 					if (!i_ddi_devi_attached(cdip)) {
4061 						mutex_exit(&plun->lun_mutex);
4062 						delay(drv_usectohz(1000000));
4063 						mutex_enter(&plun->lun_mutex);
4064 					} else {
4065 						/*
4066 						 * This Lun is ready, lets
4067 						 * check the next one.
4068 						 */
4069 						mutex_exit(&plun->lun_mutex);
4070 						plun = plun->lun_next;
4071 						while (plun && (plun->lun_state
4072 						    & FCP_LUN_OFFLINE)) {
4073 							plun = plun->lun_next;
4074 						}
4075 						if (!plun) {
4076 							break;
4077 						}
4078 						mutex_enter(&plun->lun_mutex);
4079 					}
4080 				} else {
4081 					/*
4082 					 * lun_cip field for a valid lun
4083 					 * should never be NULL. Fail the
4084 					 * command.
4085 					 */
4086 					*rval = ENXIO;
4087 					break;
4088 				}
4089 			}
4090 			if (plun) {
4091 				mutex_exit(&plun->lun_mutex);
4092 			} else {
4093 				char devnm[MAXNAMELEN];
4094 				int nmlen;
4095 
4096 				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4097 				    ddi_node_name(cdip),
4098 				    ddi_get_name_addr(cdip));
4099 
4100 				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4101 				    0) {
4102 					*rval = EFAULT;
4103 				}
4104 			}
4105 		} else {
4106 			int	i;
4107 			char	buf[25];
4108 
4109 			for (i = 0; i < FC_WWN_SIZE; i++) {
4110 				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4111 			}
4112 
4113 			fcp_log(CE_WARN, pptr->port_dip,
4114 			    "!Failed to create nodes for pwwn=%s; error=%x",
4115 			    buf, *rval);
4116 		}
4117 
4118 		(void) ndi_devi_free(useless_dip);
4119 		ddi_prop_free(bytes);
4120 		break;
4121 	}
4122 
4123 	case DEVCTL_DEVICE_RESET: {
4124 		struct fcp_lun		*plun;
4125 		child_info_t		*cip = CIP(cdip);
4126 
4127 		ASSERT(cdip != NULL);
4128 		ASSERT(pptr != NULL);
4129 		mutex_enter(&pptr->port_mutex);
4130 		if (pip != NULL) {
4131 			cip = CIP(pip);
4132 		}
4133 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4134 			mutex_exit(&pptr->port_mutex);
4135 			*rval = ENXIO;
4136 			break;
4137 		}
4138 		mutex_exit(&pptr->port_mutex);
4139 
4140 		mutex_enter(&plun->lun_tgt->tgt_mutex);
4141 		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4142 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4143 
4144 			*rval = ENXIO;
4145 			break;
4146 		}
4147 
4148 		if (plun->lun_sd == NULL) {
4149 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4150 
4151 			*rval = ENXIO;
4152 			break;
4153 		}
4154 		mutex_exit(&plun->lun_tgt->tgt_mutex);
4155 
4156 		/*
4157 		 * set up ap so that fcp_reset can figure out
4158 		 * which target to reset
4159 		 */
4160 		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4161 		    RESET_TARGET) == FALSE) {
4162 			*rval = EIO;
4163 		}
4164 		break;
4165 	}
4166 
4167 	case DEVCTL_BUS_GETSTATE:
4168 		ASSERT(dcp != NULL);
4169 		ASSERT(pptr != NULL);
4170 		ASSERT(pptr->port_dip != NULL);
4171 		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4172 		    NDI_SUCCESS) {
4173 			*rval = EFAULT;
4174 		}
4175 		break;
4176 
4177 	case DEVCTL_BUS_QUIESCE:
4178 	case DEVCTL_BUS_UNQUIESCE:
4179 		*rval = ENOTSUP;
4180 		break;
4181 
4182 	case DEVCTL_BUS_RESET:
4183 	case DEVCTL_BUS_RESETALL:
4184 		ASSERT(pptr != NULL);
4185 		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4186 		break;
4187 
4188 	default:
4189 		ASSERT(dcp != NULL);
4190 		*rval = ENOTTY;
4191 		break;
4192 	}
4193 
4194 	/* all done -- clean up and return */
4195 out:	if (devi_entered) {
4196 		if (is_mpxio) {
4197 			mdi_devi_exit(pptr->port_dip, circ);
4198 		} else {
4199 			ndi_devi_exit(pptr->port_dip, circ);
4200 		}
4201 	}
4202 
4203 	if (dcp != NULL) {
4204 		ndi_dc_freehdl(dcp);
4205 	}
4206 
4207 	return (retval);
4208 }
4209 
4210 
4211 /*ARGSUSED*/
4212 static int
4213 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4214     uint32_t claimed)
4215 {
4216 	uchar_t			r_ctl;
4217 	uchar_t			ls_code;
4218 	struct fcp_port	*pptr;
4219 
4220 	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4221 		return (FC_UNCLAIMED);
4222 	}
4223 
4224 	mutex_enter(&pptr->port_mutex);
4225 	if (pptr->port_state & (FCP_STATE_DETACHING |
4226 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4227 		mutex_exit(&pptr->port_mutex);
4228 		return (FC_UNCLAIMED);
4229 	}
4230 	mutex_exit(&pptr->port_mutex);
4231 
4232 	r_ctl = buf->ub_frame.r_ctl;
4233 
4234 	switch (r_ctl & R_CTL_ROUTING) {
4235 	case R_CTL_EXTENDED_SVC:
4236 		if (r_ctl == R_CTL_ELS_REQ) {
4237 			ls_code = buf->ub_buffer[0];
4238 
4239 			switch (ls_code) {
4240 			case LA_ELS_PRLI:
4241 				/*
4242 				 * We really don't care if something fails.
4243 				 * If the PRLI was not sent out, then the
4244 				 * other end will time it out.
4245 				 */
4246 				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4247 					return (FC_SUCCESS);
4248 				}
4249 				return (FC_UNCLAIMED);
4250 				/* NOTREACHED */
4251 
4252 			default:
4253 				break;
4254 			}
4255 		}
4256 		/* FALLTHROUGH */
4257 
4258 	default:
4259 		return (FC_UNCLAIMED);
4260 	}
4261 }
4262 
4263 
4264 /*ARGSUSED*/
4265 static int
4266 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4267     uint32_t claimed)
4268 {
4269 	return (FC_UNCLAIMED);
4270 }
4271 
4272 /*
4273  *     Function: fcp_statec_callback
4274  *
4275  *  Description: The purpose of this function is to handle a port state change.
4276  *		 It is called from fp/fctl and, in a few instances, internally.
4277  *
4278  *     Argument: ulph		fp/fctl port handle
4279  *		 port_handle	fcp_port structure
4280  *		 port_state	Physical state of the port
4281  *		 port_top	Topology
4282  *		 *devlist	Pointer to the first entry of a table
4283  *				containing the remote ports that can be
4284  *				reached.
4285  *		 dev_cnt	Number of entries pointed by devlist.
4286  *		 port_sid	Port ID of the local port.
4287  *
4288  * Return Value: None
4289  */
4290 /*ARGSUSED*/
4291 static void
4292 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4293     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4294     uint32_t dev_cnt, uint32_t port_sid)
4295 {
4296 	uint32_t		link_count;
4297 	int			map_len = 0;
4298 	struct fcp_port	*pptr;
4299 	fcp_map_tag_t		*map_tag = NULL;
4300 
4301 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
4302 		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4303 		return;			/* nothing to work with! */
4304 	}
4305 
4306 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4307 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
4308 	    "fcp_statec_callback: port state/dev_cnt/top ="
4309 	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4310 	    dev_cnt, port_top);
4311 
4312 	mutex_enter(&pptr->port_mutex);
4313 
4314 	/*
4315 	 * If a thread is in detach, don't do anything.
4316 	 */
4317 	if (pptr->port_state & (FCP_STATE_DETACHING |
4318 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4319 		mutex_exit(&pptr->port_mutex);
4320 		return;
4321 	}
4322 
4323 	/*
4324 	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4325 	 * init_pkt is called, it knows whether or not the target's status
4326 	 * (or pd) might be changing.
4327 	 */
4328 
4329 	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4330 		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4331 	}
4332 
4333 	/*
4334 	 * the transport doesn't allocate or probe unless being
4335 	 * asked to by either the applications or ULPs
4336 	 *
4337 	 * in cases where the port is OFFLINE at the time of port
4338 	 * attach callback and the link comes ONLINE later, for
4339 	 * easier automatic node creation (i.e. without you having to
4340 	 * go out and run the utility to perform LOGINs) the
4341 	 * following conditional is helpful
4342 	 */
4343 	pptr->port_phys_state = port_state;
4344 
4345 	if (dev_cnt) {
4346 		mutex_exit(&pptr->port_mutex);
4347 
4348 		map_len = sizeof (*map_tag) * dev_cnt;
4349 		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4350 		if (map_tag == NULL) {
4351 			fcp_log(CE_WARN, pptr->port_dip,
4352 			    "!fcp%d: failed to allocate for map tags; "
4353 			    " state change will not be processed",
4354 			    pptr->port_instance);
4355 
4356 			mutex_enter(&pptr->port_mutex);
4357 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4358 			mutex_exit(&pptr->port_mutex);
4359 
4360 			return;
4361 		}
4362 
4363 		mutex_enter(&pptr->port_mutex);
4364 	}
4365 
4366 	if (pptr->port_id != port_sid) {
4367 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4368 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4369 		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4370 		    port_sid);
4371 		/*
4372 		 * The local port changed ID. It is the first time a port ID
4373 		 * is assigned or something drastic happened.  We might have
4374 		 * been unplugged and replugged on another loop or fabric port
4375 		 * or somebody grabbed the AL_PA we had or somebody rezoned
4376 		 * the fabric we were plugged into.
4377 		 */
4378 		pptr->port_id = port_sid;
4379 	}
4380 
4381 	switch (FC_PORT_STATE_MASK(port_state)) {
4382 	case FC_STATE_OFFLINE:
4383 	case FC_STATE_RESET_REQUESTED:
4384 		/*
4385 		 * link has gone from online to offline -- just update the
4386 		 * state of this port to BUSY and MARKed to go offline
4387 		 */
4388 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4389 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4390 		    "link went offline");
4391 		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4392 			/*
4393 			 * We were offline a while ago and this one
4394 			 * seems to indicate that the loop has gone
4395 			 * dead forever.
4396 			 */
4397 			pptr->port_tmp_cnt += dev_cnt;
4398 			pptr->port_state &= ~FCP_STATE_OFFLINE;
4399 			pptr->port_state |= FCP_STATE_INIT;
4400 			link_count = pptr->port_link_cnt;
4401 			fcp_handle_devices(pptr, devlist, dev_cnt,
4402 			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4403 		} else {
4404 			pptr->port_link_cnt++;
4405 			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4406 			fcp_update_state(pptr, (FCP_LUN_BUSY |
4407 			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4408 			if (pptr->port_mpxio) {
4409 				fcp_update_mpxio_path_verifybusy(pptr);
4410 			}
4411 			pptr->port_state |= FCP_STATE_OFFLINE;
4412 			pptr->port_state &=
4413 			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4414 			pptr->port_tmp_cnt = 0;
4415 		}
4416 		mutex_exit(&pptr->port_mutex);
4417 		break;
4418 
4419 	case FC_STATE_ONLINE:
4420 	case FC_STATE_LIP:
4421 	case FC_STATE_LIP_LBIT_SET:
4422 		/*
4423 		 * link has gone from offline to online
4424 		 */
4425 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4426 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4427 		    "link went online");
4428 
4429 		pptr->port_link_cnt++;
4430 
4431 		while (pptr->port_ipkt_cnt) {
4432 			mutex_exit(&pptr->port_mutex);
4433 			delay(drv_usectohz(1000000));
4434 			mutex_enter(&pptr->port_mutex);
4435 		}
4436 
4437 		pptr->port_topology = port_top;
4438 
4439 		/*
4440 		 * The state of the targets and luns accessible through this
4441 		 * port is updated.
4442 		 */
4443 		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4444 		    FCP_CAUSE_LINK_CHANGE);
4445 
4446 		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4447 		pptr->port_state |= FCP_STATE_ONLINING;
4448 		pptr->port_tmp_cnt = dev_cnt;
4449 		link_count = pptr->port_link_cnt;
4450 
4451 		pptr->port_deadline = fcp_watchdog_time +
4452 		    FCP_ICMD_DEADLINE;
4453 
4454 		if (!dev_cnt) {
4455 			/*
4456 			 * We go directly to the online state if no remote
4457 			 * ports were discovered.
4458 			 */
4459 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4460 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4461 			    "No remote ports discovered");
4462 
4463 			pptr->port_state &= ~FCP_STATE_ONLINING;
4464 			pptr->port_state |= FCP_STATE_ONLINE;
4465 		}
4466 
4467 		switch (port_top) {
4468 		case FC_TOP_FABRIC:
4469 		case FC_TOP_PUBLIC_LOOP:
4470 		case FC_TOP_PRIVATE_LOOP:
4471 		case FC_TOP_PT_PT:
4472 
4473 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4474 				fcp_retry_ns_registry(pptr, port_sid);
4475 			}
4476 
4477 			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4478 			    map_tag, FCP_CAUSE_LINK_CHANGE);
4479 			break;
4480 
4481 		default:
4482 			/*
4483 			 * We got here because we were provided with an unknown
4484 			 * topology.
4485 			 */
4486 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4487 				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4488 			}
4489 
4490 			pptr->port_tmp_cnt -= dev_cnt;
4491 			fcp_log(CE_WARN, pptr->port_dip,
4492 			    "!unknown/unsupported topology (0x%x)", port_top);
4493 			break;
4494 		}
4495 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4496 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4497 		    "Notify ssd of the reset to reinstate the reservations");
4498 
4499 		scsi_hba_reset_notify_callback(&pptr->port_mutex,
4500 		    &pptr->port_reset_notify_listf);
4501 
4502 		mutex_exit(&pptr->port_mutex);
4503 
4504 		break;
4505 
4506 	case FC_STATE_RESET:
4507 		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4508 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4509 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4510 		    "RESET state, waiting for Offline/Online state_cb");
4511 		mutex_exit(&pptr->port_mutex);
4512 		break;
4513 
4514 	case FC_STATE_DEVICE_CHANGE:
4515 		/*
4516 		 * We come here when an application has requested
4517 		 * Dynamic node creation/deletion in Fabric connectivity.
4518 		 */
4519 		if (pptr->port_state & (FCP_STATE_OFFLINE |
4520 		    FCP_STATE_INIT)) {
4521 			/*
4522 			 * This case can happen when the FCTL is in the
4523 			 * process of giving us on online and the host on
4524 			 * the other side issues a PLOGI/PLOGO. Ideally
4525 			 * the state changes should be serialized unless
4526 			 * they are opposite (online-offline).
4527 			 * The transport will give us a final state change
4528 			 * so we can ignore this for the time being.
4529 			 */
4530 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4531 			mutex_exit(&pptr->port_mutex);
4532 			break;
4533 		}
4534 
4535 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4536 			fcp_retry_ns_registry(pptr, port_sid);
4537 		}
4538 
4539 		/*
4540 		 * Extend the deadline under steady state conditions
4541 		 * to provide more time for the device-change-commands
4542 		 */
4543 		if (!pptr->port_ipkt_cnt) {
4544 			pptr->port_deadline = fcp_watchdog_time +
4545 			    FCP_ICMD_DEADLINE;
4546 		}
4547 
4548 		/*
4549 		 * There is another race condition here, where if we were
4550 		 * in ONLINEING state and a devices in the map logs out,
4551 		 * fp will give another state change as DEVICE_CHANGE
4552 		 * and OLD. This will result in that target being offlined.
4553 		 * The pd_handle is freed. If from the first statec callback
4554 		 * we were going to fire a PLOGI/PRLI, the system will
4555 		 * panic in fc_ulp_transport with invalid pd_handle.
4556 		 * The fix is to check for the link_cnt before issuing
4557 		 * any command down.
4558 		 */
4559 		fcp_update_targets(pptr, devlist, dev_cnt,
4560 		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4561 
4562 		link_count = pptr->port_link_cnt;
4563 
4564 		fcp_handle_devices(pptr, devlist, dev_cnt,
4565 		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4566 
4567 		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4568 
4569 		mutex_exit(&pptr->port_mutex);
4570 		break;
4571 
4572 	case FC_STATE_TARGET_PORT_RESET:
4573 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4574 			fcp_retry_ns_registry(pptr, port_sid);
4575 		}
4576 
4577 		/* Do nothing else */
4578 		mutex_exit(&pptr->port_mutex);
4579 		break;
4580 
4581 	default:
4582 		fcp_log(CE_WARN, pptr->port_dip,
4583 		    "!Invalid state change=0x%x", port_state);
4584 		mutex_exit(&pptr->port_mutex);
4585 		break;
4586 	}
4587 
4588 	if (map_tag) {
4589 		kmem_free(map_tag, map_len);
4590 	}
4591 }
4592 
4593 /*
4594  *     Function: fcp_handle_devices
4595  *
4596  *  Description: This function updates the devices currently known by
4597  *		 walking the list provided by the caller.  The list passed
4598  *		 by the caller is supposed to be the list of reachable
4599  *		 devices.
4600  *
4601  *     Argument: *pptr		Fcp port structure.
4602  *		 *devlist	Pointer to the first entry of a table
4603  *				containing the remote ports that can be
4604  *				reached.
4605  *		 dev_cnt	Number of entries pointed by devlist.
4606  *		 link_cnt	Link state count.
4607  *		 *map_tag	Array of fcp_map_tag_t structures.
4608  *		 cause		What caused this function to be called.
4609  *
4610  * Return Value: None
4611  *
4612  *	  Notes: The pptr->port_mutex must be held.
4613  */
4614 static void
4615 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4616     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4617 {
4618 	int			i;
4619 	int			check_finish_init = 0;
4620 	fc_portmap_t		*map_entry;
4621 	struct fcp_tgt	*ptgt = NULL;
4622 
4623 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4624 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
4625 	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4626 
4627 	if (dev_cnt) {
4628 		ASSERT(map_tag != NULL);
4629 	}
4630 
4631 	/*
4632 	 * The following code goes through the list of remote ports that are
4633 	 * accessible through this (pptr) local port (The list walked is the
4634 	 * one provided by the caller which is the list of the remote ports
4635 	 * currently reachable).  It checks if any of them was already
4636 	 * known by looking for the corresponding target structure based on
4637 	 * the world wide name.	 If a target is part of the list it is tagged
4638 	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4639 	 *
4640 	 * Old comment
4641 	 * -----------
4642 	 * Before we drop port mutex; we MUST get the tags updated; This
4643 	 * two step process is somewhat slow, but more reliable.
4644 	 */
4645 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4646 		map_entry = &(devlist[i]);
4647 
4648 		/*
4649 		 * get ptr to this map entry in our port's
4650 		 * list (if any)
4651 		 */
4652 		ptgt = fcp_lookup_target(pptr,
4653 		    (uchar_t *)&(map_entry->map_pwwn));
4654 
4655 		if (ptgt) {
4656 			map_tag[i] = ptgt->tgt_change_cnt;
4657 			if (cause == FCP_CAUSE_LINK_CHANGE) {
4658 				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4659 			}
4660 		}
4661 	}
4662 
4663 	/*
4664 	 * At this point we know which devices of the new list were already
4665 	 * known (The field tgt_aux_state of the target structure has been
4666 	 * set to FCP_TGT_TAGGED).
4667 	 *
4668 	 * The following code goes through the list of targets currently known
4669 	 * by the local port (the list is actually a hashing table).  If a
4670 	 * target is found and is not tagged, it means the target cannot
4671 	 * be reached anymore through the local port (pptr).  It is offlined.
4672 	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4673 	 */
4674 	for (i = 0; i < FCP_NUM_HASH; i++) {
4675 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4676 		    ptgt = ptgt->tgt_next) {
4677 			mutex_enter(&ptgt->tgt_mutex);
4678 			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4679 			    (cause == FCP_CAUSE_LINK_CHANGE) &&
4680 			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4681 				fcp_offline_target_now(pptr, ptgt,
4682 				    link_cnt, ptgt->tgt_change_cnt, 0);
4683 			}
4684 			mutex_exit(&ptgt->tgt_mutex);
4685 		}
4686 	}
4687 
4688 	/*
4689 	 * At this point, the devices that were known but cannot be reached
4690 	 * anymore, have most likely been offlined.
4691 	 *
4692 	 * The following section of code seems to go through the list of
4693 	 * remote ports that can now be reached.  For every single one it
4694 	 * checks if it is already known or if it is a new port.
4695 	 */
4696 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4697 
4698 		if (check_finish_init) {
4699 			ASSERT(i > 0);
4700 			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4701 			    map_tag[i - 1], cause);
4702 			check_finish_init = 0;
4703 		}
4704 
4705 		/* get a pointer to this map entry */
4706 		map_entry = &(devlist[i]);
4707 
4708 		/*
4709 		 * Check for the duplicate map entry flag. If we have marked
4710 		 * this entry as a duplicate we skip it since the correct
4711 		 * (perhaps even same) state change will be encountered
4712 		 * later in the list.
4713 		 */
4714 		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4715 			continue;
4716 		}
4717 
4718 		/* get ptr to this map entry in our port's list (if any) */
4719 		ptgt = fcp_lookup_target(pptr,
4720 		    (uchar_t *)&(map_entry->map_pwwn));
4721 
4722 		if (ptgt) {
4723 			/*
4724 			 * This device was already known.  The field
4725 			 * tgt_aux_state is reset (was probably set to
4726 			 * FCP_TGT_TAGGED previously in this routine).
4727 			 */
4728 			ptgt->tgt_aux_state = 0;
4729 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4730 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4731 			    "handle_devices: map did/state/type/flags = "
4732 			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4733 			    "tgt_state=%d",
4734 			    map_entry->map_did.port_id, map_entry->map_state,
4735 			    map_entry->map_type, map_entry->map_flags,
4736 			    ptgt->tgt_d_id, ptgt->tgt_state);
4737 		}
4738 
4739 		if (map_entry->map_type == PORT_DEVICE_OLD ||
4740 		    map_entry->map_type == PORT_DEVICE_NEW ||
4741 		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4742 		    map_entry->map_type == PORT_DEVICE_CHANGED) {
4743 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4744 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
4745 			    "map_type=%x, did = %x",
4746 			    map_entry->map_type,
4747 			    map_entry->map_did.port_id);
4748 		}
4749 
4750 		switch (map_entry->map_type) {
4751 		case PORT_DEVICE_NOCHANGE:
4752 		case PORT_DEVICE_USER_CREATE:
4753 		case PORT_DEVICE_USER_LOGIN:
4754 		case PORT_DEVICE_NEW:
4755 		case PORT_DEVICE_REPORTLUN_CHANGED:
4756 			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4757 
4758 			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4759 			    link_cnt, (ptgt) ? map_tag[i] : 0,
4760 			    cause) == TRUE) {
4761 
4762 				FCP_TGT_TRACE(ptgt, map_tag[i],
4763 				    FCP_TGT_TRACE_2);
4764 				check_finish_init++;
4765 			}
4766 			break;
4767 
4768 		case PORT_DEVICE_OLD:
4769 			if (ptgt != NULL) {
4770 				FCP_TGT_TRACE(ptgt, map_tag[i],
4771 				    FCP_TGT_TRACE_3);
4772 
4773 				mutex_enter(&ptgt->tgt_mutex);
4774 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4775 					/*
4776 					 * Must do an in-line wait for I/Os
4777 					 * to get drained
4778 					 */
4779 					mutex_exit(&ptgt->tgt_mutex);
4780 					mutex_exit(&pptr->port_mutex);
4781 
4782 					mutex_enter(&ptgt->tgt_mutex);
4783 					while (ptgt->tgt_ipkt_cnt ||
4784 					    fcp_outstanding_lun_cmds(ptgt)
4785 					    == FC_SUCCESS) {
4786 						mutex_exit(&ptgt->tgt_mutex);
4787 						delay(drv_usectohz(1000000));
4788 						mutex_enter(&ptgt->tgt_mutex);
4789 					}
4790 					mutex_exit(&ptgt->tgt_mutex);
4791 
4792 					mutex_enter(&pptr->port_mutex);
4793 					mutex_enter(&ptgt->tgt_mutex);
4794 
4795 					(void) fcp_offline_target(pptr, ptgt,
4796 					    link_cnt, map_tag[i], 0, 0);
4797 				}
4798 				mutex_exit(&ptgt->tgt_mutex);
4799 			}
4800 			check_finish_init++;
4801 			break;
4802 
4803 		case PORT_DEVICE_USER_DELETE:
4804 		case PORT_DEVICE_USER_LOGOUT:
4805 			if (ptgt != NULL) {
4806 				FCP_TGT_TRACE(ptgt, map_tag[i],
4807 				    FCP_TGT_TRACE_4);
4808 
4809 				mutex_enter(&ptgt->tgt_mutex);
4810 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4811 					(void) fcp_offline_target(pptr, ptgt,
4812 					    link_cnt, map_tag[i], 1, 0);
4813 				}
4814 				mutex_exit(&ptgt->tgt_mutex);
4815 			}
4816 			check_finish_init++;
4817 			break;
4818 
4819 		case PORT_DEVICE_CHANGED:
4820 			if (ptgt != NULL) {
4821 				FCP_TGT_TRACE(ptgt, map_tag[i],
4822 				    FCP_TGT_TRACE_5);
4823 
4824 				if (fcp_device_changed(pptr, ptgt,
4825 				    map_entry, link_cnt, map_tag[i],
4826 				    cause) == TRUE) {
4827 					check_finish_init++;
4828 				}
4829 			} else {
4830 				if (fcp_handle_mapflags(pptr, ptgt,
4831 				    map_entry, link_cnt, 0, cause) == TRUE) {
4832 					check_finish_init++;
4833 				}
4834 			}
4835 			break;
4836 
4837 		default:
4838 			fcp_log(CE_WARN, pptr->port_dip,
4839 			    "!Invalid map_type=0x%x", map_entry->map_type);
4840 			check_finish_init++;
4841 			break;
4842 		}
4843 	}
4844 
4845 	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4846 		ASSERT(i > 0);
4847 		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4848 		    map_tag[i-1], cause);
4849 	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4850 		fcp_offline_all(pptr, link_cnt, cause);
4851 	}
4852 }
4853 
4854 static int
4855 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4856 {
4857 	struct fcp_lun	*plun;
4858 	struct fcp_port *pptr;
4859 	int		 rscn_count;
4860 	int		 lun0_newalloc;
4861 	int		 ret  = TRUE;
4862 
4863 	ASSERT(ptgt);
4864 	pptr = ptgt->tgt_port;
4865 	lun0_newalloc = 0;
4866 	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4867 		/*
4868 		 * no LUN struct for LUN 0 yet exists,
4869 		 * so create one
4870 		 */
4871 		plun = fcp_alloc_lun(ptgt);
4872 		if (plun == NULL) {
4873 			fcp_log(CE_WARN, pptr->port_dip,
4874 			    "!Failed to allocate lun 0 for"
4875 			    " D_ID=%x", ptgt->tgt_d_id);
4876 			return (ret);
4877 		}
4878 		lun0_newalloc = 1;
4879 	}
4880 
4881 	mutex_enter(&ptgt->tgt_mutex);
4882 	/*
4883 	 * consider lun 0 as device not connected if it is
4884 	 * offlined or newly allocated
4885 	 */
4886 	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4887 		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4888 	}
4889 	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4890 	plun->lun_state &= ~FCP_LUN_OFFLINE;
4891 	ptgt->tgt_lun_cnt = 1;
4892 	ptgt->tgt_report_lun_cnt = 0;
4893 	mutex_exit(&ptgt->tgt_mutex);
4894 
4895 	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4896 	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4897 	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4898 	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4899 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4900 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4901 		    "to D_ID=%x", ptgt->tgt_d_id);
4902 	} else {
4903 		ret = FALSE;
4904 	}
4905 
4906 	return (ret);
4907 }
4908 
4909 /*
4910  *     Function: fcp_handle_mapflags
4911  *
4912  *  Description: This function creates a target structure if the ptgt passed
4913  *		 is NULL.  It also kicks off the PLOGI if we are not logged
4914  *		 into the target yet or the PRLI if we are logged into the
4915  *		 target already.  The rest of the treatment is done in the
4916  *		 callbacks of the PLOGI or PRLI.
4917  *
4918  *     Argument: *pptr		FCP Port structure.
4919  *		 *ptgt		Target structure.
4920  *		 *map_entry	Array of fc_portmap_t structures.
4921  *		 link_cnt	Link state count.
4922  *		 tgt_cnt	Target state count.
4923  *		 cause		What caused this function to be called.
4924  *
4925  * Return Value: TRUE	Failed
4926  *		 FALSE	Succeeded
4927  *
4928  *	  Notes: pptr->port_mutex must be owned.
4929  */
4930 static int
4931 fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
4932     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4933 {
4934 	int			lcount;
4935 	int			tcount;
4936 	int			ret = TRUE;
4937 	int			alloc;
4938 	struct fcp_ipkt	*icmd;
4939 	struct fcp_lun	*pseq_lun = NULL;
4940 	uchar_t			opcode;
4941 	int			valid_ptgt_was_passed = FALSE;
4942 
4943 	ASSERT(mutex_owned(&pptr->port_mutex));
4944 
4945 	/*
4946 	 * This case is possible where the FCTL has come up and done discovery
4947 	 * before FCP was loaded and attached. FCTL would have discovered the
4948 	 * devices and later the ULP came online. In this case ULP's would get
4949 	 * PORT_DEVICE_NOCHANGE but target would be NULL.
4950 	 */
4951 	if (ptgt == NULL) {
4952 		/* don't already have a target */
4953 		mutex_exit(&pptr->port_mutex);
4954 		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4955 		mutex_enter(&pptr->port_mutex);
4956 
4957 		if (ptgt == NULL) {
4958 			fcp_log(CE_WARN, pptr->port_dip,
4959 			    "!FC target allocation failed");
4960 			return (ret);
4961 		}
4962 		mutex_enter(&ptgt->tgt_mutex);
4963 		ptgt->tgt_statec_cause = cause;
4964 		ptgt->tgt_tmp_cnt = 1;
4965 		mutex_exit(&ptgt->tgt_mutex);
4966 	} else {
4967 		valid_ptgt_was_passed = TRUE;
4968 	}
4969 
4970 	/*
4971 	 * Copy in the target parameters
4972 	 */
4973 	mutex_enter(&ptgt->tgt_mutex);
4974 	ptgt->tgt_d_id = map_entry->map_did.port_id;
4975 	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4976 	ptgt->tgt_pd_handle = map_entry->map_pd;
4977 	ptgt->tgt_fca_dev = NULL;
4978 
4979 	/* Copy port and node WWNs */
4980 	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4981 	    FC_WWN_SIZE);
4982 	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4983 	    FC_WWN_SIZE);
4984 
4985 	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4986 	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4987 	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4988 	    valid_ptgt_was_passed) {
4989 		/*
4990 		 * determine if there are any tape LUNs on this target
4991 		 */
4992 		for (pseq_lun = ptgt->tgt_lun;
4993 		    pseq_lun != NULL;
4994 		    pseq_lun = pseq_lun->lun_next) {
4995 			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4996 			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4997 				fcp_update_tgt_state(ptgt, FCP_RESET,
4998 				    FCP_LUN_MARK);
4999 				mutex_exit(&ptgt->tgt_mutex);
5000 				return (ret);
5001 			}
5002 		}
5003 	}
5004 
5005 	/*
5006 	 * if UA'REPORT_LUN_CHANGED received,
5007 	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
5008 	 */
5009 	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5010 		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5011 		mutex_exit(&ptgt->tgt_mutex);
5012 		mutex_exit(&pptr->port_mutex);
5013 
5014 		ret = fcp_handle_reportlun_changed(ptgt, cause);
5015 
5016 		mutex_enter(&pptr->port_mutex);
5017 		return (ret);
5018 	}
5019 
5020 	/*
5021 	 * If ptgt was NULL when this function was entered, then tgt_node_state
5022 	 * was never specifically initialized but zeroed out which means
5023 	 * FCP_TGT_NODE_NONE.
5024 	 */
5025 	switch (ptgt->tgt_node_state) {
5026 	case FCP_TGT_NODE_NONE:
5027 	case FCP_TGT_NODE_ON_DEMAND:
5028 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5029 		    !fcp_enable_auto_configuration &&
5030 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5031 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5032 		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5033 		    fcp_enable_auto_configuration &&
5034 		    (ptgt->tgt_manual_config_only == 1) &&
5035 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5036 			/*
5037 			 * If auto configuration is set and
5038 			 * the tgt_manual_config_only flag is set then
5039 			 * we only want the user to be able to change
5040 			 * the state through create_on_demand.
5041 			 */
5042 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5043 		} else {
5044 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5045 		}
5046 		break;
5047 
5048 	case FCP_TGT_NODE_PRESENT:
5049 		break;
5050 	}
5051 	/*
5052 	 * If we are booting from a fabric device, make sure we
5053 	 * mark the node state appropriately for this target to be
5054 	 * enumerated
5055 	 */
5056 	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5057 		if (bcmp((caddr_t)pptr->port_boot_wwn,
5058 		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5059 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
5060 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5061 		}
5062 	}
5063 	mutex_exit(&ptgt->tgt_mutex);
5064 
5065 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5066 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
5067 	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5068 	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5069 	    map_entry->map_rscn_info.ulp_rscn_count);
5070 
5071 	mutex_enter(&ptgt->tgt_mutex);
5072 
5073 	/*
5074 	 * Reset target OFFLINE state and mark the target BUSY
5075 	 */
5076 	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5077 	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5078 
5079 	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5080 	lcount = link_cnt;
5081 
5082 	mutex_exit(&ptgt->tgt_mutex);
5083 	mutex_exit(&pptr->port_mutex);
5084 
5085 	/*
5086 	 * if we are already logged in, then we do a PRLI, else
5087 	 * we do a PLOGI first (to get logged in)
5088 	 *
5089 	 * We will not check if we are the PLOGI initiator
5090 	 */
5091 	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5092 	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5093 
5094 	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5095 
5096 	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5097 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5098 	    cause, map_entry->map_rscn_info.ulp_rscn_count);
5099 
5100 	if (icmd == NULL) {
5101 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5102 		/*
5103 		 * We've exited port_mutex before calling fcp_icmd_alloc,
5104 		 * we need to make sure we reacquire it before returning.
5105 		 */
5106 		mutex_enter(&pptr->port_mutex);
5107 		return (FALSE);
5108 	}
5109 
5110 	/* TRUE is only returned while target is intended skipped */
5111 	ret = FALSE;
5112 	/* discover info about this target */
5113 	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5114 	    lcount, tcount, cause)) == DDI_SUCCESS) {
5115 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5116 	} else {
5117 		fcp_icmd_free(pptr, icmd);
5118 		ret = TRUE;
5119 	}
5120 	mutex_enter(&pptr->port_mutex);
5121 
5122 	return (ret);
5123 }
5124 
5125 /*
5126  *     Function: fcp_send_els
5127  *
5128  *  Description: Sends an ELS to the target specified by the caller.  Supports
5129  *		 PLOGI and PRLI.
5130  *
5131  *     Argument: *pptr		Fcp port.
5132  *		 *ptgt		Target to send the ELS to.
5133  *		 *icmd		Internal packet
5134  *		 opcode		ELS opcode
5135  *		 lcount		Link state change counter
5136  *		 tcount		Target state change counter
5137  *		 cause		What caused the call
5138  *
5139  * Return Value: DDI_SUCCESS
5140  *		 Others
5141  */
5142 static int
5143 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5144     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5145 {
5146 	fc_packet_t		*fpkt;
5147 	fc_frame_hdr_t		*hp;
5148 	int			internal = 0;
5149 	int			alloc;
5150 	int			cmd_len;
5151 	int			resp_len;
5152 	int			res = DDI_FAILURE; /* default result */
5153 	int			rval = DDI_FAILURE;
5154 
5155 	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5156 	ASSERT(ptgt->tgt_port == pptr);
5157 
5158 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5159 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5160 	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5161 	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5162 
5163 	if (opcode == LA_ELS_PLOGI) {
5164 		cmd_len = sizeof (la_els_logi_t);
5165 		resp_len = sizeof (la_els_logi_t);
5166 	} else {
5167 		ASSERT(opcode == LA_ELS_PRLI);
5168 		cmd_len = sizeof (la_els_prli_t);
5169 		resp_len = sizeof (la_els_prli_t);
5170 	}
5171 
5172 	if (icmd == NULL) {
5173 		alloc = FCP_MAX(sizeof (la_els_logi_t),
5174 		    sizeof (la_els_prli_t));
5175 		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5176 		    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5177 		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5178 		if (icmd == NULL) {
5179 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5180 			return (res);
5181 		}
5182 		internal++;
5183 	}
5184 	fpkt = icmd->ipkt_fpkt;
5185 
5186 	fpkt->pkt_cmdlen = cmd_len;
5187 	fpkt->pkt_rsplen = resp_len;
5188 	fpkt->pkt_datalen = 0;
5189 	icmd->ipkt_retries = 0;
5190 
5191 	/* fill in fpkt info */
5192 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5193 	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5194 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5195 
5196 	/* get ptr to frame hdr in fpkt */
5197 	hp = &fpkt->pkt_cmd_fhdr;
5198 
5199 	/*
5200 	 * fill in frame hdr
5201 	 */
5202 	hp->r_ctl = R_CTL_ELS_REQ;
5203 	hp->s_id = pptr->port_id;	/* source ID */
5204 	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
5205 	hp->type = FC_TYPE_EXTENDED_LS;
5206 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5207 	hp->seq_id = 0;
5208 	hp->rsvd = 0;
5209 	hp->df_ctl  = 0;
5210 	hp->seq_cnt = 0;
5211 	hp->ox_id = 0xffff;		/* i.e. none */
5212 	hp->rx_id = 0xffff;		/* i.e. none */
5213 	hp->ro = 0;
5214 
5215 	/*
5216 	 * at this point we have a filled in cmd pkt
5217 	 *
5218 	 * fill in the respective info, then use the transport to send
5219 	 * the packet
5220 	 *
5221 	 * for a PLOGI call fc_ulp_login(), and
5222 	 * for a PRLI call fc_ulp_issue_els()
5223 	 */
5224 	switch (opcode) {
5225 	case LA_ELS_PLOGI: {
5226 		struct la_els_logi logi;
5227 
5228 		bzero(&logi, sizeof (struct la_els_logi));
5229 
5230 		hp = &fpkt->pkt_cmd_fhdr;
5231 		hp->r_ctl = R_CTL_ELS_REQ;
5232 		logi.ls_code.ls_code = LA_ELS_PLOGI;
5233 		logi.ls_code.mbz = 0;
5234 
5235 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5236 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5237 
5238 		icmd->ipkt_opcode = LA_ELS_PLOGI;
5239 
5240 		mutex_enter(&pptr->port_mutex);
5241 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5242 
5243 			mutex_exit(&pptr->port_mutex);
5244 
5245 			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5246 			if (rval == FC_SUCCESS) {
5247 				res = DDI_SUCCESS;
5248 				break;
5249 			}
5250 
5251 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5252 
5253 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5254 			    rval, "PLOGI");
5255 		} else {
5256 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5257 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
5258 			    "fcp_send_els1: state change occured"
5259 			    " for D_ID=0x%x", ptgt->tgt_d_id);
5260 			mutex_exit(&pptr->port_mutex);
5261 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5262 		}
5263 		break;
5264 	}
5265 
5266 	case LA_ELS_PRLI: {
5267 		struct la_els_prli	prli;
5268 		struct fcp_prli		*fprli;
5269 
5270 		bzero(&prli, sizeof (struct la_els_prli));
5271 
5272 		hp = &fpkt->pkt_cmd_fhdr;
5273 		hp->r_ctl = R_CTL_ELS_REQ;
5274 
5275 		/* fill in PRLI cmd ELS fields */
5276 		prli.ls_code = LA_ELS_PRLI;
5277 		prli.page_length = 0x10;	/* huh? */
5278 		prli.payload_length = sizeof (struct la_els_prli);
5279 
5280 		icmd->ipkt_opcode = LA_ELS_PRLI;
5281 
5282 		/* get ptr to PRLI service params */
5283 		fprli = (struct fcp_prli *)prli.service_params;
5284 
5285 		/* fill in service params */
5286 		fprli->type = 0x08;
5287 		fprli->resvd1 = 0;
5288 		fprli->orig_process_assoc_valid = 0;
5289 		fprli->resp_process_assoc_valid = 0;
5290 		fprli->establish_image_pair = 1;
5291 		fprli->resvd2 = 0;
5292 		fprli->resvd3 = 0;
5293 		fprli->obsolete_1 = 0;
5294 		fprli->obsolete_2 = 0;
5295 		fprli->data_overlay_allowed = 0;
5296 		fprli->initiator_fn = 1;
5297 		fprli->confirmed_compl_allowed = 1;
5298 
5299 		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5300 			fprli->target_fn = 1;
5301 		} else {
5302 			fprli->target_fn = 0;
5303 		}
5304 
5305 		fprli->retry = 1;
5306 		fprli->read_xfer_rdy_disabled = 1;
5307 		fprli->write_xfer_rdy_disabled = 0;
5308 
5309 		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5310 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5311 
5312 		/* issue the PRLI request */
5313 
5314 		mutex_enter(&pptr->port_mutex);
5315 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5316 
5317 			mutex_exit(&pptr->port_mutex);
5318 
5319 			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5320 			if (rval == FC_SUCCESS) {
5321 				res = DDI_SUCCESS;
5322 				break;
5323 			}
5324 
5325 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5326 
5327 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5328 			    rval, "PRLI");
5329 		} else {
5330 			mutex_exit(&pptr->port_mutex);
5331 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5332 		}
5333 		break;
5334 	}
5335 
5336 	default:
5337 		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5338 		break;
5339 	}
5340 
5341 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5342 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5343 	    "fcp_send_els: returning %d", res);
5344 
5345 	if (res != DDI_SUCCESS) {
5346 		if (internal) {
5347 			fcp_icmd_free(pptr, icmd);
5348 		}
5349 	}
5350 
5351 	return (res);
5352 }
5353 
5354 
5355 /*
5356  * called internally update the state of all of the tgts and each LUN
5357  * for this port (i.e. each target  known to be attached to this port)
5358  * if they are not already offline
5359  *
5360  * must be called with the port mutex owned
5361  *
5362  * acquires and releases the target mutexes for each target attached
5363  * to this port
5364  */
5365 void
5366 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5367 {
5368 	int i;
5369 	struct fcp_tgt *ptgt;
5370 
5371 	ASSERT(mutex_owned(&pptr->port_mutex));
5372 
5373 	for (i = 0; i < FCP_NUM_HASH; i++) {
5374 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5375 		    ptgt = ptgt->tgt_next) {
5376 			mutex_enter(&ptgt->tgt_mutex);
5377 			fcp_update_tgt_state(ptgt, FCP_SET, state);
5378 			ptgt->tgt_change_cnt++;
5379 			ptgt->tgt_statec_cause = cause;
5380 			ptgt->tgt_tmp_cnt = 1;
5381 			ptgt->tgt_done = 0;
5382 			mutex_exit(&ptgt->tgt_mutex);
5383 		}
5384 	}
5385 }
5386 
5387 
5388 static void
5389 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5390 {
5391 	int i;
5392 	int ndevs;
5393 	struct fcp_tgt *ptgt;
5394 
5395 	ASSERT(mutex_owned(&pptr->port_mutex));
5396 
5397 	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5398 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5399 		    ptgt = ptgt->tgt_next) {
5400 			ndevs++;
5401 		}
5402 	}
5403 
5404 	if (ndevs == 0) {
5405 		return;
5406 	}
5407 	pptr->port_tmp_cnt = ndevs;
5408 
5409 	for (i = 0; i < FCP_NUM_HASH; i++) {
5410 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5411 		    ptgt = ptgt->tgt_next) {
5412 			(void) fcp_call_finish_init_held(pptr, ptgt,
5413 			    lcount, ptgt->tgt_change_cnt, cause);
5414 		}
5415 	}
5416 }
5417 
5418 /*
5419  *     Function: fcp_update_tgt_state
5420  *
5421  *  Description: This function updates the field tgt_state of a target.	 That
5422  *		 field is a bitmap and which bit can be set or reset
5423  *		 individually.	The action applied to the target state is also
5424  *		 applied to all the LUNs belonging to the target (provided the
5425  *		 LUN is not offline).  A side effect of applying the state
5426  *		 modification to the target and the LUNs is the field tgt_trace
5427  *		 of the target and lun_trace of the LUNs is set to zero.
5428  *
5429  *
5430  *     Argument: *ptgt	Target structure.
5431  *		 flag	Flag indication what action to apply (set/reset).
5432  *		 state	State bits to update.
5433  *
5434  * Return Value: None
5435  *
5436  *	Context: Interrupt, Kernel or User context.
5437  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5438  *		 calling this function.
5439  */
5440 void
5441 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5442 {
5443 	struct fcp_lun *plun;
5444 
5445 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5446 
5447 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5448 		/* The target is not offline. */
5449 		if (flag == FCP_SET) {
5450 			ptgt->tgt_state |= state;
5451 			ptgt->tgt_trace = 0;
5452 		} else {
5453 			ptgt->tgt_state &= ~state;
5454 		}
5455 
5456 		for (plun = ptgt->tgt_lun; plun != NULL;
5457 		    plun = plun->lun_next) {
5458 			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5459 				/* The LUN is not offline. */
5460 				if (flag == FCP_SET) {
5461 					plun->lun_state |= state;
5462 					plun->lun_trace = 0;
5463 				} else {
5464 					plun->lun_state &= ~state;
5465 				}
5466 			}
5467 		}
5468 	}
5469 }
5470 
5471 /*
5472  *     Function: fcp_update_tgt_state
5473  *
5474  *  Description: This function updates the field lun_state of a LUN.  That
5475  *		 field is a bitmap and which bit can be set or reset
5476  *		 individually.
5477  *
5478  *     Argument: *plun	LUN structure.
5479  *		 flag	Flag indication what action to apply (set/reset).
5480  *		 state	State bits to update.
5481  *
5482  * Return Value: None
5483  *
5484  *	Context: Interrupt, Kernel or User context.
5485  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5486  *		 calling this function.
5487  */
5488 void
5489 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5490 {
5491 	struct fcp_tgt	*ptgt = plun->lun_tgt;
5492 
5493 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5494 
5495 	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5496 		if (flag == FCP_SET) {
5497 			plun->lun_state |= state;
5498 		} else {
5499 			plun->lun_state &= ~state;
5500 		}
5501 	}
5502 }
5503 
5504 /*
5505  *     Function: fcp_get_port
5506  *
5507  *  Description: This function returns the fcp_port structure from the opaque
5508  *		 handle passed by the caller.  That opaque handle is the handle
5509  *		 used by fp/fctl to identify a particular local port.  That
5510  *		 handle has been stored in the corresponding fcp_port
5511  *		 structure.  This function is going to walk the global list of
5512  *		 fcp_port structures till one has a port_fp_handle that matches
5513  *		 the handle passed by the caller.  This function enters the
5514  *		 mutex fcp_global_mutex while walking the global list and then
5515  *		 releases it.
5516  *
5517  *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
5518  *				particular port.
5519  *
5520  * Return Value: NULL		Not found.
5521  *		 Not NULL	Pointer to the fcp_port structure.
5522  *
5523  *	Context: Interrupt, Kernel or User context.
5524  */
5525 static struct fcp_port *
5526 fcp_get_port(opaque_t port_handle)
5527 {
5528 	struct fcp_port *pptr;
5529 
5530 	ASSERT(port_handle != NULL);
5531 
5532 	mutex_enter(&fcp_global_mutex);
5533 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5534 		if (pptr->port_fp_handle == port_handle) {
5535 			break;
5536 		}
5537 	}
5538 	mutex_exit(&fcp_global_mutex);
5539 
5540 	return (pptr);
5541 }
5542 
5543 
5544 static void
5545 fcp_unsol_callback(fc_packet_t *fpkt)
5546 {
5547 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5548 	struct fcp_port *pptr = icmd->ipkt_port;
5549 
5550 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5551 		caddr_t state, reason, action, expln;
5552 
5553 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
5554 		    &action, &expln);
5555 
5556 		fcp_log(CE_WARN, pptr->port_dip,
5557 		    "!couldn't post response to unsolicited request: "
5558 		    " state=%s reason=%s rx_id=%x ox_id=%x",
5559 		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5560 		    fpkt->pkt_cmd_fhdr.rx_id);
5561 	}
5562 	fcp_icmd_free(pptr, icmd);
5563 }
5564 
5565 
5566 /*
5567  * Perform general purpose preparation of a response to an unsolicited request
5568  */
5569 static void
5570 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5571     uchar_t r_ctl, uchar_t type)
5572 {
5573 	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5574 	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5575 	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5576 	pkt->pkt_cmd_fhdr.type = type;
5577 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5578 	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5579 	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5580 	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5581 	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5582 	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5583 	pkt->pkt_cmd_fhdr.ro = 0;
5584 	pkt->pkt_cmd_fhdr.rsvd = 0;
5585 	pkt->pkt_comp = fcp_unsol_callback;
5586 	pkt->pkt_pd = NULL;
5587 	pkt->pkt_ub_resp_token = (opaque_t)buf;
5588 }
5589 
5590 
5591 /*ARGSUSED*/
5592 static int
5593 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5594 {
5595 	fc_packet_t		*fpkt;
5596 	struct la_els_prli	prli;
5597 	struct fcp_prli		*fprli;
5598 	struct fcp_ipkt	*icmd;
5599 	struct la_els_prli	*from;
5600 	struct fcp_prli		*orig;
5601 	struct fcp_tgt	*ptgt;
5602 	int			tcount = 0;
5603 	int			lcount;
5604 
5605 	from = (struct la_els_prli *)buf->ub_buffer;
5606 	orig = (struct fcp_prli *)from->service_params;
5607 	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5608 	    NULL) {
5609 		mutex_enter(&ptgt->tgt_mutex);
5610 		tcount = ptgt->tgt_change_cnt;
5611 		mutex_exit(&ptgt->tgt_mutex);
5612 	}
5613 
5614 	mutex_enter(&pptr->port_mutex);
5615 	lcount = pptr->port_link_cnt;
5616 	mutex_exit(&pptr->port_mutex);
5617 
5618 	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5619 	    sizeof (la_els_prli_t), 0,
5620 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5621 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5622 		return (FC_FAILURE);
5623 	}
5624 
5625 	fpkt = icmd->ipkt_fpkt;
5626 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5627 	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5628 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5629 	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5630 	fpkt->pkt_rsplen = 0;
5631 	fpkt->pkt_datalen = 0;
5632 
5633 	icmd->ipkt_opcode = LA_ELS_PRLI;
5634 
5635 	bzero(&prli, sizeof (struct la_els_prli));
5636 	fprli = (struct fcp_prli *)prli.service_params;
5637 	prli.ls_code = LA_ELS_ACC;
5638 	prli.page_length = 0x10;
5639 	prli.payload_length = sizeof (struct la_els_prli);
5640 
5641 	/* fill in service params */
5642 	fprli->type = 0x08;
5643 	fprli->resvd1 = 0;
5644 	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5645 	fprli->orig_process_associator = orig->orig_process_associator;
5646 	fprli->resp_process_assoc_valid = 0;
5647 	fprli->establish_image_pair = 1;
5648 	fprli->resvd2 = 0;
5649 	fprli->resvd3 = 0;
5650 	fprli->obsolete_1 = 0;
5651 	fprli->obsolete_2 = 0;
5652 	fprli->data_overlay_allowed = 0;
5653 	fprli->initiator_fn = 1;
5654 	fprli->confirmed_compl_allowed = 1;
5655 
5656 	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5657 		fprli->target_fn = 1;
5658 	} else {
5659 		fprli->target_fn = 0;
5660 	}
5661 
5662 	fprli->retry = 1;
5663 	fprli->read_xfer_rdy_disabled = 1;
5664 	fprli->write_xfer_rdy_disabled = 0;
5665 
5666 	/* save the unsol prli payload first */
5667 	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5668 	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5669 
5670 	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5671 	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5672 
5673 	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5674 
5675 	mutex_enter(&pptr->port_mutex);
5676 	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5677 		int rval;
5678 		mutex_exit(&pptr->port_mutex);
5679 
5680 		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5681 		    FC_SUCCESS) {
5682 			if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5683 			    ptgt != NULL) {
5684 				fcp_queue_ipkt(pptr, fpkt);
5685 				return (FC_SUCCESS);
5686 			}
5687 			/* Let it timeout */
5688 			fcp_icmd_free(pptr, icmd);
5689 			return (FC_FAILURE);
5690 		}
5691 	} else {
5692 		mutex_exit(&pptr->port_mutex);
5693 		fcp_icmd_free(pptr, icmd);
5694 		return (FC_FAILURE);
5695 	}
5696 
5697 	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5698 
5699 	return (FC_SUCCESS);
5700 }
5701 
5702 /*
5703  *     Function: fcp_icmd_alloc
5704  *
5705  *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
5706  *		 field is initialized to fcp_icmd_callback.  Sometimes it is
5707  *		 modified by the caller (such as fcp_send_scsi).  The
5708  *		 structure is also tied to the state of the line and of the
5709  *		 target at a particular time.  That link is established by
5710  *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5711  *		 and tcount which came respectively from pptr->link_cnt and
5712  *		 ptgt->tgt_change_cnt.
5713  *
5714  *     Argument: *pptr		Fcp port.
5715  *		 *ptgt		Target (destination of the command).
5716  *		 cmd_len	Length of the command.
5717  *		 resp_len	Length of the expected response.
5718  *		 data_len	Length of the data.
5719  *		 nodma		Indicates weither the command and response.
5720  *				will be transfer through DMA or not.
5721  *		 lcount		Link state change counter.
5722  *		 tcount		Target state change counter.
5723  *		 cause		Reason that lead to this call.
5724  *
5725  * Return Value: NULL		Failed.
5726  *		 Not NULL	Internal packet address.
5727  */
5728 static struct fcp_ipkt *
5729 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5730     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5731     uint32_t rscn_count)
5732 {
5733 	int			dma_setup = 0;
5734 	fc_packet_t		*fpkt;
5735 	struct fcp_ipkt	*icmd = NULL;
5736 
5737 	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5738 	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5739 	    KM_NOSLEEP);
5740 	if (icmd == NULL) {
5741 		fcp_log(CE_WARN, pptr->port_dip,
5742 		    "!internal packet allocation failed");
5743 		return (NULL);
5744 	}
5745 
5746 	/*
5747 	 * initialize the allocated packet
5748 	 */
5749 	icmd->ipkt_nodma = nodma;
5750 	icmd->ipkt_next = icmd->ipkt_prev = NULL;
5751 	icmd->ipkt_lun = NULL;
5752 
5753 	icmd->ipkt_link_cnt = lcount;
5754 	icmd->ipkt_change_cnt = tcount;
5755 	icmd->ipkt_cause = cause;
5756 
5757 	mutex_enter(&pptr->port_mutex);
5758 	icmd->ipkt_port = pptr;
5759 	mutex_exit(&pptr->port_mutex);
5760 
5761 	/* keep track of amt of data to be sent in pkt */
5762 	icmd->ipkt_cmdlen = cmd_len;
5763 	icmd->ipkt_resplen = resp_len;
5764 	icmd->ipkt_datalen = data_len;
5765 
5766 	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5767 	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5768 
5769 	/* set pkt's private ptr to point to cmd pkt */
5770 	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5771 
5772 	/* set FCA private ptr to memory just beyond */
5773 	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5774 	    ((char *)icmd + sizeof (struct fcp_ipkt) +
5775 	    pptr->port_dmacookie_sz);
5776 
5777 	/* get ptr to fpkt substruct and fill it in */
5778 	fpkt = icmd->ipkt_fpkt;
5779 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5780 	    sizeof (struct fcp_ipkt));
5781 
5782 	if (ptgt != NULL) {
5783 		icmd->ipkt_tgt = ptgt;
5784 		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5785 	}
5786 
5787 	fpkt->pkt_comp = fcp_icmd_callback;
5788 	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5789 	fpkt->pkt_cmdlen = cmd_len;
5790 	fpkt->pkt_rsplen = resp_len;
5791 	fpkt->pkt_datalen = data_len;
5792 
5793 	/*
5794 	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5795 	 * rscn_count as fcp knows down to the transport. If a valid count was
5796 	 * passed into this function, we allocate memory to actually pass down
5797 	 * this info.
5798 	 *
5799 	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5800 	 * basically mean that fcp will not be able to help transport
5801 	 * distinguish if a new RSCN has come after fcp was last informed about
5802 	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5803 	 * 5068068 where the device might end up going offline in case of RSCN
5804 	 * storms.
5805 	 */
5806 	fpkt->pkt_ulp_rscn_infop = NULL;
5807 	if (rscn_count != FC_INVALID_RSCN_COUNT) {
5808 		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5809 		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5810 		if (fpkt->pkt_ulp_rscn_infop == NULL) {
5811 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5812 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5813 			    "Failed to alloc memory to pass rscn info");
5814 		}
5815 	}
5816 
5817 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5818 		fc_ulp_rscn_info_t	*rscnp;
5819 
5820 		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5821 		rscnp->ulp_rscn_count = rscn_count;
5822 	}
5823 
5824 	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5825 		goto fail;
5826 	}
5827 	dma_setup++;
5828 
5829 	/*
5830 	 * Must hold target mutex across setting of pkt_pd and call to
5831 	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5832 	 * away while we're not looking.
5833 	 */
5834 	if (ptgt != NULL) {
5835 		mutex_enter(&ptgt->tgt_mutex);
5836 		fpkt->pkt_pd = ptgt->tgt_pd_handle;
5837 
5838 		/* ask transport to do its initialization on this pkt */
5839 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5840 		    != FC_SUCCESS) {
5841 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5842 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5843 			    "fc_ulp_init_packet failed");
5844 			mutex_exit(&ptgt->tgt_mutex);
5845 			goto fail;
5846 		}
5847 		mutex_exit(&ptgt->tgt_mutex);
5848 	} else {
5849 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5850 		    != FC_SUCCESS) {
5851 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5852 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5853 			    "fc_ulp_init_packet failed");
5854 			goto fail;
5855 		}
5856 	}
5857 
5858 	mutex_enter(&pptr->port_mutex);
5859 	if (pptr->port_state & (FCP_STATE_DETACHING |
5860 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5861 		int rval;
5862 
5863 		mutex_exit(&pptr->port_mutex);
5864 
5865 		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5866 		ASSERT(rval == FC_SUCCESS);
5867 
5868 		goto fail;
5869 	}
5870 
5871 	if (ptgt != NULL) {
5872 		mutex_enter(&ptgt->tgt_mutex);
5873 		ptgt->tgt_ipkt_cnt++;
5874 		mutex_exit(&ptgt->tgt_mutex);
5875 	}
5876 
5877 	pptr->port_ipkt_cnt++;
5878 
5879 	mutex_exit(&pptr->port_mutex);
5880 
5881 	return (icmd);
5882 
5883 fail:
5884 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5885 		kmem_free(fpkt->pkt_ulp_rscn_infop,
5886 		    sizeof (fc_ulp_rscn_info_t));
5887 		fpkt->pkt_ulp_rscn_infop = NULL;
5888 	}
5889 
5890 	if (dma_setup) {
5891 		fcp_free_dma(pptr, icmd);
5892 	}
5893 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5894 	    (size_t)pptr->port_dmacookie_sz);
5895 
5896 	return (NULL);
5897 }
5898 
5899 /*
5900  *     Function: fcp_icmd_free
5901  *
5902  *  Description: Frees the internal command passed by the caller.
5903  *
5904  *     Argument: *pptr		Fcp port.
5905  *		 *icmd		Internal packet to free.
5906  *
5907  * Return Value: None
5908  */
5909 static void
5910 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5911 {
5912 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
5913 
5914 	/* Let the underlying layers do their cleanup. */
5915 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5916 	    icmd->ipkt_fpkt);
5917 
5918 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5919 		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5920 		    sizeof (fc_ulp_rscn_info_t));
5921 	}
5922 
5923 	fcp_free_dma(pptr, icmd);
5924 
5925 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5926 	    (size_t)pptr->port_dmacookie_sz);
5927 
5928 	mutex_enter(&pptr->port_mutex);
5929 
5930 	if (ptgt) {
5931 		mutex_enter(&ptgt->tgt_mutex);
5932 		ptgt->tgt_ipkt_cnt--;
5933 		mutex_exit(&ptgt->tgt_mutex);
5934 	}
5935 
5936 	pptr->port_ipkt_cnt--;
5937 	mutex_exit(&pptr->port_mutex);
5938 }
5939 
5940 /*
5941  *     Function: fcp_alloc_dma
5942  *
5943  *  Description: Allocated the DMA resources required for the internal
5944  *		 packet.
5945  *
5946  *     Argument: *pptr	FCP port.
5947  *		 *icmd	Internal FCP packet.
5948  *		 nodma	Indicates if the Cmd and Resp will be DMAed.
5949  *		 flags	Allocation flags (Sleep or NoSleep).
5950  *
5951  * Return Value: FC_SUCCESS
5952  *		 FC_NOMEM
5953  */
5954 static int
5955 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5956     int nodma, int flags)
5957 {
5958 	int		rval;
5959 	size_t		real_size;
5960 	uint_t		ccount;
5961 	int		bound = 0;
5962 	int		cmd_resp = 0;
5963 	fc_packet_t	*fpkt;
5964 	ddi_dma_cookie_t	pkt_data_cookie;
5965 	ddi_dma_cookie_t	*cp;
5966 	uint32_t		cnt;
5967 
5968 	fpkt = &icmd->ipkt_fc_packet;
5969 
5970 	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5971 	    fpkt->pkt_resp_dma == NULL);
5972 
5973 	icmd->ipkt_nodma = nodma;
5974 
5975 	if (nodma) {
5976 		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5977 		if (fpkt->pkt_cmd == NULL) {
5978 			goto fail;
5979 		}
5980 
5981 		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5982 		if (fpkt->pkt_resp == NULL) {
5983 			goto fail;
5984 		}
5985 	} else {
5986 		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5987 
5988 		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5989 		if (rval == FC_FAILURE) {
5990 			ASSERT(fpkt->pkt_cmd_dma == NULL &&
5991 			    fpkt->pkt_resp_dma == NULL);
5992 			goto fail;
5993 		}
5994 		cmd_resp++;
5995 	}
5996 
5997 	if ((fpkt->pkt_datalen != 0) &&
5998 	    !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
5999 		/*
6000 		 * set up DMA handle and memory for the data in this packet
6001 		 */
6002 		if (ddi_dma_alloc_handle(pptr->port_dip,
6003 		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6004 		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6005 			goto fail;
6006 		}
6007 
6008 		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6009 		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6010 		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6011 		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6012 			goto fail;
6013 		}
6014 
6015 		/* was DMA mem size gotten < size asked for/needed ?? */
6016 		if (real_size < fpkt->pkt_datalen) {
6017 			goto fail;
6018 		}
6019 
6020 		/* bind DMA address and handle together */
6021 		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6022 		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6023 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6024 		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6025 			goto fail;
6026 		}
6027 		bound++;
6028 
6029 		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6030 			goto fail;
6031 		}
6032 
6033 		fpkt->pkt_data_cookie_cnt = ccount;
6034 
6035 		cp = fpkt->pkt_data_cookie;
6036 		*cp = pkt_data_cookie;
6037 		cp++;
6038 
6039 		for (cnt = 1; cnt < ccount; cnt++, cp++) {
6040 			ddi_dma_nextcookie(fpkt->pkt_data_dma,
6041 			    &pkt_data_cookie);
6042 			*cp = pkt_data_cookie;
6043 		}
6044 
6045 	} else if (fpkt->pkt_datalen != 0) {
6046 		/*
6047 		 * If it's a pseudo FCA, then it can't support DMA even in
6048 		 * SCSI data phase.
6049 		 */
6050 		fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6051 		if (fpkt->pkt_data == NULL) {
6052 			goto fail;
6053 		}
6054 
6055 	}
6056 
6057 	return (FC_SUCCESS);
6058 
6059 fail:
6060 	if (bound) {
6061 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6062 	}
6063 
6064 	if (fpkt->pkt_data_dma) {
6065 		if (fpkt->pkt_data) {
6066 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6067 		}
6068 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6069 	} else {
6070 		if (fpkt->pkt_data) {
6071 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6072 		}
6073 	}
6074 
6075 	if (nodma) {
6076 		if (fpkt->pkt_cmd) {
6077 			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6078 		}
6079 		if (fpkt->pkt_resp) {
6080 			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6081 		}
6082 	} else {
6083 		if (cmd_resp) {
6084 			fcp_free_cmd_resp(pptr, fpkt);
6085 		}
6086 	}
6087 
6088 	return (FC_NOMEM);
6089 }
6090 
6091 
6092 static void
6093 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6094 {
6095 	fc_packet_t *fpkt = icmd->ipkt_fpkt;
6096 
6097 	if (fpkt->pkt_data_dma) {
6098 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6099 		if (fpkt->pkt_data) {
6100 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6101 		}
6102 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6103 	} else {
6104 		if (fpkt->pkt_data) {
6105 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6106 		}
6107 		/*
6108 		 * Need we reset pkt_* to zero???
6109 		 */
6110 	}
6111 
6112 	if (icmd->ipkt_nodma) {
6113 		if (fpkt->pkt_cmd) {
6114 			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6115 		}
6116 		if (fpkt->pkt_resp) {
6117 			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6118 		}
6119 	} else {
6120 		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6121 
6122 		fcp_free_cmd_resp(pptr, fpkt);
6123 	}
6124 }
6125 
6126 /*
6127  *     Function: fcp_lookup_target
6128  *
6129  *  Description: Finds a target given a WWN.
6130  *
6131  *     Argument: *pptr	FCP port.
6132  *		 *wwn	World Wide Name of the device to look for.
6133  *
6134  * Return Value: NULL		No target found
6135  *		 Not NULL	Target structure
6136  *
6137  *	Context: Interrupt context.
6138  *		 The mutex pptr->port_mutex must be owned.
6139  */
6140 /* ARGSUSED */
6141 static struct fcp_tgt *
6142 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6143 {
6144 	int			hash;
6145 	struct fcp_tgt	*ptgt;
6146 
6147 	ASSERT(mutex_owned(&pptr->port_mutex));
6148 
6149 	hash = FCP_HASH(wwn);
6150 
6151 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6152 	    ptgt = ptgt->tgt_next) {
6153 		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6154 		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6155 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
6156 			break;
6157 		}
6158 	}
6159 
6160 	return (ptgt);
6161 }
6162 
6163 
6164 /*
6165  * Find target structure given a port identifier
6166  */
6167 static struct fcp_tgt *
6168 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6169 {
6170 	fc_portid_t		port_id;
6171 	la_wwn_t		pwwn;
6172 	struct fcp_tgt	*ptgt = NULL;
6173 
6174 	port_id.priv_lilp_posit = 0;
6175 	port_id.port_id = d_id;
6176 	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6177 	    &pwwn) == FC_SUCCESS) {
6178 		mutex_enter(&pptr->port_mutex);
6179 		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6180 		mutex_exit(&pptr->port_mutex);
6181 	}
6182 
6183 	return (ptgt);
6184 }
6185 
6186 
6187 /*
6188  * the packet completion callback routine for info cmd pkts
6189  *
6190  * this means fpkt pts to a response to either a PLOGI or a PRLI
6191  *
6192  * if there is an error an attempt is made to call a routine to resend
6193  * the command that failed
6194  */
6195 static void
6196 fcp_icmd_callback(fc_packet_t *fpkt)
6197 {
6198 	struct fcp_ipkt	*icmd;
6199 	struct fcp_port	*pptr;
6200 	struct fcp_tgt	*ptgt;
6201 	struct la_els_prli	*prli;
6202 	struct la_els_prli	prli_s;
6203 	struct fcp_prli		*fprli;
6204 	struct fcp_lun	*plun;
6205 	int		free_pkt = 1;
6206 	int		rval;
6207 	ls_code_t	resp;
6208 	uchar_t		prli_acc = 0;
6209 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
6210 	int		lun0_newalloc;
6211 
6212 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6213 
6214 	/* get ptrs to the port and target structs for the cmd */
6215 	pptr = icmd->ipkt_port;
6216 	ptgt = icmd->ipkt_tgt;
6217 
6218 	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6219 
6220 	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6221 		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6222 		    sizeof (prli_s));
6223 		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6224 	}
6225 
6226 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6227 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6228 	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
6229 	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6230 	    ptgt->tgt_d_id);
6231 
6232 	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6233 	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6234 
6235 		mutex_enter(&ptgt->tgt_mutex);
6236 		if (ptgt->tgt_pd_handle == NULL) {
6237 			/*
6238 			 * in a fabric environment the port device handles
6239 			 * get created only after successful LOGIN into the
6240 			 * transport, so the transport makes this port
6241 			 * device (pd) handle available in this packet, so
6242 			 * save it now
6243 			 */
6244 			ASSERT(fpkt->pkt_pd != NULL);
6245 			ptgt->tgt_pd_handle = fpkt->pkt_pd;
6246 		}
6247 		mutex_exit(&ptgt->tgt_mutex);
6248 
6249 		/* which ELS cmd is this response for ?? */
6250 		switch (icmd->ipkt_opcode) {
6251 		case LA_ELS_PLOGI:
6252 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6253 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6254 			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6255 			    ptgt->tgt_d_id,
6256 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6257 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6258 
6259 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6260 			    FCP_TGT_TRACE_15);
6261 
6262 			/* Note that we are not allocating a new icmd */
6263 			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6264 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6265 			    icmd->ipkt_cause) != DDI_SUCCESS) {
6266 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6267 				    FCP_TGT_TRACE_16);
6268 				goto fail;
6269 			}
6270 			break;
6271 
6272 		case LA_ELS_PRLI:
6273 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6274 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6275 			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6276 
6277 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6278 			    FCP_TGT_TRACE_17);
6279 
6280 			prli = &prli_s;
6281 
6282 			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6283 			    sizeof (prli_s));
6284 
6285 			fprli = (struct fcp_prli *)prli->service_params;
6286 
6287 			mutex_enter(&ptgt->tgt_mutex);
6288 			ptgt->tgt_icap = fprli->initiator_fn;
6289 			ptgt->tgt_tcap = fprli->target_fn;
6290 			mutex_exit(&ptgt->tgt_mutex);
6291 
6292 			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6293 				/*
6294 				 * this FCP device does not support target mode
6295 				 */
6296 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6297 				    FCP_TGT_TRACE_18);
6298 				goto fail;
6299 			}
6300 			if (fprli->retry == 1) {
6301 				fc_ulp_disable_relogin(pptr->port_fp_handle,
6302 				    &ptgt->tgt_port_wwn);
6303 			}
6304 
6305 			/* target is no longer offline */
6306 			mutex_enter(&pptr->port_mutex);
6307 			mutex_enter(&ptgt->tgt_mutex);
6308 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6309 				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6310 				    FCP_TGT_MARK);
6311 			} else {
6312 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6313 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6314 				    "fcp_icmd_callback,1: state change "
6315 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6316 				mutex_exit(&ptgt->tgt_mutex);
6317 				mutex_exit(&pptr->port_mutex);
6318 				goto fail;
6319 			}
6320 			mutex_exit(&ptgt->tgt_mutex);
6321 			mutex_exit(&pptr->port_mutex);
6322 
6323 			/*
6324 			 * lun 0 should always respond to inquiry, so
6325 			 * get the LUN struct for LUN 0
6326 			 *
6327 			 * Currently we deal with first level of addressing.
6328 			 * If / when we start supporting 0x device types
6329 			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6330 			 * this logic will need revisiting.
6331 			 */
6332 			lun0_newalloc = 0;
6333 			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6334 				/*
6335 				 * no LUN struct for LUN 0 yet exists,
6336 				 * so create one
6337 				 */
6338 				plun = fcp_alloc_lun(ptgt);
6339 				if (plun == NULL) {
6340 					fcp_log(CE_WARN, pptr->port_dip,
6341 					    "!Failed to allocate lun 0 for"
6342 					    " D_ID=%x", ptgt->tgt_d_id);
6343 					goto fail;
6344 				}
6345 				lun0_newalloc = 1;
6346 			}
6347 
6348 			/* fill in LUN info */
6349 			mutex_enter(&ptgt->tgt_mutex);
6350 			/*
6351 			 * consider lun 0 as device not connected if it is
6352 			 * offlined or newly allocated
6353 			 */
6354 			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6355 			    lun0_newalloc) {
6356 				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6357 			}
6358 			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6359 			plun->lun_state &= ~FCP_LUN_OFFLINE;
6360 			ptgt->tgt_lun_cnt = 1;
6361 			ptgt->tgt_report_lun_cnt = 0;
6362 			mutex_exit(&ptgt->tgt_mutex);
6363 
6364 			/* Retrieve the rscn count (if a valid one exists) */
6365 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6366 				rscn_count = ((fc_ulp_rscn_info_t *)
6367 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6368 				    ->ulp_rscn_count;
6369 			} else {
6370 				rscn_count = FC_INVALID_RSCN_COUNT;
6371 			}
6372 
6373 			/* send Report Lun request to target */
6374 			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6375 			    sizeof (struct fcp_reportlun_resp),
6376 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6377 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6378 				mutex_enter(&pptr->port_mutex);
6379 				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6380 					fcp_log(CE_WARN, pptr->port_dip,
6381 					    "!Failed to send REPORT LUN to"
6382 					    "  D_ID=%x", ptgt->tgt_d_id);
6383 				} else {
6384 					FCP_TRACE(fcp_logq,
6385 					    pptr->port_instbuf, fcp_trace,
6386 					    FCP_BUF_LEVEL_5, 0,
6387 					    "fcp_icmd_callback,2:state change"
6388 					    " occured for D_ID=0x%x",
6389 					    ptgt->tgt_d_id);
6390 				}
6391 				mutex_exit(&pptr->port_mutex);
6392 
6393 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6394 				    FCP_TGT_TRACE_19);
6395 
6396 				goto fail;
6397 			} else {
6398 				free_pkt = 0;
6399 				fcp_icmd_free(pptr, icmd);
6400 			}
6401 			break;
6402 
6403 		default:
6404 			fcp_log(CE_WARN, pptr->port_dip,
6405 			    "!fcp_icmd_callback Invalid opcode");
6406 			goto fail;
6407 		}
6408 
6409 		return;
6410 	}
6411 
6412 
6413 	/*
6414 	 * Other PLOGI failures are not retried as the
6415 	 * transport does it already
6416 	 */
6417 	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6418 		if (fcp_is_retryable(icmd) &&
6419 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6420 
6421 			if (FCP_MUST_RETRY(fpkt)) {
6422 				fcp_queue_ipkt(pptr, fpkt);
6423 				return;
6424 			}
6425 
6426 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6427 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6428 			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
6429 			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6430 			    fpkt->pkt_reason);
6431 
6432 			/*
6433 			 * Retry by recalling the routine that
6434 			 * originally queued this packet
6435 			 */
6436 			mutex_enter(&pptr->port_mutex);
6437 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6438 				caddr_t msg;
6439 
6440 				mutex_exit(&pptr->port_mutex);
6441 
6442 				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6443 
6444 				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6445 					fpkt->pkt_timeout +=
6446 					    FCP_TIMEOUT_DELTA;
6447 				}
6448 
6449 				rval = fc_ulp_issue_els(pptr->port_fp_handle,
6450 				    fpkt);
6451 				if (rval == FC_SUCCESS) {
6452 					return;
6453 				}
6454 
6455 				if (rval == FC_STATEC_BUSY ||
6456 				    rval == FC_OFFLINE) {
6457 					fcp_queue_ipkt(pptr, fpkt);
6458 					return;
6459 				}
6460 				(void) fc_ulp_error(rval, &msg);
6461 
6462 				fcp_log(CE_NOTE, pptr->port_dip,
6463 				    "!ELS 0x%x failed to d_id=0x%x;"
6464 				    " %s", icmd->ipkt_opcode,
6465 				    ptgt->tgt_d_id, msg);
6466 			} else {
6467 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6468 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6469 				    "fcp_icmd_callback,3: state change "
6470 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6471 				mutex_exit(&pptr->port_mutex);
6472 			}
6473 		}
6474 	} else {
6475 		if (fcp_is_retryable(icmd) &&
6476 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6477 			if (FCP_MUST_RETRY(fpkt)) {
6478 				fcp_queue_ipkt(pptr, fpkt);
6479 				return;
6480 			}
6481 		}
6482 		mutex_enter(&pptr->port_mutex);
6483 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6484 		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6485 			mutex_exit(&pptr->port_mutex);
6486 			fcp_print_error(fpkt);
6487 		} else {
6488 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6489 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6490 			    "fcp_icmd_callback,4: state change occured"
6491 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6492 			mutex_exit(&pptr->port_mutex);
6493 		}
6494 	}
6495 
6496 fail:
6497 	if (free_pkt) {
6498 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6499 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6500 		fcp_icmd_free(pptr, icmd);
6501 	}
6502 }
6503 
6504 
6505 /*
6506  * called internally to send an info cmd using the transport
6507  *
6508  * sends either an INQ or a REPORT_LUN
6509  *
6510  * when the packet is completed fcp_scsi_callback is called
6511  */
6512 static int
6513 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6514     int lcount, int tcount, int cause, uint32_t rscn_count)
6515 {
6516 	int			nodma;
6517 	struct fcp_ipkt		*icmd;
6518 	struct fcp_tgt		*ptgt;
6519 	struct fcp_port		*pptr;
6520 	fc_frame_hdr_t		*hp;
6521 	fc_packet_t		*fpkt;
6522 	struct fcp_cmd		fcp_cmd;
6523 	struct fcp_cmd		*fcmd;
6524 	union scsi_cdb		*scsi_cdb;
6525 
6526 	ASSERT(plun != NULL);
6527 
6528 	ptgt = plun->lun_tgt;
6529 	ASSERT(ptgt != NULL);
6530 
6531 	pptr = ptgt->tgt_port;
6532 	ASSERT(pptr != NULL);
6533 
6534 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6535 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6536 	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6537 
6538 	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6539 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6540 	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6541 	    rscn_count);
6542 
6543 	if (icmd == NULL) {
6544 		return (DDI_FAILURE);
6545 	}
6546 
6547 	fpkt = icmd->ipkt_fpkt;
6548 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6549 	icmd->ipkt_retries = 0;
6550 	icmd->ipkt_opcode = opcode;
6551 	icmd->ipkt_lun = plun;
6552 
6553 	if (nodma) {
6554 		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6555 	} else {
6556 		fcmd = &fcp_cmd;
6557 	}
6558 	bzero(fcmd, sizeof (struct fcp_cmd));
6559 
6560 	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6561 
6562 	hp = &fpkt->pkt_cmd_fhdr;
6563 
6564 	hp->s_id = pptr->port_id;
6565 	hp->d_id = ptgt->tgt_d_id;
6566 	hp->r_ctl = R_CTL_COMMAND;
6567 	hp->type = FC_TYPE_SCSI_FCP;
6568 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6569 	hp->rsvd = 0;
6570 	hp->seq_id = 0;
6571 	hp->seq_cnt = 0;
6572 	hp->ox_id = 0xffff;
6573 	hp->rx_id = 0xffff;
6574 	hp->ro = 0;
6575 
6576 	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6577 
6578 	/*
6579 	 * Request SCSI target for expedited processing
6580 	 */
6581 
6582 	/*
6583 	 * Set up for untagged queuing because we do not
6584 	 * know if the fibre device supports queuing.
6585 	 */
6586 	fcmd->fcp_cntl.cntl_reserved_0 = 0;
6587 	fcmd->fcp_cntl.cntl_reserved_1 = 0;
6588 	fcmd->fcp_cntl.cntl_reserved_2 = 0;
6589 	fcmd->fcp_cntl.cntl_reserved_3 = 0;
6590 	fcmd->fcp_cntl.cntl_reserved_4 = 0;
6591 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6592 	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6593 
6594 	switch (opcode) {
6595 	case SCMD_INQUIRY_PAGE83:
6596 		/*
6597 		 * Prepare to get the Inquiry VPD page 83 information
6598 		 */
6599 		fcmd->fcp_cntl.cntl_read_data = 1;
6600 		fcmd->fcp_cntl.cntl_write_data = 0;
6601 		fcmd->fcp_data_len = alloc_len;
6602 
6603 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6604 		fpkt->pkt_comp = fcp_scsi_callback;
6605 
6606 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6607 		scsi_cdb->g0_addr2 = 0x01;
6608 		scsi_cdb->g0_addr1 = 0x83;
6609 		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6610 		break;
6611 
6612 	case SCMD_INQUIRY:
6613 		fcmd->fcp_cntl.cntl_read_data = 1;
6614 		fcmd->fcp_cntl.cntl_write_data = 0;
6615 		fcmd->fcp_data_len = alloc_len;
6616 
6617 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6618 		fpkt->pkt_comp = fcp_scsi_callback;
6619 
6620 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6621 		scsi_cdb->g0_count0 = SUN_INQSIZE;
6622 		break;
6623 
6624 	case SCMD_REPORT_LUN: {
6625 		fc_portid_t	d_id;
6626 		opaque_t	fca_dev;
6627 
6628 		ASSERT(alloc_len >= 16);
6629 
6630 		d_id.priv_lilp_posit = 0;
6631 		d_id.port_id = ptgt->tgt_d_id;
6632 
6633 		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6634 
6635 		mutex_enter(&ptgt->tgt_mutex);
6636 		ptgt->tgt_fca_dev = fca_dev;
6637 		mutex_exit(&ptgt->tgt_mutex);
6638 
6639 		fcmd->fcp_cntl.cntl_read_data = 1;
6640 		fcmd->fcp_cntl.cntl_write_data = 0;
6641 		fcmd->fcp_data_len = alloc_len;
6642 
6643 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6644 		fpkt->pkt_comp = fcp_scsi_callback;
6645 
6646 		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6647 		scsi_cdb->scc5_count0 = alloc_len & 0xff;
6648 		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6649 		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6650 		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6651 		break;
6652 	}
6653 
6654 	default:
6655 		fcp_log(CE_WARN, pptr->port_dip,
6656 		    "!fcp_send_scsi Invalid opcode");
6657 		break;
6658 	}
6659 
6660 	if (!nodma) {
6661 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6662 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6663 	}
6664 
6665 	mutex_enter(&pptr->port_mutex);
6666 	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6667 
6668 		mutex_exit(&pptr->port_mutex);
6669 		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6670 		    FC_SUCCESS) {
6671 			fcp_icmd_free(pptr, icmd);
6672 			return (DDI_FAILURE);
6673 		}
6674 		return (DDI_SUCCESS);
6675 	} else {
6676 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6677 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6678 		    "fcp_send_scsi,1: state change occured"
6679 		    " for D_ID=0x%x", ptgt->tgt_d_id);
6680 		mutex_exit(&pptr->port_mutex);
6681 		fcp_icmd_free(pptr, icmd);
6682 		return (DDI_FAILURE);
6683 	}
6684 }
6685 
6686 
6687 /*
6688  * called by fcp_scsi_callback to check to handle the case where
6689  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6690  */
6691 static int
6692 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6693 {
6694 	uchar_t				rqlen;
6695 	int				rval = DDI_FAILURE;
6696 	struct scsi_extended_sense	sense_info, *sense;
6697 	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
6698 	    fpkt->pkt_ulp_private;
6699 	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
6700 	struct fcp_port		*pptr = ptgt->tgt_port;
6701 
6702 	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6703 
6704 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6705 		/*
6706 		 * SCSI-II Reserve Release support. Some older FC drives return
6707 		 * Reservation conflict for Report Luns command.
6708 		 */
6709 		if (icmd->ipkt_nodma) {
6710 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6711 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6712 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6713 		} else {
6714 			fcp_rsp_t	new_resp;
6715 
6716 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6717 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6718 
6719 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6720 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6721 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6722 
6723 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6724 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6725 		}
6726 
6727 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6728 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6729 
6730 		return (DDI_SUCCESS);
6731 	}
6732 
6733 	sense = &sense_info;
6734 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
6735 		/* no need to continue if sense length is not set */
6736 		return (rval);
6737 	}
6738 
6739 	/* casting 64-bit integer to 8-bit */
6740 	rqlen = (uchar_t)min(rsp->fcp_sense_len,
6741 	    sizeof (struct scsi_extended_sense));
6742 
6743 	if (rqlen < 14) {
6744 		/* no need to continue if request length isn't long enough */
6745 		return (rval);
6746 	}
6747 
6748 	if (icmd->ipkt_nodma) {
6749 		/*
6750 		 * We can safely use fcp_response_len here since the
6751 		 * only path that calls fcp_check_reportlun,
6752 		 * fcp_scsi_callback, has already called
6753 		 * fcp_validate_fcp_response.
6754 		 */
6755 		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6756 		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6757 	} else {
6758 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6759 		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6760 		    sizeof (struct scsi_extended_sense));
6761 	}
6762 
6763 	if (!FCP_SENSE_NO_LUN(sense)) {
6764 		mutex_enter(&ptgt->tgt_mutex);
6765 		/* clear the flag if any */
6766 		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6767 		mutex_exit(&ptgt->tgt_mutex);
6768 	}
6769 
6770 	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6771 	    (sense->es_add_code == 0x20)) {
6772 		if (icmd->ipkt_nodma) {
6773 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6774 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6775 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6776 		} else {
6777 			fcp_rsp_t	new_resp;
6778 
6779 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6780 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6781 
6782 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6783 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6784 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6785 
6786 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6787 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6788 		}
6789 
6790 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6791 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6792 
6793 		return (DDI_SUCCESS);
6794 	}
6795 
6796 	/*
6797 	 * This is for the STK library which returns a check condition,
6798 	 * to indicate device is not ready, manual assistance needed.
6799 	 * This is to a report lun command when the door is open.
6800 	 */
6801 	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6802 		if (icmd->ipkt_nodma) {
6803 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6804 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6805 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6806 		} else {
6807 			fcp_rsp_t	new_resp;
6808 
6809 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6810 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6811 
6812 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6813 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6814 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6815 
6816 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6817 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6818 		}
6819 
6820 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6821 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6822 
6823 		return (DDI_SUCCESS);
6824 	}
6825 
6826 	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6827 	    (FCP_SENSE_NO_LUN(sense))) {
6828 		mutex_enter(&ptgt->tgt_mutex);
6829 		if ((FCP_SENSE_NO_LUN(sense)) &&
6830 		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6831 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6832 			mutex_exit(&ptgt->tgt_mutex);
6833 			/*
6834 			 * reconfig was triggred by ILLEGAL REQUEST but
6835 			 * got ILLEGAL REQUEST again
6836 			 */
6837 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6838 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
6839 			    "!FCP: Unable to obtain Report Lun data"
6840 			    " target=%x", ptgt->tgt_d_id);
6841 		} else {
6842 			if (ptgt->tgt_tid == NULL) {
6843 				timeout_id_t	tid;
6844 				/*
6845 				 * REPORT LUN data has changed.	 Kick off
6846 				 * rediscovery
6847 				 */
6848 				tid = timeout(fcp_reconfigure_luns,
6849 				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6850 
6851 				ptgt->tgt_tid = tid;
6852 				ptgt->tgt_state |= FCP_TGT_BUSY;
6853 			}
6854 			if (FCP_SENSE_NO_LUN(sense)) {
6855 				ptgt->tgt_state |= FCP_TGT_ILLREQ;
6856 			}
6857 			mutex_exit(&ptgt->tgt_mutex);
6858 			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6859 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6860 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6861 				    "!FCP:Report Lun Has Changed"
6862 				    " target=%x", ptgt->tgt_d_id);
6863 			} else if (FCP_SENSE_NO_LUN(sense)) {
6864 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6865 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6866 				    "!FCP:LU Not Supported"
6867 				    " target=%x", ptgt->tgt_d_id);
6868 			}
6869 		}
6870 		rval = DDI_SUCCESS;
6871 	}
6872 
6873 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6874 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6875 	    "D_ID=%x, sense=%x, status=%x",
6876 	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6877 	    rsp->fcp_u.fcp_status.scsi_status);
6878 
6879 	return (rval);
6880 }
6881 
6882 /*
6883  *     Function: fcp_scsi_callback
6884  *
6885  *  Description: This is the callback routine set by fcp_send_scsi() after
6886  *		 it calls fcp_icmd_alloc().  The SCSI command completed here
6887  *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
6888  *		 INQUIRY_PAGE83.
6889  *
6890  *     Argument: *fpkt	 FC packet used to convey the command
6891  *
6892  * Return Value: None
6893  */
6894 static void
6895 fcp_scsi_callback(fc_packet_t *fpkt)
6896 {
6897 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
6898 	    fpkt->pkt_ulp_private;
6899 	struct fcp_rsp_info	fcp_rsp_err, *bep;
6900 	struct fcp_port	*pptr;
6901 	struct fcp_tgt	*ptgt;
6902 	struct fcp_lun	*plun;
6903 	struct fcp_rsp		response, *rsp;
6904 
6905 	ptgt = icmd->ipkt_tgt;
6906 	pptr = ptgt->tgt_port;
6907 	plun = icmd->ipkt_lun;
6908 
6909 	if (icmd->ipkt_nodma) {
6910 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6911 	} else {
6912 		rsp = &response;
6913 		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6914 		    sizeof (struct fcp_rsp));
6915 	}
6916 
6917 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6918 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6919 	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
6920 	    "status=%x, lun num=%x",
6921 	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6922 	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6923 
6924 	/*
6925 	 * Pre-init LUN GUID with NWWN if it is not a device that
6926 	 * supports multiple luns and we know it's not page83
6927 	 * compliant.  Although using a NWWN is not lun unique,
6928 	 * we will be fine since there is only one lun behind the taget
6929 	 * in this case.
6930 	 */
6931 	if ((plun->lun_guid_size == 0) &&
6932 	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6933 	    (fcp_symmetric_device_probe(plun) == 0)) {
6934 
6935 		char ascii_wwn[FC_WWN_SIZE*2+1];
6936 		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6937 		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6938 	}
6939 
6940 	/*
6941 	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6942 	 * when thay have more data than what is asked in CDB. An overrun
6943 	 * is really when FCP_DL is smaller than the data length in CDB.
6944 	 * In the case here we know that REPORT LUN command we formed within
6945 	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6946 	 * behavior. In reality this is FC_SUCCESS.
6947 	 */
6948 	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6949 	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6950 	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6951 		fpkt->pkt_state = FC_PKT_SUCCESS;
6952 	}
6953 
6954 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6955 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6956 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6957 		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6958 		    ptgt->tgt_d_id);
6959 
6960 		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6961 			/*
6962 			 * Inquiry VPD page command on A5K SES devices would
6963 			 * result in data CRC errors.
6964 			 */
6965 			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6966 				(void) fcp_handle_page83(fpkt, icmd, 1);
6967 				return;
6968 			}
6969 		}
6970 		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6971 		    FCP_MUST_RETRY(fpkt)) {
6972 			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6973 			fcp_retry_scsi_cmd(fpkt);
6974 			return;
6975 		}
6976 
6977 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6978 		    FCP_TGT_TRACE_20);
6979 
6980 		mutex_enter(&pptr->port_mutex);
6981 		mutex_enter(&ptgt->tgt_mutex);
6982 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6983 			mutex_exit(&ptgt->tgt_mutex);
6984 			mutex_exit(&pptr->port_mutex);
6985 			fcp_print_error(fpkt);
6986 		} else {
6987 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6988 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6989 			    "fcp_scsi_callback,1: state change occured"
6990 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6991 			mutex_exit(&ptgt->tgt_mutex);
6992 			mutex_exit(&pptr->port_mutex);
6993 		}
6994 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6995 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6996 		fcp_icmd_free(pptr, icmd);
6997 		return;
6998 	}
6999 
7000 	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7001 
7002 	mutex_enter(&pptr->port_mutex);
7003 	mutex_enter(&ptgt->tgt_mutex);
7004 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7005 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7006 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7007 		    "fcp_scsi_callback,2: state change occured"
7008 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7009 		mutex_exit(&ptgt->tgt_mutex);
7010 		mutex_exit(&pptr->port_mutex);
7011 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7012 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7013 		fcp_icmd_free(pptr, icmd);
7014 		return;
7015 	}
7016 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7017 
7018 	mutex_exit(&ptgt->tgt_mutex);
7019 	mutex_exit(&pptr->port_mutex);
7020 
7021 	if (icmd->ipkt_nodma) {
7022 		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7023 		    sizeof (struct fcp_rsp));
7024 	} else {
7025 		bep = &fcp_rsp_err;
7026 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7027 		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7028 	}
7029 
7030 	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7031 		fcp_retry_scsi_cmd(fpkt);
7032 		return;
7033 	}
7034 
7035 	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7036 	    FCP_NO_FAILURE) {
7037 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7038 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7039 		    "rsp_code=0x%x, rsp_len_set=0x%x",
7040 		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7041 		fcp_retry_scsi_cmd(fpkt);
7042 		return;
7043 	}
7044 
7045 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7046 	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7047 		fcp_queue_ipkt(pptr, fpkt);
7048 		return;
7049 	}
7050 
7051 	/*
7052 	 * Devices that do not support INQUIRY_PAGE83, return check condition
7053 	 * with illegal request as per SCSI spec.
7054 	 * Crossbridge is one such device and Daktari's SES node is another.
7055 	 * We want to ideally enumerate these devices as a non-mpxio devices.
7056 	 * SES nodes (Daktari only currently) are an exception to this.
7057 	 */
7058 	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7059 	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7060 
7061 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7062 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
7063 		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7064 		    "check condition. May enumerate as non-mpxio device",
7065 		    ptgt->tgt_d_id, plun->lun_type);
7066 
7067 		/*
7068 		 * If we let Daktari's SES be enumerated as a non-mpxio
7069 		 * device, there will be a discrepency in that the other
7070 		 * internal FC disks will get enumerated as mpxio devices.
7071 		 * Applications like luxadm expect this to be consistent.
7072 		 *
7073 		 * So, we put in a hack here to check if this is an SES device
7074 		 * and handle it here.
7075 		 */
7076 		if (plun->lun_type == DTYPE_ESI) {
7077 			/*
7078 			 * Since, pkt_state is actually FC_PKT_SUCCESS
7079 			 * at this stage, we fake a failure here so that
7080 			 * fcp_handle_page83 will create a device path using
7081 			 * the WWN instead of the GUID which is not there anyway
7082 			 */
7083 			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7084 			(void) fcp_handle_page83(fpkt, icmd, 1);
7085 			return;
7086 		}
7087 
7088 		mutex_enter(&ptgt->tgt_mutex);
7089 		plun->lun_state &= ~(FCP_LUN_OFFLINE |
7090 		    FCP_LUN_MARK | FCP_LUN_BUSY);
7091 		mutex_exit(&ptgt->tgt_mutex);
7092 
7093 		(void) fcp_call_finish_init(pptr, ptgt,
7094 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7095 		    icmd->ipkt_cause);
7096 		fcp_icmd_free(pptr, icmd);
7097 		return;
7098 	}
7099 
7100 	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7101 		int rval = DDI_FAILURE;
7102 
7103 		/*
7104 		 * handle cases where report lun isn't supported
7105 		 * by faking up our own REPORT_LUN response or
7106 		 * UNIT ATTENTION
7107 		 */
7108 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7109 			rval = fcp_check_reportlun(rsp, fpkt);
7110 
7111 			/*
7112 			 * fcp_check_reportlun might have modified the
7113 			 * FCP response. Copy it in again to get an updated
7114 			 * FCP response
7115 			 */
7116 			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7117 				rsp = &response;
7118 
7119 				FCP_CP_IN(fpkt->pkt_resp, rsp,
7120 				    fpkt->pkt_resp_acc,
7121 				    sizeof (struct fcp_rsp));
7122 			}
7123 		}
7124 
7125 		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7126 			if (rval == DDI_SUCCESS) {
7127 				(void) fcp_call_finish_init(pptr, ptgt,
7128 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7129 				    icmd->ipkt_cause);
7130 				fcp_icmd_free(pptr, icmd);
7131 			} else {
7132 				fcp_retry_scsi_cmd(fpkt);
7133 			}
7134 
7135 			return;
7136 		}
7137 	} else {
7138 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7139 			mutex_enter(&ptgt->tgt_mutex);
7140 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7141 			mutex_exit(&ptgt->tgt_mutex);
7142 		}
7143 	}
7144 
7145 	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7146 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7147 		(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7148 		    DDI_DMA_SYNC_FORCPU);
7149 	}
7150 
7151 	switch (icmd->ipkt_opcode) {
7152 	case SCMD_INQUIRY:
7153 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7154 		fcp_handle_inquiry(fpkt, icmd);
7155 		break;
7156 
7157 	case SCMD_REPORT_LUN:
7158 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7159 		    FCP_TGT_TRACE_22);
7160 		fcp_handle_reportlun(fpkt, icmd);
7161 		break;
7162 
7163 	case SCMD_INQUIRY_PAGE83:
7164 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7165 		(void) fcp_handle_page83(fpkt, icmd, 0);
7166 		break;
7167 
7168 	default:
7169 		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7170 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7171 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7172 		fcp_icmd_free(pptr, icmd);
7173 		break;
7174 	}
7175 }
7176 
7177 
7178 static void
7179 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7180 {
7181 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
7182 	    fpkt->pkt_ulp_private;
7183 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
7184 	struct fcp_port	*pptr = ptgt->tgt_port;
7185 
7186 	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7187 	    fcp_is_retryable(icmd)) {
7188 		mutex_enter(&pptr->port_mutex);
7189 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7190 			mutex_exit(&pptr->port_mutex);
7191 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7192 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7193 			    "Retrying %s to %x; state=%x, reason=%x",
7194 			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7195 			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7196 			    fpkt->pkt_state, fpkt->pkt_reason);
7197 
7198 			fcp_queue_ipkt(pptr, fpkt);
7199 		} else {
7200 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7201 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7202 			    "fcp_retry_scsi_cmd,1: state change occured"
7203 			    " for D_ID=0x%x", ptgt->tgt_d_id);
7204 			mutex_exit(&pptr->port_mutex);
7205 			(void) fcp_call_finish_init(pptr, ptgt,
7206 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7207 			    icmd->ipkt_cause);
7208 			fcp_icmd_free(pptr, icmd);
7209 		}
7210 	} else {
7211 		fcp_print_error(fpkt);
7212 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7213 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7214 		fcp_icmd_free(pptr, icmd);
7215 	}
7216 }
7217 
7218 /*
7219  *     Function: fcp_handle_page83
7220  *
7221  *  Description: Treats the response to INQUIRY_PAGE83.
7222  *
7223  *     Argument: *fpkt	FC packet used to convey the command.
7224  *		 *icmd	Original fcp_ipkt structure.
7225  *		 ignore_page83_data
7226  *			if it's 1, that means it's a special devices's
7227  *			page83 response, it should be enumerated under mpxio
7228  *
7229  * Return Value: None
7230  */
7231 static void
7232 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7233     int ignore_page83_data)
7234 {
7235 	struct fcp_port	*pptr;
7236 	struct fcp_lun	*plun;
7237 	struct fcp_tgt	*ptgt;
7238 	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7239 	int			fail = 0;
7240 	ddi_devid_t		devid;
7241 	char			*guid = NULL;
7242 	int			ret;
7243 
7244 	ASSERT(icmd != NULL && fpkt != NULL);
7245 
7246 	pptr = icmd->ipkt_port;
7247 	ptgt = icmd->ipkt_tgt;
7248 	plun = icmd->ipkt_lun;
7249 
7250 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7251 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7252 
7253 		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7254 		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
7255 
7256 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7257 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7258 		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7259 		    "dtype=0x%x, lun num=%x",
7260 		    pptr->port_instance, ptgt->tgt_d_id,
7261 		    dev_id_page[0], plun->lun_num);
7262 
7263 		ret = ddi_devid_scsi_encode(
7264 		    DEVID_SCSI_ENCODE_VERSION_LATEST,
7265 		    NULL,		/* driver name */
7266 		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
7267 		    sizeof (plun->lun_inq), /* size of standard inquiry */
7268 		    NULL,		/* page 80 data */
7269 		    0,		/* page 80 len */
7270 		    dev_id_page,	/* page 83 data */
7271 		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7272 		    &devid);
7273 
7274 		if (ret == DDI_SUCCESS) {
7275 
7276 			guid = ddi_devid_to_guid(devid);
7277 
7278 			if (guid) {
7279 				/*
7280 				 * Check our current guid.  If it's non null
7281 				 * and it has changed, we need to copy it into
7282 				 * lun_old_guid since we might still need it.
7283 				 */
7284 				if (plun->lun_guid &&
7285 				    strcmp(guid, plun->lun_guid)) {
7286 					unsigned int len;
7287 
7288 					/*
7289 					 * If the guid of the LUN changes,
7290 					 * reconfiguration should be triggered
7291 					 * to reflect the changes.
7292 					 * i.e. we should offline the LUN with
7293 					 * the old guid, and online the LUN with
7294 					 * the new guid.
7295 					 */
7296 					plun->lun_state |= FCP_LUN_CHANGED;
7297 
7298 					if (plun->lun_old_guid) {
7299 						kmem_free(plun->lun_old_guid,
7300 						    plun->lun_old_guid_size);
7301 					}
7302 
7303 					len = plun->lun_guid_size;
7304 					plun->lun_old_guid_size = len;
7305 
7306 					plun->lun_old_guid = kmem_zalloc(len,
7307 					    KM_NOSLEEP);
7308 
7309 					if (plun->lun_old_guid) {
7310 						/*
7311 						 * The alloc was successful then
7312 						 * let's do the copy.
7313 						 */
7314 						bcopy(plun->lun_guid,
7315 						    plun->lun_old_guid, len);
7316 					} else {
7317 						fail = 1;
7318 						plun->lun_old_guid_size = 0;
7319 					}
7320 				}
7321 				if (!fail) {
7322 					if (fcp_copy_guid_2_lun_block(
7323 					    plun, guid)) {
7324 						fail = 1;
7325 					}
7326 				}
7327 				ddi_devid_free_guid(guid);
7328 
7329 			} else {
7330 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7331 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
7332 				    "fcp_handle_page83: unable to create "
7333 				    "GUID");
7334 
7335 				/* couldn't create good guid from devid */
7336 				fail = 1;
7337 			}
7338 			ddi_devid_free(devid);
7339 
7340 		} else if (ret == DDI_NOT_WELL_FORMED) {
7341 			/* NULL filled data for page 83 */
7342 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7343 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7344 			    "fcp_handle_page83: retry GUID");
7345 
7346 			icmd->ipkt_retries = 0;
7347 			fcp_retry_scsi_cmd(fpkt);
7348 			return;
7349 		} else {
7350 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7351 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7352 			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7353 			    ret);
7354 			/*
7355 			 * Since the page83 validation
7356 			 * introduced late, we are being
7357 			 * tolerant to the existing devices
7358 			 * that already found to be working
7359 			 * under mpxio, like A5200's SES device,
7360 			 * its page83 response will not be standard-compliant,
7361 			 * but we still want it to be enumerated under mpxio.
7362 			 */
7363 			if (fcp_symmetric_device_probe(plun) != 0) {
7364 				fail = 1;
7365 			}
7366 		}
7367 
7368 	} else {
7369 		/* bad packet state */
7370 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7371 
7372 		/*
7373 		 * For some special devices (A5K SES and Daktari's SES devices),
7374 		 * they should be enumerated under mpxio
7375 		 * or "luxadm dis" will fail
7376 		 */
7377 		if (ignore_page83_data) {
7378 			fail = 0;
7379 		} else {
7380 			fail = 1;
7381 		}
7382 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7383 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7384 		    "!Devid page cmd failed. "
7385 		    "fpkt_state: %x fpkt_reason: %x",
7386 		    "ignore_page83: %d",
7387 		    fpkt->pkt_state, fpkt->pkt_reason,
7388 		    ignore_page83_data);
7389 	}
7390 
7391 	mutex_enter(&pptr->port_mutex);
7392 	mutex_enter(&plun->lun_mutex);
7393 	/*
7394 	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7395 	 * mismatch between lun_cip and lun_mpxio.
7396 	 */
7397 	if (plun->lun_cip == NULL) {
7398 		/*
7399 		 * If we don't have a guid for this lun it's because we were
7400 		 * unable to glean one from the page 83 response.  Set the
7401 		 * control flag to 0 here to make sure that we don't attempt to
7402 		 * enumerate it under mpxio.
7403 		 */
7404 		if (fail || pptr->port_mpxio == 0) {
7405 			plun->lun_mpxio = 0;
7406 		} else {
7407 			plun->lun_mpxio = 1;
7408 		}
7409 	}
7410 	mutex_exit(&plun->lun_mutex);
7411 	mutex_exit(&pptr->port_mutex);
7412 
7413 	mutex_enter(&ptgt->tgt_mutex);
7414 	plun->lun_state &=
7415 	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7416 	mutex_exit(&ptgt->tgt_mutex);
7417 
7418 	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7419 	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7420 
7421 	fcp_icmd_free(pptr, icmd);
7422 }
7423 
7424 /*
7425  *     Function: fcp_handle_inquiry
7426  *
7427  *  Description: Called by fcp_scsi_callback to handle the response to an
7428  *		 INQUIRY request.
7429  *
7430  *     Argument: *fpkt	FC packet used to convey the command.
7431  *		 *icmd	Original fcp_ipkt structure.
7432  *
7433  * Return Value: None
7434  */
7435 static void
7436 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7437 {
7438 	struct fcp_port	*pptr;
7439 	struct fcp_lun	*plun;
7440 	struct fcp_tgt	*ptgt;
7441 	uchar_t		dtype;
7442 	uchar_t		pqual;
7443 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
7444 
7445 	ASSERT(icmd != NULL && fpkt != NULL);
7446 
7447 	pptr = icmd->ipkt_port;
7448 	ptgt = icmd->ipkt_tgt;
7449 	plun = icmd->ipkt_lun;
7450 
7451 	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7452 	    sizeof (struct scsi_inquiry));
7453 
7454 	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7455 	pqual = plun->lun_inq.inq_dtype >> 5;
7456 
7457 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7458 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7459 	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7460 	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7461 	    plun->lun_num, dtype, pqual);
7462 
7463 	if (pqual != 0) {
7464 		/*
7465 		 * Non-zero peripheral qualifier
7466 		 */
7467 		fcp_log(CE_CONT, pptr->port_dip,
7468 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7469 		    "Device type=0x%x Peripheral qual=0x%x\n",
7470 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7471 
7472 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7473 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7474 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7475 		    "Device type=0x%x Peripheral qual=0x%x\n",
7476 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7477 
7478 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7479 
7480 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7481 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7482 		fcp_icmd_free(pptr, icmd);
7483 		return;
7484 	}
7485 
7486 	/*
7487 	 * If the device is already initialized, check the dtype
7488 	 * for a change. If it has changed then update the flags
7489 	 * so the create_luns will offline the old device and
7490 	 * create the new device. Refer to bug: 4764752
7491 	 */
7492 	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7493 		plun->lun_state |= FCP_LUN_CHANGED;
7494 	}
7495 	plun->lun_type = plun->lun_inq.inq_dtype;
7496 
7497 	/*
7498 	 * This code is setting/initializing the throttling in the FCA
7499 	 * driver.
7500 	 */
7501 	mutex_enter(&pptr->port_mutex);
7502 	if (!pptr->port_notify) {
7503 		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7504 			uint32_t cmd = 0;
7505 			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7506 			    ((cmd & 0xFFFFFF00 >> 8) |
7507 			    FCP_SVE_THROTTLE << 8));
7508 			pptr->port_notify = 1;
7509 			mutex_exit(&pptr->port_mutex);
7510 			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7511 			mutex_enter(&pptr->port_mutex);
7512 		}
7513 	}
7514 
7515 	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7516 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7517 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7518 		    "fcp_handle_inquiry,1:state change occured"
7519 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7520 		mutex_exit(&pptr->port_mutex);
7521 
7522 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7523 		(void) fcp_call_finish_init(pptr, ptgt,
7524 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7525 		    icmd->ipkt_cause);
7526 		fcp_icmd_free(pptr, icmd);
7527 		return;
7528 	}
7529 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7530 	mutex_exit(&pptr->port_mutex);
7531 
7532 	/* Retrieve the rscn count (if a valid one exists) */
7533 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7534 		rscn_count = ((fc_ulp_rscn_info_t *)
7535 		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7536 	} else {
7537 		rscn_count = FC_INVALID_RSCN_COUNT;
7538 	}
7539 
7540 	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7541 	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
7542 	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7543 	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7544 		fcp_log(CE_WARN, NULL, "!failed to send page 83");
7545 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7546 		(void) fcp_call_finish_init(pptr, ptgt,
7547 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7548 		    icmd->ipkt_cause);
7549 	}
7550 
7551 	/*
7552 	 * Read Inquiry VPD Page 0x83 to uniquely
7553 	 * identify this logical unit.
7554 	 */
7555 	fcp_icmd_free(pptr, icmd);
7556 }
7557 
7558 /*
7559  *     Function: fcp_handle_reportlun
7560  *
7561  *  Description: Called by fcp_scsi_callback to handle the response to a
7562  *		 REPORT_LUN request.
7563  *
7564  *     Argument: *fpkt	FC packet used to convey the command.
7565  *		 *icmd	Original fcp_ipkt structure.
7566  *
7567  * Return Value: None
7568  */
7569 static void
7570 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7571 {
7572 	int				i;
7573 	int				nluns_claimed;
7574 	int				nluns_bufmax;
7575 	int				len;
7576 	uint16_t			lun_num;
7577 	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
7578 	struct fcp_port			*pptr;
7579 	struct fcp_tgt			*ptgt;
7580 	struct fcp_lun			*plun;
7581 	struct fcp_reportlun_resp	*report_lun;
7582 
7583 	pptr = icmd->ipkt_port;
7584 	ptgt = icmd->ipkt_tgt;
7585 	len = fpkt->pkt_datalen;
7586 
7587 	if ((len < FCP_LUN_HEADER) ||
7588 	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7589 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7590 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7591 		fcp_icmd_free(pptr, icmd);
7592 		return;
7593 	}
7594 
7595 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7596 	    fpkt->pkt_datalen);
7597 
7598 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7599 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7600 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7601 	    pptr->port_instance, ptgt->tgt_d_id);
7602 
7603 	/*
7604 	 * Get the number of luns (which is supplied as LUNS * 8) the
7605 	 * device claims it has.
7606 	 */
7607 	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7608 
7609 	/*
7610 	 * Get the maximum number of luns the buffer submitted can hold.
7611 	 */
7612 	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7613 
7614 	/*
7615 	 * Due to limitations of certain hardware, we support only 16 bit LUNs
7616 	 */
7617 	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7618 		kmem_free(report_lun, len);
7619 
7620 		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7621 		    " 0x%x number of LUNs for target=%x", nluns_claimed,
7622 		    ptgt->tgt_d_id);
7623 
7624 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7625 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7626 		fcp_icmd_free(pptr, icmd);
7627 		return;
7628 	}
7629 
7630 	/*
7631 	 * If there are more LUNs than we have allocated memory for,
7632 	 * allocate more space and send down yet another report lun if
7633 	 * the maximum number of attempts hasn't been reached.
7634 	 */
7635 	mutex_enter(&ptgt->tgt_mutex);
7636 
7637 	if ((nluns_claimed > nluns_bufmax) &&
7638 	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7639 
7640 		struct fcp_lun *plun;
7641 
7642 		ptgt->tgt_report_lun_cnt++;
7643 		plun = ptgt->tgt_lun;
7644 		ASSERT(plun != NULL);
7645 		mutex_exit(&ptgt->tgt_mutex);
7646 
7647 		kmem_free(report_lun, len);
7648 
7649 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7650 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7651 		    "!Dynamically discovered %d LUNs for D_ID=%x",
7652 		    nluns_claimed, ptgt->tgt_d_id);
7653 
7654 		/* Retrieve the rscn count (if a valid one exists) */
7655 		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7656 			rscn_count = ((fc_ulp_rscn_info_t *)
7657 			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7658 			    ulp_rscn_count;
7659 		} else {
7660 			rscn_count = FC_INVALID_RSCN_COUNT;
7661 		}
7662 
7663 		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7664 		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7665 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7666 		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7667 			(void) fcp_call_finish_init(pptr, ptgt,
7668 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7669 			    icmd->ipkt_cause);
7670 		}
7671 
7672 		fcp_icmd_free(pptr, icmd);
7673 		return;
7674 	}
7675 
7676 	if (nluns_claimed > nluns_bufmax) {
7677 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7678 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7679 		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7680 		    "	 Number of LUNs lost=%x",
7681 		    ptgt->tgt_port_wwn.raw_wwn[0],
7682 		    ptgt->tgt_port_wwn.raw_wwn[1],
7683 		    ptgt->tgt_port_wwn.raw_wwn[2],
7684 		    ptgt->tgt_port_wwn.raw_wwn[3],
7685 		    ptgt->tgt_port_wwn.raw_wwn[4],
7686 		    ptgt->tgt_port_wwn.raw_wwn[5],
7687 		    ptgt->tgt_port_wwn.raw_wwn[6],
7688 		    ptgt->tgt_port_wwn.raw_wwn[7],
7689 		    nluns_claimed - nluns_bufmax);
7690 
7691 		nluns_claimed = nluns_bufmax;
7692 	}
7693 	ptgt->tgt_lun_cnt = nluns_claimed;
7694 
7695 	/*
7696 	 * Identify missing LUNs and print warning messages
7697 	 */
7698 	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7699 		int offline;
7700 		int exists = 0;
7701 
7702 		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7703 
7704 		for (i = 0; i < nluns_claimed && exists == 0; i++) {
7705 			uchar_t		*lun_string;
7706 
7707 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7708 
7709 			switch (lun_string[0] & 0xC0) {
7710 			case FCP_LUN_ADDRESSING:
7711 			case FCP_PD_ADDRESSING:
7712 			case FCP_VOLUME_ADDRESSING:
7713 				lun_num = ((lun_string[0] & 0x3F) << 8) |
7714 				    lun_string[1];
7715 				if (plun->lun_num == lun_num) {
7716 					exists++;
7717 					break;
7718 				}
7719 				break;
7720 
7721 			default:
7722 				break;
7723 			}
7724 		}
7725 
7726 		if (!exists && !offline) {
7727 			mutex_exit(&ptgt->tgt_mutex);
7728 
7729 			mutex_enter(&pptr->port_mutex);
7730 			mutex_enter(&ptgt->tgt_mutex);
7731 			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7732 				/*
7733 				 * set disappear flag when device was connected
7734 				 */
7735 				if (!(plun->lun_state &
7736 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7737 					plun->lun_state |= FCP_LUN_DISAPPEARED;
7738 				}
7739 				mutex_exit(&ptgt->tgt_mutex);
7740 				mutex_exit(&pptr->port_mutex);
7741 				if (!(plun->lun_state &
7742 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7743 					fcp_log(CE_NOTE, pptr->port_dip,
7744 					    "!Lun=%x for target=%x disappeared",
7745 					    plun->lun_num, ptgt->tgt_d_id);
7746 				}
7747 				mutex_enter(&ptgt->tgt_mutex);
7748 			} else {
7749 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7750 				    fcp_trace, FCP_BUF_LEVEL_5, 0,
7751 				    "fcp_handle_reportlun,1: state change"
7752 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
7753 				mutex_exit(&ptgt->tgt_mutex);
7754 				mutex_exit(&pptr->port_mutex);
7755 				kmem_free(report_lun, len);
7756 				(void) fcp_call_finish_init(pptr, ptgt,
7757 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7758 				    icmd->ipkt_cause);
7759 				fcp_icmd_free(pptr, icmd);
7760 				return;
7761 			}
7762 		} else if (exists) {
7763 			/*
7764 			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7765 			 * actually exists in REPORT_LUN response
7766 			 */
7767 			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7768 				plun->lun_state &=
7769 				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
7770 			}
7771 			if (offline || plun->lun_num == 0) {
7772 				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7773 					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7774 					mutex_exit(&ptgt->tgt_mutex);
7775 					fcp_log(CE_NOTE, pptr->port_dip,
7776 					    "!Lun=%x for target=%x reappeared",
7777 					    plun->lun_num, ptgt->tgt_d_id);
7778 					mutex_enter(&ptgt->tgt_mutex);
7779 				}
7780 			}
7781 		}
7782 	}
7783 
7784 	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7785 	mutex_exit(&ptgt->tgt_mutex);
7786 
7787 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7788 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7789 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7790 	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7791 
7792 	/* scan each lun */
7793 	for (i = 0; i < nluns_claimed; i++) {
7794 		uchar_t	*lun_string;
7795 
7796 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7797 
7798 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7799 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7800 		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7801 		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7802 		    lun_string[0]);
7803 
7804 		switch (lun_string[0] & 0xC0) {
7805 		case FCP_LUN_ADDRESSING:
7806 		case FCP_PD_ADDRESSING:
7807 		case FCP_VOLUME_ADDRESSING:
7808 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7809 
7810 			/* We will skip masked LUNs because of the blacklist. */
7811 			if (fcp_lun_blacklist != NULL) {
7812 				mutex_enter(&ptgt->tgt_mutex);
7813 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
7814 				    lun_num) == TRUE) {
7815 					ptgt->tgt_lun_cnt--;
7816 					mutex_exit(&ptgt->tgt_mutex);
7817 					break;
7818 				}
7819 				mutex_exit(&ptgt->tgt_mutex);
7820 			}
7821 
7822 			/* see if this LUN is already allocated */
7823 			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7824 				plun = fcp_alloc_lun(ptgt);
7825 				if (plun == NULL) {
7826 					fcp_log(CE_NOTE, pptr->port_dip,
7827 					    "!Lun allocation failed"
7828 					    " target=%x lun=%x",
7829 					    ptgt->tgt_d_id, lun_num);
7830 					break;
7831 				}
7832 			}
7833 
7834 			mutex_enter(&plun->lun_tgt->tgt_mutex);
7835 			/* convert to LUN */
7836 			plun->lun_addr.ent_addr_0 =
7837 			    BE_16(*(uint16_t *)&(lun_string[0]));
7838 			plun->lun_addr.ent_addr_1 =
7839 			    BE_16(*(uint16_t *)&(lun_string[2]));
7840 			plun->lun_addr.ent_addr_2 =
7841 			    BE_16(*(uint16_t *)&(lun_string[4]));
7842 			plun->lun_addr.ent_addr_3 =
7843 			    BE_16(*(uint16_t *)&(lun_string[6]));
7844 
7845 			plun->lun_num = lun_num;
7846 			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7847 			plun->lun_state &= ~FCP_LUN_OFFLINE;
7848 			mutex_exit(&plun->lun_tgt->tgt_mutex);
7849 
7850 			/* Retrieve the rscn count (if a valid one exists) */
7851 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7852 				rscn_count = ((fc_ulp_rscn_info_t *)
7853 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7854 				    ulp_rscn_count;
7855 			} else {
7856 				rscn_count = FC_INVALID_RSCN_COUNT;
7857 			}
7858 
7859 			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7860 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7861 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7862 				mutex_enter(&pptr->port_mutex);
7863 				mutex_enter(&plun->lun_tgt->tgt_mutex);
7864 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7865 					fcp_log(CE_NOTE, pptr->port_dip,
7866 					    "!failed to send INQUIRY"
7867 					    " target=%x lun=%x",
7868 					    ptgt->tgt_d_id, plun->lun_num);
7869 				} else {
7870 					FCP_TRACE(fcp_logq,
7871 					    pptr->port_instbuf, fcp_trace,
7872 					    FCP_BUF_LEVEL_5, 0,
7873 					    "fcp_handle_reportlun,2: state"
7874 					    " change occured for D_ID=0x%x",
7875 					    ptgt->tgt_d_id);
7876 				}
7877 				mutex_exit(&plun->lun_tgt->tgt_mutex);
7878 				mutex_exit(&pptr->port_mutex);
7879 			} else {
7880 				continue;
7881 			}
7882 			break;
7883 
7884 		default:
7885 			fcp_log(CE_WARN, NULL,
7886 			    "!Unsupported LUN Addressing method %x "
7887 			    "in response to REPORT_LUN", lun_string[0]);
7888 			break;
7889 		}
7890 
7891 		/*
7892 		 * each time through this loop we should decrement
7893 		 * the tmp_cnt by one -- since we go through this loop
7894 		 * one time for each LUN, the tmp_cnt should never be <=0
7895 		 */
7896 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7897 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7898 	}
7899 
7900 	if (i == 0) {
7901 		fcp_log(CE_WARN, pptr->port_dip,
7902 		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7903 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7904 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7905 	}
7906 
7907 	kmem_free(report_lun, len);
7908 	fcp_icmd_free(pptr, icmd);
7909 }
7910 
7911 
7912 /*
7913  * called internally to return a LUN given a target and a LUN number
7914  */
7915 static struct fcp_lun *
7916 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7917 {
7918 	struct fcp_lun	*plun;
7919 
7920 	mutex_enter(&ptgt->tgt_mutex);
7921 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7922 		if (plun->lun_num == lun_num) {
7923 			mutex_exit(&ptgt->tgt_mutex);
7924 			return (plun);
7925 		}
7926 	}
7927 	mutex_exit(&ptgt->tgt_mutex);
7928 
7929 	return (NULL);
7930 }
7931 
7932 
7933 /*
7934  * handle finishing one target for fcp_finish_init
7935  *
7936  * return true (non-zero) if we want finish_init to continue with the
7937  * next target
7938  *
7939  * called with the port mutex held
7940  */
7941 /*ARGSUSED*/
7942 static int
7943 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7944     int link_cnt, int tgt_cnt, int cause)
7945 {
7946 	int	rval = 1;
7947 	ASSERT(pptr != NULL);
7948 	ASSERT(ptgt != NULL);
7949 
7950 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7951 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7952 	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7953 	    ptgt->tgt_state);
7954 
7955 	ASSERT(mutex_owned(&pptr->port_mutex));
7956 
7957 	if ((pptr->port_link_cnt != link_cnt) ||
7958 	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7959 		/*
7960 		 * oh oh -- another link reset or target change
7961 		 * must have occurred while we are in here
7962 		 */
7963 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7964 
7965 		return (0);
7966 	} else {
7967 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7968 	}
7969 
7970 	mutex_enter(&ptgt->tgt_mutex);
7971 
7972 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7973 		/*
7974 		 * tgt is not offline -- is it marked (i.e. needs
7975 		 * to be offlined) ??
7976 		 */
7977 		if (ptgt->tgt_state & FCP_TGT_MARK) {
7978 			/*
7979 			 * this target not offline *and*
7980 			 * marked
7981 			 */
7982 			ptgt->tgt_state &= ~FCP_TGT_MARK;
7983 			rval = fcp_offline_target(pptr, ptgt, link_cnt,
7984 			    tgt_cnt, 0, 0);
7985 		} else {
7986 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
7987 
7988 			/* create the LUNs */
7989 			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7990 				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7991 				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7992 				    cause);
7993 				ptgt->tgt_device_created = 1;
7994 			} else {
7995 				fcp_update_tgt_state(ptgt, FCP_RESET,
7996 				    FCP_LUN_BUSY);
7997 			}
7998 		}
7999 	}
8000 
8001 	mutex_exit(&ptgt->tgt_mutex);
8002 
8003 	return (rval);
8004 }
8005 
8006 
8007 /*
8008  * this routine is called to finish port initialization
8009  *
8010  * Each port has a "temp" counter -- when a state change happens (e.g.
8011  * port online), the temp count is set to the number of devices in the map.
8012  * Then, as each device gets "discovered", the temp counter is decremented
8013  * by one.  When this count reaches zero we know that all of the devices
8014  * in the map have been discovered (or an error has occurred), so we can
8015  * then finish initialization -- which is done by this routine (well, this
8016  * and fcp-finish_tgt())
8017  *
8018  * acquires and releases the global mutex
8019  *
8020  * called with the port mutex owned
8021  */
8022 static void
8023 fcp_finish_init(struct fcp_port *pptr)
8024 {
8025 #ifdef	DEBUG
8026 	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8027 	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8028 	    FCP_STACK_DEPTH);
8029 #endif /* DEBUG */
8030 
8031 	ASSERT(mutex_owned(&pptr->port_mutex));
8032 
8033 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8034 	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8035 	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8036 
8037 	if ((pptr->port_state & FCP_STATE_ONLINING) &&
8038 	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
8039 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8040 		pptr->port_state &= ~FCP_STATE_ONLINING;
8041 		pptr->port_state |= FCP_STATE_ONLINE;
8042 	}
8043 
8044 	/* Wake up threads waiting on config done */
8045 	cv_broadcast(&pptr->port_config_cv);
8046 }
8047 
8048 
8049 /*
8050  * called from fcp_finish_init to create the LUNs for a target
8051  *
8052  * called with the port mutex owned
8053  */
8054 static void
8055 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8056 {
8057 	struct fcp_lun	*plun;
8058 	struct fcp_port	*pptr;
8059 	child_info_t		*cip = NULL;
8060 
8061 	ASSERT(ptgt != NULL);
8062 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8063 
8064 	pptr = ptgt->tgt_port;
8065 
8066 	ASSERT(pptr != NULL);
8067 
8068 	/* scan all LUNs for this target */
8069 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8070 		if (plun->lun_state & FCP_LUN_OFFLINE) {
8071 			continue;
8072 		}
8073 
8074 		if (plun->lun_state & FCP_LUN_MARK) {
8075 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8076 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8077 			    "fcp_create_luns: offlining marked LUN!");
8078 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8079 			continue;
8080 		}
8081 
8082 		plun->lun_state &= ~FCP_LUN_BUSY;
8083 
8084 		/*
8085 		 * There are conditions in which FCP_LUN_INIT flag is cleared
8086 		 * but we have a valid plun->lun_cip. To cover this case also
8087 		 * CLEAR_BUSY whenever we have a valid lun_cip.
8088 		 */
8089 		if (plun->lun_mpxio && plun->lun_cip &&
8090 		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8091 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8092 		    0, 0))) {
8093 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8094 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8095 			    "fcp_create_luns: enable lun %p failed!",
8096 			    plun);
8097 		}
8098 
8099 		if (plun->lun_state & FCP_LUN_INIT &&
8100 		    !(plun->lun_state & FCP_LUN_CHANGED)) {
8101 			continue;
8102 		}
8103 
8104 		if (cause == FCP_CAUSE_USER_CREATE) {
8105 			continue;
8106 		}
8107 
8108 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
8109 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
8110 		    "create_luns: passing ONLINE elem to HP thread");
8111 
8112 		/*
8113 		 * If lun has changed, prepare for offlining the old path.
8114 		 * Do not offline the old path right now, since it may be
8115 		 * still opened.
8116 		 */
8117 		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8118 			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8119 		}
8120 
8121 		/* pass an ONLINE element to the hotplug thread */
8122 		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8123 		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8124 
8125 			/*
8126 			 * We can not synchronous attach (i.e pass
8127 			 * NDI_ONLINE_ATTACH) here as we might be
8128 			 * coming from an interrupt or callback
8129 			 * thread.
8130 			 */
8131 			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8132 			    link_cnt, tgt_cnt, 0, 0)) {
8133 				fcp_log(CE_CONT, pptr->port_dip,
8134 				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8135 				    plun->lun_tgt->tgt_d_id, plun->lun_num);
8136 			}
8137 		}
8138 	}
8139 }
8140 
8141 
8142 /*
8143  * function to online/offline devices
8144  */
8145 static int
8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8147     int online, int lcount, int tcount, int flags)
8148 {
8149 	int			rval = NDI_FAILURE;
8150 	int			circ;
8151 	child_info_t		*ccip;
8152 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
8153 	int			is_mpxio = pptr->port_mpxio;
8154 	dev_info_t		*cdip, *pdip;
8155 	char			*devname;
8156 
8157 	if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8158 		/*
8159 		 * When this event gets serviced, lun_cip and lun_mpxio
8160 		 * has changed, so it should be invalidated now.
8161 		 */
8162 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8163 		    FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8164 		    "plun: %p, cip: %p, what:%d", plun, cip, online);
8165 		return (rval);
8166 	}
8167 
8168 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8169 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
8170 	    "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8171 	    "flags=%x mpxio=%x\n",
8172 	    plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8173 	    plun->lun_mpxio);
8174 
8175 	/*
8176 	 * lun_mpxio needs checking here because we can end up in a race
8177 	 * condition where this task has been dispatched while lun_mpxio is
8178 	 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8179 	 * enable MPXIO for the LUN, but was unable to, and hence cleared
8180 	 * the flag. We rely on the serialization of the tasks here. We return
8181 	 * NDI_SUCCESS so any callers continue without reporting spurious
8182 	 * errors, and the still think we're an MPXIO LUN.
8183 	 */
8184 
8185 	if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8186 	    online == FCP_MPXIO_PATH_SET_BUSY) {
8187 		if (plun->lun_mpxio) {
8188 			rval = fcp_update_mpxio_path(plun, cip, online);
8189 		} else {
8190 			rval = NDI_SUCCESS;
8191 		}
8192 		return (rval);
8193 	}
8194 
8195 	/*
8196 	 * Explicit devfs_clean() due to ndi_devi_offline() not
8197 	 * executing devfs_clean() if parent lock is held.
8198 	 */
8199 	ASSERT(!servicing_interrupt());
8200 	if (online == FCP_OFFLINE) {
8201 		if (plun->lun_mpxio == 0) {
8202 			if (plun->lun_cip == cip) {
8203 				cdip = DIP(plun->lun_cip);
8204 			} else {
8205 				cdip = DIP(cip);
8206 			}
8207 		} else if ((plun->lun_cip == cip) && plun->lun_cip) {
8208 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8209 		} else if ((plun->lun_cip != cip) && cip) {
8210 			/*
8211 			 * This means a DTYPE/GUID change, we shall get the
8212 			 * dip of the old cip instead of the current lun_cip.
8213 			 */
8214 			cdip = mdi_pi_get_client(PIP(cip));
8215 		}
8216 		if (cdip) {
8217 			if (i_ddi_devi_attached(cdip)) {
8218 				pdip = ddi_get_parent(cdip);
8219 				devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8220 				ndi_devi_enter(pdip, &circ);
8221 				(void) ddi_deviname(cdip, devname);
8222 				/*
8223 				 * Release parent lock before calling
8224 				 * devfs_clean().
8225 				 */
8226 				ndi_devi_exit(pdip, circ);
8227 				(void) devfs_clean(pdip, devname + 1,
8228 				    DV_CLEAN_FORCE);
8229 				kmem_free(devname, MAXNAMELEN + 1);
8230 			}
8231 		}
8232 	}
8233 
8234 	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8235 		return (NDI_FAILURE);
8236 	}
8237 
8238 	if (is_mpxio) {
8239 		mdi_devi_enter(pptr->port_dip, &circ);
8240 	} else {
8241 		ndi_devi_enter(pptr->port_dip, &circ);
8242 	}
8243 
8244 	mutex_enter(&pptr->port_mutex);
8245 	mutex_enter(&plun->lun_mutex);
8246 
8247 	if (online == FCP_ONLINE) {
8248 		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8249 		if (ccip == NULL) {
8250 			goto fail;
8251 		}
8252 	} else {
8253 		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8254 			goto fail;
8255 		}
8256 		ccip = cip;
8257 	}
8258 
8259 	if (online == FCP_ONLINE) {
8260 		rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8261 		    &circ);
8262 		fc_ulp_log_device_event(pptr->port_fp_handle,
8263 		    FC_ULP_DEVICE_ONLINE);
8264 	} else {
8265 		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8266 		    &circ);
8267 		fc_ulp_log_device_event(pptr->port_fp_handle,
8268 		    FC_ULP_DEVICE_OFFLINE);
8269 	}
8270 
8271 fail:	mutex_exit(&plun->lun_mutex);
8272 	mutex_exit(&pptr->port_mutex);
8273 
8274 	if (is_mpxio) {
8275 		mdi_devi_exit(pptr->port_dip, circ);
8276 	} else {
8277 		ndi_devi_exit(pptr->port_dip, circ);
8278 	}
8279 
8280 	fc_ulp_idle_port(pptr->port_fp_handle);
8281 
8282 	return (rval);
8283 }
8284 
8285 
8286 /*
8287  * take a target offline by taking all of its LUNs offline
8288  */
8289 /*ARGSUSED*/
8290 static int
8291 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8292     int link_cnt, int tgt_cnt, int nowait, int flags)
8293 {
8294 	struct fcp_tgt_elem	*elem;
8295 
8296 	ASSERT(mutex_owned(&pptr->port_mutex));
8297 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8298 
8299 	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8300 
8301 	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8302 	    ptgt->tgt_change_cnt)) {
8303 		mutex_exit(&ptgt->tgt_mutex);
8304 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8305 		mutex_enter(&ptgt->tgt_mutex);
8306 
8307 		return (0);
8308 	}
8309 
8310 	ptgt->tgt_pd_handle = NULL;
8311 	mutex_exit(&ptgt->tgt_mutex);
8312 	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8313 	mutex_enter(&ptgt->tgt_mutex);
8314 
8315 	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8316 
8317 	if (ptgt->tgt_tcap &&
8318 	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8319 		elem->flags = flags;
8320 		elem->time = fcp_watchdog_time;
8321 		if (nowait == 0) {
8322 			elem->time += fcp_offline_delay;
8323 		}
8324 		elem->ptgt = ptgt;
8325 		elem->link_cnt = link_cnt;
8326 		elem->tgt_cnt = tgt_cnt;
8327 		elem->next = pptr->port_offline_tgts;
8328 		pptr->port_offline_tgts = elem;
8329 	} else {
8330 		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8331 	}
8332 
8333 	return (1);
8334 }
8335 
8336 
8337 static void
8338 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8339     int link_cnt, int tgt_cnt, int flags)
8340 {
8341 	ASSERT(mutex_owned(&pptr->port_mutex));
8342 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8343 
8344 	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8345 	ptgt->tgt_state = FCP_TGT_OFFLINE;
8346 	ptgt->tgt_pd_handle = NULL;
8347 	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8348 }
8349 
8350 
8351 static void
8352 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8353     int flags)
8354 {
8355 	struct	fcp_lun	*plun;
8356 
8357 	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8358 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8359 
8360 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8361 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8362 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8363 		}
8364 	}
8365 }
8366 
8367 
8368 /*
8369  * take a LUN offline
8370  *
8371  * enters and leaves with the target mutex held, releasing it in the process
8372  *
8373  * allocates memory in non-sleep mode
8374  */
8375 static void
8376 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8377     int nowait, int flags)
8378 {
8379 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8380 	struct fcp_lun_elem	*elem;
8381 
8382 	ASSERT(plun != NULL);
8383 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8384 
8385 	if (nowait) {
8386 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8387 		return;
8388 	}
8389 
8390 	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8391 		elem->flags = flags;
8392 		elem->time = fcp_watchdog_time;
8393 		if (nowait == 0) {
8394 			elem->time += fcp_offline_delay;
8395 		}
8396 		elem->plun = plun;
8397 		elem->link_cnt = link_cnt;
8398 		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8399 		elem->next = pptr->port_offline_luns;
8400 		pptr->port_offline_luns = elem;
8401 	} else {
8402 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8403 	}
8404 }
8405 
8406 
8407 static void
8408 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8409 {
8410 	struct fcp_pkt	*head = NULL;
8411 
8412 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8413 
8414 	mutex_exit(&LUN_TGT->tgt_mutex);
8415 
8416 	head = fcp_scan_commands(plun);
8417 	if (head != NULL) {
8418 		fcp_abort_commands(head, LUN_PORT);
8419 	}
8420 
8421 	mutex_enter(&LUN_TGT->tgt_mutex);
8422 
8423 	if (plun->lun_cip && plun->lun_mpxio) {
8424 		/*
8425 		 * Intimate MPxIO lun busy is cleared
8426 		 */
8427 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8428 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8429 		    0, 0)) {
8430 			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8431 			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8432 			    LUN_TGT->tgt_d_id, plun->lun_num);
8433 		}
8434 		/*
8435 		 * Intimate MPxIO that the lun is now marked for offline
8436 		 */
8437 		mutex_exit(&LUN_TGT->tgt_mutex);
8438 		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8439 		mutex_enter(&LUN_TGT->tgt_mutex);
8440 	}
8441 }
8442 
8443 static void
8444 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8445     int flags)
8446 {
8447 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8448 
8449 	mutex_exit(&LUN_TGT->tgt_mutex);
8450 	fcp_update_offline_flags(plun);
8451 	mutex_enter(&LUN_TGT->tgt_mutex);
8452 
8453 	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8454 
8455 	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8456 	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8457 	    "offline_lun: passing OFFLINE elem to HP thread");
8458 
8459 	if (plun->lun_cip) {
8460 		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8461 		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8462 		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8463 		    LUN_TGT->tgt_trace);
8464 
8465 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8466 		    link_cnt, tgt_cnt, flags, 0)) {
8467 			fcp_log(CE_CONT, LUN_PORT->port_dip,
8468 			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8469 			    LUN_TGT->tgt_d_id, plun->lun_num);
8470 		}
8471 	}
8472 }
8473 
8474 static void
8475 fcp_scan_offline_luns(struct fcp_port *pptr)
8476 {
8477 	struct fcp_lun_elem	*elem;
8478 	struct fcp_lun_elem	*prev;
8479 	struct fcp_lun_elem	*next;
8480 
8481 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8482 
8483 	prev = NULL;
8484 	elem = pptr->port_offline_luns;
8485 	while (elem) {
8486 		next = elem->next;
8487 		if (elem->time <= fcp_watchdog_time) {
8488 			int			changed = 1;
8489 			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8490 
8491 			mutex_enter(&ptgt->tgt_mutex);
8492 			if (pptr->port_link_cnt == elem->link_cnt &&
8493 			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8494 				changed = 0;
8495 			}
8496 
8497 			if (!changed &&
8498 			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8499 				fcp_offline_lun_now(elem->plun,
8500 				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8501 			}
8502 			mutex_exit(&ptgt->tgt_mutex);
8503 
8504 			kmem_free(elem, sizeof (*elem));
8505 
8506 			if (prev) {
8507 				prev->next = next;
8508 			} else {
8509 				pptr->port_offline_luns = next;
8510 			}
8511 		} else {
8512 			prev = elem;
8513 		}
8514 		elem = next;
8515 	}
8516 }
8517 
8518 
8519 static void
8520 fcp_scan_offline_tgts(struct fcp_port *pptr)
8521 {
8522 	struct fcp_tgt_elem	*elem;
8523 	struct fcp_tgt_elem	*prev;
8524 	struct fcp_tgt_elem	*next;
8525 
8526 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8527 
8528 	prev = NULL;
8529 	elem = pptr->port_offline_tgts;
8530 	while (elem) {
8531 		next = elem->next;
8532 		if (elem->time <= fcp_watchdog_time) {
8533 			int		outdated = 1;
8534 			struct fcp_tgt	*ptgt = elem->ptgt;
8535 
8536 			mutex_enter(&ptgt->tgt_mutex);
8537 
8538 			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8539 				/* No change on tgt since elem was created. */
8540 				outdated = 0;
8541 			} else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8542 			    pptr->port_link_cnt == elem->link_cnt + 1 &&
8543 			    ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8544 				/*
8545 				 * Exactly one thing happened to the target
8546 				 * inbetween: the local port went offline.
8547 				 * For fp the remote port is already gone so
8548 				 * it will not tell us again to offline the
8549 				 * target. We must offline it now.
8550 				 */
8551 				outdated = 0;
8552 			}
8553 
8554 			if (!outdated && !(ptgt->tgt_state &
8555 			    FCP_TGT_OFFLINE)) {
8556 				fcp_offline_target_now(pptr,
8557 				    ptgt, elem->link_cnt, elem->tgt_cnt,
8558 				    elem->flags);
8559 			}
8560 
8561 			mutex_exit(&ptgt->tgt_mutex);
8562 
8563 			kmem_free(elem, sizeof (*elem));
8564 
8565 			if (prev) {
8566 				prev->next = next;
8567 			} else {
8568 				pptr->port_offline_tgts = next;
8569 			}
8570 		} else {
8571 			prev = elem;
8572 		}
8573 		elem = next;
8574 	}
8575 }
8576 
8577 
8578 static void
8579 fcp_update_offline_flags(struct fcp_lun *plun)
8580 {
8581 	struct fcp_port	*pptr = LUN_PORT;
8582 	ASSERT(plun != NULL);
8583 
8584 	mutex_enter(&LUN_TGT->tgt_mutex);
8585 	plun->lun_state |= FCP_LUN_OFFLINE;
8586 	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8587 
8588 	mutex_enter(&plun->lun_mutex);
8589 	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8590 		dev_info_t *cdip = NULL;
8591 
8592 		mutex_exit(&LUN_TGT->tgt_mutex);
8593 
8594 		if (plun->lun_mpxio == 0) {
8595 			cdip = DIP(plun->lun_cip);
8596 		} else if (plun->lun_cip) {
8597 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8598 		}
8599 
8600 		mutex_exit(&plun->lun_mutex);
8601 		if (cdip) {
8602 			(void) ndi_event_retrieve_cookie(
8603 			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8604 			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8605 			(void) ndi_event_run_callbacks(
8606 			    pptr->port_ndi_event_hdl, cdip,
8607 			    fcp_remove_eid, NULL);
8608 		}
8609 	} else {
8610 		mutex_exit(&plun->lun_mutex);
8611 		mutex_exit(&LUN_TGT->tgt_mutex);
8612 	}
8613 }
8614 
8615 
8616 /*
8617  * Scan all of the command pkts for this port, moving pkts that
8618  * match our LUN onto our own list (headed by "head")
8619  */
8620 static struct fcp_pkt *
8621 fcp_scan_commands(struct fcp_lun *plun)
8622 {
8623 	struct fcp_port	*pptr = LUN_PORT;
8624 
8625 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8626 	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8627 	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8628 
8629 	struct fcp_pkt	*head = NULL;	/* head of our list */
8630 	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8631 
8632 	int			cmds_found = 0;
8633 
8634 	mutex_enter(&pptr->port_pkt_mutex);
8635 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8636 		struct fcp_lun *tlun =
8637 		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8638 
8639 		ncmd = cmd->cmd_next;	/* set next command */
8640 
8641 		/*
8642 		 * if this pkt is for a different LUN  or the
8643 		 * command is sent down, skip it.
8644 		 */
8645 		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8646 		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8647 			pcmd = cmd;
8648 			continue;
8649 		}
8650 		cmds_found++;
8651 		if (pcmd != NULL) {
8652 			ASSERT(pptr->port_pkt_head != cmd);
8653 			pcmd->cmd_next = cmd->cmd_next;
8654 		} else {
8655 			ASSERT(cmd == pptr->port_pkt_head);
8656 			pptr->port_pkt_head = cmd->cmd_next;
8657 		}
8658 
8659 		if (cmd == pptr->port_pkt_tail) {
8660 			pptr->port_pkt_tail = pcmd;
8661 			if (pcmd) {
8662 				pcmd->cmd_next = NULL;
8663 			}
8664 		}
8665 
8666 		if (head == NULL) {
8667 			head = tail = cmd;
8668 		} else {
8669 			ASSERT(tail != NULL);
8670 
8671 			tail->cmd_next = cmd;
8672 			tail = cmd;
8673 		}
8674 		cmd->cmd_next = NULL;
8675 	}
8676 	mutex_exit(&pptr->port_pkt_mutex);
8677 
8678 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8679 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8680 	    "scan commands: %d cmd(s) found", cmds_found);
8681 
8682 	return (head);
8683 }
8684 
8685 
8686 /*
8687  * Abort all the commands in the command queue
8688  */
8689 static void
8690 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8691 {
8692 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8693 	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8694 
8695 	ASSERT(mutex_owned(&pptr->port_mutex));
8696 
8697 	/* scan through the pkts and invalid them */
8698 	for (cmd = head; cmd != NULL; cmd = ncmd) {
8699 		struct scsi_pkt *pkt = cmd->cmd_pkt;
8700 
8701 		ncmd = cmd->cmd_next;
8702 		ASSERT(pkt != NULL);
8703 
8704 		/*
8705 		 * The lun is going to be marked offline. Indicate
8706 		 * the target driver not to requeue or retry this command
8707 		 * as the device is going to be offlined pretty soon.
8708 		 */
8709 		pkt->pkt_reason = CMD_DEV_GONE;
8710 		pkt->pkt_statistics = 0;
8711 		pkt->pkt_state = 0;
8712 
8713 		/* reset cmd flags/state */
8714 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8715 		cmd->cmd_state = FCP_PKT_IDLE;
8716 
8717 		/*
8718 		 * ensure we have a packet completion routine,
8719 		 * then call it.
8720 		 */
8721 		ASSERT(pkt->pkt_comp != NULL);
8722 
8723 		mutex_exit(&pptr->port_mutex);
8724 		fcp_post_callback(cmd);
8725 		mutex_enter(&pptr->port_mutex);
8726 	}
8727 }
8728 
8729 
8730 /*
8731  * the pkt_comp callback for command packets
8732  */
8733 static void
8734 fcp_cmd_callback(fc_packet_t *fpkt)
8735 {
8736 	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8737 	struct scsi_pkt *pkt = cmd->cmd_pkt;
8738 	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8739 
8740 	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8741 
8742 	if (cmd->cmd_state == FCP_PKT_IDLE) {
8743 		cmn_err(CE_PANIC, "Packet already completed %p",
8744 		    (void *)cmd);
8745 	}
8746 
8747 	/*
8748 	 * Watch thread should be freeing the packet, ignore the pkt.
8749 	 */
8750 	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8751 		fcp_log(CE_CONT, pptr->port_dip,
8752 		    "!FCP: Pkt completed while aborting\n");
8753 		return;
8754 	}
8755 	cmd->cmd_state = FCP_PKT_IDLE;
8756 
8757 	fcp_complete_pkt(fpkt);
8758 
8759 #ifdef	DEBUG
8760 	mutex_enter(&pptr->port_pkt_mutex);
8761 	pptr->port_npkts--;
8762 	mutex_exit(&pptr->port_pkt_mutex);
8763 #endif /* DEBUG */
8764 
8765 	fcp_post_callback(cmd);
8766 }
8767 
8768 
8769 static void
8770 fcp_complete_pkt(fc_packet_t *fpkt)
8771 {
8772 	int			error = 0;
8773 	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8774 	    fpkt->pkt_ulp_private;
8775 	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8776 	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8777 	struct fcp_lun	*plun;
8778 	struct fcp_tgt	*ptgt;
8779 	struct fcp_rsp		*rsp;
8780 	struct scsi_address	save;
8781 
8782 #ifdef	DEBUG
8783 	save = pkt->pkt_address;
8784 #endif /* DEBUG */
8785 
8786 	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8787 
8788 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8789 		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8790 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8791 			    sizeof (struct fcp_rsp));
8792 		}
8793 
8794 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8795 		    STATE_SENT_CMD | STATE_GOT_STATUS;
8796 
8797 		pkt->pkt_resid = 0;
8798 
8799 		if (fpkt->pkt_datalen) {
8800 			pkt->pkt_state |= STATE_XFERRED_DATA;
8801 			if (fpkt->pkt_data_resid) {
8802 				error++;
8803 			}
8804 		}
8805 
8806 		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8807 		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8808 			/*
8809 			 * The next two checks make sure that if there
8810 			 * is no sense data or a valid response and
8811 			 * the command came back with check condition,
8812 			 * the command should be retried.
8813 			 */
8814 			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8815 			    !rsp->fcp_u.fcp_status.sense_len_set) {
8816 				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8817 				pkt->pkt_resid = cmd->cmd_dmacount;
8818 			}
8819 		}
8820 
8821 		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8822 			return;
8823 		}
8824 
8825 		plun = ADDR2LUN(&pkt->pkt_address);
8826 		ptgt = plun->lun_tgt;
8827 		ASSERT(ptgt != NULL);
8828 
8829 		/*
8830 		 * Update the transfer resid, if appropriate
8831 		 */
8832 		if (rsp->fcp_u.fcp_status.resid_over ||
8833 		    rsp->fcp_u.fcp_status.resid_under) {
8834 			pkt->pkt_resid = rsp->fcp_resid;
8835 		}
8836 
8837 		/*
8838 		 * First see if we got a FCP protocol error.
8839 		 */
8840 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8841 			struct fcp_rsp_info	*bep;
8842 			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8843 			    sizeof (struct fcp_rsp));
8844 
8845 			if (fcp_validate_fcp_response(rsp, pptr) !=
8846 			    FC_SUCCESS) {
8847 				pkt->pkt_reason = CMD_CMPLT;
8848 				*(pkt->pkt_scbp) = STATUS_CHECK;
8849 
8850 				fcp_log(CE_WARN, pptr->port_dip,
8851 				    "!SCSI command to d_id=0x%x lun=0x%x"
8852 				    " failed, Bad FCP response values:"
8853 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8854 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8855 				    ptgt->tgt_d_id, plun->lun_num,
8856 				    rsp->reserved_0, rsp->reserved_1,
8857 				    rsp->fcp_u.fcp_status.reserved_0,
8858 				    rsp->fcp_u.fcp_status.reserved_1,
8859 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8860 
8861 				return;
8862 			}
8863 
8864 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8865 				FCP_CP_IN(fpkt->pkt_resp +
8866 				    sizeof (struct fcp_rsp), bep,
8867 				    fpkt->pkt_resp_acc,
8868 				    sizeof (struct fcp_rsp_info));
8869 			}
8870 
8871 			if (bep->rsp_code != FCP_NO_FAILURE) {
8872 				child_info_t	*cip;
8873 
8874 				pkt->pkt_reason = CMD_TRAN_ERR;
8875 
8876 				mutex_enter(&plun->lun_mutex);
8877 				cip = plun->lun_cip;
8878 				mutex_exit(&plun->lun_mutex);
8879 
8880 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8881 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8882 				    "FCP response error on cmd=%p"
8883 				    " target=0x%x, cip=%p", cmd,
8884 				    ptgt->tgt_d_id, cip);
8885 			}
8886 		}
8887 
8888 		/*
8889 		 * See if we got a SCSI error with sense data
8890 		 */
8891 		if (rsp->fcp_u.fcp_status.sense_len_set) {
8892 			uchar_t				rqlen;
8893 			caddr_t				sense_from;
8894 			child_info_t			*cip;
8895 			timeout_id_t			tid;
8896 			struct scsi_arq_status		*arq;
8897 			struct scsi_extended_sense	*sense_to;
8898 
8899 			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8900 			sense_to = &arq->sts_sensedata;
8901 
8902 			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8903 			    sizeof (struct scsi_extended_sense));
8904 
8905 			sense_from = (caddr_t)fpkt->pkt_resp +
8906 			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8907 
8908 			if (fcp_validate_fcp_response(rsp, pptr) !=
8909 			    FC_SUCCESS) {
8910 				pkt->pkt_reason = CMD_CMPLT;
8911 				*(pkt->pkt_scbp) = STATUS_CHECK;
8912 
8913 				fcp_log(CE_WARN, pptr->port_dip,
8914 				    "!SCSI command to d_id=0x%x lun=0x%x"
8915 				    " failed, Bad FCP response values:"
8916 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8917 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8918 				    ptgt->tgt_d_id, plun->lun_num,
8919 				    rsp->reserved_0, rsp->reserved_1,
8920 				    rsp->fcp_u.fcp_status.reserved_0,
8921 				    rsp->fcp_u.fcp_status.reserved_1,
8922 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8923 
8924 				return;
8925 			}
8926 
8927 			/*
8928 			 * copy in sense information
8929 			 */
8930 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8931 				FCP_CP_IN(sense_from, sense_to,
8932 				    fpkt->pkt_resp_acc, rqlen);
8933 			} else {
8934 				bcopy(sense_from, sense_to, rqlen);
8935 			}
8936 
8937 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8938 			    (FCP_SENSE_NO_LUN(sense_to))) {
8939 				mutex_enter(&ptgt->tgt_mutex);
8940 				if (ptgt->tgt_tid == NULL) {
8941 					/*
8942 					 * Kick off rediscovery
8943 					 */
8944 					tid = timeout(fcp_reconfigure_luns,
8945 					    (caddr_t)ptgt, drv_usectohz(1));
8946 
8947 					ptgt->tgt_tid = tid;
8948 					ptgt->tgt_state |= FCP_TGT_BUSY;
8949 				}
8950 				mutex_exit(&ptgt->tgt_mutex);
8951 				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8952 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8953 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8954 					    "!FCP: Report Lun Has Changed"
8955 					    " target=%x", ptgt->tgt_d_id);
8956 				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8957 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8958 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8959 					    "!FCP: LU Not Supported"
8960 					    " target=%x", ptgt->tgt_d_id);
8961 				}
8962 			}
8963 			ASSERT(pkt->pkt_scbp != NULL);
8964 
8965 			pkt->pkt_state |= STATE_ARQ_DONE;
8966 
8967 			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8968 
8969 			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8970 			arq->sts_rqpkt_reason = 0;
8971 			arq->sts_rqpkt_statistics = 0;
8972 
8973 			arq->sts_rqpkt_state = STATE_GOT_BUS |
8974 			    STATE_GOT_TARGET | STATE_SENT_CMD |
8975 			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8976 			    STATE_XFERRED_DATA;
8977 
8978 			mutex_enter(&plun->lun_mutex);
8979 			cip = plun->lun_cip;
8980 			mutex_exit(&plun->lun_mutex);
8981 
8982 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8983 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
8984 			    "SCSI Check condition on cmd=%p target=0x%x"
8985 			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
8986 			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
8987 			    cmd->cmd_fcp_cmd.fcp_cdb[0],
8988 			    rsp->fcp_u.fcp_status.scsi_status,
8989 			    sense_to->es_key, sense_to->es_add_code,
8990 			    sense_to->es_qual_code);
8991 		}
8992 	} else {
8993 		plun = ADDR2LUN(&pkt->pkt_address);
8994 		ptgt = plun->lun_tgt;
8995 		ASSERT(ptgt != NULL);
8996 
8997 		/*
8998 		 * Work harder to translate errors into target driver
8999 		 * understandable ones. Note with despair that the target
9000 		 * drivers don't decode pkt_state and pkt_reason exhaustively
9001 		 * They resort to using the big hammer most often, which
9002 		 * may not get fixed in the life time of this driver.
9003 		 */
9004 		pkt->pkt_state = 0;
9005 		pkt->pkt_statistics = 0;
9006 
9007 		switch (fpkt->pkt_state) {
9008 		case FC_PKT_TRAN_ERROR:
9009 			switch (fpkt->pkt_reason) {
9010 			case FC_REASON_OVERRUN:
9011 				pkt->pkt_reason = CMD_CMD_OVR;
9012 				pkt->pkt_statistics |= STAT_ABORTED;
9013 				break;
9014 
9015 			case FC_REASON_XCHG_BSY: {
9016 				caddr_t ptr;
9017 
9018 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9019 
9020 				ptr = (caddr_t)pkt->pkt_scbp;
9021 				if (ptr) {
9022 					*ptr = STATUS_BUSY;
9023 				}
9024 				break;
9025 			}
9026 
9027 			case FC_REASON_ABORTED:
9028 				pkt->pkt_reason = CMD_TRAN_ERR;
9029 				pkt->pkt_statistics |= STAT_ABORTED;
9030 				break;
9031 
9032 			case FC_REASON_ABORT_FAILED:
9033 				pkt->pkt_reason = CMD_ABORT_FAIL;
9034 				break;
9035 
9036 			case FC_REASON_NO_SEQ_INIT:
9037 			case FC_REASON_CRC_ERROR:
9038 				pkt->pkt_reason = CMD_TRAN_ERR;
9039 				pkt->pkt_statistics |= STAT_ABORTED;
9040 				break;
9041 			default:
9042 				pkt->pkt_reason = CMD_TRAN_ERR;
9043 				break;
9044 			}
9045 			break;
9046 
9047 		case FC_PKT_PORT_OFFLINE: {
9048 			dev_info_t	*cdip = NULL;
9049 			caddr_t		ptr;
9050 
9051 			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9052 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9053 				    fcp_trace, FCP_BUF_LEVEL_8, 0,
9054 				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9055 				    ptgt->tgt_d_id);
9056 			}
9057 
9058 			mutex_enter(&plun->lun_mutex);
9059 			if (plun->lun_mpxio == 0) {
9060 				cdip = DIP(plun->lun_cip);
9061 			} else if (plun->lun_cip) {
9062 				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9063 			}
9064 
9065 			mutex_exit(&plun->lun_mutex);
9066 
9067 			if (cdip) {
9068 				(void) ndi_event_retrieve_cookie(
9069 				    pptr->port_ndi_event_hdl, cdip,
9070 				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9071 				    NDI_EVENT_NOPASS);
9072 				(void) ndi_event_run_callbacks(
9073 				    pptr->port_ndi_event_hdl, cdip,
9074 				    fcp_remove_eid, NULL);
9075 			}
9076 
9077 			/*
9078 			 * If the link goes off-line for a lip,
9079 			 * this will cause a error to the ST SG
9080 			 * SGEN drivers. By setting BUSY we will
9081 			 * give the drivers the chance to retry
9082 			 * before it blows of the job. ST will
9083 			 * remember how many times it has retried.
9084 			 */
9085 
9086 			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9087 			    (plun->lun_type == DTYPE_CHANGER)) {
9088 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9089 				ptr = (caddr_t)pkt->pkt_scbp;
9090 				if (ptr) {
9091 					*ptr = STATUS_BUSY;
9092 				}
9093 			} else {
9094 				pkt->pkt_reason = CMD_TRAN_ERR;
9095 				pkt->pkt_statistics |= STAT_BUS_RESET;
9096 			}
9097 			break;
9098 		}
9099 
9100 		case FC_PKT_TRAN_BSY:
9101 			/*
9102 			 * Use the ssd Qfull handling here.
9103 			 */
9104 			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9105 			pkt->pkt_state = STATE_GOT_BUS;
9106 			break;
9107 
9108 		case FC_PKT_TIMEOUT:
9109 			pkt->pkt_reason = CMD_TIMEOUT;
9110 			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9111 				pkt->pkt_statistics |= STAT_TIMEOUT;
9112 			} else {
9113 				pkt->pkt_statistics |= STAT_ABORTED;
9114 			}
9115 			break;
9116 
9117 		case FC_PKT_LOCAL_RJT:
9118 			switch (fpkt->pkt_reason) {
9119 			case FC_REASON_OFFLINE: {
9120 				dev_info_t	*cdip = NULL;
9121 
9122 				mutex_enter(&plun->lun_mutex);
9123 				if (plun->lun_mpxio == 0) {
9124 					cdip = DIP(plun->lun_cip);
9125 				} else if (plun->lun_cip) {
9126 					cdip = mdi_pi_get_client(
9127 					    PIP(plun->lun_cip));
9128 				}
9129 				mutex_exit(&plun->lun_mutex);
9130 
9131 				if (cdip) {
9132 					(void) ndi_event_retrieve_cookie(
9133 					    pptr->port_ndi_event_hdl, cdip,
9134 					    FCAL_REMOVE_EVENT,
9135 					    &fcp_remove_eid,
9136 					    NDI_EVENT_NOPASS);
9137 					(void) ndi_event_run_callbacks(
9138 					    pptr->port_ndi_event_hdl,
9139 					    cdip, fcp_remove_eid, NULL);
9140 				}
9141 
9142 				pkt->pkt_reason = CMD_TRAN_ERR;
9143 				pkt->pkt_statistics |= STAT_BUS_RESET;
9144 
9145 				break;
9146 			}
9147 
9148 			case FC_REASON_NOMEM:
9149 			case FC_REASON_QFULL: {
9150 				caddr_t ptr;
9151 
9152 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9153 				ptr = (caddr_t)pkt->pkt_scbp;
9154 				if (ptr) {
9155 					*ptr = STATUS_BUSY;
9156 				}
9157 				break;
9158 			}
9159 
9160 			case FC_REASON_DMA_ERROR:
9161 				pkt->pkt_reason = CMD_DMA_DERR;
9162 				pkt->pkt_statistics |= STAT_ABORTED;
9163 				break;
9164 
9165 			case FC_REASON_CRC_ERROR:
9166 			case FC_REASON_UNDERRUN: {
9167 				uchar_t		status;
9168 				/*
9169 				 * Work around for Bugid: 4240945.
9170 				 * IB on A5k doesn't set the Underrun bit
9171 				 * in the fcp status, when it is transferring
9172 				 * less than requested amount of data. Work
9173 				 * around the ses problem to keep luxadm
9174 				 * happy till ibfirmware is fixed.
9175 				 */
9176 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9177 					FCP_CP_IN(fpkt->pkt_resp, rsp,
9178 					    fpkt->pkt_resp_acc,
9179 					    sizeof (struct fcp_rsp));
9180 				}
9181 				status = rsp->fcp_u.fcp_status.scsi_status;
9182 				if (((plun->lun_type & DTYPE_MASK) ==
9183 				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9184 					pkt->pkt_reason = CMD_CMPLT;
9185 					*pkt->pkt_scbp = status;
9186 					pkt->pkt_resid = 0;
9187 				} else {
9188 					pkt->pkt_reason = CMD_TRAN_ERR;
9189 					pkt->pkt_statistics |= STAT_ABORTED;
9190 				}
9191 				break;
9192 			}
9193 
9194 			case FC_REASON_NO_CONNECTION:
9195 			case FC_REASON_UNSUPPORTED:
9196 			case FC_REASON_ILLEGAL_REQ:
9197 			case FC_REASON_BAD_SID:
9198 			case FC_REASON_DIAG_BUSY:
9199 			case FC_REASON_FCAL_OPN_FAIL:
9200 			case FC_REASON_BAD_XID:
9201 			default:
9202 				pkt->pkt_reason = CMD_TRAN_ERR;
9203 				pkt->pkt_statistics |= STAT_ABORTED;
9204 				break;
9205 
9206 			}
9207 			break;
9208 
9209 		case FC_PKT_NPORT_RJT:
9210 		case FC_PKT_FABRIC_RJT:
9211 		case FC_PKT_NPORT_BSY:
9212 		case FC_PKT_FABRIC_BSY:
9213 		default:
9214 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9215 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9216 			    "FC Status 0x%x, reason 0x%x",
9217 			    fpkt->pkt_state, fpkt->pkt_reason);
9218 			pkt->pkt_reason = CMD_TRAN_ERR;
9219 			pkt->pkt_statistics |= STAT_ABORTED;
9220 			break;
9221 		}
9222 
9223 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9224 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9225 		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9226 		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9227 		    fpkt->pkt_reason);
9228 	}
9229 
9230 	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9231 }
9232 
9233 
9234 static int
9235 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9236 {
9237 	if (rsp->reserved_0 || rsp->reserved_1 ||
9238 	    rsp->fcp_u.fcp_status.reserved_0 ||
9239 	    rsp->fcp_u.fcp_status.reserved_1) {
9240 		/*
9241 		 * These reserved fields should ideally be zero. FCP-2 does say
9242 		 * that the recipient need not check for reserved fields to be
9243 		 * zero. If they are not zero, we will not make a fuss about it
9244 		 * - just log it (in debug to both trace buffer and messages
9245 		 * file and to trace buffer only in non-debug) and move on.
9246 		 *
9247 		 * Non-zero reserved fields were seen with minnows.
9248 		 *
9249 		 * qlc takes care of some of this but we cannot assume that all
9250 		 * FCAs will do so.
9251 		 */
9252 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9253 		    FCP_BUF_LEVEL_5, 0,
9254 		    "Got fcp response packet with non-zero reserved fields "
9255 		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9256 		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9257 		    rsp->reserved_0, rsp->reserved_1,
9258 		    rsp->fcp_u.fcp_status.reserved_0,
9259 		    rsp->fcp_u.fcp_status.reserved_1);
9260 	}
9261 
9262 	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9263 	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9264 		return (FC_FAILURE);
9265 	}
9266 
9267 	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9268 	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9269 	    sizeof (struct fcp_rsp))) {
9270 		return (FC_FAILURE);
9271 	}
9272 
9273 	return (FC_SUCCESS);
9274 }
9275 
9276 
9277 /*
9278  * This is called when there is a change the in device state. The case we're
9279  * handling here is, if the d_id s does not match, offline this tgt and online
9280  * a new tgt with the new d_id.	 called from fcp_handle_devices with
9281  * port_mutex held.
9282  */
9283 static int
9284 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9285     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9286 {
9287 	ASSERT(mutex_owned(&pptr->port_mutex));
9288 
9289 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9290 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9291 	    "Starting fcp_device_changed...");
9292 
9293 	/*
9294 	 * The two cases where the port_device_changed is called is
9295 	 * either it changes it's d_id or it's hard address.
9296 	 */
9297 	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9298 	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9299 	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9300 
9301 		/* offline this target */
9302 		mutex_enter(&ptgt->tgt_mutex);
9303 		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9304 			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9305 			    0, 1, NDI_DEVI_REMOVE);
9306 		}
9307 		mutex_exit(&ptgt->tgt_mutex);
9308 
9309 		fcp_log(CE_NOTE, pptr->port_dip,
9310 		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9311 		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9312 		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9313 		    map_entry->map_hard_addr.hard_addr);
9314 	}
9315 
9316 	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9317 	    link_cnt, tgt_cnt, cause));
9318 }
9319 
9320 /*
9321  *     Function: fcp_alloc_lun
9322  *
9323  *  Description: Creates a new lun structure and adds it to the list
9324  *		 of luns of the target.
9325  *
9326  *     Argument: ptgt		Target the lun will belong to.
9327  *
9328  * Return Value: NULL		Failed
9329  *		 Not NULL	Succeeded
9330  *
9331  *	Context: Kernel context
9332  */
9333 static struct fcp_lun *
9334 fcp_alloc_lun(struct fcp_tgt *ptgt)
9335 {
9336 	struct fcp_lun *plun;
9337 
9338 	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9339 	if (plun != NULL) {
9340 		/*
9341 		 * Initialize the mutex before putting in the target list
9342 		 * especially before releasing the target mutex.
9343 		 */
9344 		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9345 		plun->lun_tgt = ptgt;
9346 
9347 		mutex_enter(&ptgt->tgt_mutex);
9348 		plun->lun_next = ptgt->tgt_lun;
9349 		ptgt->tgt_lun = plun;
9350 		plun->lun_old_guid = NULL;
9351 		plun->lun_old_guid_size = 0;
9352 		mutex_exit(&ptgt->tgt_mutex);
9353 	}
9354 
9355 	return (plun);
9356 }
9357 
9358 /*
9359  *     Function: fcp_dealloc_lun
9360  *
9361  *  Description: Frees the LUN structure passed by the caller.
9362  *
9363  *     Argument: plun		LUN structure to free.
9364  *
9365  * Return Value: None
9366  *
9367  *	Context: Kernel context.
9368  */
9369 static void
9370 fcp_dealloc_lun(struct fcp_lun *plun)
9371 {
9372 	mutex_enter(&plun->lun_mutex);
9373 	if (plun->lun_cip) {
9374 		fcp_remove_child(plun);
9375 	}
9376 	mutex_exit(&plun->lun_mutex);
9377 
9378 	mutex_destroy(&plun->lun_mutex);
9379 	if (plun->lun_guid) {
9380 		kmem_free(plun->lun_guid, plun->lun_guid_size);
9381 	}
9382 	if (plun->lun_old_guid) {
9383 		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9384 	}
9385 	kmem_free(plun, sizeof (*plun));
9386 }
9387 
9388 /*
9389  *     Function: fcp_alloc_tgt
9390  *
9391  *  Description: Creates a new target structure and adds it to the port
9392  *		 hash list.
9393  *
9394  *     Argument: pptr		fcp port structure
9395  *		 *map_entry	entry describing the target to create
9396  *		 link_cnt	Link state change counter
9397  *
9398  * Return Value: NULL		Failed
9399  *		 Not NULL	Succeeded
9400  *
9401  *	Context: Kernel context.
9402  */
9403 static struct fcp_tgt *
9404 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9405 {
9406 	int			hash;
9407 	uchar_t			*wwn;
9408 	struct fcp_tgt	*ptgt;
9409 
9410 	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9411 	if (ptgt != NULL) {
9412 		mutex_enter(&pptr->port_mutex);
9413 		if (link_cnt != pptr->port_link_cnt) {
9414 			/*
9415 			 * oh oh -- another link reset
9416 			 * in progress -- give up
9417 			 */
9418 			mutex_exit(&pptr->port_mutex);
9419 			kmem_free(ptgt, sizeof (*ptgt));
9420 			ptgt = NULL;
9421 		} else {
9422 			/*
9423 			 * initialize the mutex before putting in the port
9424 			 * wwn list, especially before releasing the port
9425 			 * mutex.
9426 			 */
9427 			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9428 
9429 			/* add new target entry to the port's hash list */
9430 			wwn = (uchar_t *)&map_entry->map_pwwn;
9431 			hash = FCP_HASH(wwn);
9432 
9433 			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9434 			pptr->port_tgt_hash_table[hash] = ptgt;
9435 
9436 			/* save cross-ptr */
9437 			ptgt->tgt_port = pptr;
9438 
9439 			ptgt->tgt_change_cnt = 1;
9440 
9441 			/* initialize the target manual_config_only flag */
9442 			if (fcp_enable_auto_configuration) {
9443 				ptgt->tgt_manual_config_only = 0;
9444 			} else {
9445 				ptgt->tgt_manual_config_only = 1;
9446 			}
9447 
9448 			mutex_exit(&pptr->port_mutex);
9449 		}
9450 	}
9451 
9452 	return (ptgt);
9453 }
9454 
9455 /*
9456  *     Function: fcp_dealloc_tgt
9457  *
9458  *  Description: Frees the target structure passed by the caller.
9459  *
9460  *     Argument: ptgt		Target structure to free.
9461  *
9462  * Return Value: None
9463  *
9464  *	Context: Kernel context.
9465  */
9466 static void
9467 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9468 {
9469 	mutex_destroy(&ptgt->tgt_mutex);
9470 	kmem_free(ptgt, sizeof (*ptgt));
9471 }
9472 
9473 
9474 /*
9475  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9476  *
9477  *	Device discovery commands will not be retried for-ever as
9478  *	this will have repercussions on other devices that need to
9479  *	be submitted to the hotplug thread. After a quick glance
9480  *	at the SCSI-3 spec, it was found that the spec doesn't
9481  *	mandate a forever retry, rather recommends a delayed retry.
9482  *
9483  *	Since Photon IB is single threaded, STATUS_BUSY is common
9484  *	in a 4+initiator environment. Make sure the total time
9485  *	spent on retries (including command timeout) does not
9486  *	60 seconds
9487  */
9488 static void
9489 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9490 {
9491 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9492 	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9493 
9494 	mutex_enter(&pptr->port_mutex);
9495 	mutex_enter(&ptgt->tgt_mutex);
9496 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9497 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9498 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9499 		    "fcp_queue_ipkt,1:state change occured"
9500 		    " for D_ID=0x%x", ptgt->tgt_d_id);
9501 		mutex_exit(&ptgt->tgt_mutex);
9502 		mutex_exit(&pptr->port_mutex);
9503 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9504 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9505 		fcp_icmd_free(pptr, icmd);
9506 		return;
9507 	}
9508 	mutex_exit(&ptgt->tgt_mutex);
9509 
9510 	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9511 
9512 	if (pptr->port_ipkt_list != NULL) {
9513 		/* add pkt to front of doubly-linked list */
9514 		pptr->port_ipkt_list->ipkt_prev = icmd;
9515 		icmd->ipkt_next = pptr->port_ipkt_list;
9516 		pptr->port_ipkt_list = icmd;
9517 		icmd->ipkt_prev = NULL;
9518 	} else {
9519 		/* this is the first/only pkt on the list */
9520 		pptr->port_ipkt_list = icmd;
9521 		icmd->ipkt_next = NULL;
9522 		icmd->ipkt_prev = NULL;
9523 	}
9524 	mutex_exit(&pptr->port_mutex);
9525 }
9526 
9527 /*
9528  *     Function: fcp_transport
9529  *
9530  *  Description: This function submits the Fibre Channel packet to the transort
9531  *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9532  *		 fails the submission, the treatment depends on the value of
9533  *		 the variable internal.
9534  *
9535  *     Argument: port_handle	fp/fctl port handle.
9536  *		 *fpkt		Packet to submit to the transport layer.
9537  *		 internal	Not zero when it's an internal packet.
9538  *
9539  * Return Value: FC_TRAN_BUSY
9540  *		 FC_STATEC_BUSY
9541  *		 FC_OFFLINE
9542  *		 FC_LOGINREQ
9543  *		 FC_DEVICE_BUSY
9544  *		 FC_SUCCESS
9545  */
9546 static int
9547 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9548 {
9549 	int	rval;
9550 
9551 	rval = fc_ulp_transport(port_handle, fpkt);
9552 	if (rval == FC_SUCCESS) {
9553 		return (rval);
9554 	}
9555 
9556 	/*
9557 	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9558 	 * a command, if the underlying modules see that there is a state
9559 	 * change, or if a port is OFFLINE, that means, that state change
9560 	 * hasn't reached FCP yet, so re-queue the command for deferred
9561 	 * submission.
9562 	 */
9563 	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9564 	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9565 	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9566 		/*
9567 		 * Defer packet re-submission. Life hang is possible on
9568 		 * internal commands if the port driver sends FC_STATEC_BUSY
9569 		 * for ever, but that shouldn't happen in a good environment.
9570 		 * Limiting re-transport for internal commands is probably a
9571 		 * good idea..
9572 		 * A race condition can happen when a port sees barrage of
9573 		 * link transitions offline to online. If the FCTL has
9574 		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9575 		 * internal commands should be queued to do the discovery.
9576 		 * The race condition is when an online comes and FCP starts
9577 		 * its internal discovery and the link goes offline. It is
9578 		 * possible that the statec_callback has not reached FCP
9579 		 * and FCP is carrying on with its internal discovery.
9580 		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9581 		 * that the link has gone offline. At this point FCP should
9582 		 * drop all the internal commands and wait for the
9583 		 * statec_callback. It will be facilitated by incrementing
9584 		 * port_link_cnt.
9585 		 *
9586 		 * For external commands, the (FC)pkt_timeout is decremented
9587 		 * by the QUEUE Delay added by our driver, Care is taken to
9588 		 * ensure that it doesn't become zero (zero means no timeout)
9589 		 * If the time expires right inside driver queue itself,
9590 		 * the watch thread will return it to the original caller
9591 		 * indicating that the command has timed-out.
9592 		 */
9593 		if (internal) {
9594 			char			*op;
9595 			struct fcp_ipkt	*icmd;
9596 
9597 			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9598 			switch (icmd->ipkt_opcode) {
9599 			case SCMD_REPORT_LUN:
9600 				op = "REPORT LUN";
9601 				break;
9602 
9603 			case SCMD_INQUIRY:
9604 				op = "INQUIRY";
9605 				break;
9606 
9607 			case SCMD_INQUIRY_PAGE83:
9608 				op = "INQUIRY-83";
9609 				break;
9610 
9611 			default:
9612 				op = "Internal SCSI COMMAND";
9613 				break;
9614 			}
9615 
9616 			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9617 			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9618 				rval = FC_SUCCESS;
9619 			}
9620 		} else {
9621 			struct fcp_pkt *cmd;
9622 			struct fcp_port *pptr;
9623 
9624 			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9625 			cmd->cmd_state = FCP_PKT_IDLE;
9626 			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9627 
9628 			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9629 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9630 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9631 				    "fcp_transport: xport busy for pkt %p",
9632 				    cmd->cmd_pkt);
9633 				rval = FC_TRAN_BUSY;
9634 			} else {
9635 				fcp_queue_pkt(pptr, cmd);
9636 				rval = FC_SUCCESS;
9637 			}
9638 		}
9639 	}
9640 
9641 	return (rval);
9642 }
9643 
9644 /*VARARGS3*/
9645 static void
9646 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9647 {
9648 	char		buf[256];
9649 	va_list		ap;
9650 
9651 	if (dip == NULL) {
9652 		dip = fcp_global_dip;
9653 	}
9654 
9655 	va_start(ap, fmt);
9656 	(void) vsprintf(buf, fmt, ap);
9657 	va_end(ap);
9658 
9659 	scsi_log(dip, "fcp", level, buf);
9660 }
9661 
9662 /*
9663  * This function retries NS registry of FC4 type.
9664  * It assumes that fcp_mutex is held.
9665  * The function does nothing if topology is not fabric
9666  * So, the topology has to be set before this function can be called
9667  */
9668 static void
9669 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9670 {
9671 	int	rval;
9672 
9673 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9674 
9675 	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9676 	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9677 	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9678 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9679 			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9680 		}
9681 		return;
9682 	}
9683 	mutex_exit(&pptr->port_mutex);
9684 	rval = fcp_do_ns_registry(pptr, s_id);
9685 	mutex_enter(&pptr->port_mutex);
9686 
9687 	if (rval == 0) {
9688 		/* Registry successful. Reset flag */
9689 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9690 	}
9691 }
9692 
9693 /*
9694  * This function registers the ULP with the switch by calling transport i/f
9695  */
9696 static int
9697 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9698 {
9699 	fc_ns_cmd_t		ns_cmd;
9700 	ns_rfc_type_t		rfc;
9701 	uint32_t		types[8];
9702 
9703 	/*
9704 	 * Prepare the Name server structure to
9705 	 * register with the transport in case of
9706 	 * Fabric configuration.
9707 	 */
9708 	bzero(&rfc, sizeof (rfc));
9709 	bzero(types, sizeof (types));
9710 
9711 	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9712 	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9713 
9714 	rfc.rfc_port_id.port_id = s_id;
9715 	bcopy(types, rfc.rfc_types, sizeof (types));
9716 
9717 	ns_cmd.ns_flags = 0;
9718 	ns_cmd.ns_cmd = NS_RFT_ID;
9719 	ns_cmd.ns_req_len = sizeof (rfc);
9720 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9721 	ns_cmd.ns_resp_len = 0;
9722 	ns_cmd.ns_resp_payload = NULL;
9723 
9724 	/*
9725 	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9726 	 */
9727 	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9728 		fcp_log(CE_WARN, pptr->port_dip,
9729 		    "!ns_registry: failed name server registration");
9730 		return (1);
9731 	}
9732 
9733 	return (0);
9734 }
9735 
9736 /*
9737  *     Function: fcp_handle_port_attach
9738  *
9739  *  Description: This function is called from fcp_port_attach() to attach a
9740  *		 new port. This routine does the following:
9741  *
9742  *		1) Allocates an fcp_port structure and initializes it.
9743  *		2) Tries to register the new FC-4 (FCP) capablity with the name
9744  *		   server.
9745  *		3) Kicks off the enumeration of the targets/luns visible
9746  *		   through this new port.  That is done by calling
9747  *		   fcp_statec_callback() if the port is online.
9748  *
9749  *     Argument: ulph		fp/fctl port handle.
9750  *		 *pinfo		Port information.
9751  *		 s_id		Port ID.
9752  *		 instance	Device instance number for the local port
9753  *				(returned by ddi_get_instance()).
9754  *
9755  * Return Value: DDI_SUCCESS
9756  *		 DDI_FAILURE
9757  *
9758  *	Context: User and Kernel context.
9759  */
9760 /*ARGSUSED*/
9761 int
9762 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9763     uint32_t s_id, int instance)
9764 {
9765 	int			res = DDI_FAILURE;
9766 	scsi_hba_tran_t		*tran;
9767 	int			mutex_initted = FALSE;
9768 	int			hba_attached = FALSE;
9769 	int			soft_state_linked = FALSE;
9770 	int			event_bind = FALSE;
9771 	struct fcp_port		*pptr;
9772 	fc_portmap_t		*tmp_list = NULL;
9773 	uint32_t		max_cnt, alloc_cnt;
9774 	uchar_t			*boot_wwn = NULL;
9775 	uint_t			nbytes;
9776 	int			manual_cfg;
9777 
9778 	/*
9779 	 * this port instance attaching for the first time (or after
9780 	 * being detached before)
9781 	 */
9782 	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9783 	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9784 
9785 	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9786 		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9787 		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9788 		    instance);
9789 		return (res);
9790 	}
9791 
9792 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9793 		/* this shouldn't happen */
9794 		ddi_soft_state_free(fcp_softstate, instance);
9795 		cmn_err(CE_WARN, "fcp: bad soft state");
9796 		return (res);
9797 	}
9798 
9799 	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9800 
9801 	/*
9802 	 * Make a copy of ulp_port_info as fctl allocates
9803 	 * a temp struct.
9804 	 */
9805 	(void) fcp_cp_pinfo(pptr, pinfo);
9806 
9807 	/*
9808 	 * Check for manual_configuration_only property.
9809 	 * Enable manual configurtion if the property is
9810 	 * set to 1, otherwise disable manual configuration.
9811 	 */
9812 	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9813 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9814 	    MANUAL_CFG_ONLY,
9815 	    -1)) != -1) {
9816 		if (manual_cfg == 1) {
9817 			char	*pathname;
9818 			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9819 			(void) ddi_pathname(pptr->port_dip, pathname);
9820 			cmn_err(CE_NOTE,
9821 			    "%s (%s%d) %s is enabled via %s.conf.",
9822 			    pathname,
9823 			    ddi_driver_name(pptr->port_dip),
9824 			    ddi_get_instance(pptr->port_dip),
9825 			    MANUAL_CFG_ONLY,
9826 			    ddi_driver_name(pptr->port_dip));
9827 			fcp_enable_auto_configuration = 0;
9828 			kmem_free(pathname, MAXPATHLEN);
9829 		}
9830 	}
9831 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9832 	pptr->port_link_cnt = 1;
9833 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9834 	pptr->port_id = s_id;
9835 	pptr->port_instance = instance;
9836 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9837 	pptr->port_state = FCP_STATE_INIT;
9838 	if (pinfo->port_acc_attr == NULL) {
9839 		/*
9840 		 * The corresponding FCA doesn't support DMA at all
9841 		 */
9842 		pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9843 	}
9844 
9845 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9846 
9847 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9848 		/*
9849 		 * If FCA supports DMA in SCSI data phase, we need preallocate
9850 		 * dma cookie, so stash the cookie size
9851 		 */
9852 		pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9853 		    pptr->port_data_dma_attr.dma_attr_sgllen;
9854 	}
9855 
9856 	/*
9857 	 * The two mutexes of fcp_port are initialized.	 The variable
9858 	 * mutex_initted is incremented to remember that fact.	That variable
9859 	 * is checked when the routine fails and the mutexes have to be
9860 	 * destroyed.
9861 	 */
9862 	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9863 	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9864 	mutex_initted++;
9865 
9866 	/*
9867 	 * The SCSI tran structure is allocate and initialized now.
9868 	 */
9869 	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9870 		fcp_log(CE_WARN, pptr->port_dip,
9871 		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9872 		goto fail;
9873 	}
9874 
9875 	/* link in the transport structure then fill it in */
9876 	pptr->port_tran = tran;
9877 	tran->tran_hba_private		= pptr;
9878 	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9879 	tran->tran_tgt_probe		= NULL;
9880 	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9881 	tran->tran_start		= fcp_scsi_start;
9882 	tran->tran_reset		= fcp_scsi_reset;
9883 	tran->tran_abort		= fcp_scsi_abort;
9884 	tran->tran_getcap		= fcp_scsi_getcap;
9885 	tran->tran_setcap		= fcp_scsi_setcap;
9886 	tran->tran_init_pkt		= NULL;
9887 	tran->tran_destroy_pkt		= NULL;
9888 	tran->tran_dmafree		= NULL;
9889 	tran->tran_sync_pkt		= NULL;
9890 	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9891 	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9892 	tran->tran_get_name		= fcp_scsi_get_name;
9893 	tran->tran_clear_aca		= NULL;
9894 	tran->tran_clear_task_set	= NULL;
9895 	tran->tran_terminate_task	= NULL;
9896 	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9897 	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9898 	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9899 	tran->tran_post_event		= fcp_scsi_bus_post_event;
9900 	tran->tran_quiesce		= NULL;
9901 	tran->tran_unquiesce		= NULL;
9902 	tran->tran_bus_reset		= NULL;
9903 	tran->tran_bus_config		= fcp_scsi_bus_config;
9904 	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9905 	tran->tran_bus_power		= NULL;
9906 	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9907 
9908 	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9909 	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9910 	tran->tran_setup_pkt		= fcp_pkt_setup;
9911 	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9912 	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9913 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9914 	if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9915 		/*
9916 		 * If FCA don't support DMA, then we use different vectors to
9917 		 * minimize the effects on DMA code flow path
9918 		 */
9919 		tran->tran_start	   = fcp_pseudo_start;
9920 		tran->tran_init_pkt	   = fcp_pseudo_init_pkt;
9921 		tran->tran_destroy_pkt	   = fcp_pseudo_destroy_pkt;
9922 		tran->tran_sync_pkt	   = fcp_pseudo_sync_pkt;
9923 		tran->tran_dmafree	   = fcp_pseudo_dmafree;
9924 		tran->tran_setup_pkt	   = NULL;
9925 		tran->tran_teardown_pkt	   = NULL;
9926 		tran->tran_pkt_constructor = NULL;
9927 		tran->tran_pkt_destructor  = NULL;
9928 		pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9929 	}
9930 
9931 	/*
9932 	 * Allocate an ndi event handle
9933 	 */
9934 	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9935 	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9936 
9937 	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9938 	    sizeof (fcp_ndi_event_defs));
9939 
9940 	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9941 	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9942 
9943 	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9944 	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9945 	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9946 
9947 	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9948 	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9949 	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9950 		goto fail;
9951 	}
9952 	event_bind++;	/* Checked in fail case */
9953 
9954 	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9955 	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9956 	    != DDI_SUCCESS) {
9957 		fcp_log(CE_WARN, pptr->port_dip,
9958 		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9959 		goto fail;
9960 	}
9961 	hba_attached++;	/* Checked in fail case */
9962 
9963 	pptr->port_mpxio = 0;
9964 	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9965 	    MDI_SUCCESS) {
9966 		pptr->port_mpxio++;
9967 	}
9968 
9969 	/*
9970 	 * The following code is putting the new port structure in the global
9971 	 * list of ports and, if it is the first port to attach, it start the
9972 	 * fcp_watchdog_tick.
9973 	 *
9974 	 * Why put this new port in the global before we are done attaching it?
9975 	 * We are actually making the structure globally known before we are
9976 	 * done attaching it.  The reason for that is: because of the code that
9977 	 * follows.  At this point the resources to handle the port are
9978 	 * allocated.  This function is now going to do the following:
9979 	 *
9980 	 *   1) It is going to try to register with the name server advertizing
9981 	 *	the new FCP capability of the port.
9982 	 *   2) It is going to play the role of the fp/fctl layer by building
9983 	 *	a list of worlwide names reachable through this port and call
9984 	 *	itself on fcp_statec_callback().  That requires the port to
9985 	 *	be part of the global list.
9986 	 */
9987 	mutex_enter(&fcp_global_mutex);
9988 	if (fcp_port_head == NULL) {
9989 		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
9990 	}
9991 	pptr->port_next = fcp_port_head;
9992 	fcp_port_head = pptr;
9993 	soft_state_linked++;
9994 
9995 	if (fcp_watchdog_init++ == 0) {
9996 		fcp_watchdog_tick = fcp_watchdog_timeout *
9997 		    drv_usectohz(1000000);
9998 		fcp_watchdog_id = timeout(fcp_watch, NULL,
9999 		    fcp_watchdog_tick);
10000 	}
10001 	mutex_exit(&fcp_global_mutex);
10002 
10003 	/*
10004 	 * Here an attempt is made to register with the name server, the new
10005 	 * FCP capability.  That is done using an RTF_ID to the name server.
10006 	 * It is done synchronously.  The function fcp_do_ns_registry()
10007 	 * doesn't return till the name server responded.
10008 	 * On failures, just ignore it for now and it will get retried during
10009 	 * state change callbacks. We'll set a flag to show this failure
10010 	 */
10011 	if (fcp_do_ns_registry(pptr, s_id)) {
10012 		mutex_enter(&pptr->port_mutex);
10013 		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10014 		mutex_exit(&pptr->port_mutex);
10015 	} else {
10016 		mutex_enter(&pptr->port_mutex);
10017 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10018 		mutex_exit(&pptr->port_mutex);
10019 	}
10020 
10021 	/*
10022 	 * Lookup for boot WWN property
10023 	 */
10024 	if (modrootloaded != 1) {
10025 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10026 		    ddi_get_parent(pinfo->port_dip),
10027 		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10028 		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10029 		    (nbytes == FC_WWN_SIZE)) {
10030 			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10031 		}
10032 		if (boot_wwn) {
10033 			ddi_prop_free(boot_wwn);
10034 		}
10035 	}
10036 
10037 	/*
10038 	 * Handle various topologies and link states.
10039 	 */
10040 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10041 	case FC_STATE_OFFLINE:
10042 
10043 		/*
10044 		 * we're attaching a port where the link is offline
10045 		 *
10046 		 * Wait for ONLINE, at which time a state
10047 		 * change will cause a statec_callback
10048 		 *
10049 		 * in the mean time, do not do anything
10050 		 */
10051 		res = DDI_SUCCESS;
10052 		pptr->port_state |= FCP_STATE_OFFLINE;
10053 		break;
10054 
10055 	case FC_STATE_ONLINE: {
10056 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
10057 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10058 			res = DDI_SUCCESS;
10059 			break;
10060 		}
10061 		/*
10062 		 * discover devices and create nodes (a private
10063 		 * loop or point-to-point)
10064 		 */
10065 		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10066 
10067 		/*
10068 		 * At this point we are going to build a list of all the ports
10069 		 * that	can be reached through this local port.	 It looks like
10070 		 * we cannot handle more than FCP_MAX_DEVICES per local port
10071 		 * (128).
10072 		 */
10073 		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10074 		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10075 		    KM_NOSLEEP)) == NULL) {
10076 			fcp_log(CE_WARN, pptr->port_dip,
10077 			    "!fcp%d: failed to allocate portmap",
10078 			    instance);
10079 			goto fail;
10080 		}
10081 
10082 		/*
10083 		 * fc_ulp_getportmap() is going to provide us with the list of
10084 		 * remote ports in the buffer we just allocated.  The way the
10085 		 * list is going to be retrieved depends on the topology.
10086 		 * However, if we are connected to a Fabric, a name server
10087 		 * request may be sent to get the list of FCP capable ports.
10088 		 * It should be noted that is the case the request is
10089 		 * synchronous.	 This means we are stuck here till the name
10090 		 * server replies.  A lot of things can change during that time
10091 		 * and including, may be, being called on
10092 		 * fcp_statec_callback() for different reasons. I'm not sure
10093 		 * the code can handle that.
10094 		 */
10095 		max_cnt = FCP_MAX_DEVICES;
10096 		alloc_cnt = FCP_MAX_DEVICES;
10097 		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10098 		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10099 		    FC_SUCCESS) {
10100 			caddr_t msg;
10101 
10102 			(void) fc_ulp_error(res, &msg);
10103 
10104 			/*
10105 			 * this	 just means the transport is
10106 			 * busy perhaps building a portmap so,
10107 			 * for now, succeed this port attach
10108 			 * when the transport has a new map,
10109 			 * it'll send us a state change then
10110 			 */
10111 			fcp_log(CE_WARN, pptr->port_dip,
10112 			    "!failed to get port map : %s", msg);
10113 
10114 			res = DDI_SUCCESS;
10115 			break;	/* go return result */
10116 		}
10117 		if (max_cnt > alloc_cnt) {
10118 			alloc_cnt = max_cnt;
10119 		}
10120 
10121 		/*
10122 		 * We are now going to call fcp_statec_callback() ourselves.
10123 		 * By issuing this call we are trying to kick off the enumera-
10124 		 * tion process.
10125 		 */
10126 		/*
10127 		 * let the state change callback do the SCSI device
10128 		 * discovery and create the devinfos
10129 		 */
10130 		fcp_statec_callback(ulph, pptr->port_fp_handle,
10131 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10132 		    max_cnt, pptr->port_id);
10133 
10134 		res = DDI_SUCCESS;
10135 		break;
10136 	}
10137 
10138 	default:
10139 		/* unknown port state */
10140 		fcp_log(CE_WARN, pptr->port_dip,
10141 		    "!fcp%d: invalid port state at attach=0x%x",
10142 		    instance, pptr->port_phys_state);
10143 
10144 		mutex_enter(&pptr->port_mutex);
10145 		pptr->port_phys_state = FCP_STATE_OFFLINE;
10146 		mutex_exit(&pptr->port_mutex);
10147 
10148 		res = DDI_SUCCESS;
10149 		break;
10150 	}
10151 
10152 	/* free temp list if used */
10153 	if (tmp_list != NULL) {
10154 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10155 	}
10156 
10157 	/* note the attach time */
10158 	pptr->port_attach_time = ddi_get_lbolt64();
10159 
10160 	/* all done */
10161 	return (res);
10162 
10163 	/* a failure we have to clean up after */
10164 fail:
10165 	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10166 
10167 	if (soft_state_linked) {
10168 		/* remove this fcp_port from the linked list */
10169 		(void) fcp_soft_state_unlink(pptr);
10170 	}
10171 
10172 	/* unbind and free event set */
10173 	if (pptr->port_ndi_event_hdl) {
10174 		if (event_bind) {
10175 			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10176 			    &pptr->port_ndi_events, NDI_SLEEP);
10177 		}
10178 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10179 	}
10180 
10181 	if (pptr->port_ndi_event_defs) {
10182 		(void) kmem_free(pptr->port_ndi_event_defs,
10183 		    sizeof (fcp_ndi_event_defs));
10184 	}
10185 
10186 	/*
10187 	 * Clean up mpxio stuff
10188 	 */
10189 	if (pptr->port_mpxio) {
10190 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10191 		pptr->port_mpxio--;
10192 	}
10193 
10194 	/* undo SCSI HBA setup */
10195 	if (hba_attached) {
10196 		(void) scsi_hba_detach(pptr->port_dip);
10197 	}
10198 	if (pptr->port_tran != NULL) {
10199 		scsi_hba_tran_free(pptr->port_tran);
10200 	}
10201 
10202 	mutex_enter(&fcp_global_mutex);
10203 
10204 	/*
10205 	 * We check soft_state_linked, because it is incremented right before
10206 	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10207 	 * soft_state_linked is still FALSE, we do not want to decrement
10208 	 * fcp_watchdog_init or possibly call untimeout.
10209 	 */
10210 
10211 	if (soft_state_linked) {
10212 		if (--fcp_watchdog_init == 0) {
10213 			timeout_id_t	tid = fcp_watchdog_id;
10214 
10215 			mutex_exit(&fcp_global_mutex);
10216 			(void) untimeout(tid);
10217 		} else {
10218 			mutex_exit(&fcp_global_mutex);
10219 		}
10220 	} else {
10221 		mutex_exit(&fcp_global_mutex);
10222 	}
10223 
10224 	if (mutex_initted) {
10225 		mutex_destroy(&pptr->port_mutex);
10226 		mutex_destroy(&pptr->port_pkt_mutex);
10227 	}
10228 
10229 	if (tmp_list != NULL) {
10230 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10231 	}
10232 
10233 	/* this makes pptr invalid */
10234 	ddi_soft_state_free(fcp_softstate, instance);
10235 
10236 	return (DDI_FAILURE);
10237 }
10238 
10239 
10240 static int
10241 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10242 {
10243 	int count = 0;
10244 
10245 	mutex_enter(&pptr->port_mutex);
10246 
10247 	/*
10248 	 * if the port is powered down or suspended, nothing else
10249 	 * to do; just return.
10250 	 */
10251 	if (flag != FCP_STATE_DETACHING) {
10252 		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10253 		    FCP_STATE_SUSPENDED)) {
10254 			pptr->port_state |= flag;
10255 			mutex_exit(&pptr->port_mutex);
10256 			return (FC_SUCCESS);
10257 		}
10258 	}
10259 
10260 	if (pptr->port_state & FCP_STATE_IN_MDI) {
10261 		mutex_exit(&pptr->port_mutex);
10262 		return (FC_FAILURE);
10263 	}
10264 
10265 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10266 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10267 	    "fcp_handle_port_detach: port is detaching");
10268 
10269 	pptr->port_state |= flag;
10270 
10271 	/*
10272 	 * Wait for any ongoing reconfig/ipkt to complete, that
10273 	 * ensures the freeing to targets/luns is safe.
10274 	 * No more ref to this port should happen from statec/ioctl
10275 	 * after that as it was removed from the global port list.
10276 	 */
10277 	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10278 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10279 		/*
10280 		 * Let's give sufficient time for reconfig/ipkt
10281 		 * to complete.
10282 		 */
10283 		if (count++ >= FCP_ICMD_DEADLINE) {
10284 			break;
10285 		}
10286 		mutex_exit(&pptr->port_mutex);
10287 		delay(drv_usectohz(1000000));
10288 		mutex_enter(&pptr->port_mutex);
10289 	}
10290 
10291 	/*
10292 	 * if the driver is still busy then fail to
10293 	 * suspend/power down.
10294 	 */
10295 	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10296 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10297 		pptr->port_state &= ~flag;
10298 		mutex_exit(&pptr->port_mutex);
10299 		return (FC_FAILURE);
10300 	}
10301 
10302 	if (flag == FCP_STATE_DETACHING) {
10303 		pptr = fcp_soft_state_unlink(pptr);
10304 		ASSERT(pptr != NULL);
10305 	}
10306 
10307 	pptr->port_link_cnt++;
10308 	pptr->port_state |= FCP_STATE_OFFLINE;
10309 	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10310 
10311 	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10312 	    FCP_CAUSE_LINK_DOWN);
10313 	mutex_exit(&pptr->port_mutex);
10314 
10315 	/* kill watch dog timer if we're the last */
10316 	mutex_enter(&fcp_global_mutex);
10317 	if (--fcp_watchdog_init == 0) {
10318 		timeout_id_t	tid = fcp_watchdog_id;
10319 		mutex_exit(&fcp_global_mutex);
10320 		(void) untimeout(tid);
10321 	} else {
10322 		mutex_exit(&fcp_global_mutex);
10323 	}
10324 
10325 	/* clean up the port structures */
10326 	if (flag == FCP_STATE_DETACHING) {
10327 		fcp_cleanup_port(pptr, instance);
10328 	}
10329 
10330 	return (FC_SUCCESS);
10331 }
10332 
10333 
10334 static void
10335 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10336 {
10337 	ASSERT(pptr != NULL);
10338 
10339 	/* unbind and free event set */
10340 	if (pptr->port_ndi_event_hdl) {
10341 		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10342 		    &pptr->port_ndi_events, NDI_SLEEP);
10343 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10344 	}
10345 
10346 	if (pptr->port_ndi_event_defs) {
10347 		(void) kmem_free(pptr->port_ndi_event_defs,
10348 		    sizeof (fcp_ndi_event_defs));
10349 	}
10350 
10351 	/* free the lun/target structures and devinfos */
10352 	fcp_free_targets(pptr);
10353 
10354 	/*
10355 	 * Clean up mpxio stuff
10356 	 */
10357 	if (pptr->port_mpxio) {
10358 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10359 		pptr->port_mpxio--;
10360 	}
10361 
10362 	/* clean up SCSA stuff */
10363 	(void) scsi_hba_detach(pptr->port_dip);
10364 	if (pptr->port_tran != NULL) {
10365 		scsi_hba_tran_free(pptr->port_tran);
10366 	}
10367 
10368 #ifdef	KSTATS_CODE
10369 	/* clean up kstats */
10370 	if (pptr->fcp_ksp != NULL) {
10371 		kstat_delete(pptr->fcp_ksp);
10372 	}
10373 #endif
10374 
10375 	/* clean up soft state mutexes/condition variables */
10376 	mutex_destroy(&pptr->port_mutex);
10377 	mutex_destroy(&pptr->port_pkt_mutex);
10378 
10379 	/* all done with soft state */
10380 	ddi_soft_state_free(fcp_softstate, instance);
10381 }
10382 
10383 /*
10384  *     Function: fcp_kmem_cache_constructor
10385  *
10386  *  Description: This function allocates and initializes the resources required
10387  *		 to build a scsi_pkt structure the target driver.  The result
10388  *		 of the allocation and initialization will be cached in the
10389  *		 memory cache.	As DMA resources may be allocated here, that
10390  *		 means DMA resources will be tied up in the cache manager.
10391  *		 This is a tradeoff that has been made for performance reasons.
10392  *
10393  *     Argument: *buf		Memory to preinitialize.
10394  *		 *arg		FCP port structure (fcp_port).
10395  *		 kmflags	Value passed to kmem_cache_alloc() and
10396  *				propagated to the constructor.
10397  *
10398  * Return Value: 0	Allocation/Initialization was successful.
10399  *		 -1	Allocation or Initialization failed.
10400  *
10401  *
10402  * If the returned value is 0, the buffer is initialized like this:
10403  *
10404  *		    +================================+
10405  *	     +----> |	      struct scsi_pkt	     |
10406  *	     |	    |				     |
10407  *	     | +--- | pkt_ha_private		     |
10408  *	     | |    |				     |
10409  *	     | |    +================================+
10410  *	     | |
10411  *	     | |    +================================+
10412  *	     | +--> |	    struct fcp_pkt	     | <---------+
10413  *	     |	    |				     |		 |
10414  *	     +----- | cmd_pkt			     |		 |
10415  *		    |			  cmd_fp_pkt | ---+	 |
10416  *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10417  *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10418  *	  |    |    |--------------------------------|	  |	 |
10419  *	  |    |    |	      struct fc_packet	     | <--+	 |
10420  *	  |    |    |				     |		 |
10421  *	  |    |    |		     pkt_ulp_private | ----------+
10422  *	  |    |    |		     pkt_fca_private | -----+
10423  *	  |    |    |		     pkt_data_cookie | ---+ |
10424  *	  |    |    | pkt_cmdlen		     |	  | |
10425  *	  |    |(a) | pkt_rsplen		     |	  | |
10426  *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10427  *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10428  *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10429  *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10430  *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10431  *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10432  *		    +================================+	  | |  |   |   |    |
10433  *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10434  *		    |				     |	    |  |   |   |    |
10435  *		    +================================+	    |  |   |   |    |
10436  *		    |	      fca_private	     | <----+  |   |   |    |
10437  *		    |				     |	       |   |   |    |
10438  *		    +================================+	       |   |   |    |
10439  *							       |   |   |    |
10440  *							       |   |   |    |
10441  *		    +================================+	 (d)   |   |   |    |
10442  *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10443  *		    |				     |		   |   |    |
10444  *		    +================================+		   |   |    |
10445  *								   |   |    |
10446  *		    +================================+	 (d)	   |   |    |
10447  *		    |		fcp_resp	     | <-----------+   |    |
10448  *		    |	(DMA resources associated)   |		       |    |
10449  *		    +================================+		       |    |
10450  *								       |    |
10451  *								       |    |
10452  *								       |    |
10453  *		    +================================+	 (c)	       |    |
10454  *		    |	     fcp_cmd cookies	     | <---------------+    |
10455  *		    |				     |			    |
10456  *		    +================================+			    |
10457  *									    |
10458  *		    +================================+	 (c)		    |
10459  *		    |		 fcp_cmd	     | <--------------------+
10460  *		    |	(DMA resources associated)   |
10461  *		    +================================+
10462  *
10463  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10464  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10465  * (c) Only if DMA is used for the FCP_CMD buffer.
10466  * (d) Only if DMA is used for the FCP_RESP buffer
10467  */
10468 static int
10469 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10470     int kmflags)
10471 {
10472 	struct fcp_pkt	*cmd;
10473 	struct fcp_port	*pptr;
10474 	fc_packet_t	*fpkt;
10475 
10476 	pptr = (struct fcp_port *)tran->tran_hba_private;
10477 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10478 	bzero(cmd, tran->tran_hba_len);
10479 
10480 	cmd->cmd_pkt = pkt;
10481 	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10482 	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10483 	cmd->cmd_fp_pkt = fpkt;
10484 
10485 	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10486 	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10487 	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10488 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10489 
10490 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10491 	    sizeof (struct fcp_pkt));
10492 
10493 	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10494 	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10495 
10496 	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10497 		/*
10498 		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10499 		 * fcp_resp.  The transfer of information will be done by
10500 		 * bcopy.
10501 		 * The naming of the flags (that is actually a value) is
10502 		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10503 		 * DMA" but instead "NO DMA".
10504 		 */
10505 		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10506 		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10507 		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10508 	} else {
10509 		/*
10510 		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10511 		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10512 		 * interfaces.
10513 		 */
10514 		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10515 			return (-1);
10516 		}
10517 	}
10518 
10519 	return (0);
10520 }
10521 
10522 /*
10523  *     Function: fcp_kmem_cache_destructor
10524  *
10525  *  Description: Called by the destructor of the cache managed by SCSA.
10526  *		 All the resources pre-allocated in fcp_pkt_constructor
10527  *		 and the data also pre-initialized in fcp_pkt_constructor
10528  *		 are freed and uninitialized here.
10529  *
10530  *     Argument: *buf		Memory to uninitialize.
10531  *		 *arg		FCP port structure (fcp_port).
10532  *
10533  * Return Value: None
10534  *
10535  *	Context: kernel
10536  */
10537 static void
10538 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10539 {
10540 	struct fcp_pkt	*cmd;
10541 	struct fcp_port	*pptr;
10542 
10543 	pptr = (struct fcp_port *)(tran->tran_hba_private);
10544 	cmd = pkt->pkt_ha_private;
10545 
10546 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10547 		/*
10548 		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10549 		 * buffer and DMA resources allocated to do so are released.
10550 		 */
10551 		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10552 	}
10553 }
10554 
10555 /*
10556  *     Function: fcp_alloc_cmd_resp
10557  *
10558  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10559  *		 will be DMAed by the HBA.  The buffer is allocated applying
10560  *		 the DMA requirements for the HBA.  The buffers allocated will
10561  *		 also be bound.	 DMA resources are allocated in the process.
10562  *		 They will be released by fcp_free_cmd_resp().
10563  *
10564  *     Argument: *pptr	FCP port.
10565  *		 *fpkt	fc packet for which the cmd and resp packet should be
10566  *			allocated.
10567  *		 flags	Allocation flags.
10568  *
10569  * Return Value: FC_FAILURE
10570  *		 FC_SUCCESS
10571  *
10572  *	Context: User or Kernel context only if flags == KM_SLEEP.
10573  *		 Interrupt context if the KM_SLEEP is not specified.
10574  */
10575 static int
10576 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10577 {
10578 	int			rval;
10579 	int			cmd_len;
10580 	int			resp_len;
10581 	ulong_t			real_len;
10582 	int			(*cb) (caddr_t);
10583 	ddi_dma_cookie_t	pkt_cookie;
10584 	ddi_dma_cookie_t	*cp;
10585 	uint32_t		cnt;
10586 
10587 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10588 
10589 	cmd_len = fpkt->pkt_cmdlen;
10590 	resp_len = fpkt->pkt_rsplen;
10591 
10592 	ASSERT(fpkt->pkt_cmd_dma == NULL);
10593 
10594 	/* Allocation of a DMA handle used in subsequent calls. */
10595 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10596 	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10597 		return (FC_FAILURE);
10598 	}
10599 
10600 	/* A buffer is allocated that satisfies the DMA requirements. */
10601 	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10602 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10603 	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10604 
10605 	if (rval != DDI_SUCCESS) {
10606 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10607 		return (FC_FAILURE);
10608 	}
10609 
10610 	if (real_len < cmd_len) {
10611 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10612 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10613 		return (FC_FAILURE);
10614 	}
10615 
10616 	/* The buffer allocated is DMA bound. */
10617 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10618 	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10619 	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10620 
10621 	if (rval != DDI_DMA_MAPPED) {
10622 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10623 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10624 		return (FC_FAILURE);
10625 	}
10626 
10627 	if (fpkt->pkt_cmd_cookie_cnt >
10628 	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10629 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10630 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10631 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10632 		return (FC_FAILURE);
10633 	}
10634 
10635 	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10636 
10637 	/*
10638 	 * The buffer where the scatter/gather list is going to be built is
10639 	 * allocated.
10640 	 */
10641 	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10642 	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10643 	    KM_NOSLEEP);
10644 
10645 	if (cp == NULL) {
10646 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10647 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10648 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10649 		return (FC_FAILURE);
10650 	}
10651 
10652 	/*
10653 	 * The scatter/gather list for the buffer we just allocated is built
10654 	 * here.
10655 	 */
10656 	*cp = pkt_cookie;
10657 	cp++;
10658 
10659 	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10660 		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10661 		    &pkt_cookie);
10662 		*cp = pkt_cookie;
10663 	}
10664 
10665 	ASSERT(fpkt->pkt_resp_dma == NULL);
10666 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10667 	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10668 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10669 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10670 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10671 		return (FC_FAILURE);
10672 	}
10673 
10674 	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10675 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10676 	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10677 	    &fpkt->pkt_resp_acc);
10678 
10679 	if (rval != DDI_SUCCESS) {
10680 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10681 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10682 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10683 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10684 		kmem_free(fpkt->pkt_cmd_cookie,
10685 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10686 		return (FC_FAILURE);
10687 	}
10688 
10689 	if (real_len < resp_len) {
10690 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10691 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10692 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10693 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10694 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10695 		kmem_free(fpkt->pkt_cmd_cookie,
10696 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10697 		return (FC_FAILURE);
10698 	}
10699 
10700 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10701 	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10702 	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10703 
10704 	if (rval != DDI_DMA_MAPPED) {
10705 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10706 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10707 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10708 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10709 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10710 		kmem_free(fpkt->pkt_cmd_cookie,
10711 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10712 		return (FC_FAILURE);
10713 	}
10714 
10715 	if (fpkt->pkt_resp_cookie_cnt >
10716 	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10717 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10718 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10719 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10720 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10721 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10722 		kmem_free(fpkt->pkt_cmd_cookie,
10723 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10724 		return (FC_FAILURE);
10725 	}
10726 
10727 	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10728 
10729 	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10730 	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10731 	    KM_NOSLEEP);
10732 
10733 	if (cp == NULL) {
10734 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10735 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10736 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10737 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10738 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10739 		kmem_free(fpkt->pkt_cmd_cookie,
10740 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10741 		return (FC_FAILURE);
10742 	}
10743 
10744 	*cp = pkt_cookie;
10745 	cp++;
10746 
10747 	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10748 		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10749 		    &pkt_cookie);
10750 		*cp = pkt_cookie;
10751 	}
10752 
10753 	return (FC_SUCCESS);
10754 }
10755 
10756 /*
10757  *     Function: fcp_free_cmd_resp
10758  *
10759  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10760  *		 allocated by fcp_alloc_cmd_resp() and all the resources
10761  *		 associated with them.	That includes the DMA resources and the
10762  *		 buffer allocated for the cookies of each one of them.
10763  *
10764  *     Argument: *pptr		FCP port context.
10765  *		 *fpkt		fc packet containing the cmd and resp packet
10766  *				to be released.
10767  *
10768  * Return Value: None
10769  *
10770  *	Context: Interrupt, User and Kernel context.
10771  */
10772 /* ARGSUSED */
10773 static void
10774 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10775 {
10776 	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10777 
10778 	if (fpkt->pkt_resp_dma) {
10779 		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10780 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10781 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10782 	}
10783 
10784 	if (fpkt->pkt_resp_cookie) {
10785 		kmem_free(fpkt->pkt_resp_cookie,
10786 		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10787 		fpkt->pkt_resp_cookie = NULL;
10788 	}
10789 
10790 	if (fpkt->pkt_cmd_dma) {
10791 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10792 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10793 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10794 	}
10795 
10796 	if (fpkt->pkt_cmd_cookie) {
10797 		kmem_free(fpkt->pkt_cmd_cookie,
10798 		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10799 		fpkt->pkt_cmd_cookie = NULL;
10800 	}
10801 }
10802 
10803 
10804 /*
10805  * called by the transport to do our own target initialization
10806  *
10807  * can acquire and release the global mutex
10808  */
10809 /* ARGSUSED */
10810 static int
10811 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10812     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10813 {
10814 	uchar_t			*bytes;
10815 	uint_t			nbytes;
10816 	uint16_t		lun_num;
10817 	struct fcp_tgt	*ptgt;
10818 	struct fcp_lun	*plun;
10819 	struct fcp_port	*pptr = (struct fcp_port *)
10820 	    hba_tran->tran_hba_private;
10821 
10822 	ASSERT(pptr != NULL);
10823 
10824 	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10825 	    FCP_BUF_LEVEL_8, 0,
10826 	    "fcp_phys_tgt_init: called for %s (instance %d)",
10827 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10828 
10829 	/* get our port WWN property */
10830 	bytes = NULL;
10831 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10832 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10833 	    (nbytes != FC_WWN_SIZE)) {
10834 		/* no port WWN property */
10835 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10836 		    FCP_BUF_LEVEL_8, 0,
10837 		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10838 		    " for %s (instance %d): bytes=%p nbytes=%x",
10839 		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10840 		    nbytes);
10841 
10842 		if (bytes != NULL) {
10843 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10844 		}
10845 
10846 		return (DDI_NOT_WELL_FORMED);
10847 	}
10848 	ASSERT(bytes != NULL);
10849 
10850 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10851 	    LUN_PROP, 0xFFFF);
10852 	if (lun_num == 0xFFFF) {
10853 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10854 		    FCP_BUF_LEVEL_8, 0,
10855 		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10856 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10857 		    ddi_get_instance(tgt_dip));
10858 
10859 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10860 		return (DDI_NOT_WELL_FORMED);
10861 	}
10862 
10863 	mutex_enter(&pptr->port_mutex);
10864 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10865 		mutex_exit(&pptr->port_mutex);
10866 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10867 		    FCP_BUF_LEVEL_8, 0,
10868 		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10869 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10870 		    ddi_get_instance(tgt_dip));
10871 
10872 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10873 		return (DDI_FAILURE);
10874 	}
10875 
10876 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10877 	    FC_WWN_SIZE) == 0);
10878 	ASSERT(plun->lun_num == lun_num);
10879 
10880 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10881 
10882 	ptgt = plun->lun_tgt;
10883 
10884 	mutex_enter(&ptgt->tgt_mutex);
10885 	plun->lun_tgt_count++;
10886 	scsi_device_hba_private_set(sd, plun);
10887 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10888 	plun->lun_sd = sd;
10889 	mutex_exit(&ptgt->tgt_mutex);
10890 	mutex_exit(&pptr->port_mutex);
10891 
10892 	return (DDI_SUCCESS);
10893 }
10894 
10895 /*ARGSUSED*/
10896 static int
10897 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10898     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10899 {
10900 	uchar_t			*bytes;
10901 	uint_t			nbytes;
10902 	uint16_t		lun_num;
10903 	struct fcp_tgt	*ptgt;
10904 	struct fcp_lun	*plun;
10905 	struct fcp_port	*pptr = (struct fcp_port *)
10906 	    hba_tran->tran_hba_private;
10907 	child_info_t		*cip;
10908 
10909 	ASSERT(pptr != NULL);
10910 
10911 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10912 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10913 	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10914 	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10915 	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10916 
10917 	cip = (child_info_t *)sd->sd_pathinfo;
10918 	if (cip == NULL) {
10919 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10920 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10921 		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10922 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10923 		    ddi_get_instance(tgt_dip));
10924 
10925 		return (DDI_NOT_WELL_FORMED);
10926 	}
10927 
10928 	/* get our port WWN property */
10929 	bytes = NULL;
10930 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10931 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10932 	    (nbytes != FC_WWN_SIZE)) {
10933 		if (bytes) {
10934 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10935 		}
10936 		return (DDI_NOT_WELL_FORMED);
10937 	}
10938 
10939 	ASSERT(bytes != NULL);
10940 
10941 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10942 	    LUN_PROP, 0xFFFF);
10943 	if (lun_num == 0xFFFF) {
10944 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10945 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10946 		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10947 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10948 		    ddi_get_instance(tgt_dip));
10949 
10950 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10951 		return (DDI_NOT_WELL_FORMED);
10952 	}
10953 
10954 	mutex_enter(&pptr->port_mutex);
10955 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10956 		mutex_exit(&pptr->port_mutex);
10957 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10958 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10959 		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10960 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10961 		    ddi_get_instance(tgt_dip));
10962 
10963 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10964 		return (DDI_FAILURE);
10965 	}
10966 
10967 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10968 	    FC_WWN_SIZE) == 0);
10969 	ASSERT(plun->lun_num == lun_num);
10970 
10971 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10972 
10973 	ptgt = plun->lun_tgt;
10974 
10975 	mutex_enter(&ptgt->tgt_mutex);
10976 	plun->lun_tgt_count++;
10977 	scsi_device_hba_private_set(sd, plun);
10978 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10979 	plun->lun_sd = sd;
10980 	mutex_exit(&ptgt->tgt_mutex);
10981 	mutex_exit(&pptr->port_mutex);
10982 
10983 	return (DDI_SUCCESS);
10984 }
10985 
10986 
10987 /*
10988  * called by the transport to do our own target initialization
10989  *
10990  * can acquire and release the global mutex
10991  */
10992 /* ARGSUSED */
10993 static int
10994 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10995     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10996 {
10997 	struct fcp_port	*pptr = (struct fcp_port *)
10998 	    hba_tran->tran_hba_private;
10999 	int			rval;
11000 
11001 	ASSERT(pptr != NULL);
11002 
11003 	/*
11004 	 * Child node is getting initialized.  Look at the mpxio component
11005 	 * type on the child device to see if this device is mpxio managed
11006 	 * or not.
11007 	 */
11008 	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11009 		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11010 	} else {
11011 		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11012 	}
11013 
11014 	return (rval);
11015 }
11016 
11017 
11018 /* ARGSUSED */
11019 static void
11020 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11021     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11022 {
11023 	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
11024 	struct fcp_tgt	*ptgt;
11025 
11026 	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11027 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
11028 	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11029 	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11030 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11031 
11032 	if (plun == NULL) {
11033 		return;
11034 	}
11035 	ptgt = plun->lun_tgt;
11036 
11037 	ASSERT(ptgt != NULL);
11038 
11039 	mutex_enter(&ptgt->tgt_mutex);
11040 	ASSERT(plun->lun_tgt_count > 0);
11041 
11042 	if (--plun->lun_tgt_count == 0) {
11043 		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11044 	}
11045 	plun->lun_sd = NULL;
11046 	mutex_exit(&ptgt->tgt_mutex);
11047 }
11048 
11049 /*
11050  *     Function: fcp_scsi_start
11051  *
11052  *  Description: This function is called by the target driver to request a
11053  *		 command to be sent.
11054  *
11055  *     Argument: *ap		SCSI address of the device.
11056  *		 *pkt		SCSI packet containing the cmd to send.
11057  *
11058  * Return Value: TRAN_ACCEPT
11059  *		 TRAN_BUSY
11060  *		 TRAN_BADPKT
11061  *		 TRAN_FATAL_ERROR
11062  */
11063 static int
11064 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11065 {
11066 	struct fcp_port	*pptr = ADDR2FCP(ap);
11067 	struct fcp_lun	*plun = ADDR2LUN(ap);
11068 	struct fcp_pkt	*cmd = PKT2CMD(pkt);
11069 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11070 	int			rval;
11071 
11072 	/* ensure command isn't already issued */
11073 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11074 
11075 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11076 	    fcp_trace, FCP_BUF_LEVEL_9, 0,
11077 	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11078 
11079 	/*
11080 	 * It is strange that we enter the fcp_port mutex and the target
11081 	 * mutex to check the lun state (which has a mutex of its own).
11082 	 */
11083 	mutex_enter(&pptr->port_mutex);
11084 	mutex_enter(&ptgt->tgt_mutex);
11085 
11086 	/*
11087 	 * If the device is offline and is not in the process of coming
11088 	 * online, fail the request.
11089 	 */
11090 
11091 	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11092 	    !(plun->lun_state & FCP_LUN_ONLINING)) {
11093 		mutex_exit(&ptgt->tgt_mutex);
11094 		mutex_exit(&pptr->port_mutex);
11095 
11096 		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11097 			pkt->pkt_reason = CMD_DEV_GONE;
11098 		}
11099 
11100 		return (TRAN_FATAL_ERROR);
11101 	}
11102 	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11103 
11104 	/*
11105 	 * If we are suspended, kernel is trying to dump, so don't
11106 	 * block, fail or defer requests - send them down right away.
11107 	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11108 	 * assume we have been suspended.  There is hardware such as
11109 	 * the v880 that doesn't do PM.	 Thus, the check for
11110 	 * ddi_in_panic.
11111 	 *
11112 	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11113 	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11114 	 * either the device will have gone away or changed and we can fail
11115 	 * the request, or we can proceed if the device didn't change.
11116 	 *
11117 	 * If the pd in the target or the packet is NULL it's probably
11118 	 * because the device has gone away, we allow the request to be
11119 	 * put on the internal queue here in case the device comes back within
11120 	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11121 	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11122 	 * could be NULL because the device was disappearing during or since
11123 	 * packet initialization.
11124 	 */
11125 
11126 	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11127 	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11128 	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11129 	    (ptgt->tgt_pd_handle == NULL) ||
11130 	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11131 		/*
11132 		 * If ((LUN is busy AND
11133 		 *	LUN not suspended AND
11134 		 *	The system is not in panic state) OR
11135 		 *	(The port is coming up))
11136 		 *
11137 		 * We check to see if the any of the flags FLAG_NOINTR or
11138 		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11139 		 * returned will be TRAN_BUSY.	If not, the request is queued.
11140 		 */
11141 		mutex_exit(&ptgt->tgt_mutex);
11142 		mutex_exit(&pptr->port_mutex);
11143 
11144 		/* see if using interrupts is allowed (so queueing'll work) */
11145 		if (pkt->pkt_flags & FLAG_NOINTR) {
11146 			pkt->pkt_resid = 0;
11147 			return (TRAN_BUSY);
11148 		}
11149 		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11150 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11151 			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11152 			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11153 			return (TRAN_BUSY);
11154 		}
11155 #ifdef	DEBUG
11156 		mutex_enter(&pptr->port_pkt_mutex);
11157 		pptr->port_npkts++;
11158 		mutex_exit(&pptr->port_pkt_mutex);
11159 #endif /* DEBUG */
11160 
11161 		/* got queue up the pkt for later */
11162 		fcp_queue_pkt(pptr, cmd);
11163 		return (TRAN_ACCEPT);
11164 	}
11165 	cmd->cmd_state = FCP_PKT_ISSUED;
11166 
11167 	mutex_exit(&ptgt->tgt_mutex);
11168 	mutex_exit(&pptr->port_mutex);
11169 
11170 	/*
11171 	 * Now that we released the mutexes, what was protected by them can
11172 	 * change.
11173 	 */
11174 
11175 	/*
11176 	 * If there is a reconfiguration in progress, wait for it to complete.
11177 	 */
11178 	fcp_reconfig_wait(pptr);
11179 
11180 	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11181 	    pkt->pkt_time : 0;
11182 
11183 	/* prepare the packet */
11184 
11185 	fcp_prepare_pkt(pptr, cmd, plun);
11186 
11187 	if (cmd->cmd_pkt->pkt_time) {
11188 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11189 	} else {
11190 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11191 	}
11192 
11193 	/*
11194 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11195 	 * have to do polled I/O
11196 	 */
11197 	if (pkt->pkt_flags & FLAG_NOINTR) {
11198 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11199 		return (fcp_dopoll(pptr, cmd));
11200 	}
11201 
11202 #ifdef	DEBUG
11203 	mutex_enter(&pptr->port_pkt_mutex);
11204 	pptr->port_npkts++;
11205 	mutex_exit(&pptr->port_pkt_mutex);
11206 #endif /* DEBUG */
11207 
11208 	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11209 	if (rval == FC_SUCCESS) {
11210 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11211 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11212 		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11213 		return (TRAN_ACCEPT);
11214 	}
11215 
11216 	cmd->cmd_state = FCP_PKT_IDLE;
11217 
11218 #ifdef	DEBUG
11219 	mutex_enter(&pptr->port_pkt_mutex);
11220 	pptr->port_npkts--;
11221 	mutex_exit(&pptr->port_pkt_mutex);
11222 #endif /* DEBUG */
11223 
11224 	/*
11225 	 * For lack of clearer definitions, choose
11226 	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11227 	 */
11228 
11229 	if (rval == FC_TRAN_BUSY) {
11230 		pkt->pkt_resid = 0;
11231 		rval = TRAN_BUSY;
11232 	} else {
11233 		mutex_enter(&ptgt->tgt_mutex);
11234 		if (plun->lun_state & FCP_LUN_OFFLINE) {
11235 			child_info_t	*cip;
11236 
11237 			mutex_enter(&plun->lun_mutex);
11238 			cip = plun->lun_cip;
11239 			mutex_exit(&plun->lun_mutex);
11240 
11241 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11242 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11243 			    "fcp_transport failed 2 for %x: %x; dip=%p",
11244 			    plun->lun_tgt->tgt_d_id, rval, cip);
11245 
11246 			rval = TRAN_FATAL_ERROR;
11247 		} else {
11248 			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11249 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11250 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11251 				    "fcp_scsi_start: FC_BUSY for pkt %p",
11252 				    pkt);
11253 				rval = TRAN_BUSY;
11254 			} else {
11255 				rval = TRAN_ACCEPT;
11256 				fcp_queue_pkt(pptr, cmd);
11257 			}
11258 		}
11259 		mutex_exit(&ptgt->tgt_mutex);
11260 	}
11261 
11262 	return (rval);
11263 }
11264 
11265 /*
11266  * called by the transport to abort a packet
11267  */
11268 /*ARGSUSED*/
11269 static int
11270 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11271 {
11272 	int tgt_cnt;
11273 	struct fcp_port		*pptr = ADDR2FCP(ap);
11274 	struct fcp_lun	*plun = ADDR2LUN(ap);
11275 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11276 
11277 	if (pkt == NULL) {
11278 		if (ptgt) {
11279 			mutex_enter(&ptgt->tgt_mutex);
11280 			tgt_cnt = ptgt->tgt_change_cnt;
11281 			mutex_exit(&ptgt->tgt_mutex);
11282 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11283 			return (TRUE);
11284 		}
11285 	}
11286 	return (FALSE);
11287 }
11288 
11289 
11290 /*
11291  * Perform reset
11292  */
11293 int
11294 fcp_scsi_reset(struct scsi_address *ap, int level)
11295 {
11296 	int			rval = 0;
11297 	struct fcp_port		*pptr = ADDR2FCP(ap);
11298 	struct fcp_lun	*plun = ADDR2LUN(ap);
11299 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11300 
11301 	if (level == RESET_ALL) {
11302 		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11303 			rval = 1;
11304 		}
11305 	} else if (level == RESET_TARGET || level == RESET_LUN) {
11306 		/*
11307 		 * If we are in the middle of discovery, return
11308 		 * SUCCESS as this target will be rediscovered
11309 		 * anyway
11310 		 */
11311 		mutex_enter(&ptgt->tgt_mutex);
11312 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11313 			mutex_exit(&ptgt->tgt_mutex);
11314 			return (1);
11315 		}
11316 		mutex_exit(&ptgt->tgt_mutex);
11317 
11318 		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11319 			rval = 1;
11320 		}
11321 	}
11322 	return (rval);
11323 }
11324 
11325 
11326 /*
11327  * called by the framework to get a SCSI capability
11328  */
11329 static int
11330 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11331 {
11332 	return (fcp_commoncap(ap, cap, 0, whom, 0));
11333 }
11334 
11335 
11336 /*
11337  * called by the framework to set a SCSI capability
11338  */
11339 static int
11340 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11341 {
11342 	return (fcp_commoncap(ap, cap, value, whom, 1));
11343 }
11344 
11345 /*
11346  *     Function: fcp_pkt_setup
11347  *
11348  *  Description: This function sets up the scsi_pkt structure passed by the
11349  *		 caller. This function assumes fcp_pkt_constructor has been
11350  *		 called previously for the packet passed by the caller.	 If
11351  *		 successful this call will have the following results:
11352  *
11353  *		   - The resources needed that will be constant through out
11354  *		     the whole transaction are allocated.
11355  *		   - The fields that will be constant through out the whole
11356  *		     transaction are initialized.
11357  *		   - The scsi packet will be linked to the LUN structure
11358  *		     addressed by the transaction.
11359  *
11360  *     Argument:
11361  *		 *pkt		Pointer to a scsi_pkt structure.
11362  *		 callback
11363  *		 arg
11364  *
11365  * Return Value: 0	Success
11366  *		 !0	Failure
11367  *
11368  *	Context: Kernel context or interrupt context
11369  */
11370 /* ARGSUSED */
11371 static int
11372 fcp_pkt_setup(struct scsi_pkt *pkt,
11373     int (*callback)(caddr_t arg),
11374     caddr_t arg)
11375 {
11376 	struct fcp_pkt	*cmd;
11377 	struct fcp_port	*pptr;
11378 	struct fcp_lun	*plun;
11379 	struct fcp_tgt	*ptgt;
11380 	int		kf;
11381 	fc_packet_t	*fpkt;
11382 	fc_frame_hdr_t	*hp;
11383 
11384 	pptr = ADDR2FCP(&pkt->pkt_address);
11385 	plun = ADDR2LUN(&pkt->pkt_address);
11386 	ptgt = plun->lun_tgt;
11387 
11388 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11389 	fpkt = cmd->cmd_fp_pkt;
11390 
11391 	/*
11392 	 * this request is for dma allocation only
11393 	 */
11394 	/*
11395 	 * First step of fcp_scsi_init_pkt: pkt allocation
11396 	 * We determine if the caller is willing to wait for the
11397 	 * resources.
11398 	 */
11399 	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11400 
11401 	/*
11402 	 * Selective zeroing of the pkt.
11403 	 */
11404 	cmd->cmd_back = NULL;
11405 	cmd->cmd_next = NULL;
11406 
11407 	/*
11408 	 * Zero out fcp command
11409 	 */
11410 	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11411 
11412 	cmd->cmd_state = FCP_PKT_IDLE;
11413 
11414 	fpkt = cmd->cmd_fp_pkt;
11415 	fpkt->pkt_data_acc = NULL;
11416 
11417 	/*
11418 	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11419 	 * could be destroyed.	We need fail pkt_setup.
11420 	 */
11421 	if (pptr->port_state & FCP_STATE_OFFLINE) {
11422 		return (-1);
11423 	}
11424 
11425 	mutex_enter(&ptgt->tgt_mutex);
11426 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11427 
11428 	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11429 	    != FC_SUCCESS) {
11430 		mutex_exit(&ptgt->tgt_mutex);
11431 		return (-1);
11432 	}
11433 
11434 	mutex_exit(&ptgt->tgt_mutex);
11435 
11436 	/* Fill in the Fabric Channel Header */
11437 	hp = &fpkt->pkt_cmd_fhdr;
11438 	hp->r_ctl = R_CTL_COMMAND;
11439 	hp->rsvd = 0;
11440 	hp->type = FC_TYPE_SCSI_FCP;
11441 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11442 	hp->seq_id = 0;
11443 	hp->df_ctl  = 0;
11444 	hp->seq_cnt = 0;
11445 	hp->ox_id = 0xffff;
11446 	hp->rx_id = 0xffff;
11447 	hp->ro = 0;
11448 
11449 	/*
11450 	 * A doubly linked list (cmd_forw, cmd_back) is built
11451 	 * out of every allocated packet on a per-lun basis
11452 	 *
11453 	 * The packets are maintained in the list so as to satisfy
11454 	 * scsi_abort() requests. At present (which is unlikely to
11455 	 * change in the future) nobody performs a real scsi_abort
11456 	 * in the SCSI target drivers (as they don't keep the packets
11457 	 * after doing scsi_transport - so they don't know how to
11458 	 * abort a packet other than sending a NULL to abort all
11459 	 * outstanding packets)
11460 	 */
11461 	mutex_enter(&plun->lun_mutex);
11462 	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11463 		plun->lun_pkt_head->cmd_back = cmd;
11464 	} else {
11465 		plun->lun_pkt_tail = cmd;
11466 	}
11467 	plun->lun_pkt_head = cmd;
11468 	mutex_exit(&plun->lun_mutex);
11469 	return (0);
11470 }
11471 
11472 /*
11473  *     Function: fcp_pkt_teardown
11474  *
11475  *  Description: This function releases a scsi_pkt structure and all the
11476  *		 resources attached to it.
11477  *
11478  *     Argument: *pkt		Pointer to a scsi_pkt structure.
11479  *
11480  * Return Value: None
11481  *
11482  *	Context: User, Kernel or Interrupt context.
11483  */
11484 static void
11485 fcp_pkt_teardown(struct scsi_pkt *pkt)
11486 {
11487 	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11488 	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11489 	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11490 
11491 	/*
11492 	 * Remove the packet from the per-lun list
11493 	 */
11494 	mutex_enter(&plun->lun_mutex);
11495 	if (cmd->cmd_back) {
11496 		ASSERT(cmd != plun->lun_pkt_head);
11497 		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11498 	} else {
11499 		ASSERT(cmd == plun->lun_pkt_head);
11500 		plun->lun_pkt_head = cmd->cmd_forw;
11501 	}
11502 
11503 	if (cmd->cmd_forw) {
11504 		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11505 	} else {
11506 		ASSERT(cmd == plun->lun_pkt_tail);
11507 		plun->lun_pkt_tail = cmd->cmd_back;
11508 	}
11509 
11510 	mutex_exit(&plun->lun_mutex);
11511 
11512 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11513 }
11514 
11515 /*
11516  * Routine for reset notification setup, to register or cancel.
11517  * This function is called by SCSA
11518  */
11519 /*ARGSUSED*/
11520 static int
11521 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11522     void (*callback)(caddr_t), caddr_t arg)
11523 {
11524 	struct fcp_port *pptr = ADDR2FCP(ap);
11525 
11526 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11527 	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11528 }
11529 
11530 
11531 static int
11532 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11533     ddi_eventcookie_t *event_cookiep)
11534 {
11535 	struct fcp_port *pptr = fcp_dip2port(dip);
11536 
11537 	if (pptr == NULL) {
11538 		return (DDI_FAILURE);
11539 	}
11540 
11541 	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11542 	    event_cookiep, NDI_EVENT_NOPASS));
11543 }
11544 
11545 
11546 static int
11547 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11548     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11549     ddi_callback_id_t *cb_id)
11550 {
11551 	struct fcp_port *pptr = fcp_dip2port(dip);
11552 
11553 	if (pptr == NULL) {
11554 		return (DDI_FAILURE);
11555 	}
11556 
11557 	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11558 	    eventid, callback, arg, NDI_SLEEP, cb_id));
11559 }
11560 
11561 
11562 static int
11563 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11564 {
11565 
11566 	struct fcp_port *pptr = fcp_dip2port(dip);
11567 
11568 	if (pptr == NULL) {
11569 		return (DDI_FAILURE);
11570 	}
11571 	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11572 }
11573 
11574 
11575 /*
11576  * called by the transport to post an event
11577  */
11578 static int
11579 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11580     ddi_eventcookie_t eventid, void *impldata)
11581 {
11582 	struct fcp_port *pptr = fcp_dip2port(dip);
11583 
11584 	if (pptr == NULL) {
11585 		return (DDI_FAILURE);
11586 	}
11587 
11588 	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11589 	    eventid, impldata));
11590 }
11591 
11592 
11593 /*
11594  * A target in in many cases in Fibre Channel has a one to one relation
11595  * with a port identifier (which is also known as D_ID and also as AL_PA
11596  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11597  * will most likely result in resetting all LUNs (which means a reset will
11598  * occur on all the SCSI devices connected at the other end of the bridge)
11599  * That is the latest favorite topic for discussion, for, one can debate as
11600  * hot as one likes and come up with arguably a best solution to one's
11601  * satisfaction
11602  *
11603  * To stay on track and not digress much, here are the problems stated
11604  * briefly:
11605  *
11606  *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11607  *	target drivers use RESET_TARGET even if their instance is on a
11608  *	LUN. Doesn't that sound a bit broken ?
11609  *
11610  *	FCP SCSI (the current spec) only defines RESET TARGET in the
11611  *	control fields of an FCP_CMND structure. It should have been
11612  *	fixed right there, giving flexibility to the initiators to
11613  *	minimize havoc that could be caused by resetting a target.
11614  */
11615 static int
11616 fcp_reset_target(struct scsi_address *ap, int level)
11617 {
11618 	int			rval = FC_FAILURE;
11619 	char			lun_id[25];
11620 	struct fcp_port		*pptr = ADDR2FCP(ap);
11621 	struct fcp_lun	*plun = ADDR2LUN(ap);
11622 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11623 	struct scsi_pkt		*pkt;
11624 	struct fcp_pkt	*cmd;
11625 	struct fcp_rsp		*rsp;
11626 	uint32_t		tgt_cnt;
11627 	struct fcp_rsp_info	*rsp_info;
11628 	struct fcp_reset_elem	*p;
11629 	int			bval;
11630 
11631 	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11632 	    KM_NOSLEEP)) == NULL) {
11633 		return (rval);
11634 	}
11635 
11636 	mutex_enter(&ptgt->tgt_mutex);
11637 	if (level == RESET_TARGET) {
11638 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11639 			mutex_exit(&ptgt->tgt_mutex);
11640 			kmem_free(p, sizeof (struct fcp_reset_elem));
11641 			return (rval);
11642 		}
11643 		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11644 		(void) strcpy(lun_id, " ");
11645 	} else {
11646 		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11647 			mutex_exit(&ptgt->tgt_mutex);
11648 			kmem_free(p, sizeof (struct fcp_reset_elem));
11649 			return (rval);
11650 		}
11651 		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11652 
11653 		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11654 	}
11655 	tgt_cnt = ptgt->tgt_change_cnt;
11656 
11657 	mutex_exit(&ptgt->tgt_mutex);
11658 
11659 	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11660 	    0, 0, NULL, 0)) == NULL) {
11661 		kmem_free(p, sizeof (struct fcp_reset_elem));
11662 		mutex_enter(&ptgt->tgt_mutex);
11663 		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11664 		mutex_exit(&ptgt->tgt_mutex);
11665 		return (rval);
11666 	}
11667 	pkt->pkt_time = FCP_POLL_TIMEOUT;
11668 
11669 	/* fill in cmd part of packet */
11670 	cmd = PKT2CMD(pkt);
11671 	if (level == RESET_TARGET) {
11672 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11673 	} else {
11674 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11675 	}
11676 	cmd->cmd_fp_pkt->pkt_comp = NULL;
11677 	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11678 
11679 	/* prepare a packet for transport */
11680 	fcp_prepare_pkt(pptr, cmd, plun);
11681 
11682 	if (cmd->cmd_pkt->pkt_time) {
11683 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11684 	} else {
11685 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11686 	}
11687 
11688 	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11689 	bval = fcp_dopoll(pptr, cmd);
11690 	fc_ulp_idle_port(pptr->port_fp_handle);
11691 
11692 	/* submit the packet */
11693 	if (bval == TRAN_ACCEPT) {
11694 		int error = 3;
11695 
11696 		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11697 		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11698 		    sizeof (struct fcp_rsp));
11699 
11700 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11701 			if (fcp_validate_fcp_response(rsp, pptr) ==
11702 			    FC_SUCCESS) {
11703 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11704 					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11705 					    sizeof (struct fcp_rsp), rsp_info,
11706 					    cmd->cmd_fp_pkt->pkt_resp_acc,
11707 					    sizeof (struct fcp_rsp_info));
11708 				}
11709 				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11710 					rval = FC_SUCCESS;
11711 					error = 0;
11712 				} else {
11713 					error = 1;
11714 				}
11715 			} else {
11716 				error = 2;
11717 			}
11718 		}
11719 
11720 		switch (error) {
11721 		case 0:
11722 			fcp_log(CE_WARN, pptr->port_dip,
11723 			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11724 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11725 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11726 			break;
11727 
11728 		case 1:
11729 			fcp_log(CE_WARN, pptr->port_dip,
11730 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11731 			    " response code=%x",
11732 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11733 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11734 			    rsp_info->rsp_code);
11735 			break;
11736 
11737 		case 2:
11738 			fcp_log(CE_WARN, pptr->port_dip,
11739 			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11740 			    " Bad FCP response values: rsvd1=%x,"
11741 			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11742 			    " rsplen=%x, senselen=%x",
11743 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11744 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11745 			    rsp->reserved_0, rsp->reserved_1,
11746 			    rsp->fcp_u.fcp_status.reserved_0,
11747 			    rsp->fcp_u.fcp_status.reserved_1,
11748 			    rsp->fcp_response_len, rsp->fcp_sense_len);
11749 			break;
11750 
11751 		default:
11752 			fcp_log(CE_WARN, pptr->port_dip,
11753 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11754 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11755 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11756 			break;
11757 		}
11758 	}
11759 	scsi_destroy_pkt(pkt);
11760 
11761 	if (rval == FC_FAILURE) {
11762 		mutex_enter(&ptgt->tgt_mutex);
11763 		if (level == RESET_TARGET) {
11764 			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11765 		} else {
11766 			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11767 		}
11768 		mutex_exit(&ptgt->tgt_mutex);
11769 		kmem_free(p, sizeof (struct fcp_reset_elem));
11770 		return (rval);
11771 	}
11772 
11773 	mutex_enter(&pptr->port_mutex);
11774 	if (level == RESET_TARGET) {
11775 		p->tgt = ptgt;
11776 		p->lun = NULL;
11777 	} else {
11778 		p->tgt = NULL;
11779 		p->lun = plun;
11780 	}
11781 	p->tgt = ptgt;
11782 	p->tgt_cnt = tgt_cnt;
11783 	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11784 	p->next = pptr->port_reset_list;
11785 	pptr->port_reset_list = p;
11786 
11787 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11788 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11789 	    "Notify ssd of the reset to reinstate the reservations");
11790 
11791 	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11792 	    &pptr->port_reset_notify_listf);
11793 
11794 	mutex_exit(&pptr->port_mutex);
11795 
11796 	return (rval);
11797 }
11798 
11799 
11800 /*
11801  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11802  * SCSI capabilities
11803  */
11804 /* ARGSUSED */
11805 static int
11806 fcp_commoncap(struct scsi_address *ap, char *cap,
11807     int val, int tgtonly, int doset)
11808 {
11809 	struct fcp_port		*pptr = ADDR2FCP(ap);
11810 	struct fcp_lun	*plun = ADDR2LUN(ap);
11811 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11812 	int			cidx;
11813 	int			rval = FALSE;
11814 
11815 	if (cap == (char *)0) {
11816 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11817 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11818 		    "fcp_commoncap: invalid arg");
11819 		return (rval);
11820 	}
11821 
11822 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11823 		return (UNDEFINED);
11824 	}
11825 
11826 	/*
11827 	 * Process setcap request.
11828 	 */
11829 	if (doset) {
11830 		/*
11831 		 * At present, we can only set binary (0/1) values
11832 		 */
11833 		switch (cidx) {
11834 		case SCSI_CAP_ARQ:
11835 			if (val == 0) {
11836 				rval = FALSE;
11837 			} else {
11838 				rval = TRUE;
11839 			}
11840 			break;
11841 
11842 		case SCSI_CAP_LUN_RESET:
11843 			if (val) {
11844 				plun->lun_cap |= FCP_LUN_CAP_RESET;
11845 			} else {
11846 				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11847 			}
11848 			rval = TRUE;
11849 			break;
11850 
11851 		case SCSI_CAP_SECTOR_SIZE:
11852 			rval = TRUE;
11853 			break;
11854 		default:
11855 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11856 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11857 			    "fcp_setcap: unsupported %d", cidx);
11858 			rval = UNDEFINED;
11859 			break;
11860 		}
11861 
11862 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11863 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11864 		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11865 		    "0x%x/0x%x/0x%x/%d",
11866 		    cap, val, tgtonly, doset, rval);
11867 
11868 	} else {
11869 		/*
11870 		 * Process getcap request.
11871 		 */
11872 		switch (cidx) {
11873 		case SCSI_CAP_DMA_MAX:
11874 			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11875 
11876 			/*
11877 			 * Need to make an adjustment qlc is uint_t 64
11878 			 * st is int, so we will make the adjustment here
11879 			 * being as nobody wants to touch this.
11880 			 * It still leaves the max single block length
11881 			 * of 2 gig. This should last .
11882 			 */
11883 
11884 			if (rval == -1) {
11885 				rval = MAX_INT_DMA;
11886 			}
11887 
11888 			break;
11889 
11890 		case SCSI_CAP_INITIATOR_ID:
11891 			rval = pptr->port_id;
11892 			break;
11893 
11894 		case SCSI_CAP_ARQ:
11895 		case SCSI_CAP_RESET_NOTIFICATION:
11896 		case SCSI_CAP_TAGGED_QING:
11897 			rval = TRUE;
11898 			break;
11899 
11900 		case SCSI_CAP_SCSI_VERSION:
11901 			rval = 3;
11902 			break;
11903 
11904 		case SCSI_CAP_INTERCONNECT_TYPE:
11905 			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11906 			    (ptgt->tgt_hard_addr == 0)) {
11907 				rval = INTERCONNECT_FABRIC;
11908 			} else {
11909 				rval = INTERCONNECT_FIBRE;
11910 			}
11911 			break;
11912 
11913 		case SCSI_CAP_LUN_RESET:
11914 			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11915 			    TRUE : FALSE;
11916 			break;
11917 
11918 		default:
11919 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11920 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11921 			    "fcp_getcap: unsupported %d", cidx);
11922 			rval = UNDEFINED;
11923 			break;
11924 		}
11925 
11926 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11927 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11928 		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11929 		    "0x%x/0x%x/0x%x/%d",
11930 		    cap, val, tgtonly, doset, rval);
11931 	}
11932 
11933 	return (rval);
11934 }
11935 
11936 /*
11937  * called by the transport to get the port-wwn and lun
11938  * properties of this device, and to create a "name" based on them
11939  *
11940  * these properties don't exist on sun4m
11941  *
11942  * return 1 for success else return 0
11943  */
11944 /* ARGSUSED */
11945 static int
11946 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11947 {
11948 	int			i;
11949 	int			*lun;
11950 	int			numChars;
11951 	uint_t			nlun;
11952 	uint_t			count;
11953 	uint_t			nbytes;
11954 	uchar_t			*bytes;
11955 	uint16_t		lun_num;
11956 	uint32_t		tgt_id;
11957 	char			**conf_wwn;
11958 	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11959 	uchar_t			barray[FC_WWN_SIZE];
11960 	dev_info_t		*tgt_dip;
11961 	struct fcp_tgt	*ptgt;
11962 	struct fcp_port	*pptr;
11963 	struct fcp_lun	*plun;
11964 
11965 	ASSERT(sd != NULL);
11966 	ASSERT(name != NULL);
11967 
11968 	tgt_dip = sd->sd_dev;
11969 	pptr = ddi_get_soft_state(fcp_softstate,
11970 	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11971 	if (pptr == NULL) {
11972 		return (0);
11973 	}
11974 
11975 	ASSERT(tgt_dip != NULL);
11976 
11977 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11978 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11979 	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11980 		name[0] = '\0';
11981 		return (0);
11982 	}
11983 
11984 	if (nlun == 0) {
11985 		ddi_prop_free(lun);
11986 		return (0);
11987 	}
11988 
11989 	lun_num = lun[0];
11990 	ddi_prop_free(lun);
11991 
11992 	/*
11993 	 * Lookup for .conf WWN property
11994 	 */
11995 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
11996 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
11997 	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
11998 		ASSERT(count >= 1);
11999 
12000 		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12001 		ddi_prop_free(conf_wwn);
12002 		mutex_enter(&pptr->port_mutex);
12003 		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12004 			mutex_exit(&pptr->port_mutex);
12005 			return (0);
12006 		}
12007 		ptgt = plun->lun_tgt;
12008 		mutex_exit(&pptr->port_mutex);
12009 
12010 		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12011 		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12012 
12013 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12014 		    ptgt->tgt_hard_addr != 0) {
12015 			tgt_id = (uint32_t)fcp_alpa_to_switch[
12016 			    ptgt->tgt_hard_addr];
12017 		} else {
12018 			tgt_id = ptgt->tgt_d_id;
12019 		}
12020 
12021 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12022 		    TARGET_PROP, tgt_id);
12023 	}
12024 
12025 	/* get the our port-wwn property */
12026 	bytes = NULL;
12027 	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12028 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12029 	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12030 		if (bytes != NULL) {
12031 			ddi_prop_free(bytes);
12032 		}
12033 		return (0);
12034 	}
12035 
12036 	for (i = 0; i < FC_WWN_SIZE; i++) {
12037 		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12038 	}
12039 
12040 	/* Stick in the address of the form "wWWN,LUN" */
12041 	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12042 
12043 	ASSERT(numChars < len);
12044 	if (numChars >= len) {
12045 		fcp_log(CE_WARN, pptr->port_dip,
12046 		    "!fcp_scsi_get_name: "
12047 		    "name parameter length too small, it needs to be %d",
12048 		    numChars+1);
12049 	}
12050 
12051 	ddi_prop_free(bytes);
12052 
12053 	return (1);
12054 }
12055 
12056 
12057 /*
12058  * called by the transport to get the SCSI target id value, returning
12059  * it in "name"
12060  *
12061  * this isn't needed/used on sun4m
12062  *
12063  * return 1 for success else return 0
12064  */
12065 /* ARGSUSED */
12066 static int
12067 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12068 {
12069 	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
12070 	struct fcp_tgt	*ptgt;
12071 	int    numChars;
12072 
12073 	if (plun == NULL) {
12074 		return (0);
12075 	}
12076 
12077 	if ((ptgt = plun->lun_tgt) == NULL) {
12078 		return (0);
12079 	}
12080 
12081 	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12082 
12083 	ASSERT(numChars < len);
12084 	if (numChars >= len) {
12085 		fcp_log(CE_WARN, NULL,
12086 		    "!fcp_scsi_get_bus_addr: "
12087 		    "name parameter length too small, it needs to be %d",
12088 		    numChars+1);
12089 	}
12090 
12091 	return (1);
12092 }
12093 
12094 
12095 /*
12096  * called internally to reset the link where the specified port lives
12097  */
12098 static int
12099 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12100 {
12101 	la_wwn_t		wwn;
12102 	struct fcp_lun	*plun;
12103 	struct fcp_tgt	*ptgt;
12104 
12105 	/* disable restart of lip if we're suspended */
12106 	mutex_enter(&pptr->port_mutex);
12107 
12108 	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12109 	    FCP_STATE_POWER_DOWN)) {
12110 		mutex_exit(&pptr->port_mutex);
12111 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12112 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12113 		    "fcp_linkreset, fcp%d: link reset "
12114 		    "disabled due to DDI_SUSPEND",
12115 		    ddi_get_instance(pptr->port_dip));
12116 		return (FC_FAILURE);
12117 	}
12118 
12119 	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12120 		mutex_exit(&pptr->port_mutex);
12121 		return (FC_SUCCESS);
12122 	}
12123 
12124 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12125 	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12126 
12127 	/*
12128 	 * If ap == NULL assume local link reset.
12129 	 */
12130 	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12131 		plun = ADDR2LUN(ap);
12132 		ptgt = plun->lun_tgt;
12133 		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12134 	} else {
12135 		bzero((caddr_t)&wwn, sizeof (wwn));
12136 	}
12137 	mutex_exit(&pptr->port_mutex);
12138 
12139 	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12140 }
12141 
12142 
12143 /*
12144  * called from fcp_port_attach() to resume a port
12145  * return DDI_* success/failure status
12146  * acquires and releases the global mutex
12147  * acquires and releases the port mutex
12148  */
12149 /*ARGSUSED*/
12150 
12151 static int
12152 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12153     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12154 {
12155 	int			res = DDI_FAILURE; /* default result */
12156 	struct fcp_port	*pptr;		/* port state ptr */
12157 	uint32_t		alloc_cnt;
12158 	uint32_t		max_cnt;
12159 	fc_portmap_t		*tmp_list = NULL;
12160 
12161 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12162 	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12163 	    instance);
12164 
12165 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12166 		cmn_err(CE_WARN, "fcp: bad soft state");
12167 		return (res);
12168 	}
12169 
12170 	mutex_enter(&pptr->port_mutex);
12171 	switch (cmd) {
12172 	case FC_CMD_RESUME:
12173 		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12174 		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12175 		break;
12176 
12177 	case FC_CMD_POWER_UP:
12178 		/*
12179 		 * If the port is DDI_SUSPENded, defer rediscovery
12180 		 * until DDI_RESUME occurs
12181 		 */
12182 		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12183 			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12184 			mutex_exit(&pptr->port_mutex);
12185 			return (DDI_SUCCESS);
12186 		}
12187 		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12188 	}
12189 	pptr->port_id = s_id;
12190 	pptr->port_state = FCP_STATE_INIT;
12191 	mutex_exit(&pptr->port_mutex);
12192 
12193 	/*
12194 	 * Make a copy of ulp_port_info as fctl allocates
12195 	 * a temp struct.
12196 	 */
12197 	(void) fcp_cp_pinfo(pptr, pinfo);
12198 
12199 	mutex_enter(&fcp_global_mutex);
12200 	if (fcp_watchdog_init++ == 0) {
12201 		fcp_watchdog_tick = fcp_watchdog_timeout *
12202 		    drv_usectohz(1000000);
12203 		fcp_watchdog_id = timeout(fcp_watch,
12204 		    NULL, fcp_watchdog_tick);
12205 	}
12206 	mutex_exit(&fcp_global_mutex);
12207 
12208 	/*
12209 	 * Handle various topologies and link states.
12210 	 */
12211 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12212 	case FC_STATE_OFFLINE:
12213 		/*
12214 		 * Wait for ONLINE, at which time a state
12215 		 * change will cause a statec_callback
12216 		 */
12217 		res = DDI_SUCCESS;
12218 		break;
12219 
12220 	case FC_STATE_ONLINE:
12221 
12222 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12223 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12224 			res = DDI_SUCCESS;
12225 			break;
12226 		}
12227 
12228 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12229 		    !fcp_enable_auto_configuration) {
12230 			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12231 			if (tmp_list == NULL) {
12232 				if (!alloc_cnt) {
12233 					res = DDI_SUCCESS;
12234 				}
12235 				break;
12236 			}
12237 			max_cnt = alloc_cnt;
12238 		} else {
12239 			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12240 
12241 			alloc_cnt = FCP_MAX_DEVICES;
12242 
12243 			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12244 			    (sizeof (fc_portmap_t)) * alloc_cnt,
12245 			    KM_NOSLEEP)) == NULL) {
12246 				fcp_log(CE_WARN, pptr->port_dip,
12247 				    "!fcp%d: failed to allocate portmap",
12248 				    instance);
12249 				break;
12250 			}
12251 
12252 			max_cnt = alloc_cnt;
12253 			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12254 			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12255 			    FC_SUCCESS) {
12256 				caddr_t msg;
12257 
12258 				(void) fc_ulp_error(res, &msg);
12259 
12260 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12261 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12262 				    "resume failed getportmap: reason=0x%x",
12263 				    res);
12264 
12265 				fcp_log(CE_WARN, pptr->port_dip,
12266 				    "!failed to get port map : %s", msg);
12267 				break;
12268 			}
12269 			if (max_cnt > alloc_cnt) {
12270 				alloc_cnt = max_cnt;
12271 			}
12272 		}
12273 
12274 		/*
12275 		 * do the SCSI device discovery and create
12276 		 * the devinfos
12277 		 */
12278 		fcp_statec_callback(ulph, pptr->port_fp_handle,
12279 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12280 		    max_cnt, pptr->port_id);
12281 
12282 		res = DDI_SUCCESS;
12283 		break;
12284 
12285 	default:
12286 		fcp_log(CE_WARN, pptr->port_dip,
12287 		    "!fcp%d: invalid port state at attach=0x%x",
12288 		    instance, pptr->port_phys_state);
12289 
12290 		mutex_enter(&pptr->port_mutex);
12291 		pptr->port_phys_state = FCP_STATE_OFFLINE;
12292 		mutex_exit(&pptr->port_mutex);
12293 		res = DDI_SUCCESS;
12294 
12295 		break;
12296 	}
12297 
12298 	if (tmp_list != NULL) {
12299 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12300 	}
12301 
12302 	return (res);
12303 }
12304 
12305 
12306 static void
12307 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12308 {
12309 	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12310 	pptr->port_dip = pinfo->port_dip;
12311 	pptr->port_fp_handle = pinfo->port_handle;
12312 	if (pinfo->port_acc_attr != NULL) {
12313 		/*
12314 		 * FCA supports DMA
12315 		 */
12316 		pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12317 		pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12318 		pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12319 		pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12320 	}
12321 	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12322 	pptr->port_max_exch = pinfo->port_fca_max_exch;
12323 	pptr->port_phys_state = pinfo->port_state;
12324 	pptr->port_topology = pinfo->port_flags;
12325 	pptr->port_reset_action = pinfo->port_reset_action;
12326 	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12327 	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12328 	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12329 	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12330 
12331 	/* Clear FMA caps to avoid fm-capability ereport */
12332 	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12333 		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12334 	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12335 		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12336 	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12337 		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12338 }
12339 
12340 /*
12341  * If the elements wait field is set to 1 then
12342  * another thread is waiting for the operation to complete. Once
12343  * it is complete, the waiting thread is signaled and the element is
12344  * freed by the waiting thread. If the elements wait field is set to 0
12345  * the element is freed.
12346  */
12347 static void
12348 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12349 {
12350 	ASSERT(elem != NULL);
12351 	mutex_enter(&elem->mutex);
12352 	elem->result = result;
12353 	if (elem->wait) {
12354 		elem->wait = 0;
12355 		cv_signal(&elem->cv);
12356 		mutex_exit(&elem->mutex);
12357 	} else {
12358 		mutex_exit(&elem->mutex);
12359 		cv_destroy(&elem->cv);
12360 		mutex_destroy(&elem->mutex);
12361 		kmem_free(elem, sizeof (struct fcp_hp_elem));
12362 	}
12363 }
12364 
12365 /*
12366  * This function is invoked from the taskq thread to allocate
12367  * devinfo nodes and to online/offline them.
12368  */
12369 static void
12370 fcp_hp_task(void *arg)
12371 {
12372 	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12373 	struct fcp_lun	*plun = elem->lun;
12374 	struct fcp_port		*pptr = elem->port;
12375 	int			result;
12376 
12377 	ASSERT(elem->what == FCP_ONLINE ||
12378 	    elem->what == FCP_OFFLINE ||
12379 	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12380 	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12381 
12382 	mutex_enter(&pptr->port_mutex);
12383 	mutex_enter(&plun->lun_mutex);
12384 	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12385 	    plun->lun_event_count != elem->event_cnt) ||
12386 	    pptr->port_state & (FCP_STATE_SUSPENDED |
12387 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12388 		mutex_exit(&plun->lun_mutex);
12389 		mutex_exit(&pptr->port_mutex);
12390 		fcp_process_elem(elem, NDI_FAILURE);
12391 		return;
12392 	}
12393 	mutex_exit(&plun->lun_mutex);
12394 	mutex_exit(&pptr->port_mutex);
12395 
12396 	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12397 	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12398 	fcp_process_elem(elem, result);
12399 }
12400 
12401 
12402 static child_info_t *
12403 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12404     int tcount)
12405 {
12406 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12407 
12408 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12409 		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12410 
12411 		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12412 		/*
12413 		 * Child has not been created yet. Create the child device
12414 		 * based on the per-Lun flags.
12415 		 */
12416 		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12417 			plun->lun_cip =
12418 			    CIP(fcp_create_dip(plun, lcount, tcount));
12419 			plun->lun_mpxio = 0;
12420 		} else {
12421 			plun->lun_cip =
12422 			    CIP(fcp_create_pip(plun, lcount, tcount));
12423 			plun->lun_mpxio = 1;
12424 		}
12425 	} else {
12426 		plun->lun_cip = cip;
12427 	}
12428 
12429 	return (plun->lun_cip);
12430 }
12431 
12432 
12433 static int
12434 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12435 {
12436 	int		rval = FC_FAILURE;
12437 	dev_info_t	*pdip;
12438 	struct dev_info	*dip;
12439 	int		circular;
12440 
12441 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12442 
12443 	pdip = plun->lun_tgt->tgt_port->port_dip;
12444 
12445 	if (plun->lun_cip == NULL) {
12446 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12447 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12448 		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12449 		    "plun: %p lun state: %x num: %d target state: %x",
12450 		    plun, plun->lun_state, plun->lun_num,
12451 		    plun->lun_tgt->tgt_port->port_state);
12452 		return (rval);
12453 	}
12454 	ndi_devi_enter(pdip, &circular);
12455 	dip = DEVI(pdip)->devi_child;
12456 	while (dip) {
12457 		if (dip == DEVI(cdip)) {
12458 			rval = FC_SUCCESS;
12459 			break;
12460 		}
12461 		dip = dip->devi_sibling;
12462 	}
12463 	ndi_devi_exit(pdip, circular);
12464 	return (rval);
12465 }
12466 
12467 static int
12468 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12469 {
12470 	int		rval = FC_FAILURE;
12471 
12472 	ASSERT(plun != NULL);
12473 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12474 
12475 	if (plun->lun_mpxio == 0) {
12476 		rval = fcp_is_dip_present(plun, DIP(cip));
12477 	} else {
12478 		rval = fcp_is_pip_present(plun, PIP(cip));
12479 	}
12480 
12481 	return (rval);
12482 }
12483 
12484 /*
12485  *     Function: fcp_create_dip
12486  *
12487  *  Description: Creates a dev_info_t structure for the LUN specified by the
12488  *		 caller.
12489  *
12490  *     Argument: plun		Lun structure
12491  *		 link_cnt	Link state count.
12492  *		 tgt_cnt	Target state change count.
12493  *
12494  * Return Value: NULL if it failed
12495  *		 dev_info_t structure address if it succeeded
12496  *
12497  *	Context: Kernel context
12498  */
12499 static dev_info_t *
12500 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12501 {
12502 	int			failure = 0;
12503 	uint32_t		tgt_id;
12504 	uint64_t		sam_lun;
12505 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12506 	struct fcp_port	*pptr = ptgt->tgt_port;
12507 	dev_info_t		*pdip = pptr->port_dip;
12508 	dev_info_t		*cdip = NULL;
12509 	dev_info_t		*old_dip = DIP(plun->lun_cip);
12510 	char			*nname = NULL;
12511 	char			**compatible = NULL;
12512 	int			ncompatible;
12513 	char			*scsi_binding_set;
12514 	char			t_pwwn[17];
12515 
12516 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12517 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12518 
12519 	/* get the 'scsi-binding-set' property */
12520 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12521 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12522 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12523 		scsi_binding_set = NULL;
12524 	}
12525 
12526 	/* determine the node name and compatible */
12527 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12528 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12529 	if (scsi_binding_set) {
12530 		ddi_prop_free(scsi_binding_set);
12531 	}
12532 
12533 	if (nname == NULL) {
12534 #ifdef	DEBUG
12535 		cmn_err(CE_WARN, "%s%d: no driver for "
12536 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12537 		    "	 compatible: %s",
12538 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12539 		    ptgt->tgt_port_wwn.raw_wwn[0],
12540 		    ptgt->tgt_port_wwn.raw_wwn[1],
12541 		    ptgt->tgt_port_wwn.raw_wwn[2],
12542 		    ptgt->tgt_port_wwn.raw_wwn[3],
12543 		    ptgt->tgt_port_wwn.raw_wwn[4],
12544 		    ptgt->tgt_port_wwn.raw_wwn[5],
12545 		    ptgt->tgt_port_wwn.raw_wwn[6],
12546 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12547 		    *compatible);
12548 #endif	/* DEBUG */
12549 		failure++;
12550 		goto end_of_fcp_create_dip;
12551 	}
12552 
12553 	cdip = fcp_find_existing_dip(plun, pdip, nname);
12554 
12555 	/*
12556 	 * if the old_dip does not match the cdip, that means there is
12557 	 * some property change. since we'll be using the cdip, we need
12558 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12559 	 * then the dtype for the device has been updated. Offline the
12560 	 * the old device and create a new device with the new device type
12561 	 * Refer to bug: 4764752
12562 	 */
12563 	if (old_dip && (cdip != old_dip ||
12564 	    plun->lun_state & FCP_LUN_CHANGED)) {
12565 		plun->lun_state &= ~(FCP_LUN_INIT);
12566 		mutex_exit(&plun->lun_mutex);
12567 		mutex_exit(&pptr->port_mutex);
12568 
12569 		mutex_enter(&ptgt->tgt_mutex);
12570 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12571 		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12572 		mutex_exit(&ptgt->tgt_mutex);
12573 
12574 #ifdef DEBUG
12575 		if (cdip != NULL) {
12576 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12577 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12578 			    "Old dip=%p; New dip=%p don't match", old_dip,
12579 			    cdip);
12580 		} else {
12581 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12582 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12583 			    "Old dip=%p; New dip=NULL don't match", old_dip);
12584 		}
12585 #endif
12586 
12587 		mutex_enter(&pptr->port_mutex);
12588 		mutex_enter(&plun->lun_mutex);
12589 	}
12590 
12591 	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12592 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12593 		if (ndi_devi_alloc(pptr->port_dip, nname,
12594 		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12595 			failure++;
12596 			goto end_of_fcp_create_dip;
12597 		}
12598 	}
12599 
12600 	/*
12601 	 * Previously all the properties for the devinfo were destroyed here
12602 	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12603 	 * the devid property (and other properties established by the target
12604 	 * driver or framework) which the code does not always recreate, this
12605 	 * call was removed.
12606 	 * This opens a theoretical possibility that we may return with a
12607 	 * stale devid on the node if the scsi entity behind the fibre channel
12608 	 * lun has changed.
12609 	 */
12610 
12611 	/* decorate the node with compatible */
12612 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12613 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12614 		failure++;
12615 		goto end_of_fcp_create_dip;
12616 	}
12617 
12618 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12619 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12620 		failure++;
12621 		goto end_of_fcp_create_dip;
12622 	}
12623 
12624 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12625 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12626 		failure++;
12627 		goto end_of_fcp_create_dip;
12628 	}
12629 
12630 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12631 	t_pwwn[16] = '\0';
12632 	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12633 	    != DDI_PROP_SUCCESS) {
12634 		failure++;
12635 		goto end_of_fcp_create_dip;
12636 	}
12637 
12638 	/*
12639 	 * If there is no hard address - We might have to deal with
12640 	 * that by using WWN - Having said that it is important to
12641 	 * recognize this problem early so ssd can be informed of
12642 	 * the right interconnect type.
12643 	 */
12644 	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12645 		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12646 	} else {
12647 		tgt_id = ptgt->tgt_d_id;
12648 	}
12649 
12650 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12651 	    tgt_id) != DDI_PROP_SUCCESS) {
12652 		failure++;
12653 		goto end_of_fcp_create_dip;
12654 	}
12655 
12656 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12657 	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12658 		failure++;
12659 		goto end_of_fcp_create_dip;
12660 	}
12661 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12662 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12663 	    sam_lun) != DDI_PROP_SUCCESS) {
12664 		failure++;
12665 		goto end_of_fcp_create_dip;
12666 	}
12667 
12668 end_of_fcp_create_dip:
12669 	scsi_hba_nodename_compatible_free(nname, compatible);
12670 
12671 	if (cdip != NULL && failure) {
12672 		(void) ndi_prop_remove_all(cdip);
12673 		(void) ndi_devi_free(cdip);
12674 		cdip = NULL;
12675 	}
12676 
12677 	return (cdip);
12678 }
12679 
12680 /*
12681  *     Function: fcp_create_pip
12682  *
12683  *  Description: Creates a Path Id for the LUN specified by the caller.
12684  *
12685  *     Argument: plun		Lun structure
12686  *		 link_cnt	Link state count.
12687  *		 tgt_cnt	Target state count.
12688  *
12689  * Return Value: NULL if it failed
12690  *		 mdi_pathinfo_t structure address if it succeeded
12691  *
12692  *	Context: Kernel context
12693  */
12694 static mdi_pathinfo_t *
12695 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12696 {
12697 	int			i;
12698 	char			buf[MAXNAMELEN];
12699 	char			uaddr[MAXNAMELEN];
12700 	int			failure = 0;
12701 	uint32_t		tgt_id;
12702 	uint64_t		sam_lun;
12703 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12704 	struct fcp_port	*pptr = ptgt->tgt_port;
12705 	dev_info_t		*pdip = pptr->port_dip;
12706 	mdi_pathinfo_t		*pip = NULL;
12707 	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12708 	char			*nname = NULL;
12709 	char			**compatible = NULL;
12710 	int			ncompatible;
12711 	char			*scsi_binding_set;
12712 	char			t_pwwn[17];
12713 
12714 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12715 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12716 
12717 	scsi_binding_set = "vhci";
12718 
12719 	/* determine the node name and compatible */
12720 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12721 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12722 
12723 	if (nname == NULL) {
12724 #ifdef	DEBUG
12725 		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12726 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12727 		    "	 compatible: %s",
12728 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12729 		    ptgt->tgt_port_wwn.raw_wwn[0],
12730 		    ptgt->tgt_port_wwn.raw_wwn[1],
12731 		    ptgt->tgt_port_wwn.raw_wwn[2],
12732 		    ptgt->tgt_port_wwn.raw_wwn[3],
12733 		    ptgt->tgt_port_wwn.raw_wwn[4],
12734 		    ptgt->tgt_port_wwn.raw_wwn[5],
12735 		    ptgt->tgt_port_wwn.raw_wwn[6],
12736 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12737 		    *compatible);
12738 #endif	/* DEBUG */
12739 		failure++;
12740 		goto end_of_fcp_create_pip;
12741 	}
12742 
12743 	pip = fcp_find_existing_pip(plun, pdip);
12744 
12745 	/*
12746 	 * if the old_dip does not match the cdip, that means there is
12747 	 * some property change. since we'll be using the cdip, we need
12748 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12749 	 * then the dtype for the device has been updated. Offline the
12750 	 * the old device and create a new device with the new device type
12751 	 * Refer to bug: 4764752
12752 	 */
12753 	if (old_pip && (pip != old_pip ||
12754 	    plun->lun_state & FCP_LUN_CHANGED)) {
12755 		plun->lun_state &= ~(FCP_LUN_INIT);
12756 		mutex_exit(&plun->lun_mutex);
12757 		mutex_exit(&pptr->port_mutex);
12758 
12759 		mutex_enter(&ptgt->tgt_mutex);
12760 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12761 		    FCP_OFFLINE, lcount, tcount,
12762 		    NDI_DEVI_REMOVE, 0);
12763 		mutex_exit(&ptgt->tgt_mutex);
12764 
12765 		if (pip != NULL) {
12766 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12767 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12768 			    "Old pip=%p; New pip=%p don't match",
12769 			    old_pip, pip);
12770 		} else {
12771 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12772 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12773 			    "Old pip=%p; New pip=NULL don't match",
12774 			    old_pip);
12775 		}
12776 
12777 		mutex_enter(&pptr->port_mutex);
12778 		mutex_enter(&plun->lun_mutex);
12779 	}
12780 
12781 	/*
12782 	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12783 	 * lun_guid_size which is dependent on the target, I don't
12784 	 * believe the same trancation happens here UNLESS the standards
12785 	 * change the FC_WWN_SIZE value to something larger than
12786 	 * MAXNAMELEN(currently 255 bytes).
12787 	 */
12788 
12789 	for (i = 0; i < FC_WWN_SIZE; i++) {
12790 		(void) sprintf(&buf[i << 1], "%02x",
12791 		    ptgt->tgt_port_wwn.raw_wwn[i]);
12792 	}
12793 
12794 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12795 	    buf, plun->lun_num);
12796 
12797 	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12798 		/*
12799 		 * Release the locks before calling into
12800 		 * mdi_pi_alloc_compatible() since this can result in a
12801 		 * callback into fcp which can result in a deadlock
12802 		 * (see bug # 4870272).
12803 		 *
12804 		 * Basically, what we are trying to avoid is the scenario where
12805 		 * one thread does ndi_devi_enter() and tries to grab
12806 		 * fcp_mutex and another does it the other way round.
12807 		 *
12808 		 * But before we do that, make sure that nobody releases the
12809 		 * port in the meantime. We can do this by setting a flag.
12810 		 */
12811 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12812 		pptr->port_state |= FCP_STATE_IN_MDI;
12813 		mutex_exit(&plun->lun_mutex);
12814 		mutex_exit(&pptr->port_mutex);
12815 		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12816 		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12817 			fcp_log(CE_WARN, pptr->port_dip,
12818 			    "!path alloc failed:0x%x", plun);
12819 			mutex_enter(&pptr->port_mutex);
12820 			mutex_enter(&plun->lun_mutex);
12821 			pptr->port_state &= ~FCP_STATE_IN_MDI;
12822 			failure++;
12823 			goto end_of_fcp_create_pip;
12824 		}
12825 		mutex_enter(&pptr->port_mutex);
12826 		mutex_enter(&plun->lun_mutex);
12827 		pptr->port_state &= ~FCP_STATE_IN_MDI;
12828 	} else {
12829 		(void) mdi_prop_remove(pip, NULL);
12830 	}
12831 
12832 	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12833 
12834 	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12835 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12836 	    != DDI_PROP_SUCCESS) {
12837 		failure++;
12838 		goto end_of_fcp_create_pip;
12839 	}
12840 
12841 	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12842 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12843 	    != DDI_PROP_SUCCESS) {
12844 		failure++;
12845 		goto end_of_fcp_create_pip;
12846 	}
12847 
12848 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12849 	t_pwwn[16] = '\0';
12850 	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12851 	    != DDI_PROP_SUCCESS) {
12852 		failure++;
12853 		goto end_of_fcp_create_pip;
12854 	}
12855 
12856 	/*
12857 	 * If there is no hard address - We might have to deal with
12858 	 * that by using WWN - Having said that it is important to
12859 	 * recognize this problem early so ssd can be informed of
12860 	 * the right interconnect type.
12861 	 */
12862 	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12863 	    ptgt->tgt_hard_addr != 0) {
12864 		tgt_id = (uint32_t)
12865 		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12866 	} else {
12867 		tgt_id = ptgt->tgt_d_id;
12868 	}
12869 
12870 	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12871 	    != DDI_PROP_SUCCESS) {
12872 		failure++;
12873 		goto end_of_fcp_create_pip;
12874 	}
12875 
12876 	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12877 	    != DDI_PROP_SUCCESS) {
12878 		failure++;
12879 		goto end_of_fcp_create_pip;
12880 	}
12881 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12882 	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12883 	    != DDI_PROP_SUCCESS) {
12884 		failure++;
12885 		goto end_of_fcp_create_pip;
12886 	}
12887 
12888 end_of_fcp_create_pip:
12889 	scsi_hba_nodename_compatible_free(nname, compatible);
12890 
12891 	if (pip != NULL && failure) {
12892 		(void) mdi_prop_remove(pip, NULL);
12893 		mutex_exit(&plun->lun_mutex);
12894 		mutex_exit(&pptr->port_mutex);
12895 		(void) mdi_pi_free(pip, 0);
12896 		mutex_enter(&pptr->port_mutex);
12897 		mutex_enter(&plun->lun_mutex);
12898 		pip = NULL;
12899 	}
12900 
12901 	return (pip);
12902 }
12903 
12904 static dev_info_t *
12905 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12906 {
12907 	uint_t			nbytes;
12908 	uchar_t			*bytes;
12909 	uint_t			nwords;
12910 	uint32_t		tgt_id;
12911 	int			*words;
12912 	dev_info_t		*cdip;
12913 	dev_info_t		*ndip;
12914 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12915 	struct fcp_port	*pptr = ptgt->tgt_port;
12916 	int			circular;
12917 
12918 	ndi_devi_enter(pdip, &circular);
12919 
12920 	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12921 	while ((cdip = ndip) != NULL) {
12922 		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12923 
12924 		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12925 			continue;
12926 		}
12927 
12928 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12929 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12930 		    &nbytes) != DDI_PROP_SUCCESS) {
12931 			continue;
12932 		}
12933 
12934 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12935 			if (bytes != NULL) {
12936 				ddi_prop_free(bytes);
12937 			}
12938 			continue;
12939 		}
12940 		ASSERT(bytes != NULL);
12941 
12942 		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12943 			ddi_prop_free(bytes);
12944 			continue;
12945 		}
12946 
12947 		ddi_prop_free(bytes);
12948 
12949 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12950 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12951 		    &nbytes) != DDI_PROP_SUCCESS) {
12952 			continue;
12953 		}
12954 
12955 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12956 			if (bytes != NULL) {
12957 				ddi_prop_free(bytes);
12958 			}
12959 			continue;
12960 		}
12961 		ASSERT(bytes != NULL);
12962 
12963 		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12964 			ddi_prop_free(bytes);
12965 			continue;
12966 		}
12967 
12968 		ddi_prop_free(bytes);
12969 
12970 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12971 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12972 		    &nwords) != DDI_PROP_SUCCESS) {
12973 			continue;
12974 		}
12975 
12976 		if (nwords != 1 || words == NULL) {
12977 			if (words != NULL) {
12978 				ddi_prop_free(words);
12979 			}
12980 			continue;
12981 		}
12982 		ASSERT(words != NULL);
12983 
12984 		/*
12985 		 * If there is no hard address - We might have to deal with
12986 		 * that by using WWN - Having said that it is important to
12987 		 * recognize this problem early so ssd can be informed of
12988 		 * the right interconnect type.
12989 		 */
12990 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12991 		    ptgt->tgt_hard_addr != 0) {
12992 			tgt_id =
12993 			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12994 		} else {
12995 			tgt_id = ptgt->tgt_d_id;
12996 		}
12997 
12998 		if (tgt_id != (uint32_t)*words) {
12999 			ddi_prop_free(words);
13000 			continue;
13001 		}
13002 		ddi_prop_free(words);
13003 
13004 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13005 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13006 		    &nwords) != DDI_PROP_SUCCESS) {
13007 			continue;
13008 		}
13009 
13010 		if (nwords != 1 || words == NULL) {
13011 			if (words != NULL) {
13012 				ddi_prop_free(words);
13013 			}
13014 			continue;
13015 		}
13016 		ASSERT(words != NULL);
13017 
13018 		if (plun->lun_num == (uint16_t)*words) {
13019 			ddi_prop_free(words);
13020 			break;
13021 		}
13022 		ddi_prop_free(words);
13023 	}
13024 	ndi_devi_exit(pdip, circular);
13025 
13026 	return (cdip);
13027 }
13028 
13029 
13030 static int
13031 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13032 {
13033 	dev_info_t	*pdip;
13034 	char		buf[MAXNAMELEN];
13035 	char		uaddr[MAXNAMELEN];
13036 	int		rval = FC_FAILURE;
13037 
13038 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13039 
13040 	pdip = plun->lun_tgt->tgt_port->port_dip;
13041 
13042 	/*
13043 	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13044 	 * non-NULL even when the LUN is not there as in the case when a LUN is
13045 	 * configured and then deleted on the device end (for T3/T4 case). In
13046 	 * such cases, pip will be NULL.
13047 	 *
13048 	 * If the device generates an RSCN, it will end up getting offlined when
13049 	 * it disappeared and a new LUN will get created when it is rediscovered
13050 	 * on the device. If we check for lun_cip here, the LUN will not end
13051 	 * up getting onlined since this function will end up returning a
13052 	 * FC_SUCCESS.
13053 	 *
13054 	 * The behavior is different on other devices. For instance, on a HDS,
13055 	 * there was no RSCN generated by the device but the next I/O generated
13056 	 * a check condition and rediscovery got triggered that way. So, in
13057 	 * such cases, this path will not be exercised
13058 	 */
13059 	if (pip == NULL) {
13060 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13061 		    fcp_trace, FCP_BUF_LEVEL_4, 0,
13062 		    "fcp_is_pip_present: plun->lun_cip is NULL: "
13063 		    "plun: %p lun state: %x num: %d target state: %x",
13064 		    plun, plun->lun_state, plun->lun_num,
13065 		    plun->lun_tgt->tgt_port->port_state);
13066 		return (rval);
13067 	}
13068 
13069 	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13070 
13071 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13072 
13073 	if (plun->lun_old_guid) {
13074 		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13075 			rval = FC_SUCCESS;
13076 		}
13077 	} else {
13078 		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13079 			rval = FC_SUCCESS;
13080 		}
13081 	}
13082 	return (rval);
13083 }
13084 
13085 static mdi_pathinfo_t *
13086 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13087 {
13088 	char			buf[MAXNAMELEN];
13089 	char			uaddr[MAXNAMELEN];
13090 	mdi_pathinfo_t		*pip;
13091 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13092 	struct fcp_port	*pptr = ptgt->tgt_port;
13093 
13094 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13095 
13096 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13097 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13098 
13099 	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13100 
13101 	return (pip);
13102 }
13103 
13104 
13105 static int
13106 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13107     int tcount, int flags, int *circ)
13108 {
13109 	int			rval;
13110 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13111 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13112 	dev_info_t		*cdip = NULL;
13113 
13114 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13115 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13116 
13117 	if (plun->lun_cip == NULL) {
13118 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13119 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13120 		    "fcp_online_child: plun->lun_cip is NULL: "
13121 		    "plun: %p state: %x num: %d target state: %x",
13122 		    plun, plun->lun_state, plun->lun_num,
13123 		    plun->lun_tgt->tgt_port->port_state);
13124 		return (NDI_FAILURE);
13125 	}
13126 again:
13127 	if (plun->lun_mpxio == 0) {
13128 		cdip = DIP(cip);
13129 		mutex_exit(&plun->lun_mutex);
13130 		mutex_exit(&pptr->port_mutex);
13131 
13132 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13133 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13134 		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13135 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13136 
13137 		/*
13138 		 * We could check for FCP_LUN_INIT here but chances
13139 		 * of getting here when it's already in FCP_LUN_INIT
13140 		 * is rare and a duplicate ndi_devi_online wouldn't
13141 		 * hurt either (as the node would already have been
13142 		 * in CF2)
13143 		 */
13144 		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13145 			rval = ndi_devi_bind_driver(cdip, flags);
13146 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13147 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13148 			    "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13149 		} else {
13150 			rval = ndi_devi_online(cdip, flags);
13151 		}
13152 
13153 		/*
13154 		 * We log the message into trace buffer if the device
13155 		 * is "ses" and into syslog for any other device
13156 		 * type. This is to prevent the ndi_devi_online failure
13157 		 * message that appears for V880/A5K ses devices.
13158 		 */
13159 		if (rval == NDI_SUCCESS) {
13160 			mutex_enter(&ptgt->tgt_mutex);
13161 			plun->lun_state |= FCP_LUN_INIT;
13162 			mutex_exit(&ptgt->tgt_mutex);
13163 		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13164 			fcp_log(CE_NOTE, pptr->port_dip,
13165 			    "!ndi_devi_online:"
13166 			    " failed for %s: target=%x lun=%x %x",
13167 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13168 			    plun->lun_num, rval);
13169 		} else {
13170 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13171 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13172 			    " !ndi_devi_online:"
13173 			    " failed for %s: target=%x lun=%x %x",
13174 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13175 			    plun->lun_num, rval);
13176 		}
13177 	} else {
13178 		cdip = mdi_pi_get_client(PIP(cip));
13179 		mutex_exit(&plun->lun_mutex);
13180 		mutex_exit(&pptr->port_mutex);
13181 
13182 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13183 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13184 		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13185 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13186 
13187 		/*
13188 		 * Hold path and exit phci to avoid deadlock with power
13189 		 * management code during mdi_pi_online.
13190 		 */
13191 		mdi_hold_path(PIP(cip));
13192 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13193 
13194 		rval = mdi_pi_online(PIP(cip), flags);
13195 
13196 		mdi_devi_enter_phci(pptr->port_dip, circ);
13197 		mdi_rele_path(PIP(cip));
13198 
13199 		if (rval == MDI_SUCCESS) {
13200 			mutex_enter(&ptgt->tgt_mutex);
13201 			plun->lun_state |= FCP_LUN_INIT;
13202 			mutex_exit(&ptgt->tgt_mutex);
13203 
13204 			/*
13205 			 * Clear MPxIO path permanent disable in case
13206 			 * fcp hotplug dropped the offline event.
13207 			 */
13208 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13209 
13210 		} else if (rval == MDI_NOT_SUPPORTED) {
13211 			child_info_t	*old_cip = cip;
13212 
13213 			/*
13214 			 * MPxIO does not support this device yet.
13215 			 * Enumerate in legacy mode.
13216 			 */
13217 			mutex_enter(&pptr->port_mutex);
13218 			mutex_enter(&plun->lun_mutex);
13219 			plun->lun_mpxio = 0;
13220 			plun->lun_cip = NULL;
13221 			cdip = fcp_create_dip(plun, lcount, tcount);
13222 			plun->lun_cip = cip = CIP(cdip);
13223 			if (cip == NULL) {
13224 				fcp_log(CE_WARN, pptr->port_dip,
13225 				    "!fcp_online_child: "
13226 				    "Create devinfo failed for LU=%p", plun);
13227 				mutex_exit(&plun->lun_mutex);
13228 
13229 				mutex_enter(&ptgt->tgt_mutex);
13230 				plun->lun_state |= FCP_LUN_OFFLINE;
13231 				mutex_exit(&ptgt->tgt_mutex);
13232 
13233 				mutex_exit(&pptr->port_mutex);
13234 
13235 				/*
13236 				 * free the mdi_pathinfo node
13237 				 */
13238 				(void) mdi_pi_free(PIP(old_cip), 0);
13239 			} else {
13240 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13241 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13242 				    "fcp_online_child: creating devinfo "
13243 				    "node 0x%p for plun 0x%p",
13244 				    cip, plun);
13245 				mutex_exit(&plun->lun_mutex);
13246 				mutex_exit(&pptr->port_mutex);
13247 				/*
13248 				 * free the mdi_pathinfo node
13249 				 */
13250 				(void) mdi_pi_free(PIP(old_cip), 0);
13251 				mutex_enter(&pptr->port_mutex);
13252 				mutex_enter(&plun->lun_mutex);
13253 				goto again;
13254 			}
13255 		} else {
13256 			if (cdip) {
13257 				fcp_log(CE_NOTE, pptr->port_dip,
13258 				    "!fcp_online_child: mdi_pi_online:"
13259 				    " failed for %s: target=%x lun=%x %x",
13260 				    ddi_get_name(cdip), ptgt->tgt_d_id,
13261 				    plun->lun_num, rval);
13262 			}
13263 		}
13264 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13265 	}
13266 
13267 	if (rval == NDI_SUCCESS) {
13268 		if (cdip) {
13269 			(void) ndi_event_retrieve_cookie(
13270 			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13271 			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13272 			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13273 			    cdip, fcp_insert_eid, NULL);
13274 		}
13275 	}
13276 	mutex_enter(&pptr->port_mutex);
13277 	mutex_enter(&plun->lun_mutex);
13278 	return (rval);
13279 }
13280 
13281 /* ARGSUSED */
13282 static int
13283 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13284     int tcount, int flags, int *circ)
13285 {
13286 	int		rval;
13287 	int		lun_mpxio;
13288 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
13289 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13290 	dev_info_t	*cdip;
13291 
13292 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13293 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13294 
13295 	if (plun->lun_cip == NULL) {
13296 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13297 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13298 		    "fcp_offline_child: plun->lun_cip is NULL: "
13299 		    "plun: %p lun state: %x num: %d target state: %x",
13300 		    plun, plun->lun_state, plun->lun_num,
13301 		    plun->lun_tgt->tgt_port->port_state);
13302 		return (NDI_FAILURE);
13303 	}
13304 
13305 	/*
13306 	 * We will use this value twice. Make a copy to be sure we use
13307 	 * the same value in both places.
13308 	 */
13309 	lun_mpxio = plun->lun_mpxio;
13310 
13311 	if (lun_mpxio == 0) {
13312 		cdip = DIP(cip);
13313 		mutex_exit(&plun->lun_mutex);
13314 		mutex_exit(&pptr->port_mutex);
13315 		rval = ndi_devi_offline(DIP(cip), flags);
13316 		if (rval != NDI_SUCCESS) {
13317 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13318 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13319 			    "fcp_offline_child: ndi_devi_offline failed "
13320 			    "rval=%x cip=%p", rval, cip);
13321 		}
13322 	} else {
13323 		cdip = mdi_pi_get_client(PIP(cip));
13324 		mutex_exit(&plun->lun_mutex);
13325 		mutex_exit(&pptr->port_mutex);
13326 
13327 		/*
13328 		 * Exit phci to avoid deadlock with power management code
13329 		 * during mdi_pi_offline
13330 		 */
13331 		mdi_hold_path(PIP(cip));
13332 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13333 
13334 		rval = mdi_pi_offline(PIP(cip), flags);
13335 
13336 		mdi_devi_enter_phci(pptr->port_dip, circ);
13337 		mdi_rele_path(PIP(cip));
13338 
13339 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13340 	}
13341 
13342 	mutex_enter(&ptgt->tgt_mutex);
13343 	plun->lun_state &= ~FCP_LUN_INIT;
13344 	mutex_exit(&ptgt->tgt_mutex);
13345 
13346 	if (rval == NDI_SUCCESS) {
13347 		cdip = NULL;
13348 		if (flags & NDI_DEVI_REMOVE) {
13349 			mutex_enter(&plun->lun_mutex);
13350 			/*
13351 			 * If the guid of the LUN changes, lun_cip will not
13352 			 * equal to cip, and after offlining the LUN with the
13353 			 * old guid, we should keep lun_cip since it's the cip
13354 			 * of the LUN with the new guid.
13355 			 * Otherwise remove our reference to child node.
13356 			 *
13357 			 * This must be done before the child node is freed,
13358 			 * otherwise other threads could see a stale lun_cip
13359 			 * pointer.
13360 			 */
13361 			if (plun->lun_cip == cip) {
13362 				plun->lun_cip = NULL;
13363 			}
13364 			if (plun->lun_old_guid) {
13365 				kmem_free(plun->lun_old_guid,
13366 				    plun->lun_old_guid_size);
13367 				plun->lun_old_guid = NULL;
13368 				plun->lun_old_guid_size = 0;
13369 			}
13370 			mutex_exit(&plun->lun_mutex);
13371 		}
13372 	}
13373 
13374 	if (lun_mpxio != 0) {
13375 		if (rval == NDI_SUCCESS) {
13376 			/*
13377 			 * Clear MPxIO path permanent disable as the path is
13378 			 * already offlined.
13379 			 */
13380 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13381 
13382 			if (flags & NDI_DEVI_REMOVE) {
13383 				(void) mdi_pi_free(PIP(cip), 0);
13384 			}
13385 		} else {
13386 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13387 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13388 			    "fcp_offline_child: mdi_pi_offline failed "
13389 			    "rval=%x cip=%p", rval, cip);
13390 		}
13391 	}
13392 
13393 	mutex_enter(&pptr->port_mutex);
13394 	mutex_enter(&plun->lun_mutex);
13395 
13396 	if (cdip) {
13397 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13398 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13399 		    " target=%x lun=%x", "ndi_offline",
13400 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13401 	}
13402 
13403 	return (rval);
13404 }
13405 
13406 static void
13407 fcp_remove_child(struct fcp_lun *plun)
13408 {
13409 	child_info_t *cip;
13410 	int circ;
13411 
13412 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13413 
13414 	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13415 		if (plun->lun_mpxio == 0) {
13416 			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13417 			(void) ndi_devi_free(DIP(plun->lun_cip));
13418 			plun->lun_cip = NULL;
13419 		} else {
13420 			/*
13421 			 * Clear reference to the child node in the lun.
13422 			 * This must be done before freeing it with mdi_pi_free
13423 			 * and with lun_mutex held so that other threads always
13424 			 * see either valid lun_cip or NULL when holding
13425 			 * lun_mutex. We keep a copy in cip.
13426 			 */
13427 			cip = plun->lun_cip;
13428 			plun->lun_cip = NULL;
13429 
13430 			mutex_exit(&plun->lun_mutex);
13431 			mutex_exit(&plun->lun_tgt->tgt_mutex);
13432 			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13433 
13434 			mdi_devi_enter(
13435 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13436 
13437 			/*
13438 			 * Exit phci to avoid deadlock with power management
13439 			 * code during mdi_pi_offline
13440 			 */
13441 			mdi_hold_path(PIP(cip));
13442 			mdi_devi_exit_phci(
13443 			    plun->lun_tgt->tgt_port->port_dip, circ);
13444 			(void) mdi_pi_offline(PIP(cip),
13445 			    NDI_DEVI_REMOVE);
13446 			mdi_devi_enter_phci(
13447 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13448 			mdi_rele_path(PIP(cip));
13449 
13450 			mdi_devi_exit(
13451 			    plun->lun_tgt->tgt_port->port_dip, circ);
13452 
13453 			FCP_TRACE(fcp_logq,
13454 			    plun->lun_tgt->tgt_port->port_instbuf,
13455 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13456 			    "lun=%p pip freed %p", plun, cip);
13457 
13458 			(void) mdi_prop_remove(PIP(cip), NULL);
13459 			(void) mdi_pi_free(PIP(cip), 0);
13460 
13461 			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13462 			mutex_enter(&plun->lun_tgt->tgt_mutex);
13463 			mutex_enter(&plun->lun_mutex);
13464 		}
13465 	} else {
13466 		plun->lun_cip = NULL;
13467 	}
13468 }
13469 
13470 /*
13471  * called when a timeout occurs
13472  *
13473  * can be scheduled during an attach or resume (if not already running)
13474  *
13475  * one timeout is set up for all ports
13476  *
13477  * acquires and releases the global mutex
13478  */
13479 /*ARGSUSED*/
13480 static void
13481 fcp_watch(void *arg)
13482 {
13483 	struct fcp_port	*pptr;
13484 	struct fcp_ipkt	*icmd;
13485 	struct fcp_ipkt	*nicmd;
13486 	struct fcp_pkt	*cmd;
13487 	struct fcp_pkt	*ncmd;
13488 	struct fcp_pkt	*tail;
13489 	struct fcp_pkt	*pcmd;
13490 	struct fcp_pkt	*save_head;
13491 	struct fcp_port	*save_port;
13492 
13493 	/* increment global watchdog time */
13494 	fcp_watchdog_time += fcp_watchdog_timeout;
13495 
13496 	mutex_enter(&fcp_global_mutex);
13497 
13498 	/* scan each port in our list */
13499 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13500 		save_port = fcp_port_head;
13501 		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13502 		mutex_exit(&fcp_global_mutex);
13503 
13504 		mutex_enter(&pptr->port_mutex);
13505 		if (pptr->port_ipkt_list == NULL &&
13506 		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13507 		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13508 			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13509 			mutex_exit(&pptr->port_mutex);
13510 			mutex_enter(&fcp_global_mutex);
13511 			goto end_of_watchdog;
13512 		}
13513 
13514 		/*
13515 		 * We check if a list of targets need to be offlined.
13516 		 */
13517 		if (pptr->port_offline_tgts) {
13518 			fcp_scan_offline_tgts(pptr);
13519 		}
13520 
13521 		/*
13522 		 * We check if a list of luns need to be offlined.
13523 		 */
13524 		if (pptr->port_offline_luns) {
13525 			fcp_scan_offline_luns(pptr);
13526 		}
13527 
13528 		/*
13529 		 * We check if a list of targets or luns need to be reset.
13530 		 */
13531 		if (pptr->port_reset_list) {
13532 			fcp_check_reset_delay(pptr);
13533 		}
13534 
13535 		mutex_exit(&pptr->port_mutex);
13536 
13537 		/*
13538 		 * This is where the pending commands (pkt) are checked for
13539 		 * timeout.
13540 		 */
13541 		mutex_enter(&pptr->port_pkt_mutex);
13542 		tail = pptr->port_pkt_tail;
13543 
13544 		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13545 		    cmd != NULL; cmd = ncmd) {
13546 			ncmd = cmd->cmd_next;
13547 			/*
13548 			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13549 			 * must be set.
13550 			 */
13551 			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13552 			/*
13553 			 * FCP_INVALID_TIMEOUT will be set for those
13554 			 * command that need to be failed. Mostly those
13555 			 * cmds that could not be queued down for the
13556 			 * "timeout" value. cmd->cmd_timeout is used
13557 			 * to try and requeue the command regularly.
13558 			 */
13559 			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13560 				/*
13561 				 * This command hasn't timed out yet.  Let's
13562 				 * go to the next one.
13563 				 */
13564 				pcmd = cmd;
13565 				goto end_of_loop;
13566 			}
13567 
13568 			if (cmd == pptr->port_pkt_head) {
13569 				ASSERT(pcmd == NULL);
13570 				pptr->port_pkt_head = cmd->cmd_next;
13571 			} else {
13572 				ASSERT(pcmd != NULL);
13573 				pcmd->cmd_next = cmd->cmd_next;
13574 			}
13575 
13576 			if (cmd == pptr->port_pkt_tail) {
13577 				ASSERT(cmd->cmd_next == NULL);
13578 				pptr->port_pkt_tail = pcmd;
13579 				if (pcmd) {
13580 					pcmd->cmd_next = NULL;
13581 				}
13582 			}
13583 			cmd->cmd_next = NULL;
13584 
13585 			/*
13586 			 * save the current head before dropping the
13587 			 * mutex - If the head doesn't remain the
13588 			 * same after re acquiring the mutex, just
13589 			 * bail out and revisit on next tick.
13590 			 *
13591 			 * PS: The tail pointer can change as the commands
13592 			 * get requeued after failure to retransport
13593 			 */
13594 			save_head = pptr->port_pkt_head;
13595 			mutex_exit(&pptr->port_pkt_mutex);
13596 
13597 			if (cmd->cmd_fp_pkt->pkt_timeout ==
13598 			    FCP_INVALID_TIMEOUT) {
13599 				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13600 				struct fcp_lun	*plun;
13601 				struct fcp_tgt	*ptgt;
13602 
13603 				plun = ADDR2LUN(&pkt->pkt_address);
13604 				ptgt = plun->lun_tgt;
13605 
13606 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13607 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13608 				    "SCSI cmd 0x%x to D_ID=%x timed out",
13609 				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13610 
13611 				cmd->cmd_state == FCP_PKT_ABORTING ?
13612 				    fcp_fail_cmd(cmd, CMD_RESET,
13613 				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13614 				    CMD_TIMEOUT, STAT_ABORTED);
13615 			} else {
13616 				fcp_retransport_cmd(pptr, cmd);
13617 			}
13618 			mutex_enter(&pptr->port_pkt_mutex);
13619 			if (save_head && save_head != pptr->port_pkt_head) {
13620 				/*
13621 				 * Looks like linked list got changed (mostly
13622 				 * happens when an an OFFLINE LUN code starts
13623 				 * returning overflow queue commands in
13624 				 * parallel. So bail out and revisit during
13625 				 * next tick
13626 				 */
13627 				break;
13628 			}
13629 		end_of_loop:
13630 			/*
13631 			 * Scan only upto the previously known tail pointer
13632 			 * to avoid excessive processing - lots of new packets
13633 			 * could have been added to the tail or the old ones
13634 			 * re-queued.
13635 			 */
13636 			if (cmd == tail) {
13637 				break;
13638 			}
13639 		}
13640 		mutex_exit(&pptr->port_pkt_mutex);
13641 
13642 		mutex_enter(&pptr->port_mutex);
13643 		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13644 			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13645 
13646 			nicmd = icmd->ipkt_next;
13647 			if ((icmd->ipkt_restart != 0) &&
13648 			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13649 				/* packet has not timed out */
13650 				continue;
13651 			}
13652 
13653 			/* time for packet re-transport */
13654 			if (icmd == pptr->port_ipkt_list) {
13655 				pptr->port_ipkt_list = icmd->ipkt_next;
13656 				if (pptr->port_ipkt_list) {
13657 					pptr->port_ipkt_list->ipkt_prev =
13658 					    NULL;
13659 				}
13660 			} else {
13661 				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13662 				if (icmd->ipkt_next) {
13663 					icmd->ipkt_next->ipkt_prev =
13664 					    icmd->ipkt_prev;
13665 				}
13666 			}
13667 			icmd->ipkt_next = NULL;
13668 			icmd->ipkt_prev = NULL;
13669 			mutex_exit(&pptr->port_mutex);
13670 
13671 			if (fcp_is_retryable(icmd)) {
13672 				fc_ulp_rscn_info_t *rscnp =
13673 				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13674 				    pkt_ulp_rscn_infop;
13675 
13676 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13677 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13678 				    "%x to D_ID=%x Retrying..",
13679 				    icmd->ipkt_opcode,
13680 				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13681 
13682 				/*
13683 				 * Update the RSCN count in the packet
13684 				 * before resending.
13685 				 */
13686 
13687 				if (rscnp != NULL) {
13688 					rscnp->ulp_rscn_count =
13689 					    fc_ulp_get_rscn_count(pptr->
13690 					    port_fp_handle);
13691 				}
13692 
13693 				mutex_enter(&pptr->port_mutex);
13694 				mutex_enter(&ptgt->tgt_mutex);
13695 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13696 					mutex_exit(&ptgt->tgt_mutex);
13697 					mutex_exit(&pptr->port_mutex);
13698 					switch (icmd->ipkt_opcode) {
13699 						int rval;
13700 					case LA_ELS_PLOGI:
13701 						if ((rval = fc_ulp_login(
13702 						    pptr->port_fp_handle,
13703 						    &icmd->ipkt_fpkt, 1)) ==
13704 						    FC_SUCCESS) {
13705 							mutex_enter(
13706 							    &pptr->port_mutex);
13707 							continue;
13708 						}
13709 						if (fcp_handle_ipkt_errors(
13710 						    pptr, ptgt, icmd, rval,
13711 						    "PLOGI") == DDI_SUCCESS) {
13712 							mutex_enter(
13713 							    &pptr->port_mutex);
13714 							continue;
13715 						}
13716 						break;
13717 
13718 					case LA_ELS_PRLI:
13719 						if ((rval = fc_ulp_issue_els(
13720 						    pptr->port_fp_handle,
13721 						    icmd->ipkt_fpkt)) ==
13722 						    FC_SUCCESS) {
13723 							mutex_enter(
13724 							    &pptr->port_mutex);
13725 							continue;
13726 						}
13727 						if (fcp_handle_ipkt_errors(
13728 						    pptr, ptgt, icmd, rval,
13729 						    "PRLI") == DDI_SUCCESS) {
13730 							mutex_enter(
13731 							    &pptr->port_mutex);
13732 							continue;
13733 						}
13734 						break;
13735 
13736 					default:
13737 						if ((rval = fcp_transport(
13738 						    pptr->port_fp_handle,
13739 						    icmd->ipkt_fpkt, 1)) ==
13740 						    FC_SUCCESS) {
13741 							mutex_enter(
13742 							    &pptr->port_mutex);
13743 							continue;
13744 						}
13745 						if (fcp_handle_ipkt_errors(
13746 						    pptr, ptgt, icmd, rval,
13747 						    "PRLI") == DDI_SUCCESS) {
13748 							mutex_enter(
13749 							    &pptr->port_mutex);
13750 							continue;
13751 						}
13752 						break;
13753 					}
13754 				} else {
13755 					mutex_exit(&ptgt->tgt_mutex);
13756 					mutex_exit(&pptr->port_mutex);
13757 				}
13758 			} else {
13759 				fcp_print_error(icmd->ipkt_fpkt);
13760 			}
13761 
13762 			(void) fcp_call_finish_init(pptr, ptgt,
13763 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13764 			    icmd->ipkt_cause);
13765 			fcp_icmd_free(pptr, icmd);
13766 			mutex_enter(&pptr->port_mutex);
13767 		}
13768 
13769 		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13770 		mutex_exit(&pptr->port_mutex);
13771 		mutex_enter(&fcp_global_mutex);
13772 
13773 	end_of_watchdog:
13774 		/*
13775 		 * Bail out early before getting into trouble
13776 		 */
13777 		if (save_port != fcp_port_head) {
13778 			break;
13779 		}
13780 	}
13781 
13782 	if (fcp_watchdog_init > 0) {
13783 		/* reschedule timeout to go again */
13784 		fcp_watchdog_id =
13785 		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13786 	}
13787 	mutex_exit(&fcp_global_mutex);
13788 }
13789 
13790 
13791 static void
13792 fcp_check_reset_delay(struct fcp_port *pptr)
13793 {
13794 	uint32_t		tgt_cnt;
13795 	int			level;
13796 	struct fcp_tgt	*ptgt;
13797 	struct fcp_lun	*plun;
13798 	struct fcp_reset_elem *cur = NULL;
13799 	struct fcp_reset_elem *next = NULL;
13800 	struct fcp_reset_elem *prev = NULL;
13801 
13802 	ASSERT(mutex_owned(&pptr->port_mutex));
13803 
13804 	next = pptr->port_reset_list;
13805 	while ((cur = next) != NULL) {
13806 		next = cur->next;
13807 
13808 		if (cur->timeout < fcp_watchdog_time) {
13809 			prev = cur;
13810 			continue;
13811 		}
13812 
13813 		ptgt = cur->tgt;
13814 		plun = cur->lun;
13815 		tgt_cnt = cur->tgt_cnt;
13816 
13817 		if (ptgt) {
13818 			level = RESET_TARGET;
13819 		} else {
13820 			ASSERT(plun != NULL);
13821 			level = RESET_LUN;
13822 			ptgt = plun->lun_tgt;
13823 		}
13824 		if (prev) {
13825 			prev->next = next;
13826 		} else {
13827 			/*
13828 			 * Because we drop port mutex while doing aborts for
13829 			 * packets, we can't rely on reset_list pointing to
13830 			 * our head
13831 			 */
13832 			if (cur == pptr->port_reset_list) {
13833 				pptr->port_reset_list = next;
13834 			} else {
13835 				struct fcp_reset_elem *which;
13836 
13837 				which = pptr->port_reset_list;
13838 				while (which && which->next != cur) {
13839 					which = which->next;
13840 				}
13841 				ASSERT(which != NULL);
13842 
13843 				which->next = next;
13844 				prev = which;
13845 			}
13846 		}
13847 
13848 		kmem_free(cur, sizeof (*cur));
13849 
13850 		if (tgt_cnt == ptgt->tgt_change_cnt) {
13851 			mutex_enter(&ptgt->tgt_mutex);
13852 			if (level == RESET_TARGET) {
13853 				fcp_update_tgt_state(ptgt,
13854 				    FCP_RESET, FCP_LUN_BUSY);
13855 			} else {
13856 				fcp_update_lun_state(plun,
13857 				    FCP_RESET, FCP_LUN_BUSY);
13858 			}
13859 			mutex_exit(&ptgt->tgt_mutex);
13860 
13861 			mutex_exit(&pptr->port_mutex);
13862 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13863 			mutex_enter(&pptr->port_mutex);
13864 		}
13865 	}
13866 }
13867 
13868 
13869 static void
13870 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13871     struct fcp_lun *rlun, int tgt_cnt)
13872 {
13873 	int			rval;
13874 	struct fcp_lun	*tlun, *nlun;
13875 	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13876 	    *cmd = NULL, *head = NULL,
13877 	    *tail = NULL;
13878 
13879 	mutex_enter(&pptr->port_pkt_mutex);
13880 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13881 		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13882 		struct fcp_tgt *ptgt = plun->lun_tgt;
13883 
13884 		ncmd = cmd->cmd_next;
13885 
13886 		if (ptgt != ttgt && plun != rlun) {
13887 			pcmd = cmd;
13888 			continue;
13889 		}
13890 
13891 		if (pcmd != NULL) {
13892 			ASSERT(pptr->port_pkt_head != cmd);
13893 			pcmd->cmd_next = ncmd;
13894 		} else {
13895 			ASSERT(cmd == pptr->port_pkt_head);
13896 			pptr->port_pkt_head = ncmd;
13897 		}
13898 		if (pptr->port_pkt_tail == cmd) {
13899 			ASSERT(cmd->cmd_next == NULL);
13900 			pptr->port_pkt_tail = pcmd;
13901 			if (pcmd != NULL) {
13902 				pcmd->cmd_next = NULL;
13903 			}
13904 		}
13905 
13906 		if (head == NULL) {
13907 			head = tail = cmd;
13908 		} else {
13909 			ASSERT(tail != NULL);
13910 			tail->cmd_next = cmd;
13911 			tail = cmd;
13912 		}
13913 		cmd->cmd_next = NULL;
13914 	}
13915 	mutex_exit(&pptr->port_pkt_mutex);
13916 
13917 	for (cmd = head; cmd != NULL; cmd = ncmd) {
13918 		struct scsi_pkt *pkt = cmd->cmd_pkt;
13919 
13920 		ncmd = cmd->cmd_next;
13921 		ASSERT(pkt != NULL);
13922 
13923 		mutex_enter(&pptr->port_mutex);
13924 		if (ttgt->tgt_change_cnt == tgt_cnt) {
13925 			mutex_exit(&pptr->port_mutex);
13926 			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13927 			pkt->pkt_reason = CMD_RESET;
13928 			pkt->pkt_statistics |= STAT_DEV_RESET;
13929 			cmd->cmd_state = FCP_PKT_IDLE;
13930 			fcp_post_callback(cmd);
13931 		} else {
13932 			mutex_exit(&pptr->port_mutex);
13933 		}
13934 	}
13935 
13936 	/*
13937 	 * If the FCA will return all the commands in its queue then our
13938 	 * work is easy, just return.
13939 	 */
13940 
13941 	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13942 		return;
13943 	}
13944 
13945 	/*
13946 	 * For RESET_LUN get hold of target pointer
13947 	 */
13948 	if (ttgt == NULL) {
13949 		ASSERT(rlun != NULL);
13950 
13951 		ttgt = rlun->lun_tgt;
13952 
13953 		ASSERT(ttgt != NULL);
13954 	}
13955 
13956 	/*
13957 	 * There are some severe race conditions here.
13958 	 * While we are trying to abort the pkt, it might be completing
13959 	 * so mark it aborted and if the abort does not succeed then
13960 	 * handle it in the watch thread.
13961 	 */
13962 	mutex_enter(&ttgt->tgt_mutex);
13963 	nlun = ttgt->tgt_lun;
13964 	mutex_exit(&ttgt->tgt_mutex);
13965 	while ((tlun = nlun) != NULL) {
13966 		int restart = 0;
13967 		if (rlun && rlun != tlun) {
13968 			mutex_enter(&ttgt->tgt_mutex);
13969 			nlun = tlun->lun_next;
13970 			mutex_exit(&ttgt->tgt_mutex);
13971 			continue;
13972 		}
13973 		mutex_enter(&tlun->lun_mutex);
13974 		cmd = tlun->lun_pkt_head;
13975 		while (cmd != NULL) {
13976 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13977 				struct scsi_pkt *pkt;
13978 
13979 				restart = 1;
13980 				cmd->cmd_state = FCP_PKT_ABORTING;
13981 				mutex_exit(&tlun->lun_mutex);
13982 				rval = fc_ulp_abort(pptr->port_fp_handle,
13983 				    cmd->cmd_fp_pkt, KM_SLEEP);
13984 				if (rval == FC_SUCCESS) {
13985 					pkt = cmd->cmd_pkt;
13986 					pkt->pkt_reason = CMD_RESET;
13987 					pkt->pkt_statistics |= STAT_DEV_RESET;
13988 					cmd->cmd_state = FCP_PKT_IDLE;
13989 					fcp_post_callback(cmd);
13990 				} else {
13991 					caddr_t msg;
13992 
13993 					(void) fc_ulp_error(rval, &msg);
13994 
13995 					/*
13996 					 * This part is tricky. The abort
13997 					 * failed and now the command could
13998 					 * be completing.  The cmd_state ==
13999 					 * FCP_PKT_ABORTING should save
14000 					 * us in fcp_cmd_callback. If we
14001 					 * are already aborting ignore the
14002 					 * command in fcp_cmd_callback.
14003 					 * Here we leave this packet for 20
14004 					 * sec to be aborted in the
14005 					 * fcp_watch thread.
14006 					 */
14007 					fcp_log(CE_WARN, pptr->port_dip,
14008 					    "!Abort failed after reset %s",
14009 					    msg);
14010 
14011 					cmd->cmd_timeout =
14012 					    fcp_watchdog_time +
14013 					    cmd->cmd_pkt->pkt_time +
14014 					    FCP_FAILED_DELAY;
14015 
14016 					cmd->cmd_fp_pkt->pkt_timeout =
14017 					    FCP_INVALID_TIMEOUT;
14018 					/*
14019 					 * This is a hack, cmd is put in the
14020 					 * overflow queue so that it can be
14021 					 * timed out finally
14022 					 */
14023 					cmd->cmd_flags |= CFLAG_IN_QUEUE;
14024 
14025 					mutex_enter(&pptr->port_pkt_mutex);
14026 					if (pptr->port_pkt_head) {
14027 						ASSERT(pptr->port_pkt_tail
14028 						    != NULL);
14029 						pptr->port_pkt_tail->cmd_next
14030 						    = cmd;
14031 						pptr->port_pkt_tail = cmd;
14032 					} else {
14033 						ASSERT(pptr->port_pkt_tail
14034 						    == NULL);
14035 						pptr->port_pkt_head =
14036 						    pptr->port_pkt_tail
14037 						    = cmd;
14038 					}
14039 					cmd->cmd_next = NULL;
14040 					mutex_exit(&pptr->port_pkt_mutex);
14041 				}
14042 				mutex_enter(&tlun->lun_mutex);
14043 				cmd = tlun->lun_pkt_head;
14044 			} else {
14045 				cmd = cmd->cmd_forw;
14046 			}
14047 		}
14048 		mutex_exit(&tlun->lun_mutex);
14049 
14050 		mutex_enter(&ttgt->tgt_mutex);
14051 		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14052 		mutex_exit(&ttgt->tgt_mutex);
14053 
14054 		mutex_enter(&pptr->port_mutex);
14055 		if (tgt_cnt != ttgt->tgt_change_cnt) {
14056 			mutex_exit(&pptr->port_mutex);
14057 			return;
14058 		} else {
14059 			mutex_exit(&pptr->port_mutex);
14060 		}
14061 	}
14062 }
14063 
14064 
14065 /*
14066  * unlink the soft state, returning the soft state found (if any)
14067  *
14068  * acquires and releases the global mutex
14069  */
14070 struct fcp_port *
14071 fcp_soft_state_unlink(struct fcp_port *pptr)
14072 {
14073 	struct fcp_port	*hptr;		/* ptr index */
14074 	struct fcp_port	*tptr;		/* prev hptr */
14075 
14076 	mutex_enter(&fcp_global_mutex);
14077 	for (hptr = fcp_port_head, tptr = NULL;
14078 	    hptr != NULL;
14079 	    tptr = hptr, hptr = hptr->port_next) {
14080 		if (hptr == pptr) {
14081 			/* we found a match -- remove this item */
14082 			if (tptr == NULL) {
14083 				/* we're at the head of the list */
14084 				fcp_port_head = hptr->port_next;
14085 			} else {
14086 				tptr->port_next = hptr->port_next;
14087 			}
14088 			break;			/* success */
14089 		}
14090 	}
14091 	if (fcp_port_head == NULL) {
14092 		fcp_cleanup_blacklist(&fcp_lun_blacklist);
14093 	}
14094 	mutex_exit(&fcp_global_mutex);
14095 	return (hptr);
14096 }
14097 
14098 
14099 /*
14100  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14101  * WWN and a LUN number
14102  */
14103 /* ARGSUSED */
14104 static struct fcp_lun *
14105 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14106 {
14107 	int hash;
14108 	struct fcp_tgt *ptgt;
14109 	struct fcp_lun *plun;
14110 
14111 	ASSERT(mutex_owned(&pptr->port_mutex));
14112 
14113 	hash = FCP_HASH(wwn);
14114 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14115 	    ptgt = ptgt->tgt_next) {
14116 		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14117 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
14118 			mutex_enter(&ptgt->tgt_mutex);
14119 			for (plun = ptgt->tgt_lun;
14120 			    plun != NULL;
14121 			    plun = plun->lun_next) {
14122 				if (plun->lun_num == lun) {
14123 					mutex_exit(&ptgt->tgt_mutex);
14124 					return (plun);
14125 				}
14126 			}
14127 			mutex_exit(&ptgt->tgt_mutex);
14128 			return (NULL);
14129 		}
14130 	}
14131 	return (NULL);
14132 }
14133 
14134 /*
14135  *     Function: fcp_prepare_pkt
14136  *
14137  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14138  *		 for fcp_start(). It binds the data or partially maps it.
14139  *		 Builds the FCP header and starts the initialization of the
14140  *		 Fibre Channel header.
14141  *
14142  *     Argument: *pptr		FCP port.
14143  *		 *cmd		FCP packet.
14144  *		 *plun		LUN the command will be sent to.
14145  *
14146  *	Context: User, Kernel and Interrupt context.
14147  */
14148 static void
14149 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14150     struct fcp_lun *plun)
14151 {
14152 	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
14153 	struct fcp_tgt		*ptgt = plun->lun_tgt;
14154 	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
14155 
14156 	ASSERT(cmd->cmd_pkt->pkt_comp ||
14157 	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14158 
14159 	if (cmd->cmd_pkt->pkt_numcookies) {
14160 		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14161 			fcmd->fcp_cntl.cntl_read_data = 1;
14162 			fcmd->fcp_cntl.cntl_write_data = 0;
14163 			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14164 		} else {
14165 			fcmd->fcp_cntl.cntl_read_data = 0;
14166 			fcmd->fcp_cntl.cntl_write_data = 1;
14167 			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14168 		}
14169 
14170 		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14171 
14172 		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14173 		ASSERT(fpkt->pkt_data_cookie_cnt <=
14174 		    pptr->port_data_dma_attr.dma_attr_sgllen);
14175 
14176 		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14177 
14178 		/* FCA needs pkt_datalen to be set */
14179 		fpkt->pkt_datalen = cmd->cmd_dmacount;
14180 		fcmd->fcp_data_len = cmd->cmd_dmacount;
14181 	} else {
14182 		fcmd->fcp_cntl.cntl_read_data = 0;
14183 		fcmd->fcp_cntl.cntl_write_data = 0;
14184 		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14185 		fpkt->pkt_datalen = 0;
14186 		fcmd->fcp_data_len = 0;
14187 	}
14188 
14189 	/* set up the Tagged Queuing type */
14190 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14191 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14192 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14193 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14194 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14195 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14196 	} else {
14197 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14198 	}
14199 
14200 	fcmd->fcp_ent_addr = plun->lun_addr;
14201 
14202 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14203 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14204 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14205 	} else {
14206 		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14207 	}
14208 
14209 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14210 	cmd->cmd_pkt->pkt_state = 0;
14211 	cmd->cmd_pkt->pkt_statistics = 0;
14212 	cmd->cmd_pkt->pkt_resid = 0;
14213 
14214 	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14215 
14216 	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14217 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14218 		fpkt->pkt_comp = NULL;
14219 	} else {
14220 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14221 		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14222 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14223 		}
14224 		fpkt->pkt_comp = fcp_cmd_callback;
14225 	}
14226 
14227 	mutex_enter(&pptr->port_mutex);
14228 	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14229 		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14230 	}
14231 	mutex_exit(&pptr->port_mutex);
14232 
14233 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14234 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14235 
14236 	/*
14237 	 * Save a few kernel cycles here
14238 	 */
14239 #ifndef	__lock_lint
14240 	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14241 #endif /* __lock_lint */
14242 }
14243 
14244 static void
14245 fcp_post_callback(struct fcp_pkt *cmd)
14246 {
14247 	scsi_hba_pkt_comp(cmd->cmd_pkt);
14248 }
14249 
14250 
14251 /*
14252  * called to do polled I/O by fcp_start()
14253  *
14254  * return a transport status value, i.e. TRAN_ACCECPT for success
14255  */
14256 static int
14257 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14258 {
14259 	int	rval;
14260 
14261 #ifdef	DEBUG
14262 	mutex_enter(&pptr->port_pkt_mutex);
14263 	pptr->port_npkts++;
14264 	mutex_exit(&pptr->port_pkt_mutex);
14265 #endif /* DEBUG */
14266 
14267 	if (cmd->cmd_fp_pkt->pkt_timeout) {
14268 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14269 	} else {
14270 		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14271 	}
14272 
14273 	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14274 
14275 	cmd->cmd_state = FCP_PKT_ISSUED;
14276 
14277 	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14278 
14279 #ifdef	DEBUG
14280 	mutex_enter(&pptr->port_pkt_mutex);
14281 	pptr->port_npkts--;
14282 	mutex_exit(&pptr->port_pkt_mutex);
14283 #endif /* DEBUG */
14284 
14285 	cmd->cmd_state = FCP_PKT_IDLE;
14286 
14287 	switch (rval) {
14288 	case FC_SUCCESS:
14289 		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14290 			fcp_complete_pkt(cmd->cmd_fp_pkt);
14291 			rval = TRAN_ACCEPT;
14292 		} else {
14293 			rval = TRAN_FATAL_ERROR;
14294 		}
14295 		break;
14296 
14297 	case FC_TRAN_BUSY:
14298 		rval = TRAN_BUSY;
14299 		cmd->cmd_pkt->pkt_resid = 0;
14300 		break;
14301 
14302 	case FC_BADPACKET:
14303 		rval = TRAN_BADPKT;
14304 		break;
14305 
14306 	default:
14307 		rval = TRAN_FATAL_ERROR;
14308 		break;
14309 	}
14310 
14311 	return (rval);
14312 }
14313 
14314 
14315 /*
14316  * called by some of the following transport-called routines to convert
14317  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14318  */
14319 static struct fcp_port *
14320 fcp_dip2port(dev_info_t *dip)
14321 {
14322 	int	instance;
14323 
14324 	instance = ddi_get_instance(dip);
14325 	return (ddi_get_soft_state(fcp_softstate, instance));
14326 }
14327 
14328 
14329 /*
14330  * called internally to return a LUN given a dip
14331  */
14332 struct fcp_lun *
14333 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14334 {
14335 	struct fcp_tgt *ptgt;
14336 	struct fcp_lun *plun;
14337 	int i;
14338 
14339 
14340 	ASSERT(mutex_owned(&pptr->port_mutex));
14341 
14342 	for (i = 0; i < FCP_NUM_HASH; i++) {
14343 		for (ptgt = pptr->port_tgt_hash_table[i];
14344 		    ptgt != NULL;
14345 		    ptgt = ptgt->tgt_next) {
14346 			mutex_enter(&ptgt->tgt_mutex);
14347 			for (plun = ptgt->tgt_lun; plun != NULL;
14348 			    plun = plun->lun_next) {
14349 				mutex_enter(&plun->lun_mutex);
14350 				if (plun->lun_cip == cip) {
14351 					mutex_exit(&plun->lun_mutex);
14352 					mutex_exit(&ptgt->tgt_mutex);
14353 					return (plun); /* match found */
14354 				}
14355 				mutex_exit(&plun->lun_mutex);
14356 			}
14357 			mutex_exit(&ptgt->tgt_mutex);
14358 		}
14359 	}
14360 	return (NULL);				/* no LUN found */
14361 }
14362 
14363 /*
14364  * pass an element to the hotplug list, kick the hotplug thread
14365  * and wait for the element to get processed by the hotplug thread.
14366  * on return the element is freed.
14367  *
14368  * return zero success and non-zero on failure
14369  *
14370  * acquires/releases the target mutex
14371  *
14372  */
14373 static int
14374 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14375     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14376 {
14377 	struct fcp_hp_elem	*elem;
14378 	int			rval;
14379 
14380 	mutex_enter(&plun->lun_tgt->tgt_mutex);
14381 	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14382 	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14383 		mutex_exit(&plun->lun_tgt->tgt_mutex);
14384 		fcp_log(CE_CONT, pptr->port_dip,
14385 		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14386 		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14387 		return (NDI_FAILURE);
14388 	}
14389 	mutex_exit(&plun->lun_tgt->tgt_mutex);
14390 	mutex_enter(&elem->mutex);
14391 	if (elem->wait) {
14392 		while (elem->wait) {
14393 			cv_wait(&elem->cv, &elem->mutex);
14394 		}
14395 	}
14396 	rval = (elem->result);
14397 	mutex_exit(&elem->mutex);
14398 	mutex_destroy(&elem->mutex);
14399 	cv_destroy(&elem->cv);
14400 	kmem_free(elem, sizeof (struct fcp_hp_elem));
14401 	return (rval);
14402 }
14403 
14404 /*
14405  * pass an element to the hotplug list, and then
14406  * kick the hotplug thread
14407  *
14408  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14409  *
14410  * acquires/releases the hotplug mutex
14411  *
14412  * called with the target mutex owned
14413  *
14414  * memory acquired in NOSLEEP mode
14415  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14416  *	 for the hp daemon to process the request and is responsible for
14417  *	 freeing the element
14418  */
14419 static struct fcp_hp_elem *
14420 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14421     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14422 {
14423 	struct fcp_hp_elem	*elem;
14424 	dev_info_t *pdip;
14425 
14426 	ASSERT(pptr != NULL);
14427 	ASSERT(plun != NULL);
14428 	ASSERT(plun->lun_tgt != NULL);
14429 	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14430 
14431 	/* create space for a hotplug element */
14432 	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14433 	    == NULL) {
14434 		fcp_log(CE_WARN, NULL,
14435 		    "!can't allocate memory for hotplug element");
14436 		return (NULL);
14437 	}
14438 
14439 	/* fill in hotplug element */
14440 	elem->port = pptr;
14441 	elem->lun = plun;
14442 	elem->cip = cip;
14443 	elem->old_lun_mpxio = plun->lun_mpxio;
14444 	elem->what = what;
14445 	elem->flags = flags;
14446 	elem->link_cnt = link_cnt;
14447 	elem->tgt_cnt = tgt_cnt;
14448 	elem->wait = wait;
14449 	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14450 	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14451 
14452 	/* schedule the hotplug task */
14453 	pdip = pptr->port_dip;
14454 	mutex_enter(&plun->lun_mutex);
14455 	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14456 		plun->lun_event_count++;
14457 		elem->event_cnt = plun->lun_event_count;
14458 	}
14459 	mutex_exit(&plun->lun_mutex);
14460 	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14461 	    (void *)elem, KM_NOSLEEP) == TASKQID_INVALID) {
14462 		mutex_enter(&plun->lun_mutex);
14463 		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14464 			plun->lun_event_count--;
14465 		}
14466 		mutex_exit(&plun->lun_mutex);
14467 		kmem_free(elem, sizeof (*elem));
14468 		return (0);
14469 	}
14470 
14471 	return (elem);
14472 }
14473 
14474 
14475 static void
14476 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14477 {
14478 	int			rval;
14479 	struct scsi_address	*ap;
14480 	struct fcp_lun	*plun;
14481 	struct fcp_tgt	*ptgt;
14482 	fc_packet_t	*fpkt;
14483 
14484 	ap = &cmd->cmd_pkt->pkt_address;
14485 	plun = ADDR2LUN(ap);
14486 	ptgt = plun->lun_tgt;
14487 
14488 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14489 
14490 	cmd->cmd_state = FCP_PKT_IDLE;
14491 
14492 	mutex_enter(&pptr->port_mutex);
14493 	mutex_enter(&ptgt->tgt_mutex);
14494 	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14495 	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14496 		fc_ulp_rscn_info_t *rscnp;
14497 
14498 		cmd->cmd_state = FCP_PKT_ISSUED;
14499 
14500 		/*
14501 		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14502 		 * originally NULL, hence we try to set it to the pd pointed
14503 		 * to by the SCSI device we're trying to get to.
14504 		 */
14505 
14506 		fpkt = cmd->cmd_fp_pkt;
14507 		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14508 			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14509 			/*
14510 			 * We need to notify the transport that we now have a
14511 			 * reference to the remote port handle.
14512 			 */
14513 			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14514 		}
14515 
14516 		mutex_exit(&ptgt->tgt_mutex);
14517 		mutex_exit(&pptr->port_mutex);
14518 
14519 		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14520 
14521 		/* prepare the packet */
14522 
14523 		fcp_prepare_pkt(pptr, cmd, plun);
14524 
14525 		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14526 		    pkt_ulp_rscn_infop;
14527 
14528 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14529 		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14530 
14531 		if (rscnp != NULL) {
14532 			rscnp->ulp_rscn_count =
14533 			    fc_ulp_get_rscn_count(pptr->
14534 			    port_fp_handle);
14535 		}
14536 
14537 		rval = fcp_transport(pptr->port_fp_handle,
14538 		    cmd->cmd_fp_pkt, 0);
14539 
14540 		if (rval == FC_SUCCESS) {
14541 			return;
14542 		}
14543 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14544 	} else {
14545 		mutex_exit(&ptgt->tgt_mutex);
14546 		mutex_exit(&pptr->port_mutex);
14547 	}
14548 
14549 	fcp_queue_pkt(pptr, cmd);
14550 }
14551 
14552 
14553 static void
14554 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14555 {
14556 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14557 
14558 	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14559 	cmd->cmd_state = FCP_PKT_IDLE;
14560 
14561 	cmd->cmd_pkt->pkt_reason = reason;
14562 	cmd->cmd_pkt->pkt_state = 0;
14563 	cmd->cmd_pkt->pkt_statistics = statistics;
14564 
14565 	fcp_post_callback(cmd);
14566 }
14567 
14568 /*
14569  *     Function: fcp_queue_pkt
14570  *
14571  *  Description: This function queues the packet passed by the caller into
14572  *		 the list of packets of the FCP port.
14573  *
14574  *     Argument: *pptr		FCP port.
14575  *		 *cmd		FCP packet to queue.
14576  *
14577  * Return Value: None
14578  *
14579  *	Context: User, Kernel and Interrupt context.
14580  */
14581 static void
14582 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14583 {
14584 	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == 0);
14585 
14586 	mutex_enter(&pptr->port_pkt_mutex);
14587 	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14588 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14589 	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14590 
14591 	/*
14592 	 * zero pkt_time means hang around for ever
14593 	 */
14594 	if (cmd->cmd_pkt->pkt_time) {
14595 		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14596 			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14597 		} else {
14598 			/*
14599 			 * Indicate the watch thread to fail the
14600 			 * command by setting it to highest value
14601 			 */
14602 			cmd->cmd_timeout = fcp_watchdog_time;
14603 			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14604 		}
14605 	}
14606 
14607 	if (pptr->port_pkt_head) {
14608 		ASSERT(pptr->port_pkt_tail != NULL);
14609 
14610 		pptr->port_pkt_tail->cmd_next = cmd;
14611 		pptr->port_pkt_tail = cmd;
14612 	} else {
14613 		ASSERT(pptr->port_pkt_tail == NULL);
14614 
14615 		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14616 	}
14617 	cmd->cmd_next = NULL;
14618 	mutex_exit(&pptr->port_pkt_mutex);
14619 }
14620 
14621 /*
14622  *     Function: fcp_update_targets
14623  *
14624  *  Description: This function applies the specified change of state to all
14625  *		 the targets listed.  The operation applied is 'set'.
14626  *
14627  *     Argument: *pptr		FCP port.
14628  *		 *dev_list	Array of fc_portmap_t structures.
14629  *		 count		Length of dev_list.
14630  *		 state		State bits to update.
14631  *		 cause		Reason for the update.
14632  *
14633  * Return Value: None
14634  *
14635  *	Context: User, Kernel and Interrupt context.
14636  *		 The mutex pptr->port_mutex must be held.
14637  */
14638 static void
14639 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14640     uint32_t count, uint32_t state, int cause)
14641 {
14642 	fc_portmap_t		*map_entry;
14643 	struct fcp_tgt	*ptgt;
14644 
14645 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14646 
14647 	while (count--) {
14648 		map_entry = &(dev_list[count]);
14649 		ptgt = fcp_lookup_target(pptr,
14650 		    (uchar_t *)&(map_entry->map_pwwn));
14651 		if (ptgt == NULL) {
14652 			continue;
14653 		}
14654 
14655 		mutex_enter(&ptgt->tgt_mutex);
14656 		ptgt->tgt_trace = 0;
14657 		ptgt->tgt_change_cnt++;
14658 		ptgt->tgt_statec_cause = cause;
14659 		ptgt->tgt_tmp_cnt = 1;
14660 		fcp_update_tgt_state(ptgt, FCP_SET, state);
14661 		mutex_exit(&ptgt->tgt_mutex);
14662 	}
14663 }
14664 
14665 static int
14666 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14667     int lcount, int tcount, int cause)
14668 {
14669 	int rval;
14670 
14671 	mutex_enter(&pptr->port_mutex);
14672 	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14673 	mutex_exit(&pptr->port_mutex);
14674 
14675 	return (rval);
14676 }
14677 
14678 
14679 static int
14680 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14681     int lcount, int tcount, int cause)
14682 {
14683 	int	finish_init = 0;
14684 	int	finish_tgt = 0;
14685 	int	do_finish_init = 0;
14686 	int	rval = FCP_NO_CHANGE;
14687 
14688 	if (cause == FCP_CAUSE_LINK_CHANGE ||
14689 	    cause == FCP_CAUSE_LINK_DOWN) {
14690 		do_finish_init = 1;
14691 	}
14692 
14693 	if (ptgt != NULL) {
14694 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14695 		    FCP_BUF_LEVEL_2, 0,
14696 		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14697 		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14698 		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14699 		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14700 		    ptgt->tgt_d_id, ptgt->tgt_done);
14701 
14702 		mutex_enter(&ptgt->tgt_mutex);
14703 
14704 		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14705 			rval = FCP_DEV_CHANGE;
14706 			if (do_finish_init && ptgt->tgt_done == 0) {
14707 				ptgt->tgt_done++;
14708 				finish_init = 1;
14709 			}
14710 		} else {
14711 			if (--ptgt->tgt_tmp_cnt <= 0) {
14712 				ptgt->tgt_tmp_cnt = 0;
14713 				finish_tgt = 1;
14714 
14715 				if (do_finish_init) {
14716 					finish_init = 1;
14717 				}
14718 			}
14719 		}
14720 		mutex_exit(&ptgt->tgt_mutex);
14721 	} else {
14722 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14723 		    FCP_BUF_LEVEL_2, 0,
14724 		    "Call Finish Init for NO target");
14725 
14726 		if (do_finish_init) {
14727 			finish_init = 1;
14728 		}
14729 	}
14730 
14731 	if (finish_tgt) {
14732 		ASSERT(ptgt != NULL);
14733 
14734 		mutex_enter(&ptgt->tgt_mutex);
14735 #ifdef	DEBUG
14736 		bzero(ptgt->tgt_tmp_cnt_stack,
14737 		    sizeof (ptgt->tgt_tmp_cnt_stack));
14738 
14739 		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14740 		    FCP_STACK_DEPTH);
14741 #endif /* DEBUG */
14742 		mutex_exit(&ptgt->tgt_mutex);
14743 
14744 		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14745 	}
14746 
14747 	if (finish_init && lcount == pptr->port_link_cnt) {
14748 		ASSERT(pptr->port_tmp_cnt > 0);
14749 		if (--pptr->port_tmp_cnt == 0) {
14750 			fcp_finish_init(pptr);
14751 		}
14752 	} else if (lcount != pptr->port_link_cnt) {
14753 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14754 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14755 		    "fcp_call_finish_init_held,1: state change occured"
14756 		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14757 	}
14758 
14759 	return (rval);
14760 }
14761 
14762 static void
14763 fcp_reconfigure_luns(void * tgt_handle)
14764 {
14765 	uint32_t		dev_cnt;
14766 	fc_portmap_t		*devlist;
14767 	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14768 	struct fcp_port		*pptr = ptgt->tgt_port;
14769 
14770 	/*
14771 	 * If the timer that fires this off got canceled too late, the
14772 	 * target could have been destroyed.
14773 	 */
14774 
14775 	if (ptgt->tgt_tid == NULL) {
14776 		return;
14777 	}
14778 
14779 	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14780 	if (devlist == NULL) {
14781 		fcp_log(CE_WARN, pptr->port_dip,
14782 		    "!fcp%d: failed to allocate for portmap",
14783 		    pptr->port_instance);
14784 		return;
14785 	}
14786 
14787 	dev_cnt = 1;
14788 	devlist->map_pd = ptgt->tgt_pd_handle;
14789 	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14790 	devlist->map_did.port_id = ptgt->tgt_d_id;
14791 
14792 	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14793 	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14794 
14795 	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14796 	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14797 	devlist->map_flags = 0;
14798 
14799 	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14800 	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14801 
14802 	/*
14803 	 * Clear the tgt_tid after no more references to
14804 	 * the fcp_tgt
14805 	 */
14806 	mutex_enter(&ptgt->tgt_mutex);
14807 	ptgt->tgt_tid = NULL;
14808 	mutex_exit(&ptgt->tgt_mutex);
14809 
14810 	kmem_free(devlist, sizeof (*devlist));
14811 }
14812 
14813 
14814 static void
14815 fcp_free_targets(struct fcp_port *pptr)
14816 {
14817 	int			i;
14818 	struct fcp_tgt	*ptgt;
14819 
14820 	mutex_enter(&pptr->port_mutex);
14821 	for (i = 0; i < FCP_NUM_HASH; i++) {
14822 		ptgt = pptr->port_tgt_hash_table[i];
14823 		while (ptgt != NULL) {
14824 			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14825 
14826 			fcp_free_target(ptgt);
14827 			ptgt = next_tgt;
14828 		}
14829 	}
14830 	mutex_exit(&pptr->port_mutex);
14831 }
14832 
14833 
14834 static void
14835 fcp_free_target(struct fcp_tgt *ptgt)
14836 {
14837 	struct fcp_lun	*plun;
14838 	timeout_id_t		tid;
14839 
14840 	mutex_enter(&ptgt->tgt_mutex);
14841 	tid = ptgt->tgt_tid;
14842 
14843 	/*
14844 	 * Cancel any pending timeouts for this target.
14845 	 */
14846 
14847 	if (tid != NULL) {
14848 		/*
14849 		 * Set tgt_tid to NULL first to avoid a race in the callback.
14850 		 * If tgt_tid is NULL, the callback will simply return.
14851 		 */
14852 		ptgt->tgt_tid = NULL;
14853 		mutex_exit(&ptgt->tgt_mutex);
14854 		(void) untimeout(tid);
14855 		mutex_enter(&ptgt->tgt_mutex);
14856 	}
14857 
14858 	plun = ptgt->tgt_lun;
14859 	while (plun != NULL) {
14860 		struct fcp_lun *next_lun = plun->lun_next;
14861 
14862 		fcp_dealloc_lun(plun);
14863 		plun = next_lun;
14864 	}
14865 
14866 	mutex_exit(&ptgt->tgt_mutex);
14867 	fcp_dealloc_tgt(ptgt);
14868 }
14869 
14870 /*
14871  *     Function: fcp_is_retryable
14872  *
14873  *  Description: Indicates if the internal packet is retryable.
14874  *
14875  *     Argument: *icmd		FCP internal packet.
14876  *
14877  * Return Value: 0	Not retryable
14878  *		 1	Retryable
14879  *
14880  *	Context: User, Kernel and Interrupt context
14881  */
14882 static int
14883 fcp_is_retryable(struct fcp_ipkt *icmd)
14884 {
14885 	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14886 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14887 		return (0);
14888 	}
14889 
14890 	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14891 	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14892 }
14893 
14894 /*
14895  *     Function: fcp_create_on_demand
14896  *
14897  *     Argument: *pptr		FCP port.
14898  *		 *pwwn		Port WWN.
14899  *
14900  * Return Value: 0	Success
14901  *		 EIO
14902  *		 ENOMEM
14903  *		 EBUSY
14904  *		 EINVAL
14905  *
14906  *	Context: User and Kernel context
14907  */
14908 static int
14909 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14910 {
14911 	int			wait_ms;
14912 	int			tcount;
14913 	int			lcount;
14914 	int			ret;
14915 	int			error;
14916 	int			rval = EIO;
14917 	int			ntries;
14918 	fc_portmap_t		*devlist;
14919 	opaque_t		pd;
14920 	struct fcp_lun		*plun;
14921 	struct fcp_tgt		*ptgt;
14922 	int			old_manual = 0;
14923 
14924 	/* Allocates the fc_portmap_t structure. */
14925 	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14926 
14927 	/*
14928 	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14929 	 * in the commented statement below:
14930 	 *
14931 	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14932 	 *
14933 	 * Below, the deadline for the discovery process is set.
14934 	 */
14935 	mutex_enter(&pptr->port_mutex);
14936 	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14937 	mutex_exit(&pptr->port_mutex);
14938 
14939 	/*
14940 	 * We try to find the remote port based on the WWN provided by the
14941 	 * caller.  We actually ask fp/fctl if it has it.
14942 	 */
14943 	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14944 	    (la_wwn_t *)pwwn, &error, 1);
14945 
14946 	if (pd == NULL) {
14947 		kmem_free(devlist, sizeof (*devlist));
14948 		return (rval);
14949 	}
14950 
14951 	/*
14952 	 * The remote port was found.  We ask fp/fctl to update our
14953 	 * fc_portmap_t structure.
14954 	 */
14955 	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14956 	    (la_wwn_t *)pwwn, devlist);
14957 	if (ret != FC_SUCCESS) {
14958 		kmem_free(devlist, sizeof (*devlist));
14959 		return (rval);
14960 	}
14961 
14962 	/*
14963 	 * The map flag field is set to indicates that the creation is being
14964 	 * done at the user request (Ioclt probably luxadm or cfgadm).
14965 	 */
14966 	devlist->map_type = PORT_DEVICE_USER_CREATE;
14967 
14968 	mutex_enter(&pptr->port_mutex);
14969 
14970 	/*
14971 	 * We check to see if fcp already has a target that describes the
14972 	 * device being created.  If not it is created.
14973 	 */
14974 	ptgt = fcp_lookup_target(pptr, pwwn);
14975 	if (ptgt == NULL) {
14976 		lcount = pptr->port_link_cnt;
14977 		mutex_exit(&pptr->port_mutex);
14978 
14979 		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14980 		if (ptgt == NULL) {
14981 			fcp_log(CE_WARN, pptr->port_dip,
14982 			    "!FC target allocation failed");
14983 			return (ENOMEM);
14984 		}
14985 
14986 		mutex_enter(&pptr->port_mutex);
14987 	}
14988 
14989 	mutex_enter(&ptgt->tgt_mutex);
14990 	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
14991 	ptgt->tgt_tmp_cnt = 1;
14992 	ptgt->tgt_device_created = 0;
14993 	/*
14994 	 * If fabric and auto config is set but the target was
14995 	 * manually unconfigured then reset to the manual_config_only to
14996 	 * 0 so the device will get configured.
14997 	 */
14998 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14999 	    fcp_enable_auto_configuration &&
15000 	    ptgt->tgt_manual_config_only == 1) {
15001 		old_manual = 1;
15002 		ptgt->tgt_manual_config_only = 0;
15003 	}
15004 	mutex_exit(&ptgt->tgt_mutex);
15005 
15006 	fcp_update_targets(pptr, devlist, 1,
15007 	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15008 
15009 	lcount = pptr->port_link_cnt;
15010 	tcount = ptgt->tgt_change_cnt;
15011 
15012 	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15013 	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15014 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15015 		    fcp_enable_auto_configuration && old_manual) {
15016 			mutex_enter(&ptgt->tgt_mutex);
15017 			ptgt->tgt_manual_config_only = 1;
15018 			mutex_exit(&ptgt->tgt_mutex);
15019 		}
15020 
15021 		if (pptr->port_link_cnt != lcount ||
15022 		    ptgt->tgt_change_cnt != tcount) {
15023 			rval = EBUSY;
15024 		}
15025 		mutex_exit(&pptr->port_mutex);
15026 
15027 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15028 		    FCP_BUF_LEVEL_3, 0,
15029 		    "fcp_create_on_demand: mapflags ptgt=%x, "
15030 		    "lcount=%x::port_link_cnt=%x, "
15031 		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
15032 		    ptgt, lcount, pptr->port_link_cnt,
15033 		    tcount, ptgt->tgt_change_cnt, rval);
15034 		return (rval);
15035 	}
15036 
15037 	/*
15038 	 * Due to lack of synchronization mechanisms, we perform
15039 	 * periodic monitoring of our request; Because requests
15040 	 * get dropped when another one supercedes (either because
15041 	 * of a link change or a target change), it is difficult to
15042 	 * provide a clean synchronization mechanism (such as a
15043 	 * semaphore or a conditional variable) without exhaustively
15044 	 * rewriting the mainline discovery code of this driver.
15045 	 */
15046 	wait_ms = 500;
15047 
15048 	ntries = fcp_max_target_retries;
15049 
15050 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15051 	    FCP_BUF_LEVEL_3, 0,
15052 	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15053 	    "lcount=%x::port_link_cnt=%x, "
15054 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15055 	    "tgt_tmp_cnt =%x",
15056 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15057 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15058 	    ptgt->tgt_tmp_cnt);
15059 
15060 	mutex_enter(&ptgt->tgt_mutex);
15061 	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15062 	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15063 		mutex_exit(&ptgt->tgt_mutex);
15064 		mutex_exit(&pptr->port_mutex);
15065 
15066 		delay(drv_usectohz(wait_ms * 1000));
15067 
15068 		mutex_enter(&pptr->port_mutex);
15069 		mutex_enter(&ptgt->tgt_mutex);
15070 	}
15071 
15072 
15073 	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15074 		rval = EBUSY;
15075 	} else {
15076 		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15077 		    FCP_TGT_NODE_PRESENT) {
15078 			rval = 0;
15079 		}
15080 	}
15081 
15082 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15083 	    FCP_BUF_LEVEL_3, 0,
15084 	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15085 	    "lcount=%x::port_link_cnt=%x, "
15086 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15087 	    "tgt_tmp_cnt =%x",
15088 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15089 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15090 	    ptgt->tgt_tmp_cnt);
15091 
15092 	if (rval) {
15093 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15094 		    fcp_enable_auto_configuration && old_manual) {
15095 			ptgt->tgt_manual_config_only = 1;
15096 		}
15097 		mutex_exit(&ptgt->tgt_mutex);
15098 		mutex_exit(&pptr->port_mutex);
15099 		kmem_free(devlist, sizeof (*devlist));
15100 
15101 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15102 		    FCP_BUF_LEVEL_3, 0,
15103 		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15104 		    "lcount=%x::port_link_cnt=%x, "
15105 		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15106 		    "tgt_device_created=%x, tgt D_ID=%x",
15107 		    ntries, ptgt, lcount, pptr->port_link_cnt,
15108 		    tcount, ptgt->tgt_change_cnt, rval,
15109 		    ptgt->tgt_device_created, ptgt->tgt_d_id);
15110 		return (rval);
15111 	}
15112 
15113 	if ((plun = ptgt->tgt_lun) != NULL) {
15114 		tcount = plun->lun_tgt->tgt_change_cnt;
15115 	} else {
15116 		rval = EINVAL;
15117 	}
15118 	lcount = pptr->port_link_cnt;
15119 
15120 	/*
15121 	 * Configuring the target with no LUNs will fail. We
15122 	 * should reset the node state so that it is not
15123 	 * automatically configured when the LUNs are added
15124 	 * to this target.
15125 	 */
15126 	if (ptgt->tgt_lun_cnt == 0) {
15127 		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15128 	}
15129 	mutex_exit(&ptgt->tgt_mutex);
15130 	mutex_exit(&pptr->port_mutex);
15131 
15132 	while (plun) {
15133 		child_info_t	*cip;
15134 
15135 		mutex_enter(&plun->lun_mutex);
15136 		cip = plun->lun_cip;
15137 		mutex_exit(&plun->lun_mutex);
15138 
15139 		mutex_enter(&ptgt->tgt_mutex);
15140 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15141 			mutex_exit(&ptgt->tgt_mutex);
15142 
15143 			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15144 			    FCP_ONLINE, lcount, tcount,
15145 			    NDI_ONLINE_ATTACH);
15146 			if (rval != NDI_SUCCESS) {
15147 				FCP_TRACE(fcp_logq,
15148 				    pptr->port_instbuf, fcp_trace,
15149 				    FCP_BUF_LEVEL_3, 0,
15150 				    "fcp_create_on_demand: "
15151 				    "pass_to_hp_and_wait failed "
15152 				    "rval=%x", rval);
15153 				rval = EIO;
15154 			} else {
15155 				mutex_enter(&LUN_TGT->tgt_mutex);
15156 				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15157 				    FCP_LUN_BUSY);
15158 				mutex_exit(&LUN_TGT->tgt_mutex);
15159 			}
15160 			mutex_enter(&ptgt->tgt_mutex);
15161 		}
15162 
15163 		plun = plun->lun_next;
15164 		mutex_exit(&ptgt->tgt_mutex);
15165 	}
15166 
15167 	kmem_free(devlist, sizeof (*devlist));
15168 
15169 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15170 	    fcp_enable_auto_configuration && old_manual) {
15171 		mutex_enter(&ptgt->tgt_mutex);
15172 		/* if successful then set manual to 0 */
15173 		if (rval == 0) {
15174 			ptgt->tgt_manual_config_only = 0;
15175 		} else {
15176 			/* reset to 1 so the user has to do the config */
15177 			ptgt->tgt_manual_config_only = 1;
15178 		}
15179 		mutex_exit(&ptgt->tgt_mutex);
15180 	}
15181 
15182 	return (rval);
15183 }
15184 
15185 
15186 static void
15187 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15188 {
15189 	int		count;
15190 	uchar_t		byte;
15191 
15192 	count = 0;
15193 	while (*string) {
15194 		byte = FCP_ATOB(*string); string++;
15195 		byte = byte << 4 | FCP_ATOB(*string); string++;
15196 		bytes[count++] = byte;
15197 
15198 		if (count >= byte_len) {
15199 			break;
15200 		}
15201 	}
15202 }
15203 
15204 static void
15205 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15206 {
15207 	int		i;
15208 
15209 	for (i = 0; i < FC_WWN_SIZE; i++) {
15210 		(void) sprintf(string + (i * 2),
15211 		    "%02x", wwn[i]);
15212 	}
15213 
15214 }
15215 
15216 static void
15217 fcp_print_error(fc_packet_t *fpkt)
15218 {
15219 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15220 	    fpkt->pkt_ulp_private;
15221 	struct fcp_port	*pptr;
15222 	struct fcp_tgt	*ptgt;
15223 	struct fcp_lun	*plun;
15224 	caddr_t			buf;
15225 	int			scsi_cmd = 0;
15226 
15227 	ptgt = icmd->ipkt_tgt;
15228 	plun = icmd->ipkt_lun;
15229 	pptr = ptgt->tgt_port;
15230 
15231 	buf = kmem_zalloc(256, KM_NOSLEEP);
15232 	if (buf == NULL) {
15233 		return;
15234 	}
15235 
15236 	switch (icmd->ipkt_opcode) {
15237 	case SCMD_REPORT_LUN:
15238 		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15239 		    " lun=0x%%x failed");
15240 		scsi_cmd++;
15241 		break;
15242 
15243 	case SCMD_INQUIRY_PAGE83:
15244 		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15245 		    " lun=0x%%x failed");
15246 		scsi_cmd++;
15247 		break;
15248 
15249 	case SCMD_INQUIRY:
15250 		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15251 		    " lun=0x%%x failed");
15252 		scsi_cmd++;
15253 		break;
15254 
15255 	case LA_ELS_PLOGI:
15256 		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15257 		break;
15258 
15259 	case LA_ELS_PRLI:
15260 		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15261 		break;
15262 	}
15263 
15264 	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15265 		struct fcp_rsp		response, *rsp;
15266 		uchar_t			asc, ascq;
15267 		caddr_t			sense_key = NULL;
15268 		struct fcp_rsp_info	fcp_rsp_err, *bep;
15269 
15270 		if (icmd->ipkt_nodma) {
15271 			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15272 			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15273 			    sizeof (struct fcp_rsp));
15274 		} else {
15275 			rsp = &response;
15276 			bep = &fcp_rsp_err;
15277 
15278 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15279 			    sizeof (struct fcp_rsp));
15280 
15281 			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15282 			    bep, fpkt->pkt_resp_acc,
15283 			    sizeof (struct fcp_rsp_info));
15284 		}
15285 
15286 
15287 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15288 			(void) sprintf(buf + strlen(buf),
15289 			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15290 			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15291 			    " senselen=%%x. Giving up");
15292 
15293 			fcp_log(CE_WARN, pptr->port_dip, buf,
15294 			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15295 			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15296 			    rsp->fcp_u.fcp_status.reserved_1,
15297 			    rsp->fcp_response_len, rsp->fcp_sense_len);
15298 
15299 			kmem_free(buf, 256);
15300 			return;
15301 		}
15302 
15303 		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15304 		    bep->rsp_code != FCP_NO_FAILURE) {
15305 			(void) sprintf(buf + strlen(buf),
15306 			    " FCP Response code = 0x%x", bep->rsp_code);
15307 		}
15308 
15309 		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15310 			struct scsi_extended_sense sense_info, *sense_ptr;
15311 
15312 			if (icmd->ipkt_nodma) {
15313 				sense_ptr = (struct scsi_extended_sense *)
15314 				    ((caddr_t)fpkt->pkt_resp +
15315 				    sizeof (struct fcp_rsp) +
15316 				    rsp->fcp_response_len);
15317 			} else {
15318 				sense_ptr = &sense_info;
15319 
15320 				FCP_CP_IN(fpkt->pkt_resp +
15321 				    sizeof (struct fcp_rsp) +
15322 				    rsp->fcp_response_len, &sense_info,
15323 				    fpkt->pkt_resp_acc,
15324 				    sizeof (struct scsi_extended_sense));
15325 			}
15326 
15327 			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15328 			    NUM_IMPL_SENSE_KEYS) {
15329 				sense_key = sense_keys[sense_ptr->es_key];
15330 			} else {
15331 				sense_key = "Undefined";
15332 			}
15333 
15334 			asc = sense_ptr->es_add_code;
15335 			ascq = sense_ptr->es_qual_code;
15336 
15337 			(void) sprintf(buf + strlen(buf),
15338 			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15339 			    " Giving up");
15340 
15341 			fcp_log(CE_WARN, pptr->port_dip, buf,
15342 			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15343 			    asc, ascq);
15344 		} else {
15345 			(void) sprintf(buf + strlen(buf),
15346 			    " : SCSI status=%%x. Giving up");
15347 
15348 			fcp_log(CE_WARN, pptr->port_dip, buf,
15349 			    ptgt->tgt_d_id, plun->lun_num,
15350 			    rsp->fcp_u.fcp_status.scsi_status);
15351 		}
15352 	} else {
15353 		caddr_t state, reason, action, expln;
15354 
15355 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15356 		    &action, &expln);
15357 
15358 		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15359 		    " Reason:%%s. Giving up");
15360 
15361 		if (scsi_cmd) {
15362 			fcp_log(CE_WARN, pptr->port_dip, buf,
15363 			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15364 		} else {
15365 			fcp_log(CE_WARN, pptr->port_dip, buf,
15366 			    ptgt->tgt_d_id, state, reason);
15367 		}
15368 	}
15369 
15370 	kmem_free(buf, 256);
15371 }
15372 
15373 
15374 static int
15375 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15376     struct fcp_ipkt *icmd, int rval, caddr_t op)
15377 {
15378 	int	ret = DDI_FAILURE;
15379 	char	*error;
15380 
15381 	switch (rval) {
15382 	case FC_DEVICE_BUSY_NEW_RSCN:
15383 		/*
15384 		 * This means that there was a new RSCN that the transport
15385 		 * knows about (which the ULP *may* know about too) but the
15386 		 * pkt that was sent down was related to an older RSCN. So, we
15387 		 * are just going to reset the retry count and deadline and
15388 		 * continue to retry. The idea is that transport is currently
15389 		 * working on the new RSCN and will soon let the ULPs know
15390 		 * about it and when it does the existing logic will kick in
15391 		 * where it will change the tcount to indicate that something
15392 		 * changed on the target. So, rediscovery will start and there
15393 		 * will not be an infinite retry.
15394 		 *
15395 		 * For a full flow of how the RSCN info is transferred back and
15396 		 * forth, see fp.c
15397 		 */
15398 		icmd->ipkt_retries = 0;
15399 		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15400 		    FCP_ICMD_DEADLINE;
15401 
15402 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15403 		    FCP_BUF_LEVEL_3, 0,
15404 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15405 		    rval, ptgt->tgt_d_id);
15406 		/* FALLTHROUGH */
15407 
15408 	case FC_STATEC_BUSY:
15409 	case FC_DEVICE_BUSY:
15410 	case FC_PBUSY:
15411 	case FC_FBUSY:
15412 	case FC_TRAN_BUSY:
15413 	case FC_OFFLINE:
15414 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15415 		    FCP_BUF_LEVEL_3, 0,
15416 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15417 		    rval, ptgt->tgt_d_id);
15418 		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15419 		    fcp_is_retryable(icmd)) {
15420 			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15421 			ret = DDI_SUCCESS;
15422 		}
15423 		break;
15424 
15425 	case FC_LOGINREQ:
15426 		/*
15427 		 * FC_LOGINREQ used to be handled just like all the cases
15428 		 * above. It has been changed to handled a PRLI that fails
15429 		 * with FC_LOGINREQ different than other ipkts that fail
15430 		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15431 		 * a simple matter to turn it into a PLOGI instead, so that's
15432 		 * exactly what we do here.
15433 		 */
15434 		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15435 			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15436 			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15437 			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15438 		} else {
15439 			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15440 			    FCP_BUF_LEVEL_3, 0,
15441 			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15442 			    rval, ptgt->tgt_d_id);
15443 			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15444 			    fcp_is_retryable(icmd)) {
15445 				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15446 				ret = DDI_SUCCESS;
15447 			}
15448 		}
15449 		break;
15450 
15451 	default:
15452 		mutex_enter(&pptr->port_mutex);
15453 		mutex_enter(&ptgt->tgt_mutex);
15454 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15455 			mutex_exit(&ptgt->tgt_mutex);
15456 			mutex_exit(&pptr->port_mutex);
15457 
15458 			(void) fc_ulp_error(rval, &error);
15459 			fcp_log(CE_WARN, pptr->port_dip,
15460 			    "!Failed to send %s to D_ID=%x error=%s",
15461 			    op, ptgt->tgt_d_id, error);
15462 		} else {
15463 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15464 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15465 			    "fcp_handle_ipkt_errors,1: state change occured"
15466 			    " for D_ID=0x%x", ptgt->tgt_d_id);
15467 			mutex_exit(&ptgt->tgt_mutex);
15468 			mutex_exit(&pptr->port_mutex);
15469 		}
15470 		break;
15471 	}
15472 
15473 	return (ret);
15474 }
15475 
15476 
15477 /*
15478  * Check of outstanding commands on any LUN for this target
15479  */
15480 static int
15481 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15482 {
15483 	struct	fcp_lun	*plun;
15484 	struct	fcp_pkt	*cmd;
15485 
15486 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15487 		mutex_enter(&plun->lun_mutex);
15488 		for (cmd = plun->lun_pkt_head; cmd != NULL;
15489 		    cmd = cmd->cmd_forw) {
15490 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15491 				mutex_exit(&plun->lun_mutex);
15492 				return (FC_SUCCESS);
15493 			}
15494 		}
15495 		mutex_exit(&plun->lun_mutex);
15496 	}
15497 
15498 	return (FC_FAILURE);
15499 }
15500 
15501 static fc_portmap_t *
15502 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15503 {
15504 	int			i;
15505 	fc_portmap_t		*devlist;
15506 	fc_portmap_t		*devptr = NULL;
15507 	struct fcp_tgt	*ptgt;
15508 
15509 	mutex_enter(&pptr->port_mutex);
15510 	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15511 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15512 		    ptgt = ptgt->tgt_next) {
15513 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15514 				++*dev_cnt;
15515 			}
15516 		}
15517 	}
15518 
15519 	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15520 	    KM_NOSLEEP);
15521 	if (devlist == NULL) {
15522 		mutex_exit(&pptr->port_mutex);
15523 		fcp_log(CE_WARN, pptr->port_dip,
15524 		    "!fcp%d: failed to allocate for portmap for construct map",
15525 		    pptr->port_instance);
15526 		return (devptr);
15527 	}
15528 
15529 	for (i = 0; i < FCP_NUM_HASH; i++) {
15530 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15531 		    ptgt = ptgt->tgt_next) {
15532 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15533 				int ret;
15534 
15535 				ret = fc_ulp_pwwn_to_portmap(
15536 				    pptr->port_fp_handle,
15537 				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15538 				    devlist);
15539 
15540 				if (ret == FC_SUCCESS) {
15541 					devlist++;
15542 					continue;
15543 				}
15544 
15545 				devlist->map_pd = NULL;
15546 				devlist->map_did.port_id = ptgt->tgt_d_id;
15547 				devlist->map_hard_addr.hard_addr =
15548 				    ptgt->tgt_hard_addr;
15549 
15550 				devlist->map_state = PORT_DEVICE_INVALID;
15551 				devlist->map_type = PORT_DEVICE_OLD;
15552 
15553 				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15554 				    &devlist->map_nwwn, FC_WWN_SIZE);
15555 
15556 				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15557 				    &devlist->map_pwwn, FC_WWN_SIZE);
15558 
15559 				devlist++;
15560 			}
15561 		}
15562 	}
15563 
15564 	mutex_exit(&pptr->port_mutex);
15565 
15566 	return (devptr);
15567 }
15568 /*
15569  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15570  */
15571 static void
15572 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15573 {
15574 	int i;
15575 	struct fcp_tgt	*ptgt;
15576 	struct fcp_lun	*plun;
15577 
15578 	for (i = 0; i < FCP_NUM_HASH; i++) {
15579 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15580 		    ptgt = ptgt->tgt_next) {
15581 			mutex_enter(&ptgt->tgt_mutex);
15582 			for (plun = ptgt->tgt_lun; plun != NULL;
15583 			    plun = plun->lun_next) {
15584 				if (plun->lun_mpxio &&
15585 				    plun->lun_state & FCP_LUN_BUSY) {
15586 					if (!fcp_pass_to_hp(pptr, plun,
15587 					    plun->lun_cip,
15588 					    FCP_MPXIO_PATH_SET_BUSY,
15589 					    pptr->port_link_cnt,
15590 					    ptgt->tgt_change_cnt, 0, 0)) {
15591 						FCP_TRACE(fcp_logq,
15592 						    pptr->port_instbuf,
15593 						    fcp_trace,
15594 						    FCP_BUF_LEVEL_2, 0,
15595 						    "path_verifybusy: "
15596 						    "disable lun %p failed!",
15597 						    plun);
15598 					}
15599 				}
15600 			}
15601 			mutex_exit(&ptgt->tgt_mutex);
15602 		}
15603 	}
15604 }
15605 
15606 static int
15607 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15608 {
15609 	dev_info_t		*cdip = NULL;
15610 	dev_info_t		*pdip = NULL;
15611 
15612 	ASSERT(plun);
15613 
15614 	mutex_enter(&plun->lun_mutex);
15615 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15616 		mutex_exit(&plun->lun_mutex);
15617 		return (NDI_FAILURE);
15618 	}
15619 	mutex_exit(&plun->lun_mutex);
15620 	cdip = mdi_pi_get_client(PIP(cip));
15621 	pdip = mdi_pi_get_phci(PIP(cip));
15622 
15623 	ASSERT(cdip != NULL);
15624 	ASSERT(pdip != NULL);
15625 
15626 	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15627 		/* LUN ready for IO */
15628 		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15629 	} else {
15630 		/* LUN busy to accept IO */
15631 		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15632 	}
15633 	return (NDI_SUCCESS);
15634 }
15635 
15636 /*
15637  * Caller must free the returned string of MAXPATHLEN len
15638  * If the device is offline (-1 instance number) NULL
15639  * will be returned.
15640  */
15641 static char *
15642 fcp_get_lun_path(struct fcp_lun *plun)
15643 {
15644 	dev_info_t	*dip = NULL;
15645 	char		*path = NULL;
15646 	mdi_pathinfo_t	*pip = NULL;
15647 
15648 	if (plun == NULL) {
15649 		return (NULL);
15650 	}
15651 
15652 	mutex_enter(&plun->lun_mutex);
15653 	if (plun->lun_mpxio == 0) {
15654 		dip = DIP(plun->lun_cip);
15655 		mutex_exit(&plun->lun_mutex);
15656 	} else {
15657 		/*
15658 		 * lun_cip must be accessed with lun_mutex held. Here
15659 		 * plun->lun_cip either points to a valid node or it is NULL.
15660 		 * Make a copy so that we can release lun_mutex.
15661 		 */
15662 		pip = PIP(plun->lun_cip);
15663 
15664 		/*
15665 		 * Increase ref count on the path so that we can release
15666 		 * lun_mutex and still be sure that the pathinfo node (and thus
15667 		 * also the client) is not deallocated. If pip is NULL, this
15668 		 * has no effect.
15669 		 */
15670 		mdi_hold_path(pip);
15671 
15672 		mutex_exit(&plun->lun_mutex);
15673 
15674 		/* Get the client. If pip is NULL, we get NULL. */
15675 		dip = mdi_pi_get_client(pip);
15676 	}
15677 
15678 	if (dip == NULL)
15679 		goto out;
15680 	if (ddi_get_instance(dip) < 0)
15681 		goto out;
15682 
15683 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15684 	if (path == NULL)
15685 		goto out;
15686 
15687 	(void) ddi_pathname(dip, path);
15688 
15689 	/* Clean up. */
15690 out:
15691 	if (pip != NULL)
15692 		mdi_rele_path(pip);
15693 
15694 	/*
15695 	 * In reality, the user wants a fully valid path (one they can open)
15696 	 * but this string is lacking the mount point, and the minor node.
15697 	 * It would be nice if we could "figure these out" somehow
15698 	 * and fill them in.  Otherwise, the userland code has to understand
15699 	 * driver specific details of which minor node is the "best" or
15700 	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15701 	 * which tape doesn't rewind)
15702 	 */
15703 	return (path);
15704 }
15705 
15706 static int
15707 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15708     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15709 {
15710 	int64_t reset_delay;
15711 	int rval, retry = 0;
15712 	struct fcp_port *pptr = fcp_dip2port(parent);
15713 
15714 	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15715 	    (ddi_get_lbolt64() - pptr->port_attach_time);
15716 	if (reset_delay < 0) {
15717 		reset_delay = 0;
15718 	}
15719 
15720 	if (fcp_bus_config_debug) {
15721 		flag |= NDI_DEVI_DEBUG;
15722 	}
15723 
15724 	switch (op) {
15725 	case BUS_CONFIG_ONE:
15726 		/*
15727 		 * Retry the command since we need to ensure
15728 		 * the fabric devices are available for root
15729 		 */
15730 		while (retry++ < fcp_max_bus_config_retries) {
15731 			rval =	(ndi_busop_bus_config(parent,
15732 			    flag | NDI_MDI_FALLBACK, op,
15733 			    arg, childp, (clock_t)reset_delay));
15734 			if (rval == 0) {
15735 				return (rval);
15736 			}
15737 		}
15738 
15739 		/*
15740 		 * drain taskq to make sure nodes are created and then
15741 		 * try again.
15742 		 */
15743 		taskq_wait(DEVI(parent)->devi_taskq);
15744 		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15745 		    op, arg, childp, 0));
15746 
15747 	case BUS_CONFIG_DRIVER:
15748 	case BUS_CONFIG_ALL: {
15749 		/*
15750 		 * delay till all devices report in (port_tmp_cnt == 0)
15751 		 * or FCP_INIT_WAIT_TIMEOUT
15752 		 */
15753 		mutex_enter(&pptr->port_mutex);
15754 		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15755 			(void) cv_timedwait(&pptr->port_config_cv,
15756 			    &pptr->port_mutex,
15757 			    ddi_get_lbolt() + (clock_t)reset_delay);
15758 			reset_delay =
15759 			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15760 			    (ddi_get_lbolt64() - pptr->port_attach_time);
15761 		}
15762 		mutex_exit(&pptr->port_mutex);
15763 		/* drain taskq to make sure nodes are created */
15764 		taskq_wait(DEVI(parent)->devi_taskq);
15765 		return (ndi_busop_bus_config(parent, flag, op,
15766 		    arg, childp, 0));
15767 	}
15768 
15769 	default:
15770 		return (NDI_FAILURE);
15771 	}
15772 	/*NOTREACHED*/
15773 }
15774 
15775 static int
15776 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15777     ddi_bus_config_op_t op, void *arg)
15778 {
15779 	if (fcp_bus_config_debug) {
15780 		flag |= NDI_DEVI_DEBUG;
15781 	}
15782 
15783 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15784 }
15785 
15786 
15787 /*
15788  * Routine to copy GUID into the lun structure.
15789  * returns 0 if copy was successful and 1 if encountered a
15790  * failure and did not copy the guid.
15791  */
15792 static int
15793 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15794 {
15795 
15796 	int retval = 0;
15797 
15798 	/* add one for the null terminator */
15799 	const unsigned int len = strlen(guidp) + 1;
15800 
15801 	if ((guidp == NULL) || (plun == NULL)) {
15802 		return (1);
15803 	}
15804 
15805 	/*
15806 	 * if the plun->lun_guid already has been allocated,
15807 	 * then check the size. if the size is exact, reuse
15808 	 * it....if not free it an allocate the required size.
15809 	 * The reallocation should NOT typically happen
15810 	 * unless the GUIDs reported changes between passes.
15811 	 * We free up and alloc again even if the
15812 	 * size was more than required. This is due to the
15813 	 * fact that the field lun_guid_size - serves
15814 	 * dual role of indicating the size of the wwn
15815 	 * size and ALSO the allocation size.
15816 	 */
15817 	if (plun->lun_guid) {
15818 		if (plun->lun_guid_size != len) {
15819 			/*
15820 			 * free the allocated memory and
15821 			 * initialize the field
15822 			 * lun_guid_size to 0.
15823 			 */
15824 			kmem_free(plun->lun_guid, plun->lun_guid_size);
15825 			plun->lun_guid = NULL;
15826 			plun->lun_guid_size = 0;
15827 		}
15828 	}
15829 	/*
15830 	 * alloc only if not already done.
15831 	 */
15832 	if (plun->lun_guid == NULL) {
15833 		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15834 		if (plun->lun_guid == NULL) {
15835 			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15836 			    "Unable to allocate"
15837 			    "Memory for GUID!!! size %d", len);
15838 			retval = 1;
15839 		} else {
15840 			plun->lun_guid_size = len;
15841 		}
15842 	}
15843 	if (plun->lun_guid) {
15844 		/*
15845 		 * now copy the GUID
15846 		 */
15847 		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15848 	}
15849 	return (retval);
15850 }
15851 
15852 /*
15853  * fcp_reconfig_wait
15854  *
15855  * Wait for a rediscovery/reconfiguration to complete before continuing.
15856  */
15857 
15858 static void
15859 fcp_reconfig_wait(struct fcp_port *pptr)
15860 {
15861 	clock_t		reconfig_start, wait_timeout;
15862 
15863 	/*
15864 	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15865 	 * reconfiguration in progress.
15866 	 */
15867 
15868 	mutex_enter(&pptr->port_mutex);
15869 	if (pptr->port_tmp_cnt == 0) {
15870 		mutex_exit(&pptr->port_mutex);
15871 		return;
15872 	}
15873 	mutex_exit(&pptr->port_mutex);
15874 
15875 	/*
15876 	 * If we cause a reconfig by raising power, delay until all devices
15877 	 * report in (port_tmp_cnt returns to 0)
15878 	 */
15879 
15880 	reconfig_start = ddi_get_lbolt();
15881 	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15882 
15883 	mutex_enter(&pptr->port_mutex);
15884 
15885 	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15886 	    pptr->port_tmp_cnt) {
15887 
15888 		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15889 		    reconfig_start + wait_timeout);
15890 	}
15891 
15892 	mutex_exit(&pptr->port_mutex);
15893 
15894 	/*
15895 	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15896 	 * we want may still be ok.  If not, it will error out later
15897 	 */
15898 }
15899 
15900 /*
15901  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15902  * We rely on the fcp_global_mutex to provide protection against changes to
15903  * the fcp_lun_blacklist.
15904  *
15905  * You can describe a list of target port WWNs and LUN numbers which will
15906  * not be configured. LUN numbers will be interpreted as decimal. White
15907  * spaces and ',' can be used in the list of LUN numbers.
15908  *
15909  * To prevent LUNs 1 and 2 from being configured for target
15910  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15911  *
15912  * pwwn-lun-blacklist=
15913  * "510000f010fd92a1,1,2",
15914  * "510000e012079df1,1,2";
15915  */
15916 static void
15917 fcp_read_blacklist(dev_info_t *dip,
15918     struct fcp_black_list_entry **pplun_blacklist)
15919 {
15920 	char **prop_array	= NULL;
15921 	char *curr_pwwn		= NULL;
15922 	char *curr_lun		= NULL;
15923 	uint32_t prop_item	= 0;
15924 	int idx			= 0;
15925 	int len			= 0;
15926 
15927 	ASSERT(mutex_owned(&fcp_global_mutex));
15928 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15929 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15930 	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15931 		return;
15932 	}
15933 
15934 	for (idx = 0; idx < prop_item; idx++) {
15935 
15936 		curr_pwwn = prop_array[idx];
15937 		while (*curr_pwwn == ' ') {
15938 			curr_pwwn++;
15939 		}
15940 		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15941 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15942 			    ", please check.", curr_pwwn);
15943 			continue;
15944 		}
15945 		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15946 		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15947 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15948 			    ", please check.", curr_pwwn);
15949 			continue;
15950 		}
15951 		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15952 			if (isxdigit(curr_pwwn[len]) != TRUE) {
15953 				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15954 				    "blacklist, please check.", curr_pwwn);
15955 				break;
15956 			}
15957 		}
15958 		if (len != sizeof (la_wwn_t) * 2) {
15959 			continue;
15960 		}
15961 
15962 		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15963 		*(curr_lun - 1) = '\0';
15964 		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15965 	}
15966 
15967 	ddi_prop_free(prop_array);
15968 }
15969 
15970 /*
15971  * Get the masking info about one remote target port designated by wwn.
15972  * Lun ids could be separated by ',' or white spaces.
15973  */
15974 static void
15975 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15976     struct fcp_black_list_entry **pplun_blacklist)
15977 {
15978 	int		idx			= 0;
15979 	uint32_t	offset			= 0;
15980 	unsigned long	lun_id			= 0;
15981 	char		lunid_buf[16];
15982 	char		*pend			= NULL;
15983 	int		illegal_digit		= 0;
15984 
15985 	while (offset < strlen(curr_lun)) {
15986 		while ((curr_lun[offset + idx] != ',') &&
15987 		    (curr_lun[offset + idx] != '\0') &&
15988 		    (curr_lun[offset + idx] != ' ')) {
15989 			if (isdigit(curr_lun[offset + idx]) == 0) {
15990 				illegal_digit++;
15991 			}
15992 			idx++;
15993 		}
15994 		if (illegal_digit > 0) {
15995 			offset += (idx+1);	/* To the start of next lun */
15996 			idx = 0;
15997 			illegal_digit = 0;
15998 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15999 			    "the blacklist, please check digits.",
16000 			    curr_lun, curr_pwwn);
16001 			continue;
16002 		}
16003 		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16004 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16005 			    "the blacklist, please check the length of LUN#.",
16006 			    curr_lun, curr_pwwn);
16007 			break;
16008 		}
16009 		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
16010 			offset++;
16011 			continue;
16012 		}
16013 
16014 		bcopy(curr_lun + offset, lunid_buf, idx);
16015 		lunid_buf[idx] = '\0';
16016 		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16017 			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16018 		} else {
16019 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16020 			    "the blacklist, please check %s.",
16021 			    curr_lun, curr_pwwn, lunid_buf);
16022 		}
16023 		offset += (idx+1);	/* To the start of next lun */
16024 		idx = 0;
16025 	}
16026 }
16027 
16028 /*
16029  * Add one masking record
16030  */
16031 static void
16032 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16033     struct fcp_black_list_entry **pplun_blacklist)
16034 {
16035 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16036 	struct fcp_black_list_entry	*new_entry	= NULL;
16037 	la_wwn_t			wwn;
16038 
16039 	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16040 	while (tmp_entry) {
16041 		if ((bcmp(&tmp_entry->wwn, &wwn,
16042 		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16043 			return;
16044 		}
16045 
16046 		tmp_entry = tmp_entry->next;
16047 	}
16048 
16049 	/* add to black list */
16050 	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16051 	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16052 	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16053 	new_entry->lun = lun_id;
16054 	new_entry->masked = 0;
16055 	new_entry->next = *pplun_blacklist;
16056 	*pplun_blacklist = new_entry;
16057 }
16058 
16059 /*
16060  * Check if we should mask the specified lun of this fcp_tgt
16061  */
16062 static int
16063 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id)
16064 {
16065 	struct fcp_black_list_entry *remote_port;
16066 
16067 	remote_port = fcp_lun_blacklist;
16068 	while (remote_port != NULL) {
16069 		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16070 			if (remote_port->lun == lun_id) {
16071 				remote_port->masked++;
16072 				if (remote_port->masked == 1) {
16073 					fcp_log(CE_NOTE, NULL, "LUN %d of port "
16074 					    "%02x%02x%02x%02x%02x%02x%02x%02x "
16075 					    "is masked due to black listing.\n",
16076 					    lun_id, wwn->raw_wwn[0],
16077 					    wwn->raw_wwn[1], wwn->raw_wwn[2],
16078 					    wwn->raw_wwn[3], wwn->raw_wwn[4],
16079 					    wwn->raw_wwn[5], wwn->raw_wwn[6],
16080 					    wwn->raw_wwn[7]);
16081 				}
16082 				return (TRUE);
16083 			}
16084 		}
16085 		remote_port = remote_port->next;
16086 	}
16087 	return (FALSE);
16088 }
16089 
16090 /*
16091  * Release all allocated resources
16092  */
16093 static void
16094 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist)
16095 {
16096 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16097 	struct fcp_black_list_entry	*current_entry	= NULL;
16098 
16099 	ASSERT(mutex_owned(&fcp_global_mutex));
16100 	/*
16101 	 * Traverse all luns
16102 	 */
16103 	while (tmp_entry) {
16104 		current_entry = tmp_entry;
16105 		tmp_entry = tmp_entry->next;
16106 		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16107 	}
16108 	*pplun_blacklist = NULL;
16109 }
16110 
16111 /*
16112  * In fcp module,
16113  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16114  */
16115 static struct scsi_pkt *
16116 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16117     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16118     int flags, int (*callback)(), caddr_t arg)
16119 {
16120 	fcp_port_t	*pptr = ADDR2FCP(ap);
16121 	fcp_pkt_t	*cmd  = NULL;
16122 	fc_frame_hdr_t	*hp;
16123 
16124 	/*
16125 	 * First step: get the packet
16126 	 */
16127 	if (pkt == NULL) {
16128 		pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16129 		    tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16130 		    callback, arg);
16131 		if (pkt == NULL) {
16132 			return (NULL);
16133 		}
16134 
16135 		/*
16136 		 * All fields in scsi_pkt will be initialized properly or
16137 		 * set to zero. We need do nothing for scsi_pkt.
16138 		 */
16139 		/*
16140 		 * But it's our responsibility to link other related data
16141 		 * structures. Their initialization will be done, just
16142 		 * before the scsi_pkt will be sent to FCA.
16143 		 */
16144 		cmd		= PKT2CMD(pkt);
16145 		cmd->cmd_pkt	= pkt;
16146 		cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16147 		/*
16148 		 * fc_packet_t
16149 		 */
16150 		cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16151 		cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16152 		    sizeof (struct fcp_pkt));
16153 		cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16154 		cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16155 		cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16156 		cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16157 		/*
16158 		 * Fill in the Fabric Channel Header
16159 		 */
16160 		hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16161 		hp->r_ctl = R_CTL_COMMAND;
16162 		hp->rsvd = 0;
16163 		hp->type = FC_TYPE_SCSI_FCP;
16164 		hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16165 		hp->seq_id = 0;
16166 		hp->df_ctl  = 0;
16167 		hp->seq_cnt = 0;
16168 		hp->ox_id = 0xffff;
16169 		hp->rx_id = 0xffff;
16170 		hp->ro = 0;
16171 	} else {
16172 		/*
16173 		 * We need think if we should reset any elements in
16174 		 * related data structures.
16175 		 */
16176 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
16177 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
16178 		    "reusing pkt, flags %d", flags);
16179 		cmd = PKT2CMD(pkt);
16180 		if (cmd->cmd_fp_pkt->pkt_pd) {
16181 			cmd->cmd_fp_pkt->pkt_pd = NULL;
16182 		}
16183 	}
16184 
16185 	/*
16186 	 * Second step:	 dma allocation/move
16187 	 */
16188 	if (bp && bp->b_bcount != 0) {
16189 		/*
16190 		 * Mark if it's read or write
16191 		 */
16192 		if (bp->b_flags & B_READ) {
16193 			cmd->cmd_flags |= CFLAG_IS_READ;
16194 		} else {
16195 			cmd->cmd_flags &= ~CFLAG_IS_READ;
16196 		}
16197 
16198 		bp_mapin(bp);
16199 		cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16200 		cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16201 		cmd->cmd_fp_pkt->pkt_data_resid = 0;
16202 	} else {
16203 		/*
16204 		 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16205 		 * to send zero-length read/write.
16206 		 */
16207 		cmd->cmd_fp_pkt->pkt_data = NULL;
16208 		cmd->cmd_fp_pkt->pkt_datalen = 0;
16209 	}
16210 
16211 	return (pkt);
16212 }
16213 
16214 static void
16215 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16216 {
16217 	fcp_port_t	*pptr = ADDR2FCP(ap);
16218 
16219 	/*
16220 	 * First we let FCA to uninitilize private part.
16221 	 */
16222 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16223 	    PKT2CMD(pkt)->cmd_fp_pkt);
16224 
16225 	/*
16226 	 * Then we uninitialize fc_packet.
16227 	 */
16228 
16229 	/*
16230 	 * Thirdly, we uninitializae fcp_pkt.
16231 	 */
16232 
16233 	/*
16234 	 * In the end, we free scsi_pkt.
16235 	 */
16236 	scsi_hba_pkt_free(ap, pkt);
16237 }
16238 
16239 static int
16240 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16241 {
16242 	fcp_port_t	*pptr = ADDR2FCP(ap);
16243 	fcp_lun_t	*plun = ADDR2LUN(ap);
16244 	fcp_tgt_t	*ptgt = plun->lun_tgt;
16245 	fcp_pkt_t	*cmd  = PKT2CMD(pkt);
16246 	fcp_cmd_t	*fcmd = &cmd->cmd_fcp_cmd;
16247 	fc_packet_t	*fpkt = cmd->cmd_fp_pkt;
16248 	int		 rval;
16249 
16250 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
16251 	(void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16252 
16253 	/*
16254 	 * Firstly, we need initialize fcp_pkt_t
16255 	 * Secondly, we need initialize fcp_cmd_t.
16256 	 */
16257 	bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16258 	fcmd->fcp_data_len = fpkt->pkt_datalen;
16259 	fcmd->fcp_ent_addr = plun->lun_addr;
16260 	if (pkt->pkt_flags & FLAG_HTAG) {
16261 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16262 	} else if (pkt->pkt_flags & FLAG_OTAG) {
16263 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16264 	} else if (pkt->pkt_flags & FLAG_STAG) {
16265 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16266 	} else {
16267 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16268 	}
16269 
16270 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16271 		fcmd->fcp_cntl.cntl_read_data = 1;
16272 		fcmd->fcp_cntl.cntl_write_data = 0;
16273 	} else {
16274 		fcmd->fcp_cntl.cntl_read_data = 0;
16275 		fcmd->fcp_cntl.cntl_write_data = 1;
16276 	}
16277 
16278 	/*
16279 	 * Then we need initialize fc_packet_t too.
16280 	 */
16281 	fpkt->pkt_timeout = pkt->pkt_time + 2;
16282 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16283 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16284 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16285 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16286 	} else {
16287 		fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16288 	}
16289 
16290 	if (pkt->pkt_flags & FLAG_NOINTR) {
16291 		fpkt->pkt_comp = NULL;
16292 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16293 	} else {
16294 		fpkt->pkt_comp = fcp_cmd_callback;
16295 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16296 		if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16297 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16298 		}
16299 	}
16300 
16301 	/*
16302 	 * Lastly, we need initialize scsi_pkt
16303 	 */
16304 	pkt->pkt_reason = CMD_CMPLT;
16305 	pkt->pkt_state = 0;
16306 	pkt->pkt_statistics = 0;
16307 	pkt->pkt_resid = 0;
16308 
16309 	/*
16310 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
16311 	 * have to do polled I/O
16312 	 */
16313 	if (pkt->pkt_flags & FLAG_NOINTR) {
16314 		return (fcp_dopoll(pptr, cmd));
16315 	}
16316 
16317 	cmd->cmd_state = FCP_PKT_ISSUED;
16318 	rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16319 	if (rval == FC_SUCCESS) {
16320 		return (TRAN_ACCEPT);
16321 	}
16322 
16323 	/*
16324 	 * Need more consideration
16325 	 *
16326 	 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16327 	 */
16328 	cmd->cmd_state = FCP_PKT_IDLE;
16329 	if (rval == FC_TRAN_BUSY) {
16330 		return (TRAN_BUSY);
16331 	} else {
16332 		return (TRAN_FATAL_ERROR);
16333 	}
16334 }
16335 
16336 /*
16337  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16338  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16339  */
16340 static void
16341 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16342 {
16343 	FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16344 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16345 }
16346 
16347 /*
16348  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16349  */
16350 static void
16351 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16352 {
16353 	FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16354 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16355 }
16356