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 				ndi_devi_exit(pdip, circ);
8223 				/*
8224 				 * Release parent lock before calling
8225 				 * devfs_clean().
8226 				 */
8227 				rval = devfs_clean(pdip, devname + 1,
8228 				    DV_CLEAN_FORCE);
8229 				kmem_free(devname, MAXNAMELEN + 1);
8230 				/*
8231 				 * Return if devfs_clean() fails for
8232 				 * non-MPXIO case.
8233 				 * For MPXIO case, another path could be
8234 				 * offlined.
8235 				 */
8236 				if (rval && plun->lun_mpxio == 0) {
8237 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8238 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8239 					    "fcp_trigger_lun: devfs_clean "
8240 					    "failed rval=%x  dip=%p",
8241 					    rval, pdip);
8242 					return (NDI_FAILURE);
8243 				}
8244 			}
8245 		}
8246 	}
8247 
8248 	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8249 		return (NDI_FAILURE);
8250 	}
8251 
8252 	if (is_mpxio) {
8253 		mdi_devi_enter(pptr->port_dip, &circ);
8254 	} else {
8255 		ndi_devi_enter(pptr->port_dip, &circ);
8256 	}
8257 
8258 	mutex_enter(&pptr->port_mutex);
8259 	mutex_enter(&plun->lun_mutex);
8260 
8261 	if (online == FCP_ONLINE) {
8262 		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8263 		if (ccip == NULL) {
8264 			goto fail;
8265 		}
8266 	} else {
8267 		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8268 			goto fail;
8269 		}
8270 		ccip = cip;
8271 	}
8272 
8273 	if (online == FCP_ONLINE) {
8274 		rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8275 		    &circ);
8276 		fc_ulp_log_device_event(pptr->port_fp_handle,
8277 		    FC_ULP_DEVICE_ONLINE);
8278 	} else {
8279 		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8280 		    &circ);
8281 		fc_ulp_log_device_event(pptr->port_fp_handle,
8282 		    FC_ULP_DEVICE_OFFLINE);
8283 	}
8284 
8285 fail:	mutex_exit(&plun->lun_mutex);
8286 	mutex_exit(&pptr->port_mutex);
8287 
8288 	if (is_mpxio) {
8289 		mdi_devi_exit(pptr->port_dip, circ);
8290 	} else {
8291 		ndi_devi_exit(pptr->port_dip, circ);
8292 	}
8293 
8294 	fc_ulp_idle_port(pptr->port_fp_handle);
8295 
8296 	return (rval);
8297 }
8298 
8299 
8300 /*
8301  * take a target offline by taking all of its LUNs offline
8302  */
8303 /*ARGSUSED*/
8304 static int
8305 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8306     int link_cnt, int tgt_cnt, int nowait, int flags)
8307 {
8308 	struct fcp_tgt_elem	*elem;
8309 
8310 	ASSERT(mutex_owned(&pptr->port_mutex));
8311 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8312 
8313 	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8314 
8315 	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8316 	    ptgt->tgt_change_cnt)) {
8317 		mutex_exit(&ptgt->tgt_mutex);
8318 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8319 		mutex_enter(&ptgt->tgt_mutex);
8320 
8321 		return (0);
8322 	}
8323 
8324 	ptgt->tgt_pd_handle = NULL;
8325 	mutex_exit(&ptgt->tgt_mutex);
8326 	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8327 	mutex_enter(&ptgt->tgt_mutex);
8328 
8329 	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8330 
8331 	if (ptgt->tgt_tcap &&
8332 	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8333 		elem->flags = flags;
8334 		elem->time = fcp_watchdog_time;
8335 		if (nowait == 0) {
8336 			elem->time += fcp_offline_delay;
8337 		}
8338 		elem->ptgt = ptgt;
8339 		elem->link_cnt = link_cnt;
8340 		elem->tgt_cnt = tgt_cnt;
8341 		elem->next = pptr->port_offline_tgts;
8342 		pptr->port_offline_tgts = elem;
8343 	} else {
8344 		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8345 	}
8346 
8347 	return (1);
8348 }
8349 
8350 
8351 static void
8352 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8353     int link_cnt, int tgt_cnt, int flags)
8354 {
8355 	ASSERT(mutex_owned(&pptr->port_mutex));
8356 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8357 
8358 	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8359 	ptgt->tgt_state = FCP_TGT_OFFLINE;
8360 	ptgt->tgt_pd_handle = NULL;
8361 	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8362 }
8363 
8364 
8365 static void
8366 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8367     int flags)
8368 {
8369 	struct	fcp_lun	*plun;
8370 
8371 	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8372 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8373 
8374 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8375 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8376 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8377 		}
8378 	}
8379 }
8380 
8381 
8382 /*
8383  * take a LUN offline
8384  *
8385  * enters and leaves with the target mutex held, releasing it in the process
8386  *
8387  * allocates memory in non-sleep mode
8388  */
8389 static void
8390 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8391     int nowait, int flags)
8392 {
8393 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8394 	struct fcp_lun_elem	*elem;
8395 
8396 	ASSERT(plun != NULL);
8397 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8398 
8399 	if (nowait) {
8400 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8401 		return;
8402 	}
8403 
8404 	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8405 		elem->flags = flags;
8406 		elem->time = fcp_watchdog_time;
8407 		if (nowait == 0) {
8408 			elem->time += fcp_offline_delay;
8409 		}
8410 		elem->plun = plun;
8411 		elem->link_cnt = link_cnt;
8412 		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8413 		elem->next = pptr->port_offline_luns;
8414 		pptr->port_offline_luns = elem;
8415 	} else {
8416 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8417 	}
8418 }
8419 
8420 
8421 static void
8422 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8423 {
8424 	struct fcp_pkt	*head = NULL;
8425 
8426 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8427 
8428 	mutex_exit(&LUN_TGT->tgt_mutex);
8429 
8430 	head = fcp_scan_commands(plun);
8431 	if (head != NULL) {
8432 		fcp_abort_commands(head, LUN_PORT);
8433 	}
8434 
8435 	mutex_enter(&LUN_TGT->tgt_mutex);
8436 
8437 	if (plun->lun_cip && plun->lun_mpxio) {
8438 		/*
8439 		 * Intimate MPxIO lun busy is cleared
8440 		 */
8441 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8442 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8443 		    0, 0)) {
8444 			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8445 			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8446 			    LUN_TGT->tgt_d_id, plun->lun_num);
8447 		}
8448 		/*
8449 		 * Intimate MPxIO that the lun is now marked for offline
8450 		 */
8451 		mutex_exit(&LUN_TGT->tgt_mutex);
8452 		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8453 		mutex_enter(&LUN_TGT->tgt_mutex);
8454 	}
8455 }
8456 
8457 static void
8458 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8459     int flags)
8460 {
8461 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8462 
8463 	mutex_exit(&LUN_TGT->tgt_mutex);
8464 	fcp_update_offline_flags(plun);
8465 	mutex_enter(&LUN_TGT->tgt_mutex);
8466 
8467 	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8468 
8469 	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8470 	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8471 	    "offline_lun: passing OFFLINE elem to HP thread");
8472 
8473 	if (plun->lun_cip) {
8474 		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8475 		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8476 		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8477 		    LUN_TGT->tgt_trace);
8478 
8479 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8480 		    link_cnt, tgt_cnt, flags, 0)) {
8481 			fcp_log(CE_CONT, LUN_PORT->port_dip,
8482 			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8483 			    LUN_TGT->tgt_d_id, plun->lun_num);
8484 		}
8485 	}
8486 }
8487 
8488 static void
8489 fcp_scan_offline_luns(struct fcp_port *pptr)
8490 {
8491 	struct fcp_lun_elem	*elem;
8492 	struct fcp_lun_elem	*prev;
8493 	struct fcp_lun_elem	*next;
8494 
8495 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8496 
8497 	prev = NULL;
8498 	elem = pptr->port_offline_luns;
8499 	while (elem) {
8500 		next = elem->next;
8501 		if (elem->time <= fcp_watchdog_time) {
8502 			int			changed = 1;
8503 			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8504 
8505 			mutex_enter(&ptgt->tgt_mutex);
8506 			if (pptr->port_link_cnt == elem->link_cnt &&
8507 			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8508 				changed = 0;
8509 			}
8510 
8511 			if (!changed &&
8512 			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8513 				fcp_offline_lun_now(elem->plun,
8514 				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8515 			}
8516 			mutex_exit(&ptgt->tgt_mutex);
8517 
8518 			kmem_free(elem, sizeof (*elem));
8519 
8520 			if (prev) {
8521 				prev->next = next;
8522 			} else {
8523 				pptr->port_offline_luns = next;
8524 			}
8525 		} else {
8526 			prev = elem;
8527 		}
8528 		elem = next;
8529 	}
8530 }
8531 
8532 
8533 static void
8534 fcp_scan_offline_tgts(struct fcp_port *pptr)
8535 {
8536 	struct fcp_tgt_elem	*elem;
8537 	struct fcp_tgt_elem	*prev;
8538 	struct fcp_tgt_elem	*next;
8539 
8540 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8541 
8542 	prev = NULL;
8543 	elem = pptr->port_offline_tgts;
8544 	while (elem) {
8545 		next = elem->next;
8546 		if (elem->time <= fcp_watchdog_time) {
8547 			int		outdated = 1;
8548 			struct fcp_tgt	*ptgt = elem->ptgt;
8549 
8550 			mutex_enter(&ptgt->tgt_mutex);
8551 
8552 			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8553 				/* No change on tgt since elem was created. */
8554 				outdated = 0;
8555 			} else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8556 			    pptr->port_link_cnt == elem->link_cnt + 1 &&
8557 			    ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8558 				/*
8559 				 * Exactly one thing happened to the target
8560 				 * inbetween: the local port went offline.
8561 				 * For fp the remote port is already gone so
8562 				 * it will not tell us again to offline the
8563 				 * target. We must offline it now.
8564 				 */
8565 				outdated = 0;
8566 			}
8567 
8568 			if (!outdated && !(ptgt->tgt_state &
8569 			    FCP_TGT_OFFLINE)) {
8570 				fcp_offline_target_now(pptr,
8571 				    ptgt, elem->link_cnt, elem->tgt_cnt,
8572 				    elem->flags);
8573 			}
8574 
8575 			mutex_exit(&ptgt->tgt_mutex);
8576 
8577 			kmem_free(elem, sizeof (*elem));
8578 
8579 			if (prev) {
8580 				prev->next = next;
8581 			} else {
8582 				pptr->port_offline_tgts = next;
8583 			}
8584 		} else {
8585 			prev = elem;
8586 		}
8587 		elem = next;
8588 	}
8589 }
8590 
8591 
8592 static void
8593 fcp_update_offline_flags(struct fcp_lun *plun)
8594 {
8595 	struct fcp_port	*pptr = LUN_PORT;
8596 	ASSERT(plun != NULL);
8597 
8598 	mutex_enter(&LUN_TGT->tgt_mutex);
8599 	plun->lun_state |= FCP_LUN_OFFLINE;
8600 	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8601 
8602 	mutex_enter(&plun->lun_mutex);
8603 	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8604 		dev_info_t *cdip = NULL;
8605 
8606 		mutex_exit(&LUN_TGT->tgt_mutex);
8607 
8608 		if (plun->lun_mpxio == 0) {
8609 			cdip = DIP(plun->lun_cip);
8610 		} else if (plun->lun_cip) {
8611 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8612 		}
8613 
8614 		mutex_exit(&plun->lun_mutex);
8615 		if (cdip) {
8616 			(void) ndi_event_retrieve_cookie(
8617 			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8618 			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8619 			(void) ndi_event_run_callbacks(
8620 			    pptr->port_ndi_event_hdl, cdip,
8621 			    fcp_remove_eid, NULL);
8622 		}
8623 	} else {
8624 		mutex_exit(&plun->lun_mutex);
8625 		mutex_exit(&LUN_TGT->tgt_mutex);
8626 	}
8627 }
8628 
8629 
8630 /*
8631  * Scan all of the command pkts for this port, moving pkts that
8632  * match our LUN onto our own list (headed by "head")
8633  */
8634 static struct fcp_pkt *
8635 fcp_scan_commands(struct fcp_lun *plun)
8636 {
8637 	struct fcp_port	*pptr = LUN_PORT;
8638 
8639 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8640 	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8641 	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8642 
8643 	struct fcp_pkt	*head = NULL;	/* head of our list */
8644 	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8645 
8646 	int			cmds_found = 0;
8647 
8648 	mutex_enter(&pptr->port_pkt_mutex);
8649 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8650 		struct fcp_lun *tlun =
8651 		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8652 
8653 		ncmd = cmd->cmd_next;	/* set next command */
8654 
8655 		/*
8656 		 * if this pkt is for a different LUN  or the
8657 		 * command is sent down, skip it.
8658 		 */
8659 		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8660 		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8661 			pcmd = cmd;
8662 			continue;
8663 		}
8664 		cmds_found++;
8665 		if (pcmd != NULL) {
8666 			ASSERT(pptr->port_pkt_head != cmd);
8667 			pcmd->cmd_next = cmd->cmd_next;
8668 		} else {
8669 			ASSERT(cmd == pptr->port_pkt_head);
8670 			pptr->port_pkt_head = cmd->cmd_next;
8671 		}
8672 
8673 		if (cmd == pptr->port_pkt_tail) {
8674 			pptr->port_pkt_tail = pcmd;
8675 			if (pcmd) {
8676 				pcmd->cmd_next = NULL;
8677 			}
8678 		}
8679 
8680 		if (head == NULL) {
8681 			head = tail = cmd;
8682 		} else {
8683 			ASSERT(tail != NULL);
8684 
8685 			tail->cmd_next = cmd;
8686 			tail = cmd;
8687 		}
8688 		cmd->cmd_next = NULL;
8689 	}
8690 	mutex_exit(&pptr->port_pkt_mutex);
8691 
8692 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8693 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8694 	    "scan commands: %d cmd(s) found", cmds_found);
8695 
8696 	return (head);
8697 }
8698 
8699 
8700 /*
8701  * Abort all the commands in the command queue
8702  */
8703 static void
8704 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8705 {
8706 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8707 	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8708 
8709 	ASSERT(mutex_owned(&pptr->port_mutex));
8710 
8711 	/* scan through the pkts and invalid them */
8712 	for (cmd = head; cmd != NULL; cmd = ncmd) {
8713 		struct scsi_pkt *pkt = cmd->cmd_pkt;
8714 
8715 		ncmd = cmd->cmd_next;
8716 		ASSERT(pkt != NULL);
8717 
8718 		/*
8719 		 * The lun is going to be marked offline. Indicate
8720 		 * the target driver not to requeue or retry this command
8721 		 * as the device is going to be offlined pretty soon.
8722 		 */
8723 		pkt->pkt_reason = CMD_DEV_GONE;
8724 		pkt->pkt_statistics = 0;
8725 		pkt->pkt_state = 0;
8726 
8727 		/* reset cmd flags/state */
8728 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8729 		cmd->cmd_state = FCP_PKT_IDLE;
8730 
8731 		/*
8732 		 * ensure we have a packet completion routine,
8733 		 * then call it.
8734 		 */
8735 		ASSERT(pkt->pkt_comp != NULL);
8736 
8737 		mutex_exit(&pptr->port_mutex);
8738 		fcp_post_callback(cmd);
8739 		mutex_enter(&pptr->port_mutex);
8740 	}
8741 }
8742 
8743 
8744 /*
8745  * the pkt_comp callback for command packets
8746  */
8747 static void
8748 fcp_cmd_callback(fc_packet_t *fpkt)
8749 {
8750 	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8751 	struct scsi_pkt *pkt = cmd->cmd_pkt;
8752 	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8753 
8754 	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8755 
8756 	if (cmd->cmd_state == FCP_PKT_IDLE) {
8757 		cmn_err(CE_PANIC, "Packet already completed %p",
8758 		    (void *)cmd);
8759 	}
8760 
8761 	/*
8762 	 * Watch thread should be freeing the packet, ignore the pkt.
8763 	 */
8764 	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8765 		fcp_log(CE_CONT, pptr->port_dip,
8766 		    "!FCP: Pkt completed while aborting\n");
8767 		return;
8768 	}
8769 	cmd->cmd_state = FCP_PKT_IDLE;
8770 
8771 	fcp_complete_pkt(fpkt);
8772 
8773 #ifdef	DEBUG
8774 	mutex_enter(&pptr->port_pkt_mutex);
8775 	pptr->port_npkts--;
8776 	mutex_exit(&pptr->port_pkt_mutex);
8777 #endif /* DEBUG */
8778 
8779 	fcp_post_callback(cmd);
8780 }
8781 
8782 
8783 static void
8784 fcp_complete_pkt(fc_packet_t *fpkt)
8785 {
8786 	int			error = 0;
8787 	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8788 	    fpkt->pkt_ulp_private;
8789 	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8790 	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8791 	struct fcp_lun	*plun;
8792 	struct fcp_tgt	*ptgt;
8793 	struct fcp_rsp		*rsp;
8794 	struct scsi_address	save;
8795 
8796 #ifdef	DEBUG
8797 	save = pkt->pkt_address;
8798 #endif /* DEBUG */
8799 
8800 	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8801 
8802 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8803 		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8804 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8805 			    sizeof (struct fcp_rsp));
8806 		}
8807 
8808 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8809 		    STATE_SENT_CMD | STATE_GOT_STATUS;
8810 
8811 		pkt->pkt_resid = 0;
8812 
8813 		if (fpkt->pkt_datalen) {
8814 			pkt->pkt_state |= STATE_XFERRED_DATA;
8815 			if (fpkt->pkt_data_resid) {
8816 				error++;
8817 			}
8818 		}
8819 
8820 		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8821 		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8822 			/*
8823 			 * The next two checks make sure that if there
8824 			 * is no sense data or a valid response and
8825 			 * the command came back with check condition,
8826 			 * the command should be retried.
8827 			 */
8828 			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8829 			    !rsp->fcp_u.fcp_status.sense_len_set) {
8830 				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8831 				pkt->pkt_resid = cmd->cmd_dmacount;
8832 			}
8833 		}
8834 
8835 		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8836 			return;
8837 		}
8838 
8839 		plun = ADDR2LUN(&pkt->pkt_address);
8840 		ptgt = plun->lun_tgt;
8841 		ASSERT(ptgt != NULL);
8842 
8843 		/*
8844 		 * Update the transfer resid, if appropriate
8845 		 */
8846 		if (rsp->fcp_u.fcp_status.resid_over ||
8847 		    rsp->fcp_u.fcp_status.resid_under) {
8848 			pkt->pkt_resid = rsp->fcp_resid;
8849 		}
8850 
8851 		/*
8852 		 * First see if we got a FCP protocol error.
8853 		 */
8854 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8855 			struct fcp_rsp_info	*bep;
8856 			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8857 			    sizeof (struct fcp_rsp));
8858 
8859 			if (fcp_validate_fcp_response(rsp, pptr) !=
8860 			    FC_SUCCESS) {
8861 				pkt->pkt_reason = CMD_CMPLT;
8862 				*(pkt->pkt_scbp) = STATUS_CHECK;
8863 
8864 				fcp_log(CE_WARN, pptr->port_dip,
8865 				    "!SCSI command to d_id=0x%x lun=0x%x"
8866 				    " failed, Bad FCP response values:"
8867 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8868 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8869 				    ptgt->tgt_d_id, plun->lun_num,
8870 				    rsp->reserved_0, rsp->reserved_1,
8871 				    rsp->fcp_u.fcp_status.reserved_0,
8872 				    rsp->fcp_u.fcp_status.reserved_1,
8873 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8874 
8875 				return;
8876 			}
8877 
8878 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8879 				FCP_CP_IN(fpkt->pkt_resp +
8880 				    sizeof (struct fcp_rsp), bep,
8881 				    fpkt->pkt_resp_acc,
8882 				    sizeof (struct fcp_rsp_info));
8883 			}
8884 
8885 			if (bep->rsp_code != FCP_NO_FAILURE) {
8886 				child_info_t	*cip;
8887 
8888 				pkt->pkt_reason = CMD_TRAN_ERR;
8889 
8890 				mutex_enter(&plun->lun_mutex);
8891 				cip = plun->lun_cip;
8892 				mutex_exit(&plun->lun_mutex);
8893 
8894 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8895 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8896 				    "FCP response error on cmd=%p"
8897 				    " target=0x%x, cip=%p", cmd,
8898 				    ptgt->tgt_d_id, cip);
8899 			}
8900 		}
8901 
8902 		/*
8903 		 * See if we got a SCSI error with sense data
8904 		 */
8905 		if (rsp->fcp_u.fcp_status.sense_len_set) {
8906 			uchar_t				rqlen;
8907 			caddr_t				sense_from;
8908 			child_info_t			*cip;
8909 			timeout_id_t			tid;
8910 			struct scsi_arq_status		*arq;
8911 			struct scsi_extended_sense	*sense_to;
8912 
8913 			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8914 			sense_to = &arq->sts_sensedata;
8915 
8916 			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8917 			    sizeof (struct scsi_extended_sense));
8918 
8919 			sense_from = (caddr_t)fpkt->pkt_resp +
8920 			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8921 
8922 			if (fcp_validate_fcp_response(rsp, pptr) !=
8923 			    FC_SUCCESS) {
8924 				pkt->pkt_reason = CMD_CMPLT;
8925 				*(pkt->pkt_scbp) = STATUS_CHECK;
8926 
8927 				fcp_log(CE_WARN, pptr->port_dip,
8928 				    "!SCSI command to d_id=0x%x lun=0x%x"
8929 				    " failed, Bad FCP response values:"
8930 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8931 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8932 				    ptgt->tgt_d_id, plun->lun_num,
8933 				    rsp->reserved_0, rsp->reserved_1,
8934 				    rsp->fcp_u.fcp_status.reserved_0,
8935 				    rsp->fcp_u.fcp_status.reserved_1,
8936 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8937 
8938 				return;
8939 			}
8940 
8941 			/*
8942 			 * copy in sense information
8943 			 */
8944 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8945 				FCP_CP_IN(sense_from, sense_to,
8946 				    fpkt->pkt_resp_acc, rqlen);
8947 			} else {
8948 				bcopy(sense_from, sense_to, rqlen);
8949 			}
8950 
8951 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8952 			    (FCP_SENSE_NO_LUN(sense_to))) {
8953 				mutex_enter(&ptgt->tgt_mutex);
8954 				if (ptgt->tgt_tid == NULL) {
8955 					/*
8956 					 * Kick off rediscovery
8957 					 */
8958 					tid = timeout(fcp_reconfigure_luns,
8959 					    (caddr_t)ptgt, drv_usectohz(1));
8960 
8961 					ptgt->tgt_tid = tid;
8962 					ptgt->tgt_state |= FCP_TGT_BUSY;
8963 				}
8964 				mutex_exit(&ptgt->tgt_mutex);
8965 				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8966 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8967 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8968 					    "!FCP: Report Lun Has Changed"
8969 					    " target=%x", ptgt->tgt_d_id);
8970 				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8971 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8972 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8973 					    "!FCP: LU Not Supported"
8974 					    " target=%x", ptgt->tgt_d_id);
8975 				}
8976 			}
8977 			ASSERT(pkt->pkt_scbp != NULL);
8978 
8979 			pkt->pkt_state |= STATE_ARQ_DONE;
8980 
8981 			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8982 
8983 			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8984 			arq->sts_rqpkt_reason = 0;
8985 			arq->sts_rqpkt_statistics = 0;
8986 
8987 			arq->sts_rqpkt_state = STATE_GOT_BUS |
8988 			    STATE_GOT_TARGET | STATE_SENT_CMD |
8989 			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8990 			    STATE_XFERRED_DATA;
8991 
8992 			mutex_enter(&plun->lun_mutex);
8993 			cip = plun->lun_cip;
8994 			mutex_exit(&plun->lun_mutex);
8995 
8996 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8997 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
8998 			    "SCSI Check condition on cmd=%p target=0x%x"
8999 			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
9000 			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9001 			    cmd->cmd_fcp_cmd.fcp_cdb[0],
9002 			    rsp->fcp_u.fcp_status.scsi_status,
9003 			    sense_to->es_key, sense_to->es_add_code,
9004 			    sense_to->es_qual_code);
9005 		}
9006 	} else {
9007 		plun = ADDR2LUN(&pkt->pkt_address);
9008 		ptgt = plun->lun_tgt;
9009 		ASSERT(ptgt != NULL);
9010 
9011 		/*
9012 		 * Work harder to translate errors into target driver
9013 		 * understandable ones. Note with despair that the target
9014 		 * drivers don't decode pkt_state and pkt_reason exhaustively
9015 		 * They resort to using the big hammer most often, which
9016 		 * may not get fixed in the life time of this driver.
9017 		 */
9018 		pkt->pkt_state = 0;
9019 		pkt->pkt_statistics = 0;
9020 
9021 		switch (fpkt->pkt_state) {
9022 		case FC_PKT_TRAN_ERROR:
9023 			switch (fpkt->pkt_reason) {
9024 			case FC_REASON_OVERRUN:
9025 				pkt->pkt_reason = CMD_CMD_OVR;
9026 				pkt->pkt_statistics |= STAT_ABORTED;
9027 				break;
9028 
9029 			case FC_REASON_XCHG_BSY: {
9030 				caddr_t ptr;
9031 
9032 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9033 
9034 				ptr = (caddr_t)pkt->pkt_scbp;
9035 				if (ptr) {
9036 					*ptr = STATUS_BUSY;
9037 				}
9038 				break;
9039 			}
9040 
9041 			case FC_REASON_ABORTED:
9042 				pkt->pkt_reason = CMD_TRAN_ERR;
9043 				pkt->pkt_statistics |= STAT_ABORTED;
9044 				break;
9045 
9046 			case FC_REASON_ABORT_FAILED:
9047 				pkt->pkt_reason = CMD_ABORT_FAIL;
9048 				break;
9049 
9050 			case FC_REASON_NO_SEQ_INIT:
9051 			case FC_REASON_CRC_ERROR:
9052 				pkt->pkt_reason = CMD_TRAN_ERR;
9053 				pkt->pkt_statistics |= STAT_ABORTED;
9054 				break;
9055 			default:
9056 				pkt->pkt_reason = CMD_TRAN_ERR;
9057 				break;
9058 			}
9059 			break;
9060 
9061 		case FC_PKT_PORT_OFFLINE: {
9062 			dev_info_t	*cdip = NULL;
9063 			caddr_t		ptr;
9064 
9065 			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9066 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9067 				    fcp_trace, FCP_BUF_LEVEL_8, 0,
9068 				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9069 				    ptgt->tgt_d_id);
9070 			}
9071 
9072 			mutex_enter(&plun->lun_mutex);
9073 			if (plun->lun_mpxio == 0) {
9074 				cdip = DIP(plun->lun_cip);
9075 			} else if (plun->lun_cip) {
9076 				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9077 			}
9078 
9079 			mutex_exit(&plun->lun_mutex);
9080 
9081 			if (cdip) {
9082 				(void) ndi_event_retrieve_cookie(
9083 				    pptr->port_ndi_event_hdl, cdip,
9084 				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9085 				    NDI_EVENT_NOPASS);
9086 				(void) ndi_event_run_callbacks(
9087 				    pptr->port_ndi_event_hdl, cdip,
9088 				    fcp_remove_eid, NULL);
9089 			}
9090 
9091 			/*
9092 			 * If the link goes off-line for a lip,
9093 			 * this will cause a error to the ST SG
9094 			 * SGEN drivers. By setting BUSY we will
9095 			 * give the drivers the chance to retry
9096 			 * before it blows of the job. ST will
9097 			 * remember how many times it has retried.
9098 			 */
9099 
9100 			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9101 			    (plun->lun_type == DTYPE_CHANGER)) {
9102 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9103 				ptr = (caddr_t)pkt->pkt_scbp;
9104 				if (ptr) {
9105 					*ptr = STATUS_BUSY;
9106 				}
9107 			} else {
9108 				pkt->pkt_reason = CMD_TRAN_ERR;
9109 				pkt->pkt_statistics |= STAT_BUS_RESET;
9110 			}
9111 			break;
9112 		}
9113 
9114 		case FC_PKT_TRAN_BSY:
9115 			/*
9116 			 * Use the ssd Qfull handling here.
9117 			 */
9118 			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9119 			pkt->pkt_state = STATE_GOT_BUS;
9120 			break;
9121 
9122 		case FC_PKT_TIMEOUT:
9123 			pkt->pkt_reason = CMD_TIMEOUT;
9124 			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9125 				pkt->pkt_statistics |= STAT_TIMEOUT;
9126 			} else {
9127 				pkt->pkt_statistics |= STAT_ABORTED;
9128 			}
9129 			break;
9130 
9131 		case FC_PKT_LOCAL_RJT:
9132 			switch (fpkt->pkt_reason) {
9133 			case FC_REASON_OFFLINE: {
9134 				dev_info_t	*cdip = NULL;
9135 
9136 				mutex_enter(&plun->lun_mutex);
9137 				if (plun->lun_mpxio == 0) {
9138 					cdip = DIP(plun->lun_cip);
9139 				} else if (plun->lun_cip) {
9140 					cdip = mdi_pi_get_client(
9141 					    PIP(plun->lun_cip));
9142 				}
9143 				mutex_exit(&plun->lun_mutex);
9144 
9145 				if (cdip) {
9146 					(void) ndi_event_retrieve_cookie(
9147 					    pptr->port_ndi_event_hdl, cdip,
9148 					    FCAL_REMOVE_EVENT,
9149 					    &fcp_remove_eid,
9150 					    NDI_EVENT_NOPASS);
9151 					(void) ndi_event_run_callbacks(
9152 					    pptr->port_ndi_event_hdl,
9153 					    cdip, fcp_remove_eid, NULL);
9154 				}
9155 
9156 				pkt->pkt_reason = CMD_TRAN_ERR;
9157 				pkt->pkt_statistics |= STAT_BUS_RESET;
9158 
9159 				break;
9160 			}
9161 
9162 			case FC_REASON_NOMEM:
9163 			case FC_REASON_QFULL: {
9164 				caddr_t ptr;
9165 
9166 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9167 				ptr = (caddr_t)pkt->pkt_scbp;
9168 				if (ptr) {
9169 					*ptr = STATUS_BUSY;
9170 				}
9171 				break;
9172 			}
9173 
9174 			case FC_REASON_DMA_ERROR:
9175 				pkt->pkt_reason = CMD_DMA_DERR;
9176 				pkt->pkt_statistics |= STAT_ABORTED;
9177 				break;
9178 
9179 			case FC_REASON_CRC_ERROR:
9180 			case FC_REASON_UNDERRUN: {
9181 				uchar_t		status;
9182 				/*
9183 				 * Work around for Bugid: 4240945.
9184 				 * IB on A5k doesn't set the Underrun bit
9185 				 * in the fcp status, when it is transferring
9186 				 * less than requested amount of data. Work
9187 				 * around the ses problem to keep luxadm
9188 				 * happy till ibfirmware is fixed.
9189 				 */
9190 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9191 					FCP_CP_IN(fpkt->pkt_resp, rsp,
9192 					    fpkt->pkt_resp_acc,
9193 					    sizeof (struct fcp_rsp));
9194 				}
9195 				status = rsp->fcp_u.fcp_status.scsi_status;
9196 				if (((plun->lun_type & DTYPE_MASK) ==
9197 				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9198 					pkt->pkt_reason = CMD_CMPLT;
9199 					*pkt->pkt_scbp = status;
9200 					pkt->pkt_resid = 0;
9201 				} else {
9202 					pkt->pkt_reason = CMD_TRAN_ERR;
9203 					pkt->pkt_statistics |= STAT_ABORTED;
9204 				}
9205 				break;
9206 			}
9207 
9208 			case FC_REASON_NO_CONNECTION:
9209 			case FC_REASON_UNSUPPORTED:
9210 			case FC_REASON_ILLEGAL_REQ:
9211 			case FC_REASON_BAD_SID:
9212 			case FC_REASON_DIAG_BUSY:
9213 			case FC_REASON_FCAL_OPN_FAIL:
9214 			case FC_REASON_BAD_XID:
9215 			default:
9216 				pkt->pkt_reason = CMD_TRAN_ERR;
9217 				pkt->pkt_statistics |= STAT_ABORTED;
9218 				break;
9219 
9220 			}
9221 			break;
9222 
9223 		case FC_PKT_NPORT_RJT:
9224 		case FC_PKT_FABRIC_RJT:
9225 		case FC_PKT_NPORT_BSY:
9226 		case FC_PKT_FABRIC_BSY:
9227 		default:
9228 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9229 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9230 			    "FC Status 0x%x, reason 0x%x",
9231 			    fpkt->pkt_state, fpkt->pkt_reason);
9232 			pkt->pkt_reason = CMD_TRAN_ERR;
9233 			pkt->pkt_statistics |= STAT_ABORTED;
9234 			break;
9235 		}
9236 
9237 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9238 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9239 		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9240 		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9241 		    fpkt->pkt_reason);
9242 	}
9243 
9244 	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9245 }
9246 
9247 
9248 static int
9249 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9250 {
9251 	if (rsp->reserved_0 || rsp->reserved_1 ||
9252 	    rsp->fcp_u.fcp_status.reserved_0 ||
9253 	    rsp->fcp_u.fcp_status.reserved_1) {
9254 		/*
9255 		 * These reserved fields should ideally be zero. FCP-2 does say
9256 		 * that the recipient need not check for reserved fields to be
9257 		 * zero. If they are not zero, we will not make a fuss about it
9258 		 * - just log it (in debug to both trace buffer and messages
9259 		 * file and to trace buffer only in non-debug) and move on.
9260 		 *
9261 		 * Non-zero reserved fields were seen with minnows.
9262 		 *
9263 		 * qlc takes care of some of this but we cannot assume that all
9264 		 * FCAs will do so.
9265 		 */
9266 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9267 		    FCP_BUF_LEVEL_5, 0,
9268 		    "Got fcp response packet with non-zero reserved fields "
9269 		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9270 		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9271 		    rsp->reserved_0, rsp->reserved_1,
9272 		    rsp->fcp_u.fcp_status.reserved_0,
9273 		    rsp->fcp_u.fcp_status.reserved_1);
9274 	}
9275 
9276 	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9277 	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9278 		return (FC_FAILURE);
9279 	}
9280 
9281 	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9282 	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9283 	    sizeof (struct fcp_rsp))) {
9284 		return (FC_FAILURE);
9285 	}
9286 
9287 	return (FC_SUCCESS);
9288 }
9289 
9290 
9291 /*
9292  * This is called when there is a change the in device state. The case we're
9293  * handling here is, if the d_id s does not match, offline this tgt and online
9294  * a new tgt with the new d_id.	 called from fcp_handle_devices with
9295  * port_mutex held.
9296  */
9297 static int
9298 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9299     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9300 {
9301 	ASSERT(mutex_owned(&pptr->port_mutex));
9302 
9303 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9304 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9305 	    "Starting fcp_device_changed...");
9306 
9307 	/*
9308 	 * The two cases where the port_device_changed is called is
9309 	 * either it changes it's d_id or it's hard address.
9310 	 */
9311 	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9312 	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9313 	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9314 
9315 		/* offline this target */
9316 		mutex_enter(&ptgt->tgt_mutex);
9317 		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9318 			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9319 			    0, 1, NDI_DEVI_REMOVE);
9320 		}
9321 		mutex_exit(&ptgt->tgt_mutex);
9322 
9323 		fcp_log(CE_NOTE, pptr->port_dip,
9324 		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9325 		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9326 		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9327 		    map_entry->map_hard_addr.hard_addr);
9328 	}
9329 
9330 	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9331 	    link_cnt, tgt_cnt, cause));
9332 }
9333 
9334 /*
9335  *     Function: fcp_alloc_lun
9336  *
9337  *  Description: Creates a new lun structure and adds it to the list
9338  *		 of luns of the target.
9339  *
9340  *     Argument: ptgt		Target the lun will belong to.
9341  *
9342  * Return Value: NULL		Failed
9343  *		 Not NULL	Succeeded
9344  *
9345  *	Context: Kernel context
9346  */
9347 static struct fcp_lun *
9348 fcp_alloc_lun(struct fcp_tgt *ptgt)
9349 {
9350 	struct fcp_lun *plun;
9351 
9352 	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9353 	if (plun != NULL) {
9354 		/*
9355 		 * Initialize the mutex before putting in the target list
9356 		 * especially before releasing the target mutex.
9357 		 */
9358 		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9359 		plun->lun_tgt = ptgt;
9360 
9361 		mutex_enter(&ptgt->tgt_mutex);
9362 		plun->lun_next = ptgt->tgt_lun;
9363 		ptgt->tgt_lun = plun;
9364 		plun->lun_old_guid = NULL;
9365 		plun->lun_old_guid_size = 0;
9366 		mutex_exit(&ptgt->tgt_mutex);
9367 	}
9368 
9369 	return (plun);
9370 }
9371 
9372 /*
9373  *     Function: fcp_dealloc_lun
9374  *
9375  *  Description: Frees the LUN structure passed by the caller.
9376  *
9377  *     Argument: plun		LUN structure to free.
9378  *
9379  * Return Value: None
9380  *
9381  *	Context: Kernel context.
9382  */
9383 static void
9384 fcp_dealloc_lun(struct fcp_lun *plun)
9385 {
9386 	mutex_enter(&plun->lun_mutex);
9387 	if (plun->lun_cip) {
9388 		fcp_remove_child(plun);
9389 	}
9390 	mutex_exit(&plun->lun_mutex);
9391 
9392 	mutex_destroy(&plun->lun_mutex);
9393 	if (plun->lun_guid) {
9394 		kmem_free(plun->lun_guid, plun->lun_guid_size);
9395 	}
9396 	if (plun->lun_old_guid) {
9397 		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9398 	}
9399 	kmem_free(plun, sizeof (*plun));
9400 }
9401 
9402 /*
9403  *     Function: fcp_alloc_tgt
9404  *
9405  *  Description: Creates a new target structure and adds it to the port
9406  *		 hash list.
9407  *
9408  *     Argument: pptr		fcp port structure
9409  *		 *map_entry	entry describing the target to create
9410  *		 link_cnt	Link state change counter
9411  *
9412  * Return Value: NULL		Failed
9413  *		 Not NULL	Succeeded
9414  *
9415  *	Context: Kernel context.
9416  */
9417 static struct fcp_tgt *
9418 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9419 {
9420 	int			hash;
9421 	uchar_t			*wwn;
9422 	struct fcp_tgt	*ptgt;
9423 
9424 	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9425 	if (ptgt != NULL) {
9426 		mutex_enter(&pptr->port_mutex);
9427 		if (link_cnt != pptr->port_link_cnt) {
9428 			/*
9429 			 * oh oh -- another link reset
9430 			 * in progress -- give up
9431 			 */
9432 			mutex_exit(&pptr->port_mutex);
9433 			kmem_free(ptgt, sizeof (*ptgt));
9434 			ptgt = NULL;
9435 		} else {
9436 			/*
9437 			 * initialize the mutex before putting in the port
9438 			 * wwn list, especially before releasing the port
9439 			 * mutex.
9440 			 */
9441 			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9442 
9443 			/* add new target entry to the port's hash list */
9444 			wwn = (uchar_t *)&map_entry->map_pwwn;
9445 			hash = FCP_HASH(wwn);
9446 
9447 			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9448 			pptr->port_tgt_hash_table[hash] = ptgt;
9449 
9450 			/* save cross-ptr */
9451 			ptgt->tgt_port = pptr;
9452 
9453 			ptgt->tgt_change_cnt = 1;
9454 
9455 			/* initialize the target manual_config_only flag */
9456 			if (fcp_enable_auto_configuration) {
9457 				ptgt->tgt_manual_config_only = 0;
9458 			} else {
9459 				ptgt->tgt_manual_config_only = 1;
9460 			}
9461 
9462 			mutex_exit(&pptr->port_mutex);
9463 		}
9464 	}
9465 
9466 	return (ptgt);
9467 }
9468 
9469 /*
9470  *     Function: fcp_dealloc_tgt
9471  *
9472  *  Description: Frees the target structure passed by the caller.
9473  *
9474  *     Argument: ptgt		Target structure to free.
9475  *
9476  * Return Value: None
9477  *
9478  *	Context: Kernel context.
9479  */
9480 static void
9481 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9482 {
9483 	mutex_destroy(&ptgt->tgt_mutex);
9484 	kmem_free(ptgt, sizeof (*ptgt));
9485 }
9486 
9487 
9488 /*
9489  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9490  *
9491  *	Device discovery commands will not be retried for-ever as
9492  *	this will have repercussions on other devices that need to
9493  *	be submitted to the hotplug thread. After a quick glance
9494  *	at the SCSI-3 spec, it was found that the spec doesn't
9495  *	mandate a forever retry, rather recommends a delayed retry.
9496  *
9497  *	Since Photon IB is single threaded, STATUS_BUSY is common
9498  *	in a 4+initiator environment. Make sure the total time
9499  *	spent on retries (including command timeout) does not
9500  *	60 seconds
9501  */
9502 static void
9503 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9504 {
9505 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9506 	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9507 
9508 	mutex_enter(&pptr->port_mutex);
9509 	mutex_enter(&ptgt->tgt_mutex);
9510 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9511 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9512 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9513 		    "fcp_queue_ipkt,1:state change occured"
9514 		    " for D_ID=0x%x", ptgt->tgt_d_id);
9515 		mutex_exit(&ptgt->tgt_mutex);
9516 		mutex_exit(&pptr->port_mutex);
9517 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9518 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9519 		fcp_icmd_free(pptr, icmd);
9520 		return;
9521 	}
9522 	mutex_exit(&ptgt->tgt_mutex);
9523 
9524 	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9525 
9526 	if (pptr->port_ipkt_list != NULL) {
9527 		/* add pkt to front of doubly-linked list */
9528 		pptr->port_ipkt_list->ipkt_prev = icmd;
9529 		icmd->ipkt_next = pptr->port_ipkt_list;
9530 		pptr->port_ipkt_list = icmd;
9531 		icmd->ipkt_prev = NULL;
9532 	} else {
9533 		/* this is the first/only pkt on the list */
9534 		pptr->port_ipkt_list = icmd;
9535 		icmd->ipkt_next = NULL;
9536 		icmd->ipkt_prev = NULL;
9537 	}
9538 	mutex_exit(&pptr->port_mutex);
9539 }
9540 
9541 /*
9542  *     Function: fcp_transport
9543  *
9544  *  Description: This function submits the Fibre Channel packet to the transort
9545  *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9546  *		 fails the submission, the treatment depends on the value of
9547  *		 the variable internal.
9548  *
9549  *     Argument: port_handle	fp/fctl port handle.
9550  *		 *fpkt		Packet to submit to the transport layer.
9551  *		 internal	Not zero when it's an internal packet.
9552  *
9553  * Return Value: FC_TRAN_BUSY
9554  *		 FC_STATEC_BUSY
9555  *		 FC_OFFLINE
9556  *		 FC_LOGINREQ
9557  *		 FC_DEVICE_BUSY
9558  *		 FC_SUCCESS
9559  */
9560 static int
9561 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9562 {
9563 	int	rval;
9564 
9565 	rval = fc_ulp_transport(port_handle, fpkt);
9566 	if (rval == FC_SUCCESS) {
9567 		return (rval);
9568 	}
9569 
9570 	/*
9571 	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9572 	 * a command, if the underlying modules see that there is a state
9573 	 * change, or if a port is OFFLINE, that means, that state change
9574 	 * hasn't reached FCP yet, so re-queue the command for deferred
9575 	 * submission.
9576 	 */
9577 	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9578 	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9579 	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9580 		/*
9581 		 * Defer packet re-submission. Life hang is possible on
9582 		 * internal commands if the port driver sends FC_STATEC_BUSY
9583 		 * for ever, but that shouldn't happen in a good environment.
9584 		 * Limiting re-transport for internal commands is probably a
9585 		 * good idea..
9586 		 * A race condition can happen when a port sees barrage of
9587 		 * link transitions offline to online. If the FCTL has
9588 		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9589 		 * internal commands should be queued to do the discovery.
9590 		 * The race condition is when an online comes and FCP starts
9591 		 * its internal discovery and the link goes offline. It is
9592 		 * possible that the statec_callback has not reached FCP
9593 		 * and FCP is carrying on with its internal discovery.
9594 		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9595 		 * that the link has gone offline. At this point FCP should
9596 		 * drop all the internal commands and wait for the
9597 		 * statec_callback. It will be facilitated by incrementing
9598 		 * port_link_cnt.
9599 		 *
9600 		 * For external commands, the (FC)pkt_timeout is decremented
9601 		 * by the QUEUE Delay added by our driver, Care is taken to
9602 		 * ensure that it doesn't become zero (zero means no timeout)
9603 		 * If the time expires right inside driver queue itself,
9604 		 * the watch thread will return it to the original caller
9605 		 * indicating that the command has timed-out.
9606 		 */
9607 		if (internal) {
9608 			char			*op;
9609 			struct fcp_ipkt	*icmd;
9610 
9611 			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9612 			switch (icmd->ipkt_opcode) {
9613 			case SCMD_REPORT_LUN:
9614 				op = "REPORT LUN";
9615 				break;
9616 
9617 			case SCMD_INQUIRY:
9618 				op = "INQUIRY";
9619 				break;
9620 
9621 			case SCMD_INQUIRY_PAGE83:
9622 				op = "INQUIRY-83";
9623 				break;
9624 
9625 			default:
9626 				op = "Internal SCSI COMMAND";
9627 				break;
9628 			}
9629 
9630 			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9631 			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9632 				rval = FC_SUCCESS;
9633 			}
9634 		} else {
9635 			struct fcp_pkt *cmd;
9636 			struct fcp_port *pptr;
9637 
9638 			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9639 			cmd->cmd_state = FCP_PKT_IDLE;
9640 			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9641 
9642 			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9643 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9644 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9645 				    "fcp_transport: xport busy for pkt %p",
9646 				    cmd->cmd_pkt);
9647 				rval = FC_TRAN_BUSY;
9648 			} else {
9649 				fcp_queue_pkt(pptr, cmd);
9650 				rval = FC_SUCCESS;
9651 			}
9652 		}
9653 	}
9654 
9655 	return (rval);
9656 }
9657 
9658 /*VARARGS3*/
9659 static void
9660 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9661 {
9662 	char		buf[256];
9663 	va_list		ap;
9664 
9665 	if (dip == NULL) {
9666 		dip = fcp_global_dip;
9667 	}
9668 
9669 	va_start(ap, fmt);
9670 	(void) vsprintf(buf, fmt, ap);
9671 	va_end(ap);
9672 
9673 	scsi_log(dip, "fcp", level, buf);
9674 }
9675 
9676 /*
9677  * This function retries NS registry of FC4 type.
9678  * It assumes that fcp_mutex is held.
9679  * The function does nothing if topology is not fabric
9680  * So, the topology has to be set before this function can be called
9681  */
9682 static void
9683 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9684 {
9685 	int	rval;
9686 
9687 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9688 
9689 	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9690 	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9691 	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9692 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9693 			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9694 		}
9695 		return;
9696 	}
9697 	mutex_exit(&pptr->port_mutex);
9698 	rval = fcp_do_ns_registry(pptr, s_id);
9699 	mutex_enter(&pptr->port_mutex);
9700 
9701 	if (rval == 0) {
9702 		/* Registry successful. Reset flag */
9703 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9704 	}
9705 }
9706 
9707 /*
9708  * This function registers the ULP with the switch by calling transport i/f
9709  */
9710 static int
9711 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9712 {
9713 	fc_ns_cmd_t		ns_cmd;
9714 	ns_rfc_type_t		rfc;
9715 	uint32_t		types[8];
9716 
9717 	/*
9718 	 * Prepare the Name server structure to
9719 	 * register with the transport in case of
9720 	 * Fabric configuration.
9721 	 */
9722 	bzero(&rfc, sizeof (rfc));
9723 	bzero(types, sizeof (types));
9724 
9725 	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9726 	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9727 
9728 	rfc.rfc_port_id.port_id = s_id;
9729 	bcopy(types, rfc.rfc_types, sizeof (types));
9730 
9731 	ns_cmd.ns_flags = 0;
9732 	ns_cmd.ns_cmd = NS_RFT_ID;
9733 	ns_cmd.ns_req_len = sizeof (rfc);
9734 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9735 	ns_cmd.ns_resp_len = 0;
9736 	ns_cmd.ns_resp_payload = NULL;
9737 
9738 	/*
9739 	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9740 	 */
9741 	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9742 		fcp_log(CE_WARN, pptr->port_dip,
9743 		    "!ns_registry: failed name server registration");
9744 		return (1);
9745 	}
9746 
9747 	return (0);
9748 }
9749 
9750 /*
9751  *     Function: fcp_handle_port_attach
9752  *
9753  *  Description: This function is called from fcp_port_attach() to attach a
9754  *		 new port. This routine does the following:
9755  *
9756  *		1) Allocates an fcp_port structure and initializes it.
9757  *		2) Tries to register the new FC-4 (FCP) capablity with the name
9758  *		   server.
9759  *		3) Kicks off the enumeration of the targets/luns visible
9760  *		   through this new port.  That is done by calling
9761  *		   fcp_statec_callback() if the port is online.
9762  *
9763  *     Argument: ulph		fp/fctl port handle.
9764  *		 *pinfo		Port information.
9765  *		 s_id		Port ID.
9766  *		 instance	Device instance number for the local port
9767  *				(returned by ddi_get_instance()).
9768  *
9769  * Return Value: DDI_SUCCESS
9770  *		 DDI_FAILURE
9771  *
9772  *	Context: User and Kernel context.
9773  */
9774 /*ARGSUSED*/
9775 int
9776 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9777     uint32_t s_id, int instance)
9778 {
9779 	int			res = DDI_FAILURE;
9780 	scsi_hba_tran_t		*tran;
9781 	int			mutex_initted = FALSE;
9782 	int			hba_attached = FALSE;
9783 	int			soft_state_linked = FALSE;
9784 	int			event_bind = FALSE;
9785 	struct fcp_port		*pptr;
9786 	fc_portmap_t		*tmp_list = NULL;
9787 	uint32_t		max_cnt, alloc_cnt;
9788 	uchar_t			*boot_wwn = NULL;
9789 	uint_t			nbytes;
9790 	int			manual_cfg;
9791 
9792 	/*
9793 	 * this port instance attaching for the first time (or after
9794 	 * being detached before)
9795 	 */
9796 	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9797 	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9798 
9799 	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9800 		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9801 		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9802 		    instance);
9803 		return (res);
9804 	}
9805 
9806 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9807 		/* this shouldn't happen */
9808 		ddi_soft_state_free(fcp_softstate, instance);
9809 		cmn_err(CE_WARN, "fcp: bad soft state");
9810 		return (res);
9811 	}
9812 
9813 	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9814 
9815 	/*
9816 	 * Make a copy of ulp_port_info as fctl allocates
9817 	 * a temp struct.
9818 	 */
9819 	(void) fcp_cp_pinfo(pptr, pinfo);
9820 
9821 	/*
9822 	 * Check for manual_configuration_only property.
9823 	 * Enable manual configurtion if the property is
9824 	 * set to 1, otherwise disable manual configuration.
9825 	 */
9826 	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9827 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9828 	    MANUAL_CFG_ONLY,
9829 	    -1)) != -1) {
9830 		if (manual_cfg == 1) {
9831 			char	*pathname;
9832 			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9833 			(void) ddi_pathname(pptr->port_dip, pathname);
9834 			cmn_err(CE_NOTE,
9835 			    "%s (%s%d) %s is enabled via %s.conf.",
9836 			    pathname,
9837 			    ddi_driver_name(pptr->port_dip),
9838 			    ddi_get_instance(pptr->port_dip),
9839 			    MANUAL_CFG_ONLY,
9840 			    ddi_driver_name(pptr->port_dip));
9841 			fcp_enable_auto_configuration = 0;
9842 			kmem_free(pathname, MAXPATHLEN);
9843 		}
9844 	}
9845 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9846 	pptr->port_link_cnt = 1;
9847 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9848 	pptr->port_id = s_id;
9849 	pptr->port_instance = instance;
9850 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9851 	pptr->port_state = FCP_STATE_INIT;
9852 	if (pinfo->port_acc_attr == NULL) {
9853 		/*
9854 		 * The corresponding FCA doesn't support DMA at all
9855 		 */
9856 		pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9857 	}
9858 
9859 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9860 
9861 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9862 		/*
9863 		 * If FCA supports DMA in SCSI data phase, we need preallocate
9864 		 * dma cookie, so stash the cookie size
9865 		 */
9866 		pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9867 		    pptr->port_data_dma_attr.dma_attr_sgllen;
9868 	}
9869 
9870 	/*
9871 	 * The two mutexes of fcp_port are initialized.	 The variable
9872 	 * mutex_initted is incremented to remember that fact.	That variable
9873 	 * is checked when the routine fails and the mutexes have to be
9874 	 * destroyed.
9875 	 */
9876 	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9877 	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9878 	mutex_initted++;
9879 
9880 	/*
9881 	 * The SCSI tran structure is allocate and initialized now.
9882 	 */
9883 	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9884 		fcp_log(CE_WARN, pptr->port_dip,
9885 		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9886 		goto fail;
9887 	}
9888 
9889 	/* link in the transport structure then fill it in */
9890 	pptr->port_tran = tran;
9891 	tran->tran_hba_private		= pptr;
9892 	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9893 	tran->tran_tgt_probe		= NULL;
9894 	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9895 	tran->tran_start		= fcp_scsi_start;
9896 	tran->tran_reset		= fcp_scsi_reset;
9897 	tran->tran_abort		= fcp_scsi_abort;
9898 	tran->tran_getcap		= fcp_scsi_getcap;
9899 	tran->tran_setcap		= fcp_scsi_setcap;
9900 	tran->tran_init_pkt		= NULL;
9901 	tran->tran_destroy_pkt		= NULL;
9902 	tran->tran_dmafree		= NULL;
9903 	tran->tran_sync_pkt		= NULL;
9904 	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9905 	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9906 	tran->tran_get_name		= fcp_scsi_get_name;
9907 	tran->tran_clear_aca		= NULL;
9908 	tran->tran_clear_task_set	= NULL;
9909 	tran->tran_terminate_task	= NULL;
9910 	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9911 	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9912 	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9913 	tran->tran_post_event		= fcp_scsi_bus_post_event;
9914 	tran->tran_quiesce		= NULL;
9915 	tran->tran_unquiesce		= NULL;
9916 	tran->tran_bus_reset		= NULL;
9917 	tran->tran_bus_config		= fcp_scsi_bus_config;
9918 	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9919 	tran->tran_bus_power		= NULL;
9920 	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9921 
9922 	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9923 	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9924 	tran->tran_setup_pkt		= fcp_pkt_setup;
9925 	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9926 	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9927 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9928 	if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9929 		/*
9930 		 * If FCA don't support DMA, then we use different vectors to
9931 		 * minimize the effects on DMA code flow path
9932 		 */
9933 		tran->tran_start	   = fcp_pseudo_start;
9934 		tran->tran_init_pkt	   = fcp_pseudo_init_pkt;
9935 		tran->tran_destroy_pkt	   = fcp_pseudo_destroy_pkt;
9936 		tran->tran_sync_pkt	   = fcp_pseudo_sync_pkt;
9937 		tran->tran_dmafree	   = fcp_pseudo_dmafree;
9938 		tran->tran_setup_pkt	   = NULL;
9939 		tran->tran_teardown_pkt	   = NULL;
9940 		tran->tran_pkt_constructor = NULL;
9941 		tran->tran_pkt_destructor  = NULL;
9942 		pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9943 	}
9944 
9945 	/*
9946 	 * Allocate an ndi event handle
9947 	 */
9948 	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9949 	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9950 
9951 	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9952 	    sizeof (fcp_ndi_event_defs));
9953 
9954 	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9955 	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9956 
9957 	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9958 	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9959 	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9960 
9961 	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9962 	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9963 	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9964 		goto fail;
9965 	}
9966 	event_bind++;	/* Checked in fail case */
9967 
9968 	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9969 	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9970 	    != DDI_SUCCESS) {
9971 		fcp_log(CE_WARN, pptr->port_dip,
9972 		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9973 		goto fail;
9974 	}
9975 	hba_attached++;	/* Checked in fail case */
9976 
9977 	pptr->port_mpxio = 0;
9978 	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9979 	    MDI_SUCCESS) {
9980 		pptr->port_mpxio++;
9981 	}
9982 
9983 	/*
9984 	 * The following code is putting the new port structure in the global
9985 	 * list of ports and, if it is the first port to attach, it start the
9986 	 * fcp_watchdog_tick.
9987 	 *
9988 	 * Why put this new port in the global before we are done attaching it?
9989 	 * We are actually making the structure globally known before we are
9990 	 * done attaching it.  The reason for that is: because of the code that
9991 	 * follows.  At this point the resources to handle the port are
9992 	 * allocated.  This function is now going to do the following:
9993 	 *
9994 	 *   1) It is going to try to register with the name server advertizing
9995 	 *	the new FCP capability of the port.
9996 	 *   2) It is going to play the role of the fp/fctl layer by building
9997 	 *	a list of worlwide names reachable through this port and call
9998 	 *	itself on fcp_statec_callback().  That requires the port to
9999 	 *	be part of the global list.
10000 	 */
10001 	mutex_enter(&fcp_global_mutex);
10002 	if (fcp_port_head == NULL) {
10003 		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10004 	}
10005 	pptr->port_next = fcp_port_head;
10006 	fcp_port_head = pptr;
10007 	soft_state_linked++;
10008 
10009 	if (fcp_watchdog_init++ == 0) {
10010 		fcp_watchdog_tick = fcp_watchdog_timeout *
10011 		    drv_usectohz(1000000);
10012 		fcp_watchdog_id = timeout(fcp_watch, NULL,
10013 		    fcp_watchdog_tick);
10014 	}
10015 	mutex_exit(&fcp_global_mutex);
10016 
10017 	/*
10018 	 * Here an attempt is made to register with the name server, the new
10019 	 * FCP capability.  That is done using an RTF_ID to the name server.
10020 	 * It is done synchronously.  The function fcp_do_ns_registry()
10021 	 * doesn't return till the name server responded.
10022 	 * On failures, just ignore it for now and it will get retried during
10023 	 * state change callbacks. We'll set a flag to show this failure
10024 	 */
10025 	if (fcp_do_ns_registry(pptr, s_id)) {
10026 		mutex_enter(&pptr->port_mutex);
10027 		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10028 		mutex_exit(&pptr->port_mutex);
10029 	} else {
10030 		mutex_enter(&pptr->port_mutex);
10031 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10032 		mutex_exit(&pptr->port_mutex);
10033 	}
10034 
10035 	/*
10036 	 * Lookup for boot WWN property
10037 	 */
10038 	if (modrootloaded != 1) {
10039 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10040 		    ddi_get_parent(pinfo->port_dip),
10041 		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10042 		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10043 		    (nbytes == FC_WWN_SIZE)) {
10044 			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10045 		}
10046 		if (boot_wwn) {
10047 			ddi_prop_free(boot_wwn);
10048 		}
10049 	}
10050 
10051 	/*
10052 	 * Handle various topologies and link states.
10053 	 */
10054 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10055 	case FC_STATE_OFFLINE:
10056 
10057 		/*
10058 		 * we're attaching a port where the link is offline
10059 		 *
10060 		 * Wait for ONLINE, at which time a state
10061 		 * change will cause a statec_callback
10062 		 *
10063 		 * in the mean time, do not do anything
10064 		 */
10065 		res = DDI_SUCCESS;
10066 		pptr->port_state |= FCP_STATE_OFFLINE;
10067 		break;
10068 
10069 	case FC_STATE_ONLINE: {
10070 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
10071 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10072 			res = DDI_SUCCESS;
10073 			break;
10074 		}
10075 		/*
10076 		 * discover devices and create nodes (a private
10077 		 * loop or point-to-point)
10078 		 */
10079 		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10080 
10081 		/*
10082 		 * At this point we are going to build a list of all the ports
10083 		 * that	can be reached through this local port.	 It looks like
10084 		 * we cannot handle more than FCP_MAX_DEVICES per local port
10085 		 * (128).
10086 		 */
10087 		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10088 		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10089 		    KM_NOSLEEP)) == NULL) {
10090 			fcp_log(CE_WARN, pptr->port_dip,
10091 			    "!fcp%d: failed to allocate portmap",
10092 			    instance);
10093 			goto fail;
10094 		}
10095 
10096 		/*
10097 		 * fc_ulp_getportmap() is going to provide us with the list of
10098 		 * remote ports in the buffer we just allocated.  The way the
10099 		 * list is going to be retrieved depends on the topology.
10100 		 * However, if we are connected to a Fabric, a name server
10101 		 * request may be sent to get the list of FCP capable ports.
10102 		 * It should be noted that is the case the request is
10103 		 * synchronous.	 This means we are stuck here till the name
10104 		 * server replies.  A lot of things can change during that time
10105 		 * and including, may be, being called on
10106 		 * fcp_statec_callback() for different reasons. I'm not sure
10107 		 * the code can handle that.
10108 		 */
10109 		max_cnt = FCP_MAX_DEVICES;
10110 		alloc_cnt = FCP_MAX_DEVICES;
10111 		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10112 		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10113 		    FC_SUCCESS) {
10114 			caddr_t msg;
10115 
10116 			(void) fc_ulp_error(res, &msg);
10117 
10118 			/*
10119 			 * this	 just means the transport is
10120 			 * busy perhaps building a portmap so,
10121 			 * for now, succeed this port attach
10122 			 * when the transport has a new map,
10123 			 * it'll send us a state change then
10124 			 */
10125 			fcp_log(CE_WARN, pptr->port_dip,
10126 			    "!failed to get port map : %s", msg);
10127 
10128 			res = DDI_SUCCESS;
10129 			break;	/* go return result */
10130 		}
10131 		if (max_cnt > alloc_cnt) {
10132 			alloc_cnt = max_cnt;
10133 		}
10134 
10135 		/*
10136 		 * We are now going to call fcp_statec_callback() ourselves.
10137 		 * By issuing this call we are trying to kick off the enumera-
10138 		 * tion process.
10139 		 */
10140 		/*
10141 		 * let the state change callback do the SCSI device
10142 		 * discovery and create the devinfos
10143 		 */
10144 		fcp_statec_callback(ulph, pptr->port_fp_handle,
10145 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10146 		    max_cnt, pptr->port_id);
10147 
10148 		res = DDI_SUCCESS;
10149 		break;
10150 	}
10151 
10152 	default:
10153 		/* unknown port state */
10154 		fcp_log(CE_WARN, pptr->port_dip,
10155 		    "!fcp%d: invalid port state at attach=0x%x",
10156 		    instance, pptr->port_phys_state);
10157 
10158 		mutex_enter(&pptr->port_mutex);
10159 		pptr->port_phys_state = FCP_STATE_OFFLINE;
10160 		mutex_exit(&pptr->port_mutex);
10161 
10162 		res = DDI_SUCCESS;
10163 		break;
10164 	}
10165 
10166 	/* free temp list if used */
10167 	if (tmp_list != NULL) {
10168 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10169 	}
10170 
10171 	/* note the attach time */
10172 	pptr->port_attach_time = ddi_get_lbolt64();
10173 
10174 	/* all done */
10175 	return (res);
10176 
10177 	/* a failure we have to clean up after */
10178 fail:
10179 	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10180 
10181 	if (soft_state_linked) {
10182 		/* remove this fcp_port from the linked list */
10183 		(void) fcp_soft_state_unlink(pptr);
10184 	}
10185 
10186 	/* unbind and free event set */
10187 	if (pptr->port_ndi_event_hdl) {
10188 		if (event_bind) {
10189 			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10190 			    &pptr->port_ndi_events, NDI_SLEEP);
10191 		}
10192 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10193 	}
10194 
10195 	if (pptr->port_ndi_event_defs) {
10196 		(void) kmem_free(pptr->port_ndi_event_defs,
10197 		    sizeof (fcp_ndi_event_defs));
10198 	}
10199 
10200 	/*
10201 	 * Clean up mpxio stuff
10202 	 */
10203 	if (pptr->port_mpxio) {
10204 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10205 		pptr->port_mpxio--;
10206 	}
10207 
10208 	/* undo SCSI HBA setup */
10209 	if (hba_attached) {
10210 		(void) scsi_hba_detach(pptr->port_dip);
10211 	}
10212 	if (pptr->port_tran != NULL) {
10213 		scsi_hba_tran_free(pptr->port_tran);
10214 	}
10215 
10216 	mutex_enter(&fcp_global_mutex);
10217 
10218 	/*
10219 	 * We check soft_state_linked, because it is incremented right before
10220 	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10221 	 * soft_state_linked is still FALSE, we do not want to decrement
10222 	 * fcp_watchdog_init or possibly call untimeout.
10223 	 */
10224 
10225 	if (soft_state_linked) {
10226 		if (--fcp_watchdog_init == 0) {
10227 			timeout_id_t	tid = fcp_watchdog_id;
10228 
10229 			mutex_exit(&fcp_global_mutex);
10230 			(void) untimeout(tid);
10231 		} else {
10232 			mutex_exit(&fcp_global_mutex);
10233 		}
10234 	} else {
10235 		mutex_exit(&fcp_global_mutex);
10236 	}
10237 
10238 	if (mutex_initted) {
10239 		mutex_destroy(&pptr->port_mutex);
10240 		mutex_destroy(&pptr->port_pkt_mutex);
10241 	}
10242 
10243 	if (tmp_list != NULL) {
10244 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10245 	}
10246 
10247 	/* this makes pptr invalid */
10248 	ddi_soft_state_free(fcp_softstate, instance);
10249 
10250 	return (DDI_FAILURE);
10251 }
10252 
10253 
10254 static int
10255 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10256 {
10257 	int count = 0;
10258 
10259 	mutex_enter(&pptr->port_mutex);
10260 
10261 	/*
10262 	 * if the port is powered down or suspended, nothing else
10263 	 * to do; just return.
10264 	 */
10265 	if (flag != FCP_STATE_DETACHING) {
10266 		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10267 		    FCP_STATE_SUSPENDED)) {
10268 			pptr->port_state |= flag;
10269 			mutex_exit(&pptr->port_mutex);
10270 			return (FC_SUCCESS);
10271 		}
10272 	}
10273 
10274 	if (pptr->port_state & FCP_STATE_IN_MDI) {
10275 		mutex_exit(&pptr->port_mutex);
10276 		return (FC_FAILURE);
10277 	}
10278 
10279 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10280 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10281 	    "fcp_handle_port_detach: port is detaching");
10282 
10283 	pptr->port_state |= flag;
10284 
10285 	/*
10286 	 * Wait for any ongoing reconfig/ipkt to complete, that
10287 	 * ensures the freeing to targets/luns is safe.
10288 	 * No more ref to this port should happen from statec/ioctl
10289 	 * after that as it was removed from the global port list.
10290 	 */
10291 	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10292 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10293 		/*
10294 		 * Let's give sufficient time for reconfig/ipkt
10295 		 * to complete.
10296 		 */
10297 		if (count++ >= FCP_ICMD_DEADLINE) {
10298 			break;
10299 		}
10300 		mutex_exit(&pptr->port_mutex);
10301 		delay(drv_usectohz(1000000));
10302 		mutex_enter(&pptr->port_mutex);
10303 	}
10304 
10305 	/*
10306 	 * if the driver is still busy then fail to
10307 	 * suspend/power down.
10308 	 */
10309 	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10310 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10311 		pptr->port_state &= ~flag;
10312 		mutex_exit(&pptr->port_mutex);
10313 		return (FC_FAILURE);
10314 	}
10315 
10316 	if (flag == FCP_STATE_DETACHING) {
10317 		pptr = fcp_soft_state_unlink(pptr);
10318 		ASSERT(pptr != NULL);
10319 	}
10320 
10321 	pptr->port_link_cnt++;
10322 	pptr->port_state |= FCP_STATE_OFFLINE;
10323 	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10324 
10325 	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10326 	    FCP_CAUSE_LINK_DOWN);
10327 	mutex_exit(&pptr->port_mutex);
10328 
10329 	/* kill watch dog timer if we're the last */
10330 	mutex_enter(&fcp_global_mutex);
10331 	if (--fcp_watchdog_init == 0) {
10332 		timeout_id_t	tid = fcp_watchdog_id;
10333 		mutex_exit(&fcp_global_mutex);
10334 		(void) untimeout(tid);
10335 	} else {
10336 		mutex_exit(&fcp_global_mutex);
10337 	}
10338 
10339 	/* clean up the port structures */
10340 	if (flag == FCP_STATE_DETACHING) {
10341 		fcp_cleanup_port(pptr, instance);
10342 	}
10343 
10344 	return (FC_SUCCESS);
10345 }
10346 
10347 
10348 static void
10349 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10350 {
10351 	ASSERT(pptr != NULL);
10352 
10353 	/* unbind and free event set */
10354 	if (pptr->port_ndi_event_hdl) {
10355 		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10356 		    &pptr->port_ndi_events, NDI_SLEEP);
10357 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10358 	}
10359 
10360 	if (pptr->port_ndi_event_defs) {
10361 		(void) kmem_free(pptr->port_ndi_event_defs,
10362 		    sizeof (fcp_ndi_event_defs));
10363 	}
10364 
10365 	/* free the lun/target structures and devinfos */
10366 	fcp_free_targets(pptr);
10367 
10368 	/*
10369 	 * Clean up mpxio stuff
10370 	 */
10371 	if (pptr->port_mpxio) {
10372 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10373 		pptr->port_mpxio--;
10374 	}
10375 
10376 	/* clean up SCSA stuff */
10377 	(void) scsi_hba_detach(pptr->port_dip);
10378 	if (pptr->port_tran != NULL) {
10379 		scsi_hba_tran_free(pptr->port_tran);
10380 	}
10381 
10382 #ifdef	KSTATS_CODE
10383 	/* clean up kstats */
10384 	if (pptr->fcp_ksp != NULL) {
10385 		kstat_delete(pptr->fcp_ksp);
10386 	}
10387 #endif
10388 
10389 	/* clean up soft state mutexes/condition variables */
10390 	mutex_destroy(&pptr->port_mutex);
10391 	mutex_destroy(&pptr->port_pkt_mutex);
10392 
10393 	/* all done with soft state */
10394 	ddi_soft_state_free(fcp_softstate, instance);
10395 }
10396 
10397 /*
10398  *     Function: fcp_kmem_cache_constructor
10399  *
10400  *  Description: This function allocates and initializes the resources required
10401  *		 to build a scsi_pkt structure the target driver.  The result
10402  *		 of the allocation and initialization will be cached in the
10403  *		 memory cache.	As DMA resources may be allocated here, that
10404  *		 means DMA resources will be tied up in the cache manager.
10405  *		 This is a tradeoff that has been made for performance reasons.
10406  *
10407  *     Argument: *buf		Memory to preinitialize.
10408  *		 *arg		FCP port structure (fcp_port).
10409  *		 kmflags	Value passed to kmem_cache_alloc() and
10410  *				propagated to the constructor.
10411  *
10412  * Return Value: 0	Allocation/Initialization was successful.
10413  *		 -1	Allocation or Initialization failed.
10414  *
10415  *
10416  * If the returned value is 0, the buffer is initialized like this:
10417  *
10418  *		    +================================+
10419  *	     +----> |	      struct scsi_pkt	     |
10420  *	     |	    |				     |
10421  *	     | +--- | pkt_ha_private		     |
10422  *	     | |    |				     |
10423  *	     | |    +================================+
10424  *	     | |
10425  *	     | |    +================================+
10426  *	     | +--> |	    struct fcp_pkt	     | <---------+
10427  *	     |	    |				     |		 |
10428  *	     +----- | cmd_pkt			     |		 |
10429  *		    |			  cmd_fp_pkt | ---+	 |
10430  *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10431  *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10432  *	  |    |    |--------------------------------|	  |	 |
10433  *	  |    |    |	      struct fc_packet	     | <--+	 |
10434  *	  |    |    |				     |		 |
10435  *	  |    |    |		     pkt_ulp_private | ----------+
10436  *	  |    |    |		     pkt_fca_private | -----+
10437  *	  |    |    |		     pkt_data_cookie | ---+ |
10438  *	  |    |    | pkt_cmdlen		     |	  | |
10439  *	  |    |(a) | pkt_rsplen		     |	  | |
10440  *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10441  *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10442  *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10443  *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10444  *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10445  *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10446  *		    +================================+	  | |  |   |   |    |
10447  *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10448  *		    |				     |	    |  |   |   |    |
10449  *		    +================================+	    |  |   |   |    |
10450  *		    |	      fca_private	     | <----+  |   |   |    |
10451  *		    |				     |	       |   |   |    |
10452  *		    +================================+	       |   |   |    |
10453  *							       |   |   |    |
10454  *							       |   |   |    |
10455  *		    +================================+	 (d)   |   |   |    |
10456  *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10457  *		    |				     |		   |   |    |
10458  *		    +================================+		   |   |    |
10459  *								   |   |    |
10460  *		    +================================+	 (d)	   |   |    |
10461  *		    |		fcp_resp	     | <-----------+   |    |
10462  *		    |	(DMA resources associated)   |		       |    |
10463  *		    +================================+		       |    |
10464  *								       |    |
10465  *								       |    |
10466  *								       |    |
10467  *		    +================================+	 (c)	       |    |
10468  *		    |	     fcp_cmd cookies	     | <---------------+    |
10469  *		    |				     |			    |
10470  *		    +================================+			    |
10471  *									    |
10472  *		    +================================+	 (c)		    |
10473  *		    |		 fcp_cmd	     | <--------------------+
10474  *		    |	(DMA resources associated)   |
10475  *		    +================================+
10476  *
10477  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10478  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10479  * (c) Only if DMA is used for the FCP_CMD buffer.
10480  * (d) Only if DMA is used for the FCP_RESP buffer
10481  */
10482 static int
10483 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10484     int kmflags)
10485 {
10486 	struct fcp_pkt	*cmd;
10487 	struct fcp_port	*pptr;
10488 	fc_packet_t	*fpkt;
10489 
10490 	pptr = (struct fcp_port *)tran->tran_hba_private;
10491 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10492 	bzero(cmd, tran->tran_hba_len);
10493 
10494 	cmd->cmd_pkt = pkt;
10495 	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10496 	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10497 	cmd->cmd_fp_pkt = fpkt;
10498 
10499 	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10500 	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10501 	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10502 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10503 
10504 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10505 	    sizeof (struct fcp_pkt));
10506 
10507 	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10508 	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10509 
10510 	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10511 		/*
10512 		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10513 		 * fcp_resp.  The transfer of information will be done by
10514 		 * bcopy.
10515 		 * The naming of the flags (that is actually a value) is
10516 		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10517 		 * DMA" but instead "NO DMA".
10518 		 */
10519 		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10520 		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10521 		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10522 	} else {
10523 		/*
10524 		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10525 		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10526 		 * interfaces.
10527 		 */
10528 		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10529 			return (-1);
10530 		}
10531 	}
10532 
10533 	return (0);
10534 }
10535 
10536 /*
10537  *     Function: fcp_kmem_cache_destructor
10538  *
10539  *  Description: Called by the destructor of the cache managed by SCSA.
10540  *		 All the resources pre-allocated in fcp_pkt_constructor
10541  *		 and the data also pre-initialized in fcp_pkt_constructor
10542  *		 are freed and uninitialized here.
10543  *
10544  *     Argument: *buf		Memory to uninitialize.
10545  *		 *arg		FCP port structure (fcp_port).
10546  *
10547  * Return Value: None
10548  *
10549  *	Context: kernel
10550  */
10551 static void
10552 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10553 {
10554 	struct fcp_pkt	*cmd;
10555 	struct fcp_port	*pptr;
10556 
10557 	pptr = (struct fcp_port *)(tran->tran_hba_private);
10558 	cmd = pkt->pkt_ha_private;
10559 
10560 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10561 		/*
10562 		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10563 		 * buffer and DMA resources allocated to do so are released.
10564 		 */
10565 		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10566 	}
10567 }
10568 
10569 /*
10570  *     Function: fcp_alloc_cmd_resp
10571  *
10572  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10573  *		 will be DMAed by the HBA.  The buffer is allocated applying
10574  *		 the DMA requirements for the HBA.  The buffers allocated will
10575  *		 also be bound.	 DMA resources are allocated in the process.
10576  *		 They will be released by fcp_free_cmd_resp().
10577  *
10578  *     Argument: *pptr	FCP port.
10579  *		 *fpkt	fc packet for which the cmd and resp packet should be
10580  *			allocated.
10581  *		 flags	Allocation flags.
10582  *
10583  * Return Value: FC_FAILURE
10584  *		 FC_SUCCESS
10585  *
10586  *	Context: User or Kernel context only if flags == KM_SLEEP.
10587  *		 Interrupt context if the KM_SLEEP is not specified.
10588  */
10589 static int
10590 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10591 {
10592 	int			rval;
10593 	int			cmd_len;
10594 	int			resp_len;
10595 	ulong_t			real_len;
10596 	int			(*cb) (caddr_t);
10597 	ddi_dma_cookie_t	pkt_cookie;
10598 	ddi_dma_cookie_t	*cp;
10599 	uint32_t		cnt;
10600 
10601 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10602 
10603 	cmd_len = fpkt->pkt_cmdlen;
10604 	resp_len = fpkt->pkt_rsplen;
10605 
10606 	ASSERT(fpkt->pkt_cmd_dma == NULL);
10607 
10608 	/* Allocation of a DMA handle used in subsequent calls. */
10609 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10610 	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10611 		return (FC_FAILURE);
10612 	}
10613 
10614 	/* A buffer is allocated that satisfies the DMA requirements. */
10615 	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10616 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10617 	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10618 
10619 	if (rval != DDI_SUCCESS) {
10620 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10621 		return (FC_FAILURE);
10622 	}
10623 
10624 	if (real_len < cmd_len) {
10625 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10626 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10627 		return (FC_FAILURE);
10628 	}
10629 
10630 	/* The buffer allocated is DMA bound. */
10631 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10632 	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10633 	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10634 
10635 	if (rval != DDI_DMA_MAPPED) {
10636 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10637 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10638 		return (FC_FAILURE);
10639 	}
10640 
10641 	if (fpkt->pkt_cmd_cookie_cnt >
10642 	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10643 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10644 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10645 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10646 		return (FC_FAILURE);
10647 	}
10648 
10649 	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10650 
10651 	/*
10652 	 * The buffer where the scatter/gather list is going to be built is
10653 	 * allocated.
10654 	 */
10655 	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10656 	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10657 	    KM_NOSLEEP);
10658 
10659 	if (cp == NULL) {
10660 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10661 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10662 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10663 		return (FC_FAILURE);
10664 	}
10665 
10666 	/*
10667 	 * The scatter/gather list for the buffer we just allocated is built
10668 	 * here.
10669 	 */
10670 	*cp = pkt_cookie;
10671 	cp++;
10672 
10673 	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10674 		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10675 		    &pkt_cookie);
10676 		*cp = pkt_cookie;
10677 	}
10678 
10679 	ASSERT(fpkt->pkt_resp_dma == NULL);
10680 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10681 	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10682 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10683 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10684 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10685 		return (FC_FAILURE);
10686 	}
10687 
10688 	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10689 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10690 	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10691 	    &fpkt->pkt_resp_acc);
10692 
10693 	if (rval != DDI_SUCCESS) {
10694 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10695 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10696 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10697 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10698 		kmem_free(fpkt->pkt_cmd_cookie,
10699 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10700 		return (FC_FAILURE);
10701 	}
10702 
10703 	if (real_len < resp_len) {
10704 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10705 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10706 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10707 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10708 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10709 		kmem_free(fpkt->pkt_cmd_cookie,
10710 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10711 		return (FC_FAILURE);
10712 	}
10713 
10714 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10715 	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10716 	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10717 
10718 	if (rval != DDI_DMA_MAPPED) {
10719 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10720 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10721 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10722 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10723 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10724 		kmem_free(fpkt->pkt_cmd_cookie,
10725 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10726 		return (FC_FAILURE);
10727 	}
10728 
10729 	if (fpkt->pkt_resp_cookie_cnt >
10730 	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10731 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10732 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10733 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10734 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10735 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10736 		kmem_free(fpkt->pkt_cmd_cookie,
10737 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10738 		return (FC_FAILURE);
10739 	}
10740 
10741 	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10742 
10743 	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10744 	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10745 	    KM_NOSLEEP);
10746 
10747 	if (cp == NULL) {
10748 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10749 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10750 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10751 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10752 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10753 		kmem_free(fpkt->pkt_cmd_cookie,
10754 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10755 		return (FC_FAILURE);
10756 	}
10757 
10758 	*cp = pkt_cookie;
10759 	cp++;
10760 
10761 	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10762 		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10763 		    &pkt_cookie);
10764 		*cp = pkt_cookie;
10765 	}
10766 
10767 	return (FC_SUCCESS);
10768 }
10769 
10770 /*
10771  *     Function: fcp_free_cmd_resp
10772  *
10773  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10774  *		 allocated by fcp_alloc_cmd_resp() and all the resources
10775  *		 associated with them.	That includes the DMA resources and the
10776  *		 buffer allocated for the cookies of each one of them.
10777  *
10778  *     Argument: *pptr		FCP port context.
10779  *		 *fpkt		fc packet containing the cmd and resp packet
10780  *				to be released.
10781  *
10782  * Return Value: None
10783  *
10784  *	Context: Interrupt, User and Kernel context.
10785  */
10786 /* ARGSUSED */
10787 static void
10788 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10789 {
10790 	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10791 
10792 	if (fpkt->pkt_resp_dma) {
10793 		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10794 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10795 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10796 	}
10797 
10798 	if (fpkt->pkt_resp_cookie) {
10799 		kmem_free(fpkt->pkt_resp_cookie,
10800 		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10801 		fpkt->pkt_resp_cookie = NULL;
10802 	}
10803 
10804 	if (fpkt->pkt_cmd_dma) {
10805 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10806 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10807 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10808 	}
10809 
10810 	if (fpkt->pkt_cmd_cookie) {
10811 		kmem_free(fpkt->pkt_cmd_cookie,
10812 		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10813 		fpkt->pkt_cmd_cookie = NULL;
10814 	}
10815 }
10816 
10817 
10818 /*
10819  * called by the transport to do our own target initialization
10820  *
10821  * can acquire and release the global mutex
10822  */
10823 /* ARGSUSED */
10824 static int
10825 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10826     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10827 {
10828 	uchar_t			*bytes;
10829 	uint_t			nbytes;
10830 	uint16_t		lun_num;
10831 	struct fcp_tgt	*ptgt;
10832 	struct fcp_lun	*plun;
10833 	struct fcp_port	*pptr = (struct fcp_port *)
10834 	    hba_tran->tran_hba_private;
10835 
10836 	ASSERT(pptr != NULL);
10837 
10838 	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10839 	    FCP_BUF_LEVEL_8, 0,
10840 	    "fcp_phys_tgt_init: called for %s (instance %d)",
10841 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10842 
10843 	/* get our port WWN property */
10844 	bytes = NULL;
10845 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10846 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10847 	    (nbytes != FC_WWN_SIZE)) {
10848 		/* no port WWN property */
10849 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10850 		    FCP_BUF_LEVEL_8, 0,
10851 		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10852 		    " for %s (instance %d): bytes=%p nbytes=%x",
10853 		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10854 		    nbytes);
10855 
10856 		if (bytes != NULL) {
10857 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10858 		}
10859 
10860 		return (DDI_NOT_WELL_FORMED);
10861 	}
10862 	ASSERT(bytes != NULL);
10863 
10864 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10865 	    LUN_PROP, 0xFFFF);
10866 	if (lun_num == 0xFFFF) {
10867 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10868 		    FCP_BUF_LEVEL_8, 0,
10869 		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10870 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10871 		    ddi_get_instance(tgt_dip));
10872 
10873 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10874 		return (DDI_NOT_WELL_FORMED);
10875 	}
10876 
10877 	mutex_enter(&pptr->port_mutex);
10878 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10879 		mutex_exit(&pptr->port_mutex);
10880 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10881 		    FCP_BUF_LEVEL_8, 0,
10882 		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10883 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10884 		    ddi_get_instance(tgt_dip));
10885 
10886 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10887 		return (DDI_FAILURE);
10888 	}
10889 
10890 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10891 	    FC_WWN_SIZE) == 0);
10892 	ASSERT(plun->lun_num == lun_num);
10893 
10894 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10895 
10896 	ptgt = plun->lun_tgt;
10897 
10898 	mutex_enter(&ptgt->tgt_mutex);
10899 	plun->lun_tgt_count++;
10900 	scsi_device_hba_private_set(sd, plun);
10901 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10902 	plun->lun_sd = sd;
10903 	mutex_exit(&ptgt->tgt_mutex);
10904 	mutex_exit(&pptr->port_mutex);
10905 
10906 	return (DDI_SUCCESS);
10907 }
10908 
10909 /*ARGSUSED*/
10910 static int
10911 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10912     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10913 {
10914 	uchar_t			*bytes;
10915 	uint_t			nbytes;
10916 	uint16_t		lun_num;
10917 	struct fcp_tgt	*ptgt;
10918 	struct fcp_lun	*plun;
10919 	struct fcp_port	*pptr = (struct fcp_port *)
10920 	    hba_tran->tran_hba_private;
10921 	child_info_t		*cip;
10922 
10923 	ASSERT(pptr != NULL);
10924 
10925 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10926 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10927 	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10928 	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10929 	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10930 
10931 	cip = (child_info_t *)sd->sd_pathinfo;
10932 	if (cip == NULL) {
10933 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10934 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10935 		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10936 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10937 		    ddi_get_instance(tgt_dip));
10938 
10939 		return (DDI_NOT_WELL_FORMED);
10940 	}
10941 
10942 	/* get our port WWN property */
10943 	bytes = NULL;
10944 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10945 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10946 	    (nbytes != FC_WWN_SIZE)) {
10947 		if (bytes) {
10948 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10949 		}
10950 		return (DDI_NOT_WELL_FORMED);
10951 	}
10952 
10953 	ASSERT(bytes != NULL);
10954 
10955 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10956 	    LUN_PROP, 0xFFFF);
10957 	if (lun_num == 0xFFFF) {
10958 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10959 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10960 		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10961 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10962 		    ddi_get_instance(tgt_dip));
10963 
10964 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10965 		return (DDI_NOT_WELL_FORMED);
10966 	}
10967 
10968 	mutex_enter(&pptr->port_mutex);
10969 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10970 		mutex_exit(&pptr->port_mutex);
10971 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10972 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10973 		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10974 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10975 		    ddi_get_instance(tgt_dip));
10976 
10977 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10978 		return (DDI_FAILURE);
10979 	}
10980 
10981 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10982 	    FC_WWN_SIZE) == 0);
10983 	ASSERT(plun->lun_num == lun_num);
10984 
10985 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10986 
10987 	ptgt = plun->lun_tgt;
10988 
10989 	mutex_enter(&ptgt->tgt_mutex);
10990 	plun->lun_tgt_count++;
10991 	scsi_device_hba_private_set(sd, plun);
10992 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10993 	plun->lun_sd = sd;
10994 	mutex_exit(&ptgt->tgt_mutex);
10995 	mutex_exit(&pptr->port_mutex);
10996 
10997 	return (DDI_SUCCESS);
10998 }
10999 
11000 
11001 /*
11002  * called by the transport to do our own target initialization
11003  *
11004  * can acquire and release the global mutex
11005  */
11006 /* ARGSUSED */
11007 static int
11008 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11009     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11010 {
11011 	struct fcp_port	*pptr = (struct fcp_port *)
11012 	    hba_tran->tran_hba_private;
11013 	int			rval;
11014 
11015 	ASSERT(pptr != NULL);
11016 
11017 	/*
11018 	 * Child node is getting initialized.  Look at the mpxio component
11019 	 * type on the child device to see if this device is mpxio managed
11020 	 * or not.
11021 	 */
11022 	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11023 		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11024 	} else {
11025 		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11026 	}
11027 
11028 	return (rval);
11029 }
11030 
11031 
11032 /* ARGSUSED */
11033 static void
11034 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11035     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11036 {
11037 	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
11038 	struct fcp_tgt	*ptgt;
11039 
11040 	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11041 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
11042 	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11043 	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11044 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11045 
11046 	if (plun == NULL) {
11047 		return;
11048 	}
11049 	ptgt = plun->lun_tgt;
11050 
11051 	ASSERT(ptgt != NULL);
11052 
11053 	mutex_enter(&ptgt->tgt_mutex);
11054 	ASSERT(plun->lun_tgt_count > 0);
11055 
11056 	if (--plun->lun_tgt_count == 0) {
11057 		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11058 	}
11059 	plun->lun_sd = NULL;
11060 	mutex_exit(&ptgt->tgt_mutex);
11061 }
11062 
11063 /*
11064  *     Function: fcp_scsi_start
11065  *
11066  *  Description: This function is called by the target driver to request a
11067  *		 command to be sent.
11068  *
11069  *     Argument: *ap		SCSI address of the device.
11070  *		 *pkt		SCSI packet containing the cmd to send.
11071  *
11072  * Return Value: TRAN_ACCEPT
11073  *		 TRAN_BUSY
11074  *		 TRAN_BADPKT
11075  *		 TRAN_FATAL_ERROR
11076  */
11077 static int
11078 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11079 {
11080 	struct fcp_port	*pptr = ADDR2FCP(ap);
11081 	struct fcp_lun	*plun = ADDR2LUN(ap);
11082 	struct fcp_pkt	*cmd = PKT2CMD(pkt);
11083 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11084 	int			rval;
11085 
11086 	/* ensure command isn't already issued */
11087 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11088 
11089 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11090 	    fcp_trace, FCP_BUF_LEVEL_9, 0,
11091 	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11092 
11093 	/*
11094 	 * It is strange that we enter the fcp_port mutex and the target
11095 	 * mutex to check the lun state (which has a mutex of its own).
11096 	 */
11097 	mutex_enter(&pptr->port_mutex);
11098 	mutex_enter(&ptgt->tgt_mutex);
11099 
11100 	/*
11101 	 * If the device is offline and is not in the process of coming
11102 	 * online, fail the request.
11103 	 */
11104 
11105 	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11106 	    !(plun->lun_state & FCP_LUN_ONLINING)) {
11107 		mutex_exit(&ptgt->tgt_mutex);
11108 		mutex_exit(&pptr->port_mutex);
11109 
11110 		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11111 			pkt->pkt_reason = CMD_DEV_GONE;
11112 		}
11113 
11114 		return (TRAN_FATAL_ERROR);
11115 	}
11116 	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11117 
11118 	/*
11119 	 * If we are suspended, kernel is trying to dump, so don't
11120 	 * block, fail or defer requests - send them down right away.
11121 	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11122 	 * assume we have been suspended.  There is hardware such as
11123 	 * the v880 that doesn't do PM.	 Thus, the check for
11124 	 * ddi_in_panic.
11125 	 *
11126 	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11127 	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11128 	 * either the device will have gone away or changed and we can fail
11129 	 * the request, or we can proceed if the device didn't change.
11130 	 *
11131 	 * If the pd in the target or the packet is NULL it's probably
11132 	 * because the device has gone away, we allow the request to be
11133 	 * put on the internal queue here in case the device comes back within
11134 	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11135 	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11136 	 * could be NULL because the device was disappearing during or since
11137 	 * packet initialization.
11138 	 */
11139 
11140 	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11141 	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11142 	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11143 	    (ptgt->tgt_pd_handle == NULL) ||
11144 	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11145 		/*
11146 		 * If ((LUN is busy AND
11147 		 *	LUN not suspended AND
11148 		 *	The system is not in panic state) OR
11149 		 *	(The port is coming up))
11150 		 *
11151 		 * We check to see if the any of the flags FLAG_NOINTR or
11152 		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11153 		 * returned will be TRAN_BUSY.	If not, the request is queued.
11154 		 */
11155 		mutex_exit(&ptgt->tgt_mutex);
11156 		mutex_exit(&pptr->port_mutex);
11157 
11158 		/* see if using interrupts is allowed (so queueing'll work) */
11159 		if (pkt->pkt_flags & FLAG_NOINTR) {
11160 			pkt->pkt_resid = 0;
11161 			return (TRAN_BUSY);
11162 		}
11163 		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11164 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11165 			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11166 			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11167 			return (TRAN_BUSY);
11168 		}
11169 #ifdef	DEBUG
11170 		mutex_enter(&pptr->port_pkt_mutex);
11171 		pptr->port_npkts++;
11172 		mutex_exit(&pptr->port_pkt_mutex);
11173 #endif /* DEBUG */
11174 
11175 		/* got queue up the pkt for later */
11176 		fcp_queue_pkt(pptr, cmd);
11177 		return (TRAN_ACCEPT);
11178 	}
11179 	cmd->cmd_state = FCP_PKT_ISSUED;
11180 
11181 	mutex_exit(&ptgt->tgt_mutex);
11182 	mutex_exit(&pptr->port_mutex);
11183 
11184 	/*
11185 	 * Now that we released the mutexes, what was protected by them can
11186 	 * change.
11187 	 */
11188 
11189 	/*
11190 	 * If there is a reconfiguration in progress, wait for it to complete.
11191 	 */
11192 	fcp_reconfig_wait(pptr);
11193 
11194 	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11195 	    pkt->pkt_time : 0;
11196 
11197 	/* prepare the packet */
11198 
11199 	fcp_prepare_pkt(pptr, cmd, plun);
11200 
11201 	if (cmd->cmd_pkt->pkt_time) {
11202 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11203 	} else {
11204 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11205 	}
11206 
11207 	/*
11208 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11209 	 * have to do polled I/O
11210 	 */
11211 	if (pkt->pkt_flags & FLAG_NOINTR) {
11212 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11213 		return (fcp_dopoll(pptr, cmd));
11214 	}
11215 
11216 #ifdef	DEBUG
11217 	mutex_enter(&pptr->port_pkt_mutex);
11218 	pptr->port_npkts++;
11219 	mutex_exit(&pptr->port_pkt_mutex);
11220 #endif /* DEBUG */
11221 
11222 	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11223 	if (rval == FC_SUCCESS) {
11224 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11225 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11226 		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11227 		return (TRAN_ACCEPT);
11228 	}
11229 
11230 	cmd->cmd_state = FCP_PKT_IDLE;
11231 
11232 #ifdef	DEBUG
11233 	mutex_enter(&pptr->port_pkt_mutex);
11234 	pptr->port_npkts--;
11235 	mutex_exit(&pptr->port_pkt_mutex);
11236 #endif /* DEBUG */
11237 
11238 	/*
11239 	 * For lack of clearer definitions, choose
11240 	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11241 	 */
11242 
11243 	if (rval == FC_TRAN_BUSY) {
11244 		pkt->pkt_resid = 0;
11245 		rval = TRAN_BUSY;
11246 	} else {
11247 		mutex_enter(&ptgt->tgt_mutex);
11248 		if (plun->lun_state & FCP_LUN_OFFLINE) {
11249 			child_info_t	*cip;
11250 
11251 			mutex_enter(&plun->lun_mutex);
11252 			cip = plun->lun_cip;
11253 			mutex_exit(&plun->lun_mutex);
11254 
11255 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11256 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11257 			    "fcp_transport failed 2 for %x: %x; dip=%p",
11258 			    plun->lun_tgt->tgt_d_id, rval, cip);
11259 
11260 			rval = TRAN_FATAL_ERROR;
11261 		} else {
11262 			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11263 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11264 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11265 				    "fcp_scsi_start: FC_BUSY for pkt %p",
11266 				    pkt);
11267 				rval = TRAN_BUSY;
11268 			} else {
11269 				rval = TRAN_ACCEPT;
11270 				fcp_queue_pkt(pptr, cmd);
11271 			}
11272 		}
11273 		mutex_exit(&ptgt->tgt_mutex);
11274 	}
11275 
11276 	return (rval);
11277 }
11278 
11279 /*
11280  * called by the transport to abort a packet
11281  */
11282 /*ARGSUSED*/
11283 static int
11284 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11285 {
11286 	int tgt_cnt;
11287 	struct fcp_port		*pptr = ADDR2FCP(ap);
11288 	struct fcp_lun	*plun = ADDR2LUN(ap);
11289 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11290 
11291 	if (pkt == NULL) {
11292 		if (ptgt) {
11293 			mutex_enter(&ptgt->tgt_mutex);
11294 			tgt_cnt = ptgt->tgt_change_cnt;
11295 			mutex_exit(&ptgt->tgt_mutex);
11296 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11297 			return (TRUE);
11298 		}
11299 	}
11300 	return (FALSE);
11301 }
11302 
11303 
11304 /*
11305  * Perform reset
11306  */
11307 int
11308 fcp_scsi_reset(struct scsi_address *ap, int level)
11309 {
11310 	int			rval = 0;
11311 	struct fcp_port		*pptr = ADDR2FCP(ap);
11312 	struct fcp_lun	*plun = ADDR2LUN(ap);
11313 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11314 
11315 	if (level == RESET_ALL) {
11316 		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11317 			rval = 1;
11318 		}
11319 	} else if (level == RESET_TARGET || level == RESET_LUN) {
11320 		/*
11321 		 * If we are in the middle of discovery, return
11322 		 * SUCCESS as this target will be rediscovered
11323 		 * anyway
11324 		 */
11325 		mutex_enter(&ptgt->tgt_mutex);
11326 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11327 			mutex_exit(&ptgt->tgt_mutex);
11328 			return (1);
11329 		}
11330 		mutex_exit(&ptgt->tgt_mutex);
11331 
11332 		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11333 			rval = 1;
11334 		}
11335 	}
11336 	return (rval);
11337 }
11338 
11339 
11340 /*
11341  * called by the framework to get a SCSI capability
11342  */
11343 static int
11344 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11345 {
11346 	return (fcp_commoncap(ap, cap, 0, whom, 0));
11347 }
11348 
11349 
11350 /*
11351  * called by the framework to set a SCSI capability
11352  */
11353 static int
11354 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11355 {
11356 	return (fcp_commoncap(ap, cap, value, whom, 1));
11357 }
11358 
11359 /*
11360  *     Function: fcp_pkt_setup
11361  *
11362  *  Description: This function sets up the scsi_pkt structure passed by the
11363  *		 caller. This function assumes fcp_pkt_constructor has been
11364  *		 called previously for the packet passed by the caller.	 If
11365  *		 successful this call will have the following results:
11366  *
11367  *		   - The resources needed that will be constant through out
11368  *		     the whole transaction are allocated.
11369  *		   - The fields that will be constant through out the whole
11370  *		     transaction are initialized.
11371  *		   - The scsi packet will be linked to the LUN structure
11372  *		     addressed by the transaction.
11373  *
11374  *     Argument:
11375  *		 *pkt		Pointer to a scsi_pkt structure.
11376  *		 callback
11377  *		 arg
11378  *
11379  * Return Value: 0	Success
11380  *		 !0	Failure
11381  *
11382  *	Context: Kernel context or interrupt context
11383  */
11384 /* ARGSUSED */
11385 static int
11386 fcp_pkt_setup(struct scsi_pkt *pkt,
11387     int (*callback)(caddr_t arg),
11388     caddr_t arg)
11389 {
11390 	struct fcp_pkt	*cmd;
11391 	struct fcp_port	*pptr;
11392 	struct fcp_lun	*plun;
11393 	struct fcp_tgt	*ptgt;
11394 	int		kf;
11395 	fc_packet_t	*fpkt;
11396 	fc_frame_hdr_t	*hp;
11397 
11398 	pptr = ADDR2FCP(&pkt->pkt_address);
11399 	plun = ADDR2LUN(&pkt->pkt_address);
11400 	ptgt = plun->lun_tgt;
11401 
11402 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11403 	fpkt = cmd->cmd_fp_pkt;
11404 
11405 	/*
11406 	 * this request is for dma allocation only
11407 	 */
11408 	/*
11409 	 * First step of fcp_scsi_init_pkt: pkt allocation
11410 	 * We determine if the caller is willing to wait for the
11411 	 * resources.
11412 	 */
11413 	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11414 
11415 	/*
11416 	 * Selective zeroing of the pkt.
11417 	 */
11418 	cmd->cmd_back = NULL;
11419 	cmd->cmd_next = NULL;
11420 
11421 	/*
11422 	 * Zero out fcp command
11423 	 */
11424 	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11425 
11426 	cmd->cmd_state = FCP_PKT_IDLE;
11427 
11428 	fpkt = cmd->cmd_fp_pkt;
11429 	fpkt->pkt_data_acc = NULL;
11430 
11431 	/*
11432 	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11433 	 * could be destroyed.	We need fail pkt_setup.
11434 	 */
11435 	if (pptr->port_state & FCP_STATE_OFFLINE) {
11436 		return (-1);
11437 	}
11438 
11439 	mutex_enter(&ptgt->tgt_mutex);
11440 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11441 
11442 	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11443 	    != FC_SUCCESS) {
11444 		mutex_exit(&ptgt->tgt_mutex);
11445 		return (-1);
11446 	}
11447 
11448 	mutex_exit(&ptgt->tgt_mutex);
11449 
11450 	/* Fill in the Fabric Channel Header */
11451 	hp = &fpkt->pkt_cmd_fhdr;
11452 	hp->r_ctl = R_CTL_COMMAND;
11453 	hp->rsvd = 0;
11454 	hp->type = FC_TYPE_SCSI_FCP;
11455 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11456 	hp->seq_id = 0;
11457 	hp->df_ctl  = 0;
11458 	hp->seq_cnt = 0;
11459 	hp->ox_id = 0xffff;
11460 	hp->rx_id = 0xffff;
11461 	hp->ro = 0;
11462 
11463 	/*
11464 	 * A doubly linked list (cmd_forw, cmd_back) is built
11465 	 * out of every allocated packet on a per-lun basis
11466 	 *
11467 	 * The packets are maintained in the list so as to satisfy
11468 	 * scsi_abort() requests. At present (which is unlikely to
11469 	 * change in the future) nobody performs a real scsi_abort
11470 	 * in the SCSI target drivers (as they don't keep the packets
11471 	 * after doing scsi_transport - so they don't know how to
11472 	 * abort a packet other than sending a NULL to abort all
11473 	 * outstanding packets)
11474 	 */
11475 	mutex_enter(&plun->lun_mutex);
11476 	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11477 		plun->lun_pkt_head->cmd_back = cmd;
11478 	} else {
11479 		plun->lun_pkt_tail = cmd;
11480 	}
11481 	plun->lun_pkt_head = cmd;
11482 	mutex_exit(&plun->lun_mutex);
11483 	return (0);
11484 }
11485 
11486 /*
11487  *     Function: fcp_pkt_teardown
11488  *
11489  *  Description: This function releases a scsi_pkt structure and all the
11490  *		 resources attached to it.
11491  *
11492  *     Argument: *pkt		Pointer to a scsi_pkt structure.
11493  *
11494  * Return Value: None
11495  *
11496  *	Context: User, Kernel or Interrupt context.
11497  */
11498 static void
11499 fcp_pkt_teardown(struct scsi_pkt *pkt)
11500 {
11501 	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11502 	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11503 	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11504 
11505 	/*
11506 	 * Remove the packet from the per-lun list
11507 	 */
11508 	mutex_enter(&plun->lun_mutex);
11509 	if (cmd->cmd_back) {
11510 		ASSERT(cmd != plun->lun_pkt_head);
11511 		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11512 	} else {
11513 		ASSERT(cmd == plun->lun_pkt_head);
11514 		plun->lun_pkt_head = cmd->cmd_forw;
11515 	}
11516 
11517 	if (cmd->cmd_forw) {
11518 		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11519 	} else {
11520 		ASSERT(cmd == plun->lun_pkt_tail);
11521 		plun->lun_pkt_tail = cmd->cmd_back;
11522 	}
11523 
11524 	mutex_exit(&plun->lun_mutex);
11525 
11526 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11527 }
11528 
11529 /*
11530  * Routine for reset notification setup, to register or cancel.
11531  * This function is called by SCSA
11532  */
11533 /*ARGSUSED*/
11534 static int
11535 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11536     void (*callback)(caddr_t), caddr_t arg)
11537 {
11538 	struct fcp_port *pptr = ADDR2FCP(ap);
11539 
11540 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11541 	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11542 }
11543 
11544 
11545 static int
11546 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11547     ddi_eventcookie_t *event_cookiep)
11548 {
11549 	struct fcp_port *pptr = fcp_dip2port(dip);
11550 
11551 	if (pptr == NULL) {
11552 		return (DDI_FAILURE);
11553 	}
11554 
11555 	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11556 	    event_cookiep, NDI_EVENT_NOPASS));
11557 }
11558 
11559 
11560 static int
11561 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11562     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11563     ddi_callback_id_t *cb_id)
11564 {
11565 	struct fcp_port *pptr = fcp_dip2port(dip);
11566 
11567 	if (pptr == NULL) {
11568 		return (DDI_FAILURE);
11569 	}
11570 
11571 	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11572 	    eventid, callback, arg, NDI_SLEEP, cb_id));
11573 }
11574 
11575 
11576 static int
11577 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11578 {
11579 
11580 	struct fcp_port *pptr = fcp_dip2port(dip);
11581 
11582 	if (pptr == NULL) {
11583 		return (DDI_FAILURE);
11584 	}
11585 	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11586 }
11587 
11588 
11589 /*
11590  * called by the transport to post an event
11591  */
11592 static int
11593 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11594     ddi_eventcookie_t eventid, void *impldata)
11595 {
11596 	struct fcp_port *pptr = fcp_dip2port(dip);
11597 
11598 	if (pptr == NULL) {
11599 		return (DDI_FAILURE);
11600 	}
11601 
11602 	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11603 	    eventid, impldata));
11604 }
11605 
11606 
11607 /*
11608  * A target in in many cases in Fibre Channel has a one to one relation
11609  * with a port identifier (which is also known as D_ID and also as AL_PA
11610  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11611  * will most likely result in resetting all LUNs (which means a reset will
11612  * occur on all the SCSI devices connected at the other end of the bridge)
11613  * That is the latest favorite topic for discussion, for, one can debate as
11614  * hot as one likes and come up with arguably a best solution to one's
11615  * satisfaction
11616  *
11617  * To stay on track and not digress much, here are the problems stated
11618  * briefly:
11619  *
11620  *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11621  *	target drivers use RESET_TARGET even if their instance is on a
11622  *	LUN. Doesn't that sound a bit broken ?
11623  *
11624  *	FCP SCSI (the current spec) only defines RESET TARGET in the
11625  *	control fields of an FCP_CMND structure. It should have been
11626  *	fixed right there, giving flexibility to the initiators to
11627  *	minimize havoc that could be caused by resetting a target.
11628  */
11629 static int
11630 fcp_reset_target(struct scsi_address *ap, int level)
11631 {
11632 	int			rval = FC_FAILURE;
11633 	char			lun_id[25];
11634 	struct fcp_port		*pptr = ADDR2FCP(ap);
11635 	struct fcp_lun	*plun = ADDR2LUN(ap);
11636 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11637 	struct scsi_pkt		*pkt;
11638 	struct fcp_pkt	*cmd;
11639 	struct fcp_rsp		*rsp;
11640 	uint32_t		tgt_cnt;
11641 	struct fcp_rsp_info	*rsp_info;
11642 	struct fcp_reset_elem	*p;
11643 	int			bval;
11644 
11645 	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11646 	    KM_NOSLEEP)) == NULL) {
11647 		return (rval);
11648 	}
11649 
11650 	mutex_enter(&ptgt->tgt_mutex);
11651 	if (level == RESET_TARGET) {
11652 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11653 			mutex_exit(&ptgt->tgt_mutex);
11654 			kmem_free(p, sizeof (struct fcp_reset_elem));
11655 			return (rval);
11656 		}
11657 		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11658 		(void) strcpy(lun_id, " ");
11659 	} else {
11660 		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11661 			mutex_exit(&ptgt->tgt_mutex);
11662 			kmem_free(p, sizeof (struct fcp_reset_elem));
11663 			return (rval);
11664 		}
11665 		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11666 
11667 		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11668 	}
11669 	tgt_cnt = ptgt->tgt_change_cnt;
11670 
11671 	mutex_exit(&ptgt->tgt_mutex);
11672 
11673 	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11674 	    0, 0, NULL, 0)) == NULL) {
11675 		kmem_free(p, sizeof (struct fcp_reset_elem));
11676 		mutex_enter(&ptgt->tgt_mutex);
11677 		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11678 		mutex_exit(&ptgt->tgt_mutex);
11679 		return (rval);
11680 	}
11681 	pkt->pkt_time = FCP_POLL_TIMEOUT;
11682 
11683 	/* fill in cmd part of packet */
11684 	cmd = PKT2CMD(pkt);
11685 	if (level == RESET_TARGET) {
11686 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11687 	} else {
11688 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11689 	}
11690 	cmd->cmd_fp_pkt->pkt_comp = NULL;
11691 	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11692 
11693 	/* prepare a packet for transport */
11694 	fcp_prepare_pkt(pptr, cmd, plun);
11695 
11696 	if (cmd->cmd_pkt->pkt_time) {
11697 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11698 	} else {
11699 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11700 	}
11701 
11702 	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11703 	bval = fcp_dopoll(pptr, cmd);
11704 	fc_ulp_idle_port(pptr->port_fp_handle);
11705 
11706 	/* submit the packet */
11707 	if (bval == TRAN_ACCEPT) {
11708 		int error = 3;
11709 
11710 		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11711 		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11712 		    sizeof (struct fcp_rsp));
11713 
11714 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11715 			if (fcp_validate_fcp_response(rsp, pptr) ==
11716 			    FC_SUCCESS) {
11717 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11718 					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11719 					    sizeof (struct fcp_rsp), rsp_info,
11720 					    cmd->cmd_fp_pkt->pkt_resp_acc,
11721 					    sizeof (struct fcp_rsp_info));
11722 				}
11723 				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11724 					rval = FC_SUCCESS;
11725 					error = 0;
11726 				} else {
11727 					error = 1;
11728 				}
11729 			} else {
11730 				error = 2;
11731 			}
11732 		}
11733 
11734 		switch (error) {
11735 		case 0:
11736 			fcp_log(CE_WARN, pptr->port_dip,
11737 			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11738 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11739 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11740 			break;
11741 
11742 		case 1:
11743 			fcp_log(CE_WARN, pptr->port_dip,
11744 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11745 			    " response code=%x",
11746 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11747 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11748 			    rsp_info->rsp_code);
11749 			break;
11750 
11751 		case 2:
11752 			fcp_log(CE_WARN, pptr->port_dip,
11753 			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11754 			    " Bad FCP response values: rsvd1=%x,"
11755 			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11756 			    " rsplen=%x, senselen=%x",
11757 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11758 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11759 			    rsp->reserved_0, rsp->reserved_1,
11760 			    rsp->fcp_u.fcp_status.reserved_0,
11761 			    rsp->fcp_u.fcp_status.reserved_1,
11762 			    rsp->fcp_response_len, rsp->fcp_sense_len);
11763 			break;
11764 
11765 		default:
11766 			fcp_log(CE_WARN, pptr->port_dip,
11767 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11768 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11769 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11770 			break;
11771 		}
11772 	}
11773 	scsi_destroy_pkt(pkt);
11774 
11775 	if (rval == FC_FAILURE) {
11776 		mutex_enter(&ptgt->tgt_mutex);
11777 		if (level == RESET_TARGET) {
11778 			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11779 		} else {
11780 			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11781 		}
11782 		mutex_exit(&ptgt->tgt_mutex);
11783 		kmem_free(p, sizeof (struct fcp_reset_elem));
11784 		return (rval);
11785 	}
11786 
11787 	mutex_enter(&pptr->port_mutex);
11788 	if (level == RESET_TARGET) {
11789 		p->tgt = ptgt;
11790 		p->lun = NULL;
11791 	} else {
11792 		p->tgt = NULL;
11793 		p->lun = plun;
11794 	}
11795 	p->tgt = ptgt;
11796 	p->tgt_cnt = tgt_cnt;
11797 	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11798 	p->next = pptr->port_reset_list;
11799 	pptr->port_reset_list = p;
11800 
11801 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11802 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11803 	    "Notify ssd of the reset to reinstate the reservations");
11804 
11805 	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11806 	    &pptr->port_reset_notify_listf);
11807 
11808 	mutex_exit(&pptr->port_mutex);
11809 
11810 	return (rval);
11811 }
11812 
11813 
11814 /*
11815  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11816  * SCSI capabilities
11817  */
11818 /* ARGSUSED */
11819 static int
11820 fcp_commoncap(struct scsi_address *ap, char *cap,
11821     int val, int tgtonly, int doset)
11822 {
11823 	struct fcp_port		*pptr = ADDR2FCP(ap);
11824 	struct fcp_lun	*plun = ADDR2LUN(ap);
11825 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11826 	int			cidx;
11827 	int			rval = FALSE;
11828 
11829 	if (cap == (char *)0) {
11830 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11831 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11832 		    "fcp_commoncap: invalid arg");
11833 		return (rval);
11834 	}
11835 
11836 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11837 		return (UNDEFINED);
11838 	}
11839 
11840 	/*
11841 	 * Process setcap request.
11842 	 */
11843 	if (doset) {
11844 		/*
11845 		 * At present, we can only set binary (0/1) values
11846 		 */
11847 		switch (cidx) {
11848 		case SCSI_CAP_ARQ:
11849 			if (val == 0) {
11850 				rval = FALSE;
11851 			} else {
11852 				rval = TRUE;
11853 			}
11854 			break;
11855 
11856 		case SCSI_CAP_LUN_RESET:
11857 			if (val) {
11858 				plun->lun_cap |= FCP_LUN_CAP_RESET;
11859 			} else {
11860 				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11861 			}
11862 			rval = TRUE;
11863 			break;
11864 
11865 		case SCSI_CAP_SECTOR_SIZE:
11866 			rval = TRUE;
11867 			break;
11868 		default:
11869 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11870 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11871 			    "fcp_setcap: unsupported %d", cidx);
11872 			rval = UNDEFINED;
11873 			break;
11874 		}
11875 
11876 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11877 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11878 		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11879 		    "0x%x/0x%x/0x%x/%d",
11880 		    cap, val, tgtonly, doset, rval);
11881 
11882 	} else {
11883 		/*
11884 		 * Process getcap request.
11885 		 */
11886 		switch (cidx) {
11887 		case SCSI_CAP_DMA_MAX:
11888 			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11889 
11890 			/*
11891 			 * Need to make an adjustment qlc is uint_t 64
11892 			 * st is int, so we will make the adjustment here
11893 			 * being as nobody wants to touch this.
11894 			 * It still leaves the max single block length
11895 			 * of 2 gig. This should last .
11896 			 */
11897 
11898 			if (rval == -1) {
11899 				rval = MAX_INT_DMA;
11900 			}
11901 
11902 			break;
11903 
11904 		case SCSI_CAP_INITIATOR_ID:
11905 			rval = pptr->port_id;
11906 			break;
11907 
11908 		case SCSI_CAP_ARQ:
11909 		case SCSI_CAP_RESET_NOTIFICATION:
11910 		case SCSI_CAP_TAGGED_QING:
11911 			rval = TRUE;
11912 			break;
11913 
11914 		case SCSI_CAP_SCSI_VERSION:
11915 			rval = 3;
11916 			break;
11917 
11918 		case SCSI_CAP_INTERCONNECT_TYPE:
11919 			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11920 			    (ptgt->tgt_hard_addr == 0)) {
11921 				rval = INTERCONNECT_FABRIC;
11922 			} else {
11923 				rval = INTERCONNECT_FIBRE;
11924 			}
11925 			break;
11926 
11927 		case SCSI_CAP_LUN_RESET:
11928 			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11929 			    TRUE : FALSE;
11930 			break;
11931 
11932 		default:
11933 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11934 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11935 			    "fcp_getcap: unsupported %d", cidx);
11936 			rval = UNDEFINED;
11937 			break;
11938 		}
11939 
11940 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11941 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11942 		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11943 		    "0x%x/0x%x/0x%x/%d",
11944 		    cap, val, tgtonly, doset, rval);
11945 	}
11946 
11947 	return (rval);
11948 }
11949 
11950 /*
11951  * called by the transport to get the port-wwn and lun
11952  * properties of this device, and to create a "name" based on them
11953  *
11954  * these properties don't exist on sun4m
11955  *
11956  * return 1 for success else return 0
11957  */
11958 /* ARGSUSED */
11959 static int
11960 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11961 {
11962 	int			i;
11963 	int			*lun;
11964 	int			numChars;
11965 	uint_t			nlun;
11966 	uint_t			count;
11967 	uint_t			nbytes;
11968 	uchar_t			*bytes;
11969 	uint16_t		lun_num;
11970 	uint32_t		tgt_id;
11971 	char			**conf_wwn;
11972 	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11973 	uchar_t			barray[FC_WWN_SIZE];
11974 	dev_info_t		*tgt_dip;
11975 	struct fcp_tgt	*ptgt;
11976 	struct fcp_port	*pptr;
11977 	struct fcp_lun	*plun;
11978 
11979 	ASSERT(sd != NULL);
11980 	ASSERT(name != NULL);
11981 
11982 	tgt_dip = sd->sd_dev;
11983 	pptr = ddi_get_soft_state(fcp_softstate,
11984 	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11985 	if (pptr == NULL) {
11986 		return (0);
11987 	}
11988 
11989 	ASSERT(tgt_dip != NULL);
11990 
11991 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11992 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11993 	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11994 		name[0] = '\0';
11995 		return (0);
11996 	}
11997 
11998 	if (nlun == 0) {
11999 		ddi_prop_free(lun);
12000 		return (0);
12001 	}
12002 
12003 	lun_num = lun[0];
12004 	ddi_prop_free(lun);
12005 
12006 	/*
12007 	 * Lookup for .conf WWN property
12008 	 */
12009 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12010 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12011 	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12012 		ASSERT(count >= 1);
12013 
12014 		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12015 		ddi_prop_free(conf_wwn);
12016 		mutex_enter(&pptr->port_mutex);
12017 		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12018 			mutex_exit(&pptr->port_mutex);
12019 			return (0);
12020 		}
12021 		ptgt = plun->lun_tgt;
12022 		mutex_exit(&pptr->port_mutex);
12023 
12024 		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12025 		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12026 
12027 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12028 		    ptgt->tgt_hard_addr != 0) {
12029 			tgt_id = (uint32_t)fcp_alpa_to_switch[
12030 			    ptgt->tgt_hard_addr];
12031 		} else {
12032 			tgt_id = ptgt->tgt_d_id;
12033 		}
12034 
12035 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12036 		    TARGET_PROP, tgt_id);
12037 	}
12038 
12039 	/* get the our port-wwn property */
12040 	bytes = NULL;
12041 	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12042 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12043 	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12044 		if (bytes != NULL) {
12045 			ddi_prop_free(bytes);
12046 		}
12047 		return (0);
12048 	}
12049 
12050 	for (i = 0; i < FC_WWN_SIZE; i++) {
12051 		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12052 	}
12053 
12054 	/* Stick in the address of the form "wWWN,LUN" */
12055 	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12056 
12057 	ASSERT(numChars < len);
12058 	if (numChars >= len) {
12059 		fcp_log(CE_WARN, pptr->port_dip,
12060 		    "!fcp_scsi_get_name: "
12061 		    "name parameter length too small, it needs to be %d",
12062 		    numChars+1);
12063 	}
12064 
12065 	ddi_prop_free(bytes);
12066 
12067 	return (1);
12068 }
12069 
12070 
12071 /*
12072  * called by the transport to get the SCSI target id value, returning
12073  * it in "name"
12074  *
12075  * this isn't needed/used on sun4m
12076  *
12077  * return 1 for success else return 0
12078  */
12079 /* ARGSUSED */
12080 static int
12081 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12082 {
12083 	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
12084 	struct fcp_tgt	*ptgt;
12085 	int    numChars;
12086 
12087 	if (plun == NULL) {
12088 		return (0);
12089 	}
12090 
12091 	if ((ptgt = plun->lun_tgt) == NULL) {
12092 		return (0);
12093 	}
12094 
12095 	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12096 
12097 	ASSERT(numChars < len);
12098 	if (numChars >= len) {
12099 		fcp_log(CE_WARN, NULL,
12100 		    "!fcp_scsi_get_bus_addr: "
12101 		    "name parameter length too small, it needs to be %d",
12102 		    numChars+1);
12103 	}
12104 
12105 	return (1);
12106 }
12107 
12108 
12109 /*
12110  * called internally to reset the link where the specified port lives
12111  */
12112 static int
12113 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12114 {
12115 	la_wwn_t		wwn;
12116 	struct fcp_lun	*plun;
12117 	struct fcp_tgt	*ptgt;
12118 
12119 	/* disable restart of lip if we're suspended */
12120 	mutex_enter(&pptr->port_mutex);
12121 
12122 	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12123 	    FCP_STATE_POWER_DOWN)) {
12124 		mutex_exit(&pptr->port_mutex);
12125 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12126 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12127 		    "fcp_linkreset, fcp%d: link reset "
12128 		    "disabled due to DDI_SUSPEND",
12129 		    ddi_get_instance(pptr->port_dip));
12130 		return (FC_FAILURE);
12131 	}
12132 
12133 	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12134 		mutex_exit(&pptr->port_mutex);
12135 		return (FC_SUCCESS);
12136 	}
12137 
12138 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12139 	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12140 
12141 	/*
12142 	 * If ap == NULL assume local link reset.
12143 	 */
12144 	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12145 		plun = ADDR2LUN(ap);
12146 		ptgt = plun->lun_tgt;
12147 		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12148 	} else {
12149 		bzero((caddr_t)&wwn, sizeof (wwn));
12150 	}
12151 	mutex_exit(&pptr->port_mutex);
12152 
12153 	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12154 }
12155 
12156 
12157 /*
12158  * called from fcp_port_attach() to resume a port
12159  * return DDI_* success/failure status
12160  * acquires and releases the global mutex
12161  * acquires and releases the port mutex
12162  */
12163 /*ARGSUSED*/
12164 
12165 static int
12166 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12167     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12168 {
12169 	int			res = DDI_FAILURE; /* default result */
12170 	struct fcp_port	*pptr;		/* port state ptr */
12171 	uint32_t		alloc_cnt;
12172 	uint32_t		max_cnt;
12173 	fc_portmap_t		*tmp_list = NULL;
12174 
12175 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12176 	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12177 	    instance);
12178 
12179 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12180 		cmn_err(CE_WARN, "fcp: bad soft state");
12181 		return (res);
12182 	}
12183 
12184 	mutex_enter(&pptr->port_mutex);
12185 	switch (cmd) {
12186 	case FC_CMD_RESUME:
12187 		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12188 		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12189 		break;
12190 
12191 	case FC_CMD_POWER_UP:
12192 		/*
12193 		 * If the port is DDI_SUSPENded, defer rediscovery
12194 		 * until DDI_RESUME occurs
12195 		 */
12196 		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12197 			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12198 			mutex_exit(&pptr->port_mutex);
12199 			return (DDI_SUCCESS);
12200 		}
12201 		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12202 	}
12203 	pptr->port_id = s_id;
12204 	pptr->port_state = FCP_STATE_INIT;
12205 	mutex_exit(&pptr->port_mutex);
12206 
12207 	/*
12208 	 * Make a copy of ulp_port_info as fctl allocates
12209 	 * a temp struct.
12210 	 */
12211 	(void) fcp_cp_pinfo(pptr, pinfo);
12212 
12213 	mutex_enter(&fcp_global_mutex);
12214 	if (fcp_watchdog_init++ == 0) {
12215 		fcp_watchdog_tick = fcp_watchdog_timeout *
12216 		    drv_usectohz(1000000);
12217 		fcp_watchdog_id = timeout(fcp_watch,
12218 		    NULL, fcp_watchdog_tick);
12219 	}
12220 	mutex_exit(&fcp_global_mutex);
12221 
12222 	/*
12223 	 * Handle various topologies and link states.
12224 	 */
12225 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12226 	case FC_STATE_OFFLINE:
12227 		/*
12228 		 * Wait for ONLINE, at which time a state
12229 		 * change will cause a statec_callback
12230 		 */
12231 		res = DDI_SUCCESS;
12232 		break;
12233 
12234 	case FC_STATE_ONLINE:
12235 
12236 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12237 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12238 			res = DDI_SUCCESS;
12239 			break;
12240 		}
12241 
12242 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12243 		    !fcp_enable_auto_configuration) {
12244 			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12245 			if (tmp_list == NULL) {
12246 				if (!alloc_cnt) {
12247 					res = DDI_SUCCESS;
12248 				}
12249 				break;
12250 			}
12251 			max_cnt = alloc_cnt;
12252 		} else {
12253 			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12254 
12255 			alloc_cnt = FCP_MAX_DEVICES;
12256 
12257 			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12258 			    (sizeof (fc_portmap_t)) * alloc_cnt,
12259 			    KM_NOSLEEP)) == NULL) {
12260 				fcp_log(CE_WARN, pptr->port_dip,
12261 				    "!fcp%d: failed to allocate portmap",
12262 				    instance);
12263 				break;
12264 			}
12265 
12266 			max_cnt = alloc_cnt;
12267 			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12268 			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12269 			    FC_SUCCESS) {
12270 				caddr_t msg;
12271 
12272 				(void) fc_ulp_error(res, &msg);
12273 
12274 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12275 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12276 				    "resume failed getportmap: reason=0x%x",
12277 				    res);
12278 
12279 				fcp_log(CE_WARN, pptr->port_dip,
12280 				    "!failed to get port map : %s", msg);
12281 				break;
12282 			}
12283 			if (max_cnt > alloc_cnt) {
12284 				alloc_cnt = max_cnt;
12285 			}
12286 		}
12287 
12288 		/*
12289 		 * do the SCSI device discovery and create
12290 		 * the devinfos
12291 		 */
12292 		fcp_statec_callback(ulph, pptr->port_fp_handle,
12293 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12294 		    max_cnt, pptr->port_id);
12295 
12296 		res = DDI_SUCCESS;
12297 		break;
12298 
12299 	default:
12300 		fcp_log(CE_WARN, pptr->port_dip,
12301 		    "!fcp%d: invalid port state at attach=0x%x",
12302 		    instance, pptr->port_phys_state);
12303 
12304 		mutex_enter(&pptr->port_mutex);
12305 		pptr->port_phys_state = FCP_STATE_OFFLINE;
12306 		mutex_exit(&pptr->port_mutex);
12307 		res = DDI_SUCCESS;
12308 
12309 		break;
12310 	}
12311 
12312 	if (tmp_list != NULL) {
12313 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12314 	}
12315 
12316 	return (res);
12317 }
12318 
12319 
12320 static void
12321 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12322 {
12323 	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12324 	pptr->port_dip = pinfo->port_dip;
12325 	pptr->port_fp_handle = pinfo->port_handle;
12326 	if (pinfo->port_acc_attr != NULL) {
12327 		/*
12328 		 * FCA supports DMA
12329 		 */
12330 		pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12331 		pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12332 		pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12333 		pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12334 	}
12335 	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12336 	pptr->port_max_exch = pinfo->port_fca_max_exch;
12337 	pptr->port_phys_state = pinfo->port_state;
12338 	pptr->port_topology = pinfo->port_flags;
12339 	pptr->port_reset_action = pinfo->port_reset_action;
12340 	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12341 	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12342 	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12343 	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12344 
12345 	/* Clear FMA caps to avoid fm-capability ereport */
12346 	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12347 		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12348 	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12349 		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12350 	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12351 		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12352 }
12353 
12354 /*
12355  * If the elements wait field is set to 1 then
12356  * another thread is waiting for the operation to complete. Once
12357  * it is complete, the waiting thread is signaled and the element is
12358  * freed by the waiting thread. If the elements wait field is set to 0
12359  * the element is freed.
12360  */
12361 static void
12362 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12363 {
12364 	ASSERT(elem != NULL);
12365 	mutex_enter(&elem->mutex);
12366 	elem->result = result;
12367 	if (elem->wait) {
12368 		elem->wait = 0;
12369 		cv_signal(&elem->cv);
12370 		mutex_exit(&elem->mutex);
12371 	} else {
12372 		mutex_exit(&elem->mutex);
12373 		cv_destroy(&elem->cv);
12374 		mutex_destroy(&elem->mutex);
12375 		kmem_free(elem, sizeof (struct fcp_hp_elem));
12376 	}
12377 }
12378 
12379 /*
12380  * This function is invoked from the taskq thread to allocate
12381  * devinfo nodes and to online/offline them.
12382  */
12383 static void
12384 fcp_hp_task(void *arg)
12385 {
12386 	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12387 	struct fcp_lun	*plun = elem->lun;
12388 	struct fcp_port		*pptr = elem->port;
12389 	int			result;
12390 
12391 	ASSERT(elem->what == FCP_ONLINE ||
12392 	    elem->what == FCP_OFFLINE ||
12393 	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12394 	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12395 
12396 	mutex_enter(&pptr->port_mutex);
12397 	mutex_enter(&plun->lun_mutex);
12398 	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12399 	    plun->lun_event_count != elem->event_cnt) ||
12400 	    pptr->port_state & (FCP_STATE_SUSPENDED |
12401 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12402 		mutex_exit(&plun->lun_mutex);
12403 		mutex_exit(&pptr->port_mutex);
12404 		fcp_process_elem(elem, NDI_FAILURE);
12405 		return;
12406 	}
12407 	mutex_exit(&plun->lun_mutex);
12408 	mutex_exit(&pptr->port_mutex);
12409 
12410 	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12411 	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12412 	fcp_process_elem(elem, result);
12413 }
12414 
12415 
12416 static child_info_t *
12417 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12418     int tcount)
12419 {
12420 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12421 
12422 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12423 		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12424 
12425 		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12426 		/*
12427 		 * Child has not been created yet. Create the child device
12428 		 * based on the per-Lun flags.
12429 		 */
12430 		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12431 			plun->lun_cip =
12432 			    CIP(fcp_create_dip(plun, lcount, tcount));
12433 			plun->lun_mpxio = 0;
12434 		} else {
12435 			plun->lun_cip =
12436 			    CIP(fcp_create_pip(plun, lcount, tcount));
12437 			plun->lun_mpxio = 1;
12438 		}
12439 	} else {
12440 		plun->lun_cip = cip;
12441 	}
12442 
12443 	return (plun->lun_cip);
12444 }
12445 
12446 
12447 static int
12448 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12449 {
12450 	int		rval = FC_FAILURE;
12451 	dev_info_t	*pdip;
12452 	struct dev_info	*dip;
12453 	int		circular;
12454 
12455 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12456 
12457 	pdip = plun->lun_tgt->tgt_port->port_dip;
12458 
12459 	if (plun->lun_cip == NULL) {
12460 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12461 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12462 		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12463 		    "plun: %p lun state: %x num: %d target state: %x",
12464 		    plun, plun->lun_state, plun->lun_num,
12465 		    plun->lun_tgt->tgt_port->port_state);
12466 		return (rval);
12467 	}
12468 	ndi_devi_enter(pdip, &circular);
12469 	dip = DEVI(pdip)->devi_child;
12470 	while (dip) {
12471 		if (dip == DEVI(cdip)) {
12472 			rval = FC_SUCCESS;
12473 			break;
12474 		}
12475 		dip = dip->devi_sibling;
12476 	}
12477 	ndi_devi_exit(pdip, circular);
12478 	return (rval);
12479 }
12480 
12481 static int
12482 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12483 {
12484 	int		rval = FC_FAILURE;
12485 
12486 	ASSERT(plun != NULL);
12487 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12488 
12489 	if (plun->lun_mpxio == 0) {
12490 		rval = fcp_is_dip_present(plun, DIP(cip));
12491 	} else {
12492 		rval = fcp_is_pip_present(plun, PIP(cip));
12493 	}
12494 
12495 	return (rval);
12496 }
12497 
12498 /*
12499  *     Function: fcp_create_dip
12500  *
12501  *  Description: Creates a dev_info_t structure for the LUN specified by the
12502  *		 caller.
12503  *
12504  *     Argument: plun		Lun structure
12505  *		 link_cnt	Link state count.
12506  *		 tgt_cnt	Target state change count.
12507  *
12508  * Return Value: NULL if it failed
12509  *		 dev_info_t structure address if it succeeded
12510  *
12511  *	Context: Kernel context
12512  */
12513 static dev_info_t *
12514 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12515 {
12516 	int			failure = 0;
12517 	uint32_t		tgt_id;
12518 	uint64_t		sam_lun;
12519 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12520 	struct fcp_port	*pptr = ptgt->tgt_port;
12521 	dev_info_t		*pdip = pptr->port_dip;
12522 	dev_info_t		*cdip = NULL;
12523 	dev_info_t		*old_dip = DIP(plun->lun_cip);
12524 	char			*nname = NULL;
12525 	char			**compatible = NULL;
12526 	int			ncompatible;
12527 	char			*scsi_binding_set;
12528 	char			t_pwwn[17];
12529 
12530 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12531 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12532 
12533 	/* get the 'scsi-binding-set' property */
12534 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12535 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12536 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12537 		scsi_binding_set = NULL;
12538 	}
12539 
12540 	/* determine the node name and compatible */
12541 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12542 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12543 	if (scsi_binding_set) {
12544 		ddi_prop_free(scsi_binding_set);
12545 	}
12546 
12547 	if (nname == NULL) {
12548 #ifdef	DEBUG
12549 		cmn_err(CE_WARN, "%s%d: no driver for "
12550 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12551 		    "	 compatible: %s",
12552 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12553 		    ptgt->tgt_port_wwn.raw_wwn[0],
12554 		    ptgt->tgt_port_wwn.raw_wwn[1],
12555 		    ptgt->tgt_port_wwn.raw_wwn[2],
12556 		    ptgt->tgt_port_wwn.raw_wwn[3],
12557 		    ptgt->tgt_port_wwn.raw_wwn[4],
12558 		    ptgt->tgt_port_wwn.raw_wwn[5],
12559 		    ptgt->tgt_port_wwn.raw_wwn[6],
12560 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12561 		    *compatible);
12562 #endif	/* DEBUG */
12563 		failure++;
12564 		goto end_of_fcp_create_dip;
12565 	}
12566 
12567 	cdip = fcp_find_existing_dip(plun, pdip, nname);
12568 
12569 	/*
12570 	 * if the old_dip does not match the cdip, that means there is
12571 	 * some property change. since we'll be using the cdip, we need
12572 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12573 	 * then the dtype for the device has been updated. Offline the
12574 	 * the old device and create a new device with the new device type
12575 	 * Refer to bug: 4764752
12576 	 */
12577 	if (old_dip && (cdip != old_dip ||
12578 	    plun->lun_state & FCP_LUN_CHANGED)) {
12579 		plun->lun_state &= ~(FCP_LUN_INIT);
12580 		mutex_exit(&plun->lun_mutex);
12581 		mutex_exit(&pptr->port_mutex);
12582 
12583 		mutex_enter(&ptgt->tgt_mutex);
12584 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12585 		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12586 		mutex_exit(&ptgt->tgt_mutex);
12587 
12588 #ifdef DEBUG
12589 		if (cdip != NULL) {
12590 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12591 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12592 			    "Old dip=%p; New dip=%p don't match", old_dip,
12593 			    cdip);
12594 		} else {
12595 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12596 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12597 			    "Old dip=%p; New dip=NULL don't match", old_dip);
12598 		}
12599 #endif
12600 
12601 		mutex_enter(&pptr->port_mutex);
12602 		mutex_enter(&plun->lun_mutex);
12603 	}
12604 
12605 	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12606 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12607 		if (ndi_devi_alloc(pptr->port_dip, nname,
12608 		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12609 			failure++;
12610 			goto end_of_fcp_create_dip;
12611 		}
12612 	}
12613 
12614 	/*
12615 	 * Previously all the properties for the devinfo were destroyed here
12616 	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12617 	 * the devid property (and other properties established by the target
12618 	 * driver or framework) which the code does not always recreate, this
12619 	 * call was removed.
12620 	 * This opens a theoretical possibility that we may return with a
12621 	 * stale devid on the node if the scsi entity behind the fibre channel
12622 	 * lun has changed.
12623 	 */
12624 
12625 	/* decorate the node with compatible */
12626 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12627 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12628 		failure++;
12629 		goto end_of_fcp_create_dip;
12630 	}
12631 
12632 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12633 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12634 		failure++;
12635 		goto end_of_fcp_create_dip;
12636 	}
12637 
12638 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12639 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12640 		failure++;
12641 		goto end_of_fcp_create_dip;
12642 	}
12643 
12644 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12645 	t_pwwn[16] = '\0';
12646 	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12647 	    != DDI_PROP_SUCCESS) {
12648 		failure++;
12649 		goto end_of_fcp_create_dip;
12650 	}
12651 
12652 	/*
12653 	 * If there is no hard address - We might have to deal with
12654 	 * that by using WWN - Having said that it is important to
12655 	 * recognize this problem early so ssd can be informed of
12656 	 * the right interconnect type.
12657 	 */
12658 	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12659 		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12660 	} else {
12661 		tgt_id = ptgt->tgt_d_id;
12662 	}
12663 
12664 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12665 	    tgt_id) != DDI_PROP_SUCCESS) {
12666 		failure++;
12667 		goto end_of_fcp_create_dip;
12668 	}
12669 
12670 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12671 	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12672 		failure++;
12673 		goto end_of_fcp_create_dip;
12674 	}
12675 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12676 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12677 	    sam_lun) != DDI_PROP_SUCCESS) {
12678 		failure++;
12679 		goto end_of_fcp_create_dip;
12680 	}
12681 
12682 end_of_fcp_create_dip:
12683 	scsi_hba_nodename_compatible_free(nname, compatible);
12684 
12685 	if (cdip != NULL && failure) {
12686 		(void) ndi_prop_remove_all(cdip);
12687 		(void) ndi_devi_free(cdip);
12688 		cdip = NULL;
12689 	}
12690 
12691 	return (cdip);
12692 }
12693 
12694 /*
12695  *     Function: fcp_create_pip
12696  *
12697  *  Description: Creates a Path Id for the LUN specified by the caller.
12698  *
12699  *     Argument: plun		Lun structure
12700  *		 link_cnt	Link state count.
12701  *		 tgt_cnt	Target state count.
12702  *
12703  * Return Value: NULL if it failed
12704  *		 mdi_pathinfo_t structure address if it succeeded
12705  *
12706  *	Context: Kernel context
12707  */
12708 static mdi_pathinfo_t *
12709 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12710 {
12711 	int			i;
12712 	char			buf[MAXNAMELEN];
12713 	char			uaddr[MAXNAMELEN];
12714 	int			failure = 0;
12715 	uint32_t		tgt_id;
12716 	uint64_t		sam_lun;
12717 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12718 	struct fcp_port	*pptr = ptgt->tgt_port;
12719 	dev_info_t		*pdip = pptr->port_dip;
12720 	mdi_pathinfo_t		*pip = NULL;
12721 	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12722 	char			*nname = NULL;
12723 	char			**compatible = NULL;
12724 	int			ncompatible;
12725 	char			*scsi_binding_set;
12726 	char			t_pwwn[17];
12727 
12728 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12729 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12730 
12731 	scsi_binding_set = "vhci";
12732 
12733 	/* determine the node name and compatible */
12734 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12735 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12736 
12737 	if (nname == NULL) {
12738 #ifdef	DEBUG
12739 		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12740 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12741 		    "	 compatible: %s",
12742 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12743 		    ptgt->tgt_port_wwn.raw_wwn[0],
12744 		    ptgt->tgt_port_wwn.raw_wwn[1],
12745 		    ptgt->tgt_port_wwn.raw_wwn[2],
12746 		    ptgt->tgt_port_wwn.raw_wwn[3],
12747 		    ptgt->tgt_port_wwn.raw_wwn[4],
12748 		    ptgt->tgt_port_wwn.raw_wwn[5],
12749 		    ptgt->tgt_port_wwn.raw_wwn[6],
12750 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12751 		    *compatible);
12752 #endif	/* DEBUG */
12753 		failure++;
12754 		goto end_of_fcp_create_pip;
12755 	}
12756 
12757 	pip = fcp_find_existing_pip(plun, pdip);
12758 
12759 	/*
12760 	 * if the old_dip does not match the cdip, that means there is
12761 	 * some property change. since we'll be using the cdip, we need
12762 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12763 	 * then the dtype for the device has been updated. Offline the
12764 	 * the old device and create a new device with the new device type
12765 	 * Refer to bug: 4764752
12766 	 */
12767 	if (old_pip && (pip != old_pip ||
12768 	    plun->lun_state & FCP_LUN_CHANGED)) {
12769 		plun->lun_state &= ~(FCP_LUN_INIT);
12770 		mutex_exit(&plun->lun_mutex);
12771 		mutex_exit(&pptr->port_mutex);
12772 
12773 		mutex_enter(&ptgt->tgt_mutex);
12774 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12775 		    FCP_OFFLINE, lcount, tcount,
12776 		    NDI_DEVI_REMOVE, 0);
12777 		mutex_exit(&ptgt->tgt_mutex);
12778 
12779 		if (pip != NULL) {
12780 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12781 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12782 			    "Old pip=%p; New pip=%p don't match",
12783 			    old_pip, pip);
12784 		} else {
12785 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12786 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12787 			    "Old pip=%p; New pip=NULL don't match",
12788 			    old_pip);
12789 		}
12790 
12791 		mutex_enter(&pptr->port_mutex);
12792 		mutex_enter(&plun->lun_mutex);
12793 	}
12794 
12795 	/*
12796 	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12797 	 * lun_guid_size which is dependent on the target, I don't
12798 	 * believe the same trancation happens here UNLESS the standards
12799 	 * change the FC_WWN_SIZE value to something larger than
12800 	 * MAXNAMELEN(currently 255 bytes).
12801 	 */
12802 
12803 	for (i = 0; i < FC_WWN_SIZE; i++) {
12804 		(void) sprintf(&buf[i << 1], "%02x",
12805 		    ptgt->tgt_port_wwn.raw_wwn[i]);
12806 	}
12807 
12808 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12809 	    buf, plun->lun_num);
12810 
12811 	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12812 		/*
12813 		 * Release the locks before calling into
12814 		 * mdi_pi_alloc_compatible() since this can result in a
12815 		 * callback into fcp which can result in a deadlock
12816 		 * (see bug # 4870272).
12817 		 *
12818 		 * Basically, what we are trying to avoid is the scenario where
12819 		 * one thread does ndi_devi_enter() and tries to grab
12820 		 * fcp_mutex and another does it the other way round.
12821 		 *
12822 		 * But before we do that, make sure that nobody releases the
12823 		 * port in the meantime. We can do this by setting a flag.
12824 		 */
12825 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12826 		pptr->port_state |= FCP_STATE_IN_MDI;
12827 		mutex_exit(&plun->lun_mutex);
12828 		mutex_exit(&pptr->port_mutex);
12829 		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12830 		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12831 			fcp_log(CE_WARN, pptr->port_dip,
12832 			    "!path alloc failed:0x%x", plun);
12833 			mutex_enter(&pptr->port_mutex);
12834 			mutex_enter(&plun->lun_mutex);
12835 			pptr->port_state &= ~FCP_STATE_IN_MDI;
12836 			failure++;
12837 			goto end_of_fcp_create_pip;
12838 		}
12839 		mutex_enter(&pptr->port_mutex);
12840 		mutex_enter(&plun->lun_mutex);
12841 		pptr->port_state &= ~FCP_STATE_IN_MDI;
12842 	} else {
12843 		(void) mdi_prop_remove(pip, NULL);
12844 	}
12845 
12846 	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12847 
12848 	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12849 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12850 	    != DDI_PROP_SUCCESS) {
12851 		failure++;
12852 		goto end_of_fcp_create_pip;
12853 	}
12854 
12855 	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12856 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12857 	    != DDI_PROP_SUCCESS) {
12858 		failure++;
12859 		goto end_of_fcp_create_pip;
12860 	}
12861 
12862 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12863 	t_pwwn[16] = '\0';
12864 	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12865 	    != DDI_PROP_SUCCESS) {
12866 		failure++;
12867 		goto end_of_fcp_create_pip;
12868 	}
12869 
12870 	/*
12871 	 * If there is no hard address - We might have to deal with
12872 	 * that by using WWN - Having said that it is important to
12873 	 * recognize this problem early so ssd can be informed of
12874 	 * the right interconnect type.
12875 	 */
12876 	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12877 	    ptgt->tgt_hard_addr != 0) {
12878 		tgt_id = (uint32_t)
12879 		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12880 	} else {
12881 		tgt_id = ptgt->tgt_d_id;
12882 	}
12883 
12884 	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12885 	    != DDI_PROP_SUCCESS) {
12886 		failure++;
12887 		goto end_of_fcp_create_pip;
12888 	}
12889 
12890 	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12891 	    != DDI_PROP_SUCCESS) {
12892 		failure++;
12893 		goto end_of_fcp_create_pip;
12894 	}
12895 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12896 	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12897 	    != DDI_PROP_SUCCESS) {
12898 		failure++;
12899 		goto end_of_fcp_create_pip;
12900 	}
12901 
12902 end_of_fcp_create_pip:
12903 	scsi_hba_nodename_compatible_free(nname, compatible);
12904 
12905 	if (pip != NULL && failure) {
12906 		(void) mdi_prop_remove(pip, NULL);
12907 		mutex_exit(&plun->lun_mutex);
12908 		mutex_exit(&pptr->port_mutex);
12909 		(void) mdi_pi_free(pip, 0);
12910 		mutex_enter(&pptr->port_mutex);
12911 		mutex_enter(&plun->lun_mutex);
12912 		pip = NULL;
12913 	}
12914 
12915 	return (pip);
12916 }
12917 
12918 static dev_info_t *
12919 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12920 {
12921 	uint_t			nbytes;
12922 	uchar_t			*bytes;
12923 	uint_t			nwords;
12924 	uint32_t		tgt_id;
12925 	int			*words;
12926 	dev_info_t		*cdip;
12927 	dev_info_t		*ndip;
12928 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12929 	struct fcp_port	*pptr = ptgt->tgt_port;
12930 	int			circular;
12931 
12932 	ndi_devi_enter(pdip, &circular);
12933 
12934 	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12935 	while ((cdip = ndip) != NULL) {
12936 		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12937 
12938 		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12939 			continue;
12940 		}
12941 
12942 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12943 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12944 		    &nbytes) != DDI_PROP_SUCCESS) {
12945 			continue;
12946 		}
12947 
12948 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12949 			if (bytes != NULL) {
12950 				ddi_prop_free(bytes);
12951 			}
12952 			continue;
12953 		}
12954 		ASSERT(bytes != NULL);
12955 
12956 		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12957 			ddi_prop_free(bytes);
12958 			continue;
12959 		}
12960 
12961 		ddi_prop_free(bytes);
12962 
12963 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12964 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12965 		    &nbytes) != DDI_PROP_SUCCESS) {
12966 			continue;
12967 		}
12968 
12969 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12970 			if (bytes != NULL) {
12971 				ddi_prop_free(bytes);
12972 			}
12973 			continue;
12974 		}
12975 		ASSERT(bytes != NULL);
12976 
12977 		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12978 			ddi_prop_free(bytes);
12979 			continue;
12980 		}
12981 
12982 		ddi_prop_free(bytes);
12983 
12984 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12985 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12986 		    &nwords) != DDI_PROP_SUCCESS) {
12987 			continue;
12988 		}
12989 
12990 		if (nwords != 1 || words == NULL) {
12991 			if (words != NULL) {
12992 				ddi_prop_free(words);
12993 			}
12994 			continue;
12995 		}
12996 		ASSERT(words != NULL);
12997 
12998 		/*
12999 		 * If there is no hard address - We might have to deal with
13000 		 * that by using WWN - Having said that it is important to
13001 		 * recognize this problem early so ssd can be informed of
13002 		 * the right interconnect type.
13003 		 */
13004 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13005 		    ptgt->tgt_hard_addr != 0) {
13006 			tgt_id =
13007 			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13008 		} else {
13009 			tgt_id = ptgt->tgt_d_id;
13010 		}
13011 
13012 		if (tgt_id != (uint32_t)*words) {
13013 			ddi_prop_free(words);
13014 			continue;
13015 		}
13016 		ddi_prop_free(words);
13017 
13018 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13019 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13020 		    &nwords) != DDI_PROP_SUCCESS) {
13021 			continue;
13022 		}
13023 
13024 		if (nwords != 1 || words == NULL) {
13025 			if (words != NULL) {
13026 				ddi_prop_free(words);
13027 			}
13028 			continue;
13029 		}
13030 		ASSERT(words != NULL);
13031 
13032 		if (plun->lun_num == (uint16_t)*words) {
13033 			ddi_prop_free(words);
13034 			break;
13035 		}
13036 		ddi_prop_free(words);
13037 	}
13038 	ndi_devi_exit(pdip, circular);
13039 
13040 	return (cdip);
13041 }
13042 
13043 
13044 static int
13045 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13046 {
13047 	dev_info_t	*pdip;
13048 	char		buf[MAXNAMELEN];
13049 	char		uaddr[MAXNAMELEN];
13050 	int		rval = FC_FAILURE;
13051 
13052 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13053 
13054 	pdip = plun->lun_tgt->tgt_port->port_dip;
13055 
13056 	/*
13057 	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13058 	 * non-NULL even when the LUN is not there as in the case when a LUN is
13059 	 * configured and then deleted on the device end (for T3/T4 case). In
13060 	 * such cases, pip will be NULL.
13061 	 *
13062 	 * If the device generates an RSCN, it will end up getting offlined when
13063 	 * it disappeared and a new LUN will get created when it is rediscovered
13064 	 * on the device. If we check for lun_cip here, the LUN will not end
13065 	 * up getting onlined since this function will end up returning a
13066 	 * FC_SUCCESS.
13067 	 *
13068 	 * The behavior is different on other devices. For instance, on a HDS,
13069 	 * there was no RSCN generated by the device but the next I/O generated
13070 	 * a check condition and rediscovery got triggered that way. So, in
13071 	 * such cases, this path will not be exercised
13072 	 */
13073 	if (pip == NULL) {
13074 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13075 		    fcp_trace, FCP_BUF_LEVEL_4, 0,
13076 		    "fcp_is_pip_present: plun->lun_cip is NULL: "
13077 		    "plun: %p lun state: %x num: %d target state: %x",
13078 		    plun, plun->lun_state, plun->lun_num,
13079 		    plun->lun_tgt->tgt_port->port_state);
13080 		return (rval);
13081 	}
13082 
13083 	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13084 
13085 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13086 
13087 	if (plun->lun_old_guid) {
13088 		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13089 			rval = FC_SUCCESS;
13090 		}
13091 	} else {
13092 		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13093 			rval = FC_SUCCESS;
13094 		}
13095 	}
13096 	return (rval);
13097 }
13098 
13099 static mdi_pathinfo_t *
13100 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13101 {
13102 	char			buf[MAXNAMELEN];
13103 	char			uaddr[MAXNAMELEN];
13104 	mdi_pathinfo_t		*pip;
13105 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13106 	struct fcp_port	*pptr = ptgt->tgt_port;
13107 
13108 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13109 
13110 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13111 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13112 
13113 	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13114 
13115 	return (pip);
13116 }
13117 
13118 
13119 static int
13120 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13121     int tcount, int flags, int *circ)
13122 {
13123 	int			rval;
13124 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13125 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13126 	dev_info_t		*cdip = NULL;
13127 
13128 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13129 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13130 
13131 	if (plun->lun_cip == NULL) {
13132 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13133 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13134 		    "fcp_online_child: plun->lun_cip is NULL: "
13135 		    "plun: %p state: %x num: %d target state: %x",
13136 		    plun, plun->lun_state, plun->lun_num,
13137 		    plun->lun_tgt->tgt_port->port_state);
13138 		return (NDI_FAILURE);
13139 	}
13140 again:
13141 	if (plun->lun_mpxio == 0) {
13142 		cdip = DIP(cip);
13143 		mutex_exit(&plun->lun_mutex);
13144 		mutex_exit(&pptr->port_mutex);
13145 
13146 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13147 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13148 		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13149 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13150 
13151 		/*
13152 		 * We could check for FCP_LUN_INIT here but chances
13153 		 * of getting here when it's already in FCP_LUN_INIT
13154 		 * is rare and a duplicate ndi_devi_online wouldn't
13155 		 * hurt either (as the node would already have been
13156 		 * in CF2)
13157 		 */
13158 		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13159 			rval = ndi_devi_bind_driver(cdip, flags);
13160 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13161 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13162 			    "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13163 		} else {
13164 			rval = ndi_devi_online(cdip, flags);
13165 		}
13166 
13167 		/*
13168 		 * We log the message into trace buffer if the device
13169 		 * is "ses" and into syslog for any other device
13170 		 * type. This is to prevent the ndi_devi_online failure
13171 		 * message that appears for V880/A5K ses devices.
13172 		 */
13173 		if (rval == NDI_SUCCESS) {
13174 			mutex_enter(&ptgt->tgt_mutex);
13175 			plun->lun_state |= FCP_LUN_INIT;
13176 			mutex_exit(&ptgt->tgt_mutex);
13177 		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13178 			fcp_log(CE_NOTE, pptr->port_dip,
13179 			    "!ndi_devi_online:"
13180 			    " failed for %s: target=%x lun=%x %x",
13181 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13182 			    plun->lun_num, rval);
13183 		} else {
13184 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13185 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13186 			    " !ndi_devi_online:"
13187 			    " failed for %s: target=%x lun=%x %x",
13188 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13189 			    plun->lun_num, rval);
13190 		}
13191 	} else {
13192 		cdip = mdi_pi_get_client(PIP(cip));
13193 		mutex_exit(&plun->lun_mutex);
13194 		mutex_exit(&pptr->port_mutex);
13195 
13196 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13197 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13198 		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13199 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13200 
13201 		/*
13202 		 * Hold path and exit phci to avoid deadlock with power
13203 		 * management code during mdi_pi_online.
13204 		 */
13205 		mdi_hold_path(PIP(cip));
13206 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13207 
13208 		rval = mdi_pi_online(PIP(cip), flags);
13209 
13210 		mdi_devi_enter_phci(pptr->port_dip, circ);
13211 		mdi_rele_path(PIP(cip));
13212 
13213 		if (rval == MDI_SUCCESS) {
13214 			mutex_enter(&ptgt->tgt_mutex);
13215 			plun->lun_state |= FCP_LUN_INIT;
13216 			mutex_exit(&ptgt->tgt_mutex);
13217 
13218 			/*
13219 			 * Clear MPxIO path permanent disable in case
13220 			 * fcp hotplug dropped the offline event.
13221 			 */
13222 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13223 
13224 		} else if (rval == MDI_NOT_SUPPORTED) {
13225 			child_info_t	*old_cip = cip;
13226 
13227 			/*
13228 			 * MPxIO does not support this device yet.
13229 			 * Enumerate in legacy mode.
13230 			 */
13231 			mutex_enter(&pptr->port_mutex);
13232 			mutex_enter(&plun->lun_mutex);
13233 			plun->lun_mpxio = 0;
13234 			plun->lun_cip = NULL;
13235 			cdip = fcp_create_dip(plun, lcount, tcount);
13236 			plun->lun_cip = cip = CIP(cdip);
13237 			if (cip == NULL) {
13238 				fcp_log(CE_WARN, pptr->port_dip,
13239 				    "!fcp_online_child: "
13240 				    "Create devinfo failed for LU=%p", plun);
13241 				mutex_exit(&plun->lun_mutex);
13242 
13243 				mutex_enter(&ptgt->tgt_mutex);
13244 				plun->lun_state |= FCP_LUN_OFFLINE;
13245 				mutex_exit(&ptgt->tgt_mutex);
13246 
13247 				mutex_exit(&pptr->port_mutex);
13248 
13249 				/*
13250 				 * free the mdi_pathinfo node
13251 				 */
13252 				(void) mdi_pi_free(PIP(old_cip), 0);
13253 			} else {
13254 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13255 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13256 				    "fcp_online_child: creating devinfo "
13257 				    "node 0x%p for plun 0x%p",
13258 				    cip, plun);
13259 				mutex_exit(&plun->lun_mutex);
13260 				mutex_exit(&pptr->port_mutex);
13261 				/*
13262 				 * free the mdi_pathinfo node
13263 				 */
13264 				(void) mdi_pi_free(PIP(old_cip), 0);
13265 				mutex_enter(&pptr->port_mutex);
13266 				mutex_enter(&plun->lun_mutex);
13267 				goto again;
13268 			}
13269 		} else {
13270 			if (cdip) {
13271 				fcp_log(CE_NOTE, pptr->port_dip,
13272 				    "!fcp_online_child: mdi_pi_online:"
13273 				    " failed for %s: target=%x lun=%x %x",
13274 				    ddi_get_name(cdip), ptgt->tgt_d_id,
13275 				    plun->lun_num, rval);
13276 			}
13277 		}
13278 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13279 	}
13280 
13281 	if (rval == NDI_SUCCESS) {
13282 		if (cdip) {
13283 			(void) ndi_event_retrieve_cookie(
13284 			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13285 			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13286 			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13287 			    cdip, fcp_insert_eid, NULL);
13288 		}
13289 	}
13290 	mutex_enter(&pptr->port_mutex);
13291 	mutex_enter(&plun->lun_mutex);
13292 	return (rval);
13293 }
13294 
13295 /* ARGSUSED */
13296 static int
13297 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13298     int tcount, int flags, int *circ)
13299 {
13300 	int		rval;
13301 	int		lun_mpxio;
13302 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
13303 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13304 	dev_info_t	*cdip;
13305 
13306 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13307 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13308 
13309 	if (plun->lun_cip == NULL) {
13310 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13311 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13312 		    "fcp_offline_child: plun->lun_cip is NULL: "
13313 		    "plun: %p lun state: %x num: %d target state: %x",
13314 		    plun, plun->lun_state, plun->lun_num,
13315 		    plun->lun_tgt->tgt_port->port_state);
13316 		return (NDI_FAILURE);
13317 	}
13318 
13319 	/*
13320 	 * We will use this value twice. Make a copy to be sure we use
13321 	 * the same value in both places.
13322 	 */
13323 	lun_mpxio = plun->lun_mpxio;
13324 
13325 	if (lun_mpxio == 0) {
13326 		cdip = DIP(cip);
13327 		mutex_exit(&plun->lun_mutex);
13328 		mutex_exit(&pptr->port_mutex);
13329 		rval = ndi_devi_offline(DIP(cip), flags);
13330 		if (rval != NDI_SUCCESS) {
13331 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13332 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13333 			    "fcp_offline_child: ndi_devi_offline failed "
13334 			    "rval=%x cip=%p", rval, cip);
13335 		}
13336 	} else {
13337 		cdip = mdi_pi_get_client(PIP(cip));
13338 		mutex_exit(&plun->lun_mutex);
13339 		mutex_exit(&pptr->port_mutex);
13340 
13341 		/*
13342 		 * Exit phci to avoid deadlock with power management code
13343 		 * during mdi_pi_offline
13344 		 */
13345 		mdi_hold_path(PIP(cip));
13346 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13347 
13348 		rval = mdi_pi_offline(PIP(cip), flags);
13349 
13350 		mdi_devi_enter_phci(pptr->port_dip, circ);
13351 		mdi_rele_path(PIP(cip));
13352 
13353 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13354 	}
13355 
13356 	mutex_enter(&ptgt->tgt_mutex);
13357 	plun->lun_state &= ~FCP_LUN_INIT;
13358 	mutex_exit(&ptgt->tgt_mutex);
13359 
13360 	if (rval == NDI_SUCCESS) {
13361 		cdip = NULL;
13362 		if (flags & NDI_DEVI_REMOVE) {
13363 			mutex_enter(&plun->lun_mutex);
13364 			/*
13365 			 * If the guid of the LUN changes, lun_cip will not
13366 			 * equal to cip, and after offlining the LUN with the
13367 			 * old guid, we should keep lun_cip since it's the cip
13368 			 * of the LUN with the new guid.
13369 			 * Otherwise remove our reference to child node.
13370 			 *
13371 			 * This must be done before the child node is freed,
13372 			 * otherwise other threads could see a stale lun_cip
13373 			 * pointer.
13374 			 */
13375 			if (plun->lun_cip == cip) {
13376 				plun->lun_cip = NULL;
13377 			}
13378 			if (plun->lun_old_guid) {
13379 				kmem_free(plun->lun_old_guid,
13380 				    plun->lun_old_guid_size);
13381 				plun->lun_old_guid = NULL;
13382 				plun->lun_old_guid_size = 0;
13383 			}
13384 			mutex_exit(&plun->lun_mutex);
13385 		}
13386 	}
13387 
13388 	if (lun_mpxio != 0) {
13389 		if (rval == NDI_SUCCESS) {
13390 			/*
13391 			 * Clear MPxIO path permanent disable as the path is
13392 			 * already offlined.
13393 			 */
13394 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13395 
13396 			if (flags & NDI_DEVI_REMOVE) {
13397 				(void) mdi_pi_free(PIP(cip), 0);
13398 			}
13399 		} else {
13400 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13401 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13402 			    "fcp_offline_child: mdi_pi_offline failed "
13403 			    "rval=%x cip=%p", rval, cip);
13404 		}
13405 	}
13406 
13407 	mutex_enter(&pptr->port_mutex);
13408 	mutex_enter(&plun->lun_mutex);
13409 
13410 	if (cdip) {
13411 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13412 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13413 		    " target=%x lun=%x", "ndi_offline",
13414 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13415 	}
13416 
13417 	return (rval);
13418 }
13419 
13420 static void
13421 fcp_remove_child(struct fcp_lun *plun)
13422 {
13423 	child_info_t *cip;
13424 	int circ;
13425 
13426 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13427 
13428 	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13429 		if (plun->lun_mpxio == 0) {
13430 			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13431 			(void) ndi_devi_free(DIP(plun->lun_cip));
13432 			plun->lun_cip = NULL;
13433 		} else {
13434 			/*
13435 			 * Clear reference to the child node in the lun.
13436 			 * This must be done before freeing it with mdi_pi_free
13437 			 * and with lun_mutex held so that other threads always
13438 			 * see either valid lun_cip or NULL when holding
13439 			 * lun_mutex. We keep a copy in cip.
13440 			 */
13441 			cip = plun->lun_cip;
13442 			plun->lun_cip = NULL;
13443 
13444 			mutex_exit(&plun->lun_mutex);
13445 			mutex_exit(&plun->lun_tgt->tgt_mutex);
13446 			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13447 
13448 			mdi_devi_enter(
13449 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13450 
13451 			/*
13452 			 * Exit phci to avoid deadlock with power management
13453 			 * code during mdi_pi_offline
13454 			 */
13455 			mdi_hold_path(PIP(cip));
13456 			mdi_devi_exit_phci(
13457 			    plun->lun_tgt->tgt_port->port_dip, circ);
13458 			(void) mdi_pi_offline(PIP(cip),
13459 			    NDI_DEVI_REMOVE);
13460 			mdi_devi_enter_phci(
13461 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13462 			mdi_rele_path(PIP(cip));
13463 
13464 			mdi_devi_exit(
13465 			    plun->lun_tgt->tgt_port->port_dip, circ);
13466 
13467 			FCP_TRACE(fcp_logq,
13468 			    plun->lun_tgt->tgt_port->port_instbuf,
13469 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13470 			    "lun=%p pip freed %p", plun, cip);
13471 
13472 			(void) mdi_prop_remove(PIP(cip), NULL);
13473 			(void) mdi_pi_free(PIP(cip), 0);
13474 
13475 			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13476 			mutex_enter(&plun->lun_tgt->tgt_mutex);
13477 			mutex_enter(&plun->lun_mutex);
13478 		}
13479 	} else {
13480 		plun->lun_cip = NULL;
13481 	}
13482 }
13483 
13484 /*
13485  * called when a timeout occurs
13486  *
13487  * can be scheduled during an attach or resume (if not already running)
13488  *
13489  * one timeout is set up for all ports
13490  *
13491  * acquires and releases the global mutex
13492  */
13493 /*ARGSUSED*/
13494 static void
13495 fcp_watch(void *arg)
13496 {
13497 	struct fcp_port	*pptr;
13498 	struct fcp_ipkt	*icmd;
13499 	struct fcp_ipkt	*nicmd;
13500 	struct fcp_pkt	*cmd;
13501 	struct fcp_pkt	*ncmd;
13502 	struct fcp_pkt	*tail;
13503 	struct fcp_pkt	*pcmd;
13504 	struct fcp_pkt	*save_head;
13505 	struct fcp_port	*save_port;
13506 
13507 	/* increment global watchdog time */
13508 	fcp_watchdog_time += fcp_watchdog_timeout;
13509 
13510 	mutex_enter(&fcp_global_mutex);
13511 
13512 	/* scan each port in our list */
13513 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13514 		save_port = fcp_port_head;
13515 		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13516 		mutex_exit(&fcp_global_mutex);
13517 
13518 		mutex_enter(&pptr->port_mutex);
13519 		if (pptr->port_ipkt_list == NULL &&
13520 		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13521 		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13522 			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13523 			mutex_exit(&pptr->port_mutex);
13524 			mutex_enter(&fcp_global_mutex);
13525 			goto end_of_watchdog;
13526 		}
13527 
13528 		/*
13529 		 * We check if a list of targets need to be offlined.
13530 		 */
13531 		if (pptr->port_offline_tgts) {
13532 			fcp_scan_offline_tgts(pptr);
13533 		}
13534 
13535 		/*
13536 		 * We check if a list of luns need to be offlined.
13537 		 */
13538 		if (pptr->port_offline_luns) {
13539 			fcp_scan_offline_luns(pptr);
13540 		}
13541 
13542 		/*
13543 		 * We check if a list of targets or luns need to be reset.
13544 		 */
13545 		if (pptr->port_reset_list) {
13546 			fcp_check_reset_delay(pptr);
13547 		}
13548 
13549 		mutex_exit(&pptr->port_mutex);
13550 
13551 		/*
13552 		 * This is where the pending commands (pkt) are checked for
13553 		 * timeout.
13554 		 */
13555 		mutex_enter(&pptr->port_pkt_mutex);
13556 		tail = pptr->port_pkt_tail;
13557 
13558 		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13559 		    cmd != NULL; cmd = ncmd) {
13560 			ncmd = cmd->cmd_next;
13561 			/*
13562 			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13563 			 * must be set.
13564 			 */
13565 			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13566 			/*
13567 			 * FCP_INVALID_TIMEOUT will be set for those
13568 			 * command that need to be failed. Mostly those
13569 			 * cmds that could not be queued down for the
13570 			 * "timeout" value. cmd->cmd_timeout is used
13571 			 * to try and requeue the command regularly.
13572 			 */
13573 			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13574 				/*
13575 				 * This command hasn't timed out yet.  Let's
13576 				 * go to the next one.
13577 				 */
13578 				pcmd = cmd;
13579 				goto end_of_loop;
13580 			}
13581 
13582 			if (cmd == pptr->port_pkt_head) {
13583 				ASSERT(pcmd == NULL);
13584 				pptr->port_pkt_head = cmd->cmd_next;
13585 			} else {
13586 				ASSERT(pcmd != NULL);
13587 				pcmd->cmd_next = cmd->cmd_next;
13588 			}
13589 
13590 			if (cmd == pptr->port_pkt_tail) {
13591 				ASSERT(cmd->cmd_next == NULL);
13592 				pptr->port_pkt_tail = pcmd;
13593 				if (pcmd) {
13594 					pcmd->cmd_next = NULL;
13595 				}
13596 			}
13597 			cmd->cmd_next = NULL;
13598 
13599 			/*
13600 			 * save the current head before dropping the
13601 			 * mutex - If the head doesn't remain the
13602 			 * same after re acquiring the mutex, just
13603 			 * bail out and revisit on next tick.
13604 			 *
13605 			 * PS: The tail pointer can change as the commands
13606 			 * get requeued after failure to retransport
13607 			 */
13608 			save_head = pptr->port_pkt_head;
13609 			mutex_exit(&pptr->port_pkt_mutex);
13610 
13611 			if (cmd->cmd_fp_pkt->pkt_timeout ==
13612 			    FCP_INVALID_TIMEOUT) {
13613 				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13614 				struct fcp_lun	*plun;
13615 				struct fcp_tgt	*ptgt;
13616 
13617 				plun = ADDR2LUN(&pkt->pkt_address);
13618 				ptgt = plun->lun_tgt;
13619 
13620 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13621 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13622 				    "SCSI cmd 0x%x to D_ID=%x timed out",
13623 				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13624 
13625 				cmd->cmd_state == FCP_PKT_ABORTING ?
13626 				    fcp_fail_cmd(cmd, CMD_RESET,
13627 				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13628 				    CMD_TIMEOUT, STAT_ABORTED);
13629 			} else {
13630 				fcp_retransport_cmd(pptr, cmd);
13631 			}
13632 			mutex_enter(&pptr->port_pkt_mutex);
13633 			if (save_head && save_head != pptr->port_pkt_head) {
13634 				/*
13635 				 * Looks like linked list got changed (mostly
13636 				 * happens when an an OFFLINE LUN code starts
13637 				 * returning overflow queue commands in
13638 				 * parallel. So bail out and revisit during
13639 				 * next tick
13640 				 */
13641 				break;
13642 			}
13643 		end_of_loop:
13644 			/*
13645 			 * Scan only upto the previously known tail pointer
13646 			 * to avoid excessive processing - lots of new packets
13647 			 * could have been added to the tail or the old ones
13648 			 * re-queued.
13649 			 */
13650 			if (cmd == tail) {
13651 				break;
13652 			}
13653 		}
13654 		mutex_exit(&pptr->port_pkt_mutex);
13655 
13656 		mutex_enter(&pptr->port_mutex);
13657 		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13658 			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13659 
13660 			nicmd = icmd->ipkt_next;
13661 			if ((icmd->ipkt_restart != 0) &&
13662 			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13663 				/* packet has not timed out */
13664 				continue;
13665 			}
13666 
13667 			/* time for packet re-transport */
13668 			if (icmd == pptr->port_ipkt_list) {
13669 				pptr->port_ipkt_list = icmd->ipkt_next;
13670 				if (pptr->port_ipkt_list) {
13671 					pptr->port_ipkt_list->ipkt_prev =
13672 					    NULL;
13673 				}
13674 			} else {
13675 				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13676 				if (icmd->ipkt_next) {
13677 					icmd->ipkt_next->ipkt_prev =
13678 					    icmd->ipkt_prev;
13679 				}
13680 			}
13681 			icmd->ipkt_next = NULL;
13682 			icmd->ipkt_prev = NULL;
13683 			mutex_exit(&pptr->port_mutex);
13684 
13685 			if (fcp_is_retryable(icmd)) {
13686 				fc_ulp_rscn_info_t *rscnp =
13687 				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13688 				    pkt_ulp_rscn_infop;
13689 
13690 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13691 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13692 				    "%x to D_ID=%x Retrying..",
13693 				    icmd->ipkt_opcode,
13694 				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13695 
13696 				/*
13697 				 * Update the RSCN count in the packet
13698 				 * before resending.
13699 				 */
13700 
13701 				if (rscnp != NULL) {
13702 					rscnp->ulp_rscn_count =
13703 					    fc_ulp_get_rscn_count(pptr->
13704 					    port_fp_handle);
13705 				}
13706 
13707 				mutex_enter(&pptr->port_mutex);
13708 				mutex_enter(&ptgt->tgt_mutex);
13709 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13710 					mutex_exit(&ptgt->tgt_mutex);
13711 					mutex_exit(&pptr->port_mutex);
13712 					switch (icmd->ipkt_opcode) {
13713 						int rval;
13714 					case LA_ELS_PLOGI:
13715 						if ((rval = fc_ulp_login(
13716 						    pptr->port_fp_handle,
13717 						    &icmd->ipkt_fpkt, 1)) ==
13718 						    FC_SUCCESS) {
13719 							mutex_enter(
13720 							    &pptr->port_mutex);
13721 							continue;
13722 						}
13723 						if (fcp_handle_ipkt_errors(
13724 						    pptr, ptgt, icmd, rval,
13725 						    "PLOGI") == DDI_SUCCESS) {
13726 							mutex_enter(
13727 							    &pptr->port_mutex);
13728 							continue;
13729 						}
13730 						break;
13731 
13732 					case LA_ELS_PRLI:
13733 						if ((rval = fc_ulp_issue_els(
13734 						    pptr->port_fp_handle,
13735 						    icmd->ipkt_fpkt)) ==
13736 						    FC_SUCCESS) {
13737 							mutex_enter(
13738 							    &pptr->port_mutex);
13739 							continue;
13740 						}
13741 						if (fcp_handle_ipkt_errors(
13742 						    pptr, ptgt, icmd, rval,
13743 						    "PRLI") == DDI_SUCCESS) {
13744 							mutex_enter(
13745 							    &pptr->port_mutex);
13746 							continue;
13747 						}
13748 						break;
13749 
13750 					default:
13751 						if ((rval = fcp_transport(
13752 						    pptr->port_fp_handle,
13753 						    icmd->ipkt_fpkt, 1)) ==
13754 						    FC_SUCCESS) {
13755 							mutex_enter(
13756 							    &pptr->port_mutex);
13757 							continue;
13758 						}
13759 						if (fcp_handle_ipkt_errors(
13760 						    pptr, ptgt, icmd, rval,
13761 						    "PRLI") == DDI_SUCCESS) {
13762 							mutex_enter(
13763 							    &pptr->port_mutex);
13764 							continue;
13765 						}
13766 						break;
13767 					}
13768 				} else {
13769 					mutex_exit(&ptgt->tgt_mutex);
13770 					mutex_exit(&pptr->port_mutex);
13771 				}
13772 			} else {
13773 				fcp_print_error(icmd->ipkt_fpkt);
13774 			}
13775 
13776 			(void) fcp_call_finish_init(pptr, ptgt,
13777 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13778 			    icmd->ipkt_cause);
13779 			fcp_icmd_free(pptr, icmd);
13780 			mutex_enter(&pptr->port_mutex);
13781 		}
13782 
13783 		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13784 		mutex_exit(&pptr->port_mutex);
13785 		mutex_enter(&fcp_global_mutex);
13786 
13787 	end_of_watchdog:
13788 		/*
13789 		 * Bail out early before getting into trouble
13790 		 */
13791 		if (save_port != fcp_port_head) {
13792 			break;
13793 		}
13794 	}
13795 
13796 	if (fcp_watchdog_init > 0) {
13797 		/* reschedule timeout to go again */
13798 		fcp_watchdog_id =
13799 		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13800 	}
13801 	mutex_exit(&fcp_global_mutex);
13802 }
13803 
13804 
13805 static void
13806 fcp_check_reset_delay(struct fcp_port *pptr)
13807 {
13808 	uint32_t		tgt_cnt;
13809 	int			level;
13810 	struct fcp_tgt	*ptgt;
13811 	struct fcp_lun	*plun;
13812 	struct fcp_reset_elem *cur = NULL;
13813 	struct fcp_reset_elem *next = NULL;
13814 	struct fcp_reset_elem *prev = NULL;
13815 
13816 	ASSERT(mutex_owned(&pptr->port_mutex));
13817 
13818 	next = pptr->port_reset_list;
13819 	while ((cur = next) != NULL) {
13820 		next = cur->next;
13821 
13822 		if (cur->timeout < fcp_watchdog_time) {
13823 			prev = cur;
13824 			continue;
13825 		}
13826 
13827 		ptgt = cur->tgt;
13828 		plun = cur->lun;
13829 		tgt_cnt = cur->tgt_cnt;
13830 
13831 		if (ptgt) {
13832 			level = RESET_TARGET;
13833 		} else {
13834 			ASSERT(plun != NULL);
13835 			level = RESET_LUN;
13836 			ptgt = plun->lun_tgt;
13837 		}
13838 		if (prev) {
13839 			prev->next = next;
13840 		} else {
13841 			/*
13842 			 * Because we drop port mutex while doing aborts for
13843 			 * packets, we can't rely on reset_list pointing to
13844 			 * our head
13845 			 */
13846 			if (cur == pptr->port_reset_list) {
13847 				pptr->port_reset_list = next;
13848 			} else {
13849 				struct fcp_reset_elem *which;
13850 
13851 				which = pptr->port_reset_list;
13852 				while (which && which->next != cur) {
13853 					which = which->next;
13854 				}
13855 				ASSERT(which != NULL);
13856 
13857 				which->next = next;
13858 				prev = which;
13859 			}
13860 		}
13861 
13862 		kmem_free(cur, sizeof (*cur));
13863 
13864 		if (tgt_cnt == ptgt->tgt_change_cnt) {
13865 			mutex_enter(&ptgt->tgt_mutex);
13866 			if (level == RESET_TARGET) {
13867 				fcp_update_tgt_state(ptgt,
13868 				    FCP_RESET, FCP_LUN_BUSY);
13869 			} else {
13870 				fcp_update_lun_state(plun,
13871 				    FCP_RESET, FCP_LUN_BUSY);
13872 			}
13873 			mutex_exit(&ptgt->tgt_mutex);
13874 
13875 			mutex_exit(&pptr->port_mutex);
13876 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13877 			mutex_enter(&pptr->port_mutex);
13878 		}
13879 	}
13880 }
13881 
13882 
13883 static void
13884 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13885     struct fcp_lun *rlun, int tgt_cnt)
13886 {
13887 	int			rval;
13888 	struct fcp_lun	*tlun, *nlun;
13889 	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13890 	    *cmd = NULL, *head = NULL,
13891 	    *tail = NULL;
13892 
13893 	mutex_enter(&pptr->port_pkt_mutex);
13894 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13895 		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13896 		struct fcp_tgt *ptgt = plun->lun_tgt;
13897 
13898 		ncmd = cmd->cmd_next;
13899 
13900 		if (ptgt != ttgt && plun != rlun) {
13901 			pcmd = cmd;
13902 			continue;
13903 		}
13904 
13905 		if (pcmd != NULL) {
13906 			ASSERT(pptr->port_pkt_head != cmd);
13907 			pcmd->cmd_next = ncmd;
13908 		} else {
13909 			ASSERT(cmd == pptr->port_pkt_head);
13910 			pptr->port_pkt_head = ncmd;
13911 		}
13912 		if (pptr->port_pkt_tail == cmd) {
13913 			ASSERT(cmd->cmd_next == NULL);
13914 			pptr->port_pkt_tail = pcmd;
13915 			if (pcmd != NULL) {
13916 				pcmd->cmd_next = NULL;
13917 			}
13918 		}
13919 
13920 		if (head == NULL) {
13921 			head = tail = cmd;
13922 		} else {
13923 			ASSERT(tail != NULL);
13924 			tail->cmd_next = cmd;
13925 			tail = cmd;
13926 		}
13927 		cmd->cmd_next = NULL;
13928 	}
13929 	mutex_exit(&pptr->port_pkt_mutex);
13930 
13931 	for (cmd = head; cmd != NULL; cmd = ncmd) {
13932 		struct scsi_pkt *pkt = cmd->cmd_pkt;
13933 
13934 		ncmd = cmd->cmd_next;
13935 		ASSERT(pkt != NULL);
13936 
13937 		mutex_enter(&pptr->port_mutex);
13938 		if (ttgt->tgt_change_cnt == tgt_cnt) {
13939 			mutex_exit(&pptr->port_mutex);
13940 			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13941 			pkt->pkt_reason = CMD_RESET;
13942 			pkt->pkt_statistics |= STAT_DEV_RESET;
13943 			cmd->cmd_state = FCP_PKT_IDLE;
13944 			fcp_post_callback(cmd);
13945 		} else {
13946 			mutex_exit(&pptr->port_mutex);
13947 		}
13948 	}
13949 
13950 	/*
13951 	 * If the FCA will return all the commands in its queue then our
13952 	 * work is easy, just return.
13953 	 */
13954 
13955 	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13956 		return;
13957 	}
13958 
13959 	/*
13960 	 * For RESET_LUN get hold of target pointer
13961 	 */
13962 	if (ttgt == NULL) {
13963 		ASSERT(rlun != NULL);
13964 
13965 		ttgt = rlun->lun_tgt;
13966 
13967 		ASSERT(ttgt != NULL);
13968 	}
13969 
13970 	/*
13971 	 * There are some severe race conditions here.
13972 	 * While we are trying to abort the pkt, it might be completing
13973 	 * so mark it aborted and if the abort does not succeed then
13974 	 * handle it in the watch thread.
13975 	 */
13976 	mutex_enter(&ttgt->tgt_mutex);
13977 	nlun = ttgt->tgt_lun;
13978 	mutex_exit(&ttgt->tgt_mutex);
13979 	while ((tlun = nlun) != NULL) {
13980 		int restart = 0;
13981 		if (rlun && rlun != tlun) {
13982 			mutex_enter(&ttgt->tgt_mutex);
13983 			nlun = tlun->lun_next;
13984 			mutex_exit(&ttgt->tgt_mutex);
13985 			continue;
13986 		}
13987 		mutex_enter(&tlun->lun_mutex);
13988 		cmd = tlun->lun_pkt_head;
13989 		while (cmd != NULL) {
13990 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13991 				struct scsi_pkt *pkt;
13992 
13993 				restart = 1;
13994 				cmd->cmd_state = FCP_PKT_ABORTING;
13995 				mutex_exit(&tlun->lun_mutex);
13996 				rval = fc_ulp_abort(pptr->port_fp_handle,
13997 				    cmd->cmd_fp_pkt, KM_SLEEP);
13998 				if (rval == FC_SUCCESS) {
13999 					pkt = cmd->cmd_pkt;
14000 					pkt->pkt_reason = CMD_RESET;
14001 					pkt->pkt_statistics |= STAT_DEV_RESET;
14002 					cmd->cmd_state = FCP_PKT_IDLE;
14003 					fcp_post_callback(cmd);
14004 				} else {
14005 					caddr_t msg;
14006 
14007 					(void) fc_ulp_error(rval, &msg);
14008 
14009 					/*
14010 					 * This part is tricky. The abort
14011 					 * failed and now the command could
14012 					 * be completing.  The cmd_state ==
14013 					 * FCP_PKT_ABORTING should save
14014 					 * us in fcp_cmd_callback. If we
14015 					 * are already aborting ignore the
14016 					 * command in fcp_cmd_callback.
14017 					 * Here we leave this packet for 20
14018 					 * sec to be aborted in the
14019 					 * fcp_watch thread.
14020 					 */
14021 					fcp_log(CE_WARN, pptr->port_dip,
14022 					    "!Abort failed after reset %s",
14023 					    msg);
14024 
14025 					cmd->cmd_timeout =
14026 					    fcp_watchdog_time +
14027 					    cmd->cmd_pkt->pkt_time +
14028 					    FCP_FAILED_DELAY;
14029 
14030 					cmd->cmd_fp_pkt->pkt_timeout =
14031 					    FCP_INVALID_TIMEOUT;
14032 					/*
14033 					 * This is a hack, cmd is put in the
14034 					 * overflow queue so that it can be
14035 					 * timed out finally
14036 					 */
14037 					cmd->cmd_flags |= CFLAG_IN_QUEUE;
14038 
14039 					mutex_enter(&pptr->port_pkt_mutex);
14040 					if (pptr->port_pkt_head) {
14041 						ASSERT(pptr->port_pkt_tail
14042 						    != NULL);
14043 						pptr->port_pkt_tail->cmd_next
14044 						    = cmd;
14045 						pptr->port_pkt_tail = cmd;
14046 					} else {
14047 						ASSERT(pptr->port_pkt_tail
14048 						    == NULL);
14049 						pptr->port_pkt_head =
14050 						    pptr->port_pkt_tail
14051 						    = cmd;
14052 					}
14053 					cmd->cmd_next = NULL;
14054 					mutex_exit(&pptr->port_pkt_mutex);
14055 				}
14056 				mutex_enter(&tlun->lun_mutex);
14057 				cmd = tlun->lun_pkt_head;
14058 			} else {
14059 				cmd = cmd->cmd_forw;
14060 			}
14061 		}
14062 		mutex_exit(&tlun->lun_mutex);
14063 
14064 		mutex_enter(&ttgt->tgt_mutex);
14065 		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14066 		mutex_exit(&ttgt->tgt_mutex);
14067 
14068 		mutex_enter(&pptr->port_mutex);
14069 		if (tgt_cnt != ttgt->tgt_change_cnt) {
14070 			mutex_exit(&pptr->port_mutex);
14071 			return;
14072 		} else {
14073 			mutex_exit(&pptr->port_mutex);
14074 		}
14075 	}
14076 }
14077 
14078 
14079 /*
14080  * unlink the soft state, returning the soft state found (if any)
14081  *
14082  * acquires and releases the global mutex
14083  */
14084 struct fcp_port *
14085 fcp_soft_state_unlink(struct fcp_port *pptr)
14086 {
14087 	struct fcp_port	*hptr;		/* ptr index */
14088 	struct fcp_port	*tptr;		/* prev hptr */
14089 
14090 	mutex_enter(&fcp_global_mutex);
14091 	for (hptr = fcp_port_head, tptr = NULL;
14092 	    hptr != NULL;
14093 	    tptr = hptr, hptr = hptr->port_next) {
14094 		if (hptr == pptr) {
14095 			/* we found a match -- remove this item */
14096 			if (tptr == NULL) {
14097 				/* we're at the head of the list */
14098 				fcp_port_head = hptr->port_next;
14099 			} else {
14100 				tptr->port_next = hptr->port_next;
14101 			}
14102 			break;			/* success */
14103 		}
14104 	}
14105 	if (fcp_port_head == NULL) {
14106 		fcp_cleanup_blacklist(&fcp_lun_blacklist);
14107 	}
14108 	mutex_exit(&fcp_global_mutex);
14109 	return (hptr);
14110 }
14111 
14112 
14113 /*
14114  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14115  * WWN and a LUN number
14116  */
14117 /* ARGSUSED */
14118 static struct fcp_lun *
14119 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14120 {
14121 	int hash;
14122 	struct fcp_tgt *ptgt;
14123 	struct fcp_lun *plun;
14124 
14125 	ASSERT(mutex_owned(&pptr->port_mutex));
14126 
14127 	hash = FCP_HASH(wwn);
14128 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14129 	    ptgt = ptgt->tgt_next) {
14130 		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14131 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
14132 			mutex_enter(&ptgt->tgt_mutex);
14133 			for (plun = ptgt->tgt_lun;
14134 			    plun != NULL;
14135 			    plun = plun->lun_next) {
14136 				if (plun->lun_num == lun) {
14137 					mutex_exit(&ptgt->tgt_mutex);
14138 					return (plun);
14139 				}
14140 			}
14141 			mutex_exit(&ptgt->tgt_mutex);
14142 			return (NULL);
14143 		}
14144 	}
14145 	return (NULL);
14146 }
14147 
14148 /*
14149  *     Function: fcp_prepare_pkt
14150  *
14151  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14152  *		 for fcp_start(). It binds the data or partially maps it.
14153  *		 Builds the FCP header and starts the initialization of the
14154  *		 Fibre Channel header.
14155  *
14156  *     Argument: *pptr		FCP port.
14157  *		 *cmd		FCP packet.
14158  *		 *plun		LUN the command will be sent to.
14159  *
14160  *	Context: User, Kernel and Interrupt context.
14161  */
14162 static void
14163 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14164     struct fcp_lun *plun)
14165 {
14166 	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
14167 	struct fcp_tgt		*ptgt = plun->lun_tgt;
14168 	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
14169 
14170 	ASSERT(cmd->cmd_pkt->pkt_comp ||
14171 	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14172 
14173 	if (cmd->cmd_pkt->pkt_numcookies) {
14174 		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14175 			fcmd->fcp_cntl.cntl_read_data = 1;
14176 			fcmd->fcp_cntl.cntl_write_data = 0;
14177 			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14178 		} else {
14179 			fcmd->fcp_cntl.cntl_read_data = 0;
14180 			fcmd->fcp_cntl.cntl_write_data = 1;
14181 			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14182 		}
14183 
14184 		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14185 
14186 		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14187 		ASSERT(fpkt->pkt_data_cookie_cnt <=
14188 		    pptr->port_data_dma_attr.dma_attr_sgllen);
14189 
14190 		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14191 
14192 		/* FCA needs pkt_datalen to be set */
14193 		fpkt->pkt_datalen = cmd->cmd_dmacount;
14194 		fcmd->fcp_data_len = cmd->cmd_dmacount;
14195 	} else {
14196 		fcmd->fcp_cntl.cntl_read_data = 0;
14197 		fcmd->fcp_cntl.cntl_write_data = 0;
14198 		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14199 		fpkt->pkt_datalen = 0;
14200 		fcmd->fcp_data_len = 0;
14201 	}
14202 
14203 	/* set up the Tagged Queuing type */
14204 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14205 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14206 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14207 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14208 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14209 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14210 	} else {
14211 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14212 	}
14213 
14214 	fcmd->fcp_ent_addr = plun->lun_addr;
14215 
14216 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14217 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14218 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14219 	} else {
14220 		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14221 	}
14222 
14223 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14224 	cmd->cmd_pkt->pkt_state = 0;
14225 	cmd->cmd_pkt->pkt_statistics = 0;
14226 	cmd->cmd_pkt->pkt_resid = 0;
14227 
14228 	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14229 
14230 	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14231 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14232 		fpkt->pkt_comp = NULL;
14233 	} else {
14234 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14235 		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14236 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14237 		}
14238 		fpkt->pkt_comp = fcp_cmd_callback;
14239 	}
14240 
14241 	mutex_enter(&pptr->port_mutex);
14242 	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14243 		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14244 	}
14245 	mutex_exit(&pptr->port_mutex);
14246 
14247 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14248 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14249 
14250 	/*
14251 	 * Save a few kernel cycles here
14252 	 */
14253 #ifndef	__lock_lint
14254 	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14255 #endif /* __lock_lint */
14256 }
14257 
14258 static void
14259 fcp_post_callback(struct fcp_pkt *cmd)
14260 {
14261 	scsi_hba_pkt_comp(cmd->cmd_pkt);
14262 }
14263 
14264 
14265 /*
14266  * called to do polled I/O by fcp_start()
14267  *
14268  * return a transport status value, i.e. TRAN_ACCECPT for success
14269  */
14270 static int
14271 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14272 {
14273 	int	rval;
14274 
14275 #ifdef	DEBUG
14276 	mutex_enter(&pptr->port_pkt_mutex);
14277 	pptr->port_npkts++;
14278 	mutex_exit(&pptr->port_pkt_mutex);
14279 #endif /* DEBUG */
14280 
14281 	if (cmd->cmd_fp_pkt->pkt_timeout) {
14282 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14283 	} else {
14284 		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14285 	}
14286 
14287 	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14288 
14289 	cmd->cmd_state = FCP_PKT_ISSUED;
14290 
14291 	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14292 
14293 #ifdef	DEBUG
14294 	mutex_enter(&pptr->port_pkt_mutex);
14295 	pptr->port_npkts--;
14296 	mutex_exit(&pptr->port_pkt_mutex);
14297 #endif /* DEBUG */
14298 
14299 	cmd->cmd_state = FCP_PKT_IDLE;
14300 
14301 	switch (rval) {
14302 	case FC_SUCCESS:
14303 		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14304 			fcp_complete_pkt(cmd->cmd_fp_pkt);
14305 			rval = TRAN_ACCEPT;
14306 		} else {
14307 			rval = TRAN_FATAL_ERROR;
14308 		}
14309 		break;
14310 
14311 	case FC_TRAN_BUSY:
14312 		rval = TRAN_BUSY;
14313 		cmd->cmd_pkt->pkt_resid = 0;
14314 		break;
14315 
14316 	case FC_BADPACKET:
14317 		rval = TRAN_BADPKT;
14318 		break;
14319 
14320 	default:
14321 		rval = TRAN_FATAL_ERROR;
14322 		break;
14323 	}
14324 
14325 	return (rval);
14326 }
14327 
14328 
14329 /*
14330  * called by some of the following transport-called routines to convert
14331  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14332  */
14333 static struct fcp_port *
14334 fcp_dip2port(dev_info_t *dip)
14335 {
14336 	int	instance;
14337 
14338 	instance = ddi_get_instance(dip);
14339 	return (ddi_get_soft_state(fcp_softstate, instance));
14340 }
14341 
14342 
14343 /*
14344  * called internally to return a LUN given a dip
14345  */
14346 struct fcp_lun *
14347 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14348 {
14349 	struct fcp_tgt *ptgt;
14350 	struct fcp_lun *plun;
14351 	int i;
14352 
14353 
14354 	ASSERT(mutex_owned(&pptr->port_mutex));
14355 
14356 	for (i = 0; i < FCP_NUM_HASH; i++) {
14357 		for (ptgt = pptr->port_tgt_hash_table[i];
14358 		    ptgt != NULL;
14359 		    ptgt = ptgt->tgt_next) {
14360 			mutex_enter(&ptgt->tgt_mutex);
14361 			for (plun = ptgt->tgt_lun; plun != NULL;
14362 			    plun = plun->lun_next) {
14363 				mutex_enter(&plun->lun_mutex);
14364 				if (plun->lun_cip == cip) {
14365 					mutex_exit(&plun->lun_mutex);
14366 					mutex_exit(&ptgt->tgt_mutex);
14367 					return (plun); /* match found */
14368 				}
14369 				mutex_exit(&plun->lun_mutex);
14370 			}
14371 			mutex_exit(&ptgt->tgt_mutex);
14372 		}
14373 	}
14374 	return (NULL);				/* no LUN found */
14375 }
14376 
14377 /*
14378  * pass an element to the hotplug list, kick the hotplug thread
14379  * and wait for the element to get processed by the hotplug thread.
14380  * on return the element is freed.
14381  *
14382  * return zero success and non-zero on failure
14383  *
14384  * acquires/releases the target mutex
14385  *
14386  */
14387 static int
14388 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14389     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14390 {
14391 	struct fcp_hp_elem	*elem;
14392 	int			rval;
14393 
14394 	mutex_enter(&plun->lun_tgt->tgt_mutex);
14395 	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14396 	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14397 		mutex_exit(&plun->lun_tgt->tgt_mutex);
14398 		fcp_log(CE_CONT, pptr->port_dip,
14399 		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14400 		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14401 		return (NDI_FAILURE);
14402 	}
14403 	mutex_exit(&plun->lun_tgt->tgt_mutex);
14404 	mutex_enter(&elem->mutex);
14405 	if (elem->wait) {
14406 		while (elem->wait) {
14407 			cv_wait(&elem->cv, &elem->mutex);
14408 		}
14409 	}
14410 	rval = (elem->result);
14411 	mutex_exit(&elem->mutex);
14412 	mutex_destroy(&elem->mutex);
14413 	cv_destroy(&elem->cv);
14414 	kmem_free(elem, sizeof (struct fcp_hp_elem));
14415 	return (rval);
14416 }
14417 
14418 /*
14419  * pass an element to the hotplug list, and then
14420  * kick the hotplug thread
14421  *
14422  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14423  *
14424  * acquires/releases the hotplug mutex
14425  *
14426  * called with the target mutex owned
14427  *
14428  * memory acquired in NOSLEEP mode
14429  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14430  *	 for the hp daemon to process the request and is responsible for
14431  *	 freeing the element
14432  */
14433 static struct fcp_hp_elem *
14434 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14435     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14436 {
14437 	struct fcp_hp_elem	*elem;
14438 	dev_info_t *pdip;
14439 
14440 	ASSERT(pptr != NULL);
14441 	ASSERT(plun != NULL);
14442 	ASSERT(plun->lun_tgt != NULL);
14443 	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14444 
14445 	/* create space for a hotplug element */
14446 	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14447 	    == NULL) {
14448 		fcp_log(CE_WARN, NULL,
14449 		    "!can't allocate memory for hotplug element");
14450 		return (NULL);
14451 	}
14452 
14453 	/* fill in hotplug element */
14454 	elem->port = pptr;
14455 	elem->lun = plun;
14456 	elem->cip = cip;
14457 	elem->old_lun_mpxio = plun->lun_mpxio;
14458 	elem->what = what;
14459 	elem->flags = flags;
14460 	elem->link_cnt = link_cnt;
14461 	elem->tgt_cnt = tgt_cnt;
14462 	elem->wait = wait;
14463 	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14464 	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14465 
14466 	/* schedule the hotplug task */
14467 	pdip = pptr->port_dip;
14468 	mutex_enter(&plun->lun_mutex);
14469 	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14470 		plun->lun_event_count++;
14471 		elem->event_cnt = plun->lun_event_count;
14472 	}
14473 	mutex_exit(&plun->lun_mutex);
14474 	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14475 	    (void *)elem, KM_NOSLEEP) == NULL) {
14476 		mutex_enter(&plun->lun_mutex);
14477 		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14478 			plun->lun_event_count--;
14479 		}
14480 		mutex_exit(&plun->lun_mutex);
14481 		kmem_free(elem, sizeof (*elem));
14482 		return (0);
14483 	}
14484 
14485 	return (elem);
14486 }
14487 
14488 
14489 static void
14490 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14491 {
14492 	int			rval;
14493 	struct scsi_address	*ap;
14494 	struct fcp_lun	*plun;
14495 	struct fcp_tgt	*ptgt;
14496 	fc_packet_t	*fpkt;
14497 
14498 	ap = &cmd->cmd_pkt->pkt_address;
14499 	plun = ADDR2LUN(ap);
14500 	ptgt = plun->lun_tgt;
14501 
14502 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14503 
14504 	cmd->cmd_state = FCP_PKT_IDLE;
14505 
14506 	mutex_enter(&pptr->port_mutex);
14507 	mutex_enter(&ptgt->tgt_mutex);
14508 	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14509 	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14510 		fc_ulp_rscn_info_t *rscnp;
14511 
14512 		cmd->cmd_state = FCP_PKT_ISSUED;
14513 
14514 		/*
14515 		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14516 		 * originally NULL, hence we try to set it to the pd pointed
14517 		 * to by the SCSI device we're trying to get to.
14518 		 */
14519 
14520 		fpkt = cmd->cmd_fp_pkt;
14521 		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14522 			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14523 			/*
14524 			 * We need to notify the transport that we now have a
14525 			 * reference to the remote port handle.
14526 			 */
14527 			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14528 		}
14529 
14530 		mutex_exit(&ptgt->tgt_mutex);
14531 		mutex_exit(&pptr->port_mutex);
14532 
14533 		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14534 
14535 		/* prepare the packet */
14536 
14537 		fcp_prepare_pkt(pptr, cmd, plun);
14538 
14539 		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14540 		    pkt_ulp_rscn_infop;
14541 
14542 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14543 		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14544 
14545 		if (rscnp != NULL) {
14546 			rscnp->ulp_rscn_count =
14547 			    fc_ulp_get_rscn_count(pptr->
14548 			    port_fp_handle);
14549 		}
14550 
14551 		rval = fcp_transport(pptr->port_fp_handle,
14552 		    cmd->cmd_fp_pkt, 0);
14553 
14554 		if (rval == FC_SUCCESS) {
14555 			return;
14556 		}
14557 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14558 	} else {
14559 		mutex_exit(&ptgt->tgt_mutex);
14560 		mutex_exit(&pptr->port_mutex);
14561 	}
14562 
14563 	fcp_queue_pkt(pptr, cmd);
14564 }
14565 
14566 
14567 static void
14568 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14569 {
14570 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14571 
14572 	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14573 	cmd->cmd_state = FCP_PKT_IDLE;
14574 
14575 	cmd->cmd_pkt->pkt_reason = reason;
14576 	cmd->cmd_pkt->pkt_state = 0;
14577 	cmd->cmd_pkt->pkt_statistics = statistics;
14578 
14579 	fcp_post_callback(cmd);
14580 }
14581 
14582 /*
14583  *     Function: fcp_queue_pkt
14584  *
14585  *  Description: This function queues the packet passed by the caller into
14586  *		 the list of packets of the FCP port.
14587  *
14588  *     Argument: *pptr		FCP port.
14589  *		 *cmd		FCP packet to queue.
14590  *
14591  * Return Value: None
14592  *
14593  *	Context: User, Kernel and Interrupt context.
14594  */
14595 static void
14596 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14597 {
14598 	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14599 
14600 	mutex_enter(&pptr->port_pkt_mutex);
14601 	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14602 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14603 	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14604 
14605 	/*
14606 	 * zero pkt_time means hang around for ever
14607 	 */
14608 	if (cmd->cmd_pkt->pkt_time) {
14609 		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14610 			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14611 		} else {
14612 			/*
14613 			 * Indicate the watch thread to fail the
14614 			 * command by setting it to highest value
14615 			 */
14616 			cmd->cmd_timeout = fcp_watchdog_time;
14617 			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14618 		}
14619 	}
14620 
14621 	if (pptr->port_pkt_head) {
14622 		ASSERT(pptr->port_pkt_tail != NULL);
14623 
14624 		pptr->port_pkt_tail->cmd_next = cmd;
14625 		pptr->port_pkt_tail = cmd;
14626 	} else {
14627 		ASSERT(pptr->port_pkt_tail == NULL);
14628 
14629 		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14630 	}
14631 	cmd->cmd_next = NULL;
14632 	mutex_exit(&pptr->port_pkt_mutex);
14633 }
14634 
14635 /*
14636  *     Function: fcp_update_targets
14637  *
14638  *  Description: This function applies the specified change of state to all
14639  *		 the targets listed.  The operation applied is 'set'.
14640  *
14641  *     Argument: *pptr		FCP port.
14642  *		 *dev_list	Array of fc_portmap_t structures.
14643  *		 count		Length of dev_list.
14644  *		 state		State bits to update.
14645  *		 cause		Reason for the update.
14646  *
14647  * Return Value: None
14648  *
14649  *	Context: User, Kernel and Interrupt context.
14650  *		 The mutex pptr->port_mutex must be held.
14651  */
14652 static void
14653 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14654     uint32_t count, uint32_t state, int cause)
14655 {
14656 	fc_portmap_t		*map_entry;
14657 	struct fcp_tgt	*ptgt;
14658 
14659 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14660 
14661 	while (count--) {
14662 		map_entry = &(dev_list[count]);
14663 		ptgt = fcp_lookup_target(pptr,
14664 		    (uchar_t *)&(map_entry->map_pwwn));
14665 		if (ptgt == NULL) {
14666 			continue;
14667 		}
14668 
14669 		mutex_enter(&ptgt->tgt_mutex);
14670 		ptgt->tgt_trace = 0;
14671 		ptgt->tgt_change_cnt++;
14672 		ptgt->tgt_statec_cause = cause;
14673 		ptgt->tgt_tmp_cnt = 1;
14674 		fcp_update_tgt_state(ptgt, FCP_SET, state);
14675 		mutex_exit(&ptgt->tgt_mutex);
14676 	}
14677 }
14678 
14679 static int
14680 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14681     int lcount, int tcount, int cause)
14682 {
14683 	int rval;
14684 
14685 	mutex_enter(&pptr->port_mutex);
14686 	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14687 	mutex_exit(&pptr->port_mutex);
14688 
14689 	return (rval);
14690 }
14691 
14692 
14693 static int
14694 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14695     int lcount, int tcount, int cause)
14696 {
14697 	int	finish_init = 0;
14698 	int	finish_tgt = 0;
14699 	int	do_finish_init = 0;
14700 	int	rval = FCP_NO_CHANGE;
14701 
14702 	if (cause == FCP_CAUSE_LINK_CHANGE ||
14703 	    cause == FCP_CAUSE_LINK_DOWN) {
14704 		do_finish_init = 1;
14705 	}
14706 
14707 	if (ptgt != NULL) {
14708 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14709 		    FCP_BUF_LEVEL_2, 0,
14710 		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14711 		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14712 		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14713 		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14714 		    ptgt->tgt_d_id, ptgt->tgt_done);
14715 
14716 		mutex_enter(&ptgt->tgt_mutex);
14717 
14718 		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14719 			rval = FCP_DEV_CHANGE;
14720 			if (do_finish_init && ptgt->tgt_done == 0) {
14721 				ptgt->tgt_done++;
14722 				finish_init = 1;
14723 			}
14724 		} else {
14725 			if (--ptgt->tgt_tmp_cnt <= 0) {
14726 				ptgt->tgt_tmp_cnt = 0;
14727 				finish_tgt = 1;
14728 
14729 				if (do_finish_init) {
14730 					finish_init = 1;
14731 				}
14732 			}
14733 		}
14734 		mutex_exit(&ptgt->tgt_mutex);
14735 	} else {
14736 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14737 		    FCP_BUF_LEVEL_2, 0,
14738 		    "Call Finish Init for NO target");
14739 
14740 		if (do_finish_init) {
14741 			finish_init = 1;
14742 		}
14743 	}
14744 
14745 	if (finish_tgt) {
14746 		ASSERT(ptgt != NULL);
14747 
14748 		mutex_enter(&ptgt->tgt_mutex);
14749 #ifdef	DEBUG
14750 		bzero(ptgt->tgt_tmp_cnt_stack,
14751 		    sizeof (ptgt->tgt_tmp_cnt_stack));
14752 
14753 		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14754 		    FCP_STACK_DEPTH);
14755 #endif /* DEBUG */
14756 		mutex_exit(&ptgt->tgt_mutex);
14757 
14758 		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14759 	}
14760 
14761 	if (finish_init && lcount == pptr->port_link_cnt) {
14762 		ASSERT(pptr->port_tmp_cnt > 0);
14763 		if (--pptr->port_tmp_cnt == 0) {
14764 			fcp_finish_init(pptr);
14765 		}
14766 	} else if (lcount != pptr->port_link_cnt) {
14767 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14768 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14769 		    "fcp_call_finish_init_held,1: state change occured"
14770 		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14771 	}
14772 
14773 	return (rval);
14774 }
14775 
14776 static void
14777 fcp_reconfigure_luns(void * tgt_handle)
14778 {
14779 	uint32_t		dev_cnt;
14780 	fc_portmap_t		*devlist;
14781 	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14782 	struct fcp_port		*pptr = ptgt->tgt_port;
14783 
14784 	/*
14785 	 * If the timer that fires this off got canceled too late, the
14786 	 * target could have been destroyed.
14787 	 */
14788 
14789 	if (ptgt->tgt_tid == NULL) {
14790 		return;
14791 	}
14792 
14793 	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14794 	if (devlist == NULL) {
14795 		fcp_log(CE_WARN, pptr->port_dip,
14796 		    "!fcp%d: failed to allocate for portmap",
14797 		    pptr->port_instance);
14798 		return;
14799 	}
14800 
14801 	dev_cnt = 1;
14802 	devlist->map_pd = ptgt->tgt_pd_handle;
14803 	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14804 	devlist->map_did.port_id = ptgt->tgt_d_id;
14805 
14806 	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14807 	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14808 
14809 	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14810 	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14811 	devlist->map_flags = 0;
14812 
14813 	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14814 	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14815 
14816 	/*
14817 	 * Clear the tgt_tid after no more references to
14818 	 * the fcp_tgt
14819 	 */
14820 	mutex_enter(&ptgt->tgt_mutex);
14821 	ptgt->tgt_tid = NULL;
14822 	mutex_exit(&ptgt->tgt_mutex);
14823 
14824 	kmem_free(devlist, sizeof (*devlist));
14825 }
14826 
14827 
14828 static void
14829 fcp_free_targets(struct fcp_port *pptr)
14830 {
14831 	int			i;
14832 	struct fcp_tgt	*ptgt;
14833 
14834 	mutex_enter(&pptr->port_mutex);
14835 	for (i = 0; i < FCP_NUM_HASH; i++) {
14836 		ptgt = pptr->port_tgt_hash_table[i];
14837 		while (ptgt != NULL) {
14838 			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14839 
14840 			fcp_free_target(ptgt);
14841 			ptgt = next_tgt;
14842 		}
14843 	}
14844 	mutex_exit(&pptr->port_mutex);
14845 }
14846 
14847 
14848 static void
14849 fcp_free_target(struct fcp_tgt *ptgt)
14850 {
14851 	struct fcp_lun	*plun;
14852 	timeout_id_t		tid;
14853 
14854 	mutex_enter(&ptgt->tgt_mutex);
14855 	tid = ptgt->tgt_tid;
14856 
14857 	/*
14858 	 * Cancel any pending timeouts for this target.
14859 	 */
14860 
14861 	if (tid != NULL) {
14862 		/*
14863 		 * Set tgt_tid to NULL first to avoid a race in the callback.
14864 		 * If tgt_tid is NULL, the callback will simply return.
14865 		 */
14866 		ptgt->tgt_tid = NULL;
14867 		mutex_exit(&ptgt->tgt_mutex);
14868 		(void) untimeout(tid);
14869 		mutex_enter(&ptgt->tgt_mutex);
14870 	}
14871 
14872 	plun = ptgt->tgt_lun;
14873 	while (plun != NULL) {
14874 		struct fcp_lun *next_lun = plun->lun_next;
14875 
14876 		fcp_dealloc_lun(plun);
14877 		plun = next_lun;
14878 	}
14879 
14880 	mutex_exit(&ptgt->tgt_mutex);
14881 	fcp_dealloc_tgt(ptgt);
14882 }
14883 
14884 /*
14885  *     Function: fcp_is_retryable
14886  *
14887  *  Description: Indicates if the internal packet is retryable.
14888  *
14889  *     Argument: *icmd		FCP internal packet.
14890  *
14891  * Return Value: 0	Not retryable
14892  *		 1	Retryable
14893  *
14894  *	Context: User, Kernel and Interrupt context
14895  */
14896 static int
14897 fcp_is_retryable(struct fcp_ipkt *icmd)
14898 {
14899 	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14900 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14901 		return (0);
14902 	}
14903 
14904 	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14905 	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14906 }
14907 
14908 /*
14909  *     Function: fcp_create_on_demand
14910  *
14911  *     Argument: *pptr		FCP port.
14912  *		 *pwwn		Port WWN.
14913  *
14914  * Return Value: 0	Success
14915  *		 EIO
14916  *		 ENOMEM
14917  *		 EBUSY
14918  *		 EINVAL
14919  *
14920  *	Context: User and Kernel context
14921  */
14922 static int
14923 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14924 {
14925 	int			wait_ms;
14926 	int			tcount;
14927 	int			lcount;
14928 	int			ret;
14929 	int			error;
14930 	int			rval = EIO;
14931 	int			ntries;
14932 	fc_portmap_t		*devlist;
14933 	opaque_t		pd;
14934 	struct fcp_lun		*plun;
14935 	struct fcp_tgt		*ptgt;
14936 	int			old_manual = 0;
14937 
14938 	/* Allocates the fc_portmap_t structure. */
14939 	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14940 
14941 	/*
14942 	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14943 	 * in the commented statement below:
14944 	 *
14945 	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14946 	 *
14947 	 * Below, the deadline for the discovery process is set.
14948 	 */
14949 	mutex_enter(&pptr->port_mutex);
14950 	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14951 	mutex_exit(&pptr->port_mutex);
14952 
14953 	/*
14954 	 * We try to find the remote port based on the WWN provided by the
14955 	 * caller.  We actually ask fp/fctl if it has it.
14956 	 */
14957 	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14958 	    (la_wwn_t *)pwwn, &error, 1);
14959 
14960 	if (pd == NULL) {
14961 		kmem_free(devlist, sizeof (*devlist));
14962 		return (rval);
14963 	}
14964 
14965 	/*
14966 	 * The remote port was found.  We ask fp/fctl to update our
14967 	 * fc_portmap_t structure.
14968 	 */
14969 	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14970 	    (la_wwn_t *)pwwn, devlist);
14971 	if (ret != FC_SUCCESS) {
14972 		kmem_free(devlist, sizeof (*devlist));
14973 		return (rval);
14974 	}
14975 
14976 	/*
14977 	 * The map flag field is set to indicates that the creation is being
14978 	 * done at the user request (Ioclt probably luxadm or cfgadm).
14979 	 */
14980 	devlist->map_type = PORT_DEVICE_USER_CREATE;
14981 
14982 	mutex_enter(&pptr->port_mutex);
14983 
14984 	/*
14985 	 * We check to see if fcp already has a target that describes the
14986 	 * device being created.  If not it is created.
14987 	 */
14988 	ptgt = fcp_lookup_target(pptr, pwwn);
14989 	if (ptgt == NULL) {
14990 		lcount = pptr->port_link_cnt;
14991 		mutex_exit(&pptr->port_mutex);
14992 
14993 		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14994 		if (ptgt == NULL) {
14995 			fcp_log(CE_WARN, pptr->port_dip,
14996 			    "!FC target allocation failed");
14997 			return (ENOMEM);
14998 		}
14999 
15000 		mutex_enter(&pptr->port_mutex);
15001 	}
15002 
15003 	mutex_enter(&ptgt->tgt_mutex);
15004 	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15005 	ptgt->tgt_tmp_cnt = 1;
15006 	ptgt->tgt_device_created = 0;
15007 	/*
15008 	 * If fabric and auto config is set but the target was
15009 	 * manually unconfigured then reset to the manual_config_only to
15010 	 * 0 so the device will get configured.
15011 	 */
15012 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15013 	    fcp_enable_auto_configuration &&
15014 	    ptgt->tgt_manual_config_only == 1) {
15015 		old_manual = 1;
15016 		ptgt->tgt_manual_config_only = 0;
15017 	}
15018 	mutex_exit(&ptgt->tgt_mutex);
15019 
15020 	fcp_update_targets(pptr, devlist, 1,
15021 	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15022 
15023 	lcount = pptr->port_link_cnt;
15024 	tcount = ptgt->tgt_change_cnt;
15025 
15026 	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15027 	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15028 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15029 		    fcp_enable_auto_configuration && old_manual) {
15030 			mutex_enter(&ptgt->tgt_mutex);
15031 			ptgt->tgt_manual_config_only = 1;
15032 			mutex_exit(&ptgt->tgt_mutex);
15033 		}
15034 
15035 		if (pptr->port_link_cnt != lcount ||
15036 		    ptgt->tgt_change_cnt != tcount) {
15037 			rval = EBUSY;
15038 		}
15039 		mutex_exit(&pptr->port_mutex);
15040 
15041 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15042 		    FCP_BUF_LEVEL_3, 0,
15043 		    "fcp_create_on_demand: mapflags ptgt=%x, "
15044 		    "lcount=%x::port_link_cnt=%x, "
15045 		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
15046 		    ptgt, lcount, pptr->port_link_cnt,
15047 		    tcount, ptgt->tgt_change_cnt, rval);
15048 		return (rval);
15049 	}
15050 
15051 	/*
15052 	 * Due to lack of synchronization mechanisms, we perform
15053 	 * periodic monitoring of our request; Because requests
15054 	 * get dropped when another one supercedes (either because
15055 	 * of a link change or a target change), it is difficult to
15056 	 * provide a clean synchronization mechanism (such as a
15057 	 * semaphore or a conditional variable) without exhaustively
15058 	 * rewriting the mainline discovery code of this driver.
15059 	 */
15060 	wait_ms = 500;
15061 
15062 	ntries = fcp_max_target_retries;
15063 
15064 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15065 	    FCP_BUF_LEVEL_3, 0,
15066 	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15067 	    "lcount=%x::port_link_cnt=%x, "
15068 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15069 	    "tgt_tmp_cnt =%x",
15070 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15071 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15072 	    ptgt->tgt_tmp_cnt);
15073 
15074 	mutex_enter(&ptgt->tgt_mutex);
15075 	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15076 	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15077 		mutex_exit(&ptgt->tgt_mutex);
15078 		mutex_exit(&pptr->port_mutex);
15079 
15080 		delay(drv_usectohz(wait_ms * 1000));
15081 
15082 		mutex_enter(&pptr->port_mutex);
15083 		mutex_enter(&ptgt->tgt_mutex);
15084 	}
15085 
15086 
15087 	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15088 		rval = EBUSY;
15089 	} else {
15090 		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15091 		    FCP_TGT_NODE_PRESENT) {
15092 			rval = 0;
15093 		}
15094 	}
15095 
15096 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15097 	    FCP_BUF_LEVEL_3, 0,
15098 	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15099 	    "lcount=%x::port_link_cnt=%x, "
15100 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15101 	    "tgt_tmp_cnt =%x",
15102 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15103 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15104 	    ptgt->tgt_tmp_cnt);
15105 
15106 	if (rval) {
15107 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15108 		    fcp_enable_auto_configuration && old_manual) {
15109 			ptgt->tgt_manual_config_only = 1;
15110 		}
15111 		mutex_exit(&ptgt->tgt_mutex);
15112 		mutex_exit(&pptr->port_mutex);
15113 		kmem_free(devlist, sizeof (*devlist));
15114 
15115 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15116 		    FCP_BUF_LEVEL_3, 0,
15117 		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15118 		    "lcount=%x::port_link_cnt=%x, "
15119 		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15120 		    "tgt_device_created=%x, tgt D_ID=%x",
15121 		    ntries, ptgt, lcount, pptr->port_link_cnt,
15122 		    tcount, ptgt->tgt_change_cnt, rval,
15123 		    ptgt->tgt_device_created, ptgt->tgt_d_id);
15124 		return (rval);
15125 	}
15126 
15127 	if ((plun = ptgt->tgt_lun) != NULL) {
15128 		tcount = plun->lun_tgt->tgt_change_cnt;
15129 	} else {
15130 		rval = EINVAL;
15131 	}
15132 	lcount = pptr->port_link_cnt;
15133 
15134 	/*
15135 	 * Configuring the target with no LUNs will fail. We
15136 	 * should reset the node state so that it is not
15137 	 * automatically configured when the LUNs are added
15138 	 * to this target.
15139 	 */
15140 	if (ptgt->tgt_lun_cnt == 0) {
15141 		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15142 	}
15143 	mutex_exit(&ptgt->tgt_mutex);
15144 	mutex_exit(&pptr->port_mutex);
15145 
15146 	while (plun) {
15147 		child_info_t	*cip;
15148 
15149 		mutex_enter(&plun->lun_mutex);
15150 		cip = plun->lun_cip;
15151 		mutex_exit(&plun->lun_mutex);
15152 
15153 		mutex_enter(&ptgt->tgt_mutex);
15154 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15155 			mutex_exit(&ptgt->tgt_mutex);
15156 
15157 			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15158 			    FCP_ONLINE, lcount, tcount,
15159 			    NDI_ONLINE_ATTACH);
15160 			if (rval != NDI_SUCCESS) {
15161 				FCP_TRACE(fcp_logq,
15162 				    pptr->port_instbuf, fcp_trace,
15163 				    FCP_BUF_LEVEL_3, 0,
15164 				    "fcp_create_on_demand: "
15165 				    "pass_to_hp_and_wait failed "
15166 				    "rval=%x", rval);
15167 				rval = EIO;
15168 			} else {
15169 				mutex_enter(&LUN_TGT->tgt_mutex);
15170 				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15171 				    FCP_LUN_BUSY);
15172 				mutex_exit(&LUN_TGT->tgt_mutex);
15173 			}
15174 			mutex_enter(&ptgt->tgt_mutex);
15175 		}
15176 
15177 		plun = plun->lun_next;
15178 		mutex_exit(&ptgt->tgt_mutex);
15179 	}
15180 
15181 	kmem_free(devlist, sizeof (*devlist));
15182 
15183 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15184 	    fcp_enable_auto_configuration && old_manual) {
15185 		mutex_enter(&ptgt->tgt_mutex);
15186 		/* if successful then set manual to 0 */
15187 		if (rval == 0) {
15188 			ptgt->tgt_manual_config_only = 0;
15189 		} else {
15190 			/* reset to 1 so the user has to do the config */
15191 			ptgt->tgt_manual_config_only = 1;
15192 		}
15193 		mutex_exit(&ptgt->tgt_mutex);
15194 	}
15195 
15196 	return (rval);
15197 }
15198 
15199 
15200 static void
15201 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15202 {
15203 	int		count;
15204 	uchar_t		byte;
15205 
15206 	count = 0;
15207 	while (*string) {
15208 		byte = FCP_ATOB(*string); string++;
15209 		byte = byte << 4 | FCP_ATOB(*string); string++;
15210 		bytes[count++] = byte;
15211 
15212 		if (count >= byte_len) {
15213 			break;
15214 		}
15215 	}
15216 }
15217 
15218 static void
15219 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15220 {
15221 	int		i;
15222 
15223 	for (i = 0; i < FC_WWN_SIZE; i++) {
15224 		(void) sprintf(string + (i * 2),
15225 		    "%02x", wwn[i]);
15226 	}
15227 
15228 }
15229 
15230 static void
15231 fcp_print_error(fc_packet_t *fpkt)
15232 {
15233 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15234 	    fpkt->pkt_ulp_private;
15235 	struct fcp_port	*pptr;
15236 	struct fcp_tgt	*ptgt;
15237 	struct fcp_lun	*plun;
15238 	caddr_t			buf;
15239 	int			scsi_cmd = 0;
15240 
15241 	ptgt = icmd->ipkt_tgt;
15242 	plun = icmd->ipkt_lun;
15243 	pptr = ptgt->tgt_port;
15244 
15245 	buf = kmem_zalloc(256, KM_NOSLEEP);
15246 	if (buf == NULL) {
15247 		return;
15248 	}
15249 
15250 	switch (icmd->ipkt_opcode) {
15251 	case SCMD_REPORT_LUN:
15252 		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15253 		    " lun=0x%%x failed");
15254 		scsi_cmd++;
15255 		break;
15256 
15257 	case SCMD_INQUIRY_PAGE83:
15258 		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15259 		    " lun=0x%%x failed");
15260 		scsi_cmd++;
15261 		break;
15262 
15263 	case SCMD_INQUIRY:
15264 		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15265 		    " lun=0x%%x failed");
15266 		scsi_cmd++;
15267 		break;
15268 
15269 	case LA_ELS_PLOGI:
15270 		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15271 		break;
15272 
15273 	case LA_ELS_PRLI:
15274 		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15275 		break;
15276 	}
15277 
15278 	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15279 		struct fcp_rsp		response, *rsp;
15280 		uchar_t			asc, ascq;
15281 		caddr_t			sense_key = NULL;
15282 		struct fcp_rsp_info	fcp_rsp_err, *bep;
15283 
15284 		if (icmd->ipkt_nodma) {
15285 			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15286 			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15287 			    sizeof (struct fcp_rsp));
15288 		} else {
15289 			rsp = &response;
15290 			bep = &fcp_rsp_err;
15291 
15292 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15293 			    sizeof (struct fcp_rsp));
15294 
15295 			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15296 			    bep, fpkt->pkt_resp_acc,
15297 			    sizeof (struct fcp_rsp_info));
15298 		}
15299 
15300 
15301 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15302 			(void) sprintf(buf + strlen(buf),
15303 			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15304 			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15305 			    " senselen=%%x. Giving up");
15306 
15307 			fcp_log(CE_WARN, pptr->port_dip, buf,
15308 			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15309 			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15310 			    rsp->fcp_u.fcp_status.reserved_1,
15311 			    rsp->fcp_response_len, rsp->fcp_sense_len);
15312 
15313 			kmem_free(buf, 256);
15314 			return;
15315 		}
15316 
15317 		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15318 		    bep->rsp_code != FCP_NO_FAILURE) {
15319 			(void) sprintf(buf + strlen(buf),
15320 			    " FCP Response code = 0x%x", bep->rsp_code);
15321 		}
15322 
15323 		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15324 			struct scsi_extended_sense sense_info, *sense_ptr;
15325 
15326 			if (icmd->ipkt_nodma) {
15327 				sense_ptr = (struct scsi_extended_sense *)
15328 				    ((caddr_t)fpkt->pkt_resp +
15329 				    sizeof (struct fcp_rsp) +
15330 				    rsp->fcp_response_len);
15331 			} else {
15332 				sense_ptr = &sense_info;
15333 
15334 				FCP_CP_IN(fpkt->pkt_resp +
15335 				    sizeof (struct fcp_rsp) +
15336 				    rsp->fcp_response_len, &sense_info,
15337 				    fpkt->pkt_resp_acc,
15338 				    sizeof (struct scsi_extended_sense));
15339 			}
15340 
15341 			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15342 			    NUM_IMPL_SENSE_KEYS) {
15343 				sense_key = sense_keys[sense_ptr->es_key];
15344 			} else {
15345 				sense_key = "Undefined";
15346 			}
15347 
15348 			asc = sense_ptr->es_add_code;
15349 			ascq = sense_ptr->es_qual_code;
15350 
15351 			(void) sprintf(buf + strlen(buf),
15352 			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15353 			    " Giving up");
15354 
15355 			fcp_log(CE_WARN, pptr->port_dip, buf,
15356 			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15357 			    asc, ascq);
15358 		} else {
15359 			(void) sprintf(buf + strlen(buf),
15360 			    " : SCSI status=%%x. Giving up");
15361 
15362 			fcp_log(CE_WARN, pptr->port_dip, buf,
15363 			    ptgt->tgt_d_id, plun->lun_num,
15364 			    rsp->fcp_u.fcp_status.scsi_status);
15365 		}
15366 	} else {
15367 		caddr_t state, reason, action, expln;
15368 
15369 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15370 		    &action, &expln);
15371 
15372 		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15373 		    " Reason:%%s. Giving up");
15374 
15375 		if (scsi_cmd) {
15376 			fcp_log(CE_WARN, pptr->port_dip, buf,
15377 			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15378 		} else {
15379 			fcp_log(CE_WARN, pptr->port_dip, buf,
15380 			    ptgt->tgt_d_id, state, reason);
15381 		}
15382 	}
15383 
15384 	kmem_free(buf, 256);
15385 }
15386 
15387 
15388 static int
15389 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15390     struct fcp_ipkt *icmd, int rval, caddr_t op)
15391 {
15392 	int	ret = DDI_FAILURE;
15393 	char	*error;
15394 
15395 	switch (rval) {
15396 	case FC_DEVICE_BUSY_NEW_RSCN:
15397 		/*
15398 		 * This means that there was a new RSCN that the transport
15399 		 * knows about (which the ULP *may* know about too) but the
15400 		 * pkt that was sent down was related to an older RSCN. So, we
15401 		 * are just going to reset the retry count and deadline and
15402 		 * continue to retry. The idea is that transport is currently
15403 		 * working on the new RSCN and will soon let the ULPs know
15404 		 * about it and when it does the existing logic will kick in
15405 		 * where it will change the tcount to indicate that something
15406 		 * changed on the target. So, rediscovery will start and there
15407 		 * will not be an infinite retry.
15408 		 *
15409 		 * For a full flow of how the RSCN info is transferred back and
15410 		 * forth, see fp.c
15411 		 */
15412 		icmd->ipkt_retries = 0;
15413 		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15414 		    FCP_ICMD_DEADLINE;
15415 
15416 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15417 		    FCP_BUF_LEVEL_3, 0,
15418 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15419 		    rval, ptgt->tgt_d_id);
15420 		/* FALLTHROUGH */
15421 
15422 	case FC_STATEC_BUSY:
15423 	case FC_DEVICE_BUSY:
15424 	case FC_PBUSY:
15425 	case FC_FBUSY:
15426 	case FC_TRAN_BUSY:
15427 	case FC_OFFLINE:
15428 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15429 		    FCP_BUF_LEVEL_3, 0,
15430 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15431 		    rval, ptgt->tgt_d_id);
15432 		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15433 		    fcp_is_retryable(icmd)) {
15434 			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15435 			ret = DDI_SUCCESS;
15436 		}
15437 		break;
15438 
15439 	case FC_LOGINREQ:
15440 		/*
15441 		 * FC_LOGINREQ used to be handled just like all the cases
15442 		 * above. It has been changed to handled a PRLI that fails
15443 		 * with FC_LOGINREQ different than other ipkts that fail
15444 		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15445 		 * a simple matter to turn it into a PLOGI instead, so that's
15446 		 * exactly what we do here.
15447 		 */
15448 		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15449 			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15450 			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15451 			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15452 		} else {
15453 			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15454 			    FCP_BUF_LEVEL_3, 0,
15455 			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15456 			    rval, ptgt->tgt_d_id);
15457 			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15458 			    fcp_is_retryable(icmd)) {
15459 				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15460 				ret = DDI_SUCCESS;
15461 			}
15462 		}
15463 		break;
15464 
15465 	default:
15466 		mutex_enter(&pptr->port_mutex);
15467 		mutex_enter(&ptgt->tgt_mutex);
15468 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15469 			mutex_exit(&ptgt->tgt_mutex);
15470 			mutex_exit(&pptr->port_mutex);
15471 
15472 			(void) fc_ulp_error(rval, &error);
15473 			fcp_log(CE_WARN, pptr->port_dip,
15474 			    "!Failed to send %s to D_ID=%x error=%s",
15475 			    op, ptgt->tgt_d_id, error);
15476 		} else {
15477 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15478 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15479 			    "fcp_handle_ipkt_errors,1: state change occured"
15480 			    " for D_ID=0x%x", ptgt->tgt_d_id);
15481 			mutex_exit(&ptgt->tgt_mutex);
15482 			mutex_exit(&pptr->port_mutex);
15483 		}
15484 		break;
15485 	}
15486 
15487 	return (ret);
15488 }
15489 
15490 
15491 /*
15492  * Check of outstanding commands on any LUN for this target
15493  */
15494 static int
15495 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15496 {
15497 	struct	fcp_lun	*plun;
15498 	struct	fcp_pkt	*cmd;
15499 
15500 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15501 		mutex_enter(&plun->lun_mutex);
15502 		for (cmd = plun->lun_pkt_head; cmd != NULL;
15503 		    cmd = cmd->cmd_forw) {
15504 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15505 				mutex_exit(&plun->lun_mutex);
15506 				return (FC_SUCCESS);
15507 			}
15508 		}
15509 		mutex_exit(&plun->lun_mutex);
15510 	}
15511 
15512 	return (FC_FAILURE);
15513 }
15514 
15515 static fc_portmap_t *
15516 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15517 {
15518 	int			i;
15519 	fc_portmap_t		*devlist;
15520 	fc_portmap_t		*devptr = NULL;
15521 	struct fcp_tgt	*ptgt;
15522 
15523 	mutex_enter(&pptr->port_mutex);
15524 	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15525 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15526 		    ptgt = ptgt->tgt_next) {
15527 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15528 				++*dev_cnt;
15529 			}
15530 		}
15531 	}
15532 
15533 	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15534 	    KM_NOSLEEP);
15535 	if (devlist == NULL) {
15536 		mutex_exit(&pptr->port_mutex);
15537 		fcp_log(CE_WARN, pptr->port_dip,
15538 		    "!fcp%d: failed to allocate for portmap for construct map",
15539 		    pptr->port_instance);
15540 		return (devptr);
15541 	}
15542 
15543 	for (i = 0; i < FCP_NUM_HASH; i++) {
15544 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15545 		    ptgt = ptgt->tgt_next) {
15546 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15547 				int ret;
15548 
15549 				ret = fc_ulp_pwwn_to_portmap(
15550 				    pptr->port_fp_handle,
15551 				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15552 				    devlist);
15553 
15554 				if (ret == FC_SUCCESS) {
15555 					devlist++;
15556 					continue;
15557 				}
15558 
15559 				devlist->map_pd = NULL;
15560 				devlist->map_did.port_id = ptgt->tgt_d_id;
15561 				devlist->map_hard_addr.hard_addr =
15562 				    ptgt->tgt_hard_addr;
15563 
15564 				devlist->map_state = PORT_DEVICE_INVALID;
15565 				devlist->map_type = PORT_DEVICE_OLD;
15566 
15567 				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15568 				    &devlist->map_nwwn, FC_WWN_SIZE);
15569 
15570 				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15571 				    &devlist->map_pwwn, FC_WWN_SIZE);
15572 
15573 				devlist++;
15574 			}
15575 		}
15576 	}
15577 
15578 	mutex_exit(&pptr->port_mutex);
15579 
15580 	return (devptr);
15581 }
15582 /*
15583  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15584  */
15585 static void
15586 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15587 {
15588 	int i;
15589 	struct fcp_tgt	*ptgt;
15590 	struct fcp_lun	*plun;
15591 
15592 	for (i = 0; i < FCP_NUM_HASH; i++) {
15593 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15594 		    ptgt = ptgt->tgt_next) {
15595 			mutex_enter(&ptgt->tgt_mutex);
15596 			for (plun = ptgt->tgt_lun; plun != NULL;
15597 			    plun = plun->lun_next) {
15598 				if (plun->lun_mpxio &&
15599 				    plun->lun_state & FCP_LUN_BUSY) {
15600 					if (!fcp_pass_to_hp(pptr, plun,
15601 					    plun->lun_cip,
15602 					    FCP_MPXIO_PATH_SET_BUSY,
15603 					    pptr->port_link_cnt,
15604 					    ptgt->tgt_change_cnt, 0, 0)) {
15605 						FCP_TRACE(fcp_logq,
15606 						    pptr->port_instbuf,
15607 						    fcp_trace,
15608 						    FCP_BUF_LEVEL_2, 0,
15609 						    "path_verifybusy: "
15610 						    "disable lun %p failed!",
15611 						    plun);
15612 					}
15613 				}
15614 			}
15615 			mutex_exit(&ptgt->tgt_mutex);
15616 		}
15617 	}
15618 }
15619 
15620 static int
15621 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15622 {
15623 	dev_info_t		*cdip = NULL;
15624 	dev_info_t		*pdip = NULL;
15625 
15626 	ASSERT(plun);
15627 
15628 	mutex_enter(&plun->lun_mutex);
15629 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15630 		mutex_exit(&plun->lun_mutex);
15631 		return (NDI_FAILURE);
15632 	}
15633 	mutex_exit(&plun->lun_mutex);
15634 	cdip = mdi_pi_get_client(PIP(cip));
15635 	pdip = mdi_pi_get_phci(PIP(cip));
15636 
15637 	ASSERT(cdip != NULL);
15638 	ASSERT(pdip != NULL);
15639 
15640 	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15641 		/* LUN ready for IO */
15642 		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15643 	} else {
15644 		/* LUN busy to accept IO */
15645 		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15646 	}
15647 	return (NDI_SUCCESS);
15648 }
15649 
15650 /*
15651  * Caller must free the returned string of MAXPATHLEN len
15652  * If the device is offline (-1 instance number) NULL
15653  * will be returned.
15654  */
15655 static char *
15656 fcp_get_lun_path(struct fcp_lun *plun) {
15657 	dev_info_t	*dip = NULL;
15658 	char		*path = NULL;
15659 	mdi_pathinfo_t	*pip = NULL;
15660 
15661 	if (plun == NULL) {
15662 		return (NULL);
15663 	}
15664 
15665 	mutex_enter(&plun->lun_mutex);
15666 	if (plun->lun_mpxio == 0) {
15667 		dip = DIP(plun->lun_cip);
15668 		mutex_exit(&plun->lun_mutex);
15669 	} else {
15670 		/*
15671 		 * lun_cip must be accessed with lun_mutex held. Here
15672 		 * plun->lun_cip either points to a valid node or it is NULL.
15673 		 * Make a copy so that we can release lun_mutex.
15674 		 */
15675 		pip = PIP(plun->lun_cip);
15676 
15677 		/*
15678 		 * Increase ref count on the path so that we can release
15679 		 * lun_mutex and still be sure that the pathinfo node (and thus
15680 		 * also the client) is not deallocated. If pip is NULL, this
15681 		 * has no effect.
15682 		 */
15683 		mdi_hold_path(pip);
15684 
15685 		mutex_exit(&plun->lun_mutex);
15686 
15687 		/* Get the client. If pip is NULL, we get NULL. */
15688 		dip = mdi_pi_get_client(pip);
15689 	}
15690 
15691 	if (dip == NULL)
15692 		goto out;
15693 	if (ddi_get_instance(dip) < 0)
15694 		goto out;
15695 
15696 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15697 	if (path == NULL)
15698 		goto out;
15699 
15700 	(void) ddi_pathname(dip, path);
15701 
15702 	/* Clean up. */
15703 out:
15704 	if (pip != NULL)
15705 		mdi_rele_path(pip);
15706 
15707 	/*
15708 	 * In reality, the user wants a fully valid path (one they can open)
15709 	 * but this string is lacking the mount point, and the minor node.
15710 	 * It would be nice if we could "figure these out" somehow
15711 	 * and fill them in.  Otherwise, the userland code has to understand
15712 	 * driver specific details of which minor node is the "best" or
15713 	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15714 	 * which tape doesn't rewind)
15715 	 */
15716 	return (path);
15717 }
15718 
15719 static int
15720 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15721     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15722 {
15723 	int64_t reset_delay;
15724 	int rval, retry = 0;
15725 	struct fcp_port *pptr = fcp_dip2port(parent);
15726 
15727 	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15728 	    (ddi_get_lbolt64() - pptr->port_attach_time);
15729 	if (reset_delay < 0) {
15730 		reset_delay = 0;
15731 	}
15732 
15733 	if (fcp_bus_config_debug) {
15734 		flag |= NDI_DEVI_DEBUG;
15735 	}
15736 
15737 	switch (op) {
15738 	case BUS_CONFIG_ONE:
15739 		/*
15740 		 * Retry the command since we need to ensure
15741 		 * the fabric devices are available for root
15742 		 */
15743 		while (retry++ < fcp_max_bus_config_retries) {
15744 			rval =	(ndi_busop_bus_config(parent,
15745 			    flag | NDI_MDI_FALLBACK, op,
15746 			    arg, childp, (clock_t)reset_delay));
15747 			if (rval == 0) {
15748 				return (rval);
15749 			}
15750 		}
15751 
15752 		/*
15753 		 * drain taskq to make sure nodes are created and then
15754 		 * try again.
15755 		 */
15756 		taskq_wait(DEVI(parent)->devi_taskq);
15757 		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15758 		    op, arg, childp, 0));
15759 
15760 	case BUS_CONFIG_DRIVER:
15761 	case BUS_CONFIG_ALL: {
15762 		/*
15763 		 * delay till all devices report in (port_tmp_cnt == 0)
15764 		 * or FCP_INIT_WAIT_TIMEOUT
15765 		 */
15766 		mutex_enter(&pptr->port_mutex);
15767 		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15768 			(void) cv_timedwait(&pptr->port_config_cv,
15769 			    &pptr->port_mutex,
15770 			    ddi_get_lbolt() + (clock_t)reset_delay);
15771 			reset_delay =
15772 			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15773 			    (ddi_get_lbolt64() - pptr->port_attach_time);
15774 		}
15775 		mutex_exit(&pptr->port_mutex);
15776 		/* drain taskq to make sure nodes are created */
15777 		taskq_wait(DEVI(parent)->devi_taskq);
15778 		return (ndi_busop_bus_config(parent, flag, op,
15779 		    arg, childp, 0));
15780 	}
15781 
15782 	default:
15783 		return (NDI_FAILURE);
15784 	}
15785 	/*NOTREACHED*/
15786 }
15787 
15788 static int
15789 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15790     ddi_bus_config_op_t op, void *arg)
15791 {
15792 	if (fcp_bus_config_debug) {
15793 		flag |= NDI_DEVI_DEBUG;
15794 	}
15795 
15796 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15797 }
15798 
15799 
15800 /*
15801  * Routine to copy GUID into the lun structure.
15802  * returns 0 if copy was successful and 1 if encountered a
15803  * failure and did not copy the guid.
15804  */
15805 static int
15806 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15807 {
15808 
15809 	int retval = 0;
15810 
15811 	/* add one for the null terminator */
15812 	const unsigned int len = strlen(guidp) + 1;
15813 
15814 	if ((guidp == NULL) || (plun == NULL)) {
15815 		return (1);
15816 	}
15817 
15818 	/*
15819 	 * if the plun->lun_guid already has been allocated,
15820 	 * then check the size. if the size is exact, reuse
15821 	 * it....if not free it an allocate the required size.
15822 	 * The reallocation should NOT typically happen
15823 	 * unless the GUIDs reported changes between passes.
15824 	 * We free up and alloc again even if the
15825 	 * size was more than required. This is due to the
15826 	 * fact that the field lun_guid_size - serves
15827 	 * dual role of indicating the size of the wwn
15828 	 * size and ALSO the allocation size.
15829 	 */
15830 	if (plun->lun_guid) {
15831 		if (plun->lun_guid_size != len) {
15832 			/*
15833 			 * free the allocated memory and
15834 			 * initialize the field
15835 			 * lun_guid_size to 0.
15836 			 */
15837 			kmem_free(plun->lun_guid, plun->lun_guid_size);
15838 			plun->lun_guid = NULL;
15839 			plun->lun_guid_size = 0;
15840 		}
15841 	}
15842 	/*
15843 	 * alloc only if not already done.
15844 	 */
15845 	if (plun->lun_guid == NULL) {
15846 		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15847 		if (plun->lun_guid == NULL) {
15848 			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15849 			    "Unable to allocate"
15850 			    "Memory for GUID!!! size %d", len);
15851 			retval = 1;
15852 		} else {
15853 			plun->lun_guid_size = len;
15854 		}
15855 	}
15856 	if (plun->lun_guid) {
15857 		/*
15858 		 * now copy the GUID
15859 		 */
15860 		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15861 	}
15862 	return (retval);
15863 }
15864 
15865 /*
15866  * fcp_reconfig_wait
15867  *
15868  * Wait for a rediscovery/reconfiguration to complete before continuing.
15869  */
15870 
15871 static void
15872 fcp_reconfig_wait(struct fcp_port *pptr)
15873 {
15874 	clock_t		reconfig_start, wait_timeout;
15875 
15876 	/*
15877 	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15878 	 * reconfiguration in progress.
15879 	 */
15880 
15881 	mutex_enter(&pptr->port_mutex);
15882 	if (pptr->port_tmp_cnt == 0) {
15883 		mutex_exit(&pptr->port_mutex);
15884 		return;
15885 	}
15886 	mutex_exit(&pptr->port_mutex);
15887 
15888 	/*
15889 	 * If we cause a reconfig by raising power, delay until all devices
15890 	 * report in (port_tmp_cnt returns to 0)
15891 	 */
15892 
15893 	reconfig_start = ddi_get_lbolt();
15894 	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15895 
15896 	mutex_enter(&pptr->port_mutex);
15897 
15898 	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15899 	    pptr->port_tmp_cnt) {
15900 
15901 		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15902 		    reconfig_start + wait_timeout);
15903 	}
15904 
15905 	mutex_exit(&pptr->port_mutex);
15906 
15907 	/*
15908 	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15909 	 * we want may still be ok.  If not, it will error out later
15910 	 */
15911 }
15912 
15913 /*
15914  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15915  * We rely on the fcp_global_mutex to provide protection against changes to
15916  * the fcp_lun_blacklist.
15917  *
15918  * You can describe a list of target port WWNs and LUN numbers which will
15919  * not be configured. LUN numbers will be interpreted as decimal. White
15920  * spaces and ',' can be used in the list of LUN numbers.
15921  *
15922  * To prevent LUNs 1 and 2 from being configured for target
15923  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15924  *
15925  * pwwn-lun-blacklist=
15926  * "510000f010fd92a1,1,2",
15927  * "510000e012079df1,1,2";
15928  */
15929 static void
15930 fcp_read_blacklist(dev_info_t *dip,
15931     struct fcp_black_list_entry **pplun_blacklist) {
15932 	char **prop_array	= NULL;
15933 	char *curr_pwwn		= NULL;
15934 	char *curr_lun		= NULL;
15935 	uint32_t prop_item	= 0;
15936 	int idx			= 0;
15937 	int len			= 0;
15938 
15939 	ASSERT(mutex_owned(&fcp_global_mutex));
15940 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15941 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15942 	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15943 		return;
15944 	}
15945 
15946 	for (idx = 0; idx < prop_item; idx++) {
15947 
15948 		curr_pwwn = prop_array[idx];
15949 		while (*curr_pwwn == ' ') {
15950 			curr_pwwn++;
15951 		}
15952 		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15953 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15954 			    ", please check.", curr_pwwn);
15955 			continue;
15956 		}
15957 		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15958 		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15959 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15960 			    ", please check.", curr_pwwn);
15961 			continue;
15962 		}
15963 		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15964 			if (isxdigit(curr_pwwn[len]) != TRUE) {
15965 				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15966 				    "blacklist, please check.", curr_pwwn);
15967 				break;
15968 			}
15969 		}
15970 		if (len != sizeof (la_wwn_t) * 2) {
15971 			continue;
15972 		}
15973 
15974 		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15975 		*(curr_lun - 1) = '\0';
15976 		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15977 	}
15978 
15979 	ddi_prop_free(prop_array);
15980 }
15981 
15982 /*
15983  * Get the masking info about one remote target port designated by wwn.
15984  * Lun ids could be separated by ',' or white spaces.
15985  */
15986 static void
15987 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15988     struct fcp_black_list_entry **pplun_blacklist) {
15989 	int		idx			= 0;
15990 	uint32_t	offset			= 0;
15991 	unsigned long	lun_id			= 0;
15992 	char		lunid_buf[16];
15993 	char		*pend			= NULL;
15994 	int		illegal_digit		= 0;
15995 
15996 	while (offset < strlen(curr_lun)) {
15997 		while ((curr_lun[offset + idx] != ',') &&
15998 		    (curr_lun[offset + idx] != '\0') &&
15999 		    (curr_lun[offset + idx] != ' ')) {
16000 			if (isdigit(curr_lun[offset + idx]) == 0) {
16001 				illegal_digit++;
16002 			}
16003 			idx++;
16004 		}
16005 		if (illegal_digit > 0) {
16006 			offset += (idx+1);	/* To the start of next lun */
16007 			idx = 0;
16008 			illegal_digit = 0;
16009 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16010 			    "the blacklist, please check digits.",
16011 			    curr_lun, curr_pwwn);
16012 			continue;
16013 		}
16014 		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16015 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16016 			    "the blacklist, please check the length of LUN#.",
16017 			    curr_lun, curr_pwwn);
16018 			break;
16019 		}
16020 		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
16021 		    offset++;
16022 		    continue;
16023 		}
16024 
16025 		bcopy(curr_lun + offset, lunid_buf, idx);
16026 		lunid_buf[idx] = '\0';
16027 		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16028 			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16029 		} else {
16030 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16031 			    "the blacklist, please check %s.",
16032 			    curr_lun, curr_pwwn, lunid_buf);
16033 		}
16034 		offset += (idx+1);	/* To the start of next lun */
16035 		idx = 0;
16036 	}
16037 }
16038 
16039 /*
16040  * Add one masking record
16041  */
16042 static void
16043 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16044     struct fcp_black_list_entry **pplun_blacklist) {
16045 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16046 	struct fcp_black_list_entry	*new_entry	= NULL;
16047 	la_wwn_t			wwn;
16048 
16049 	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16050 	while (tmp_entry) {
16051 		if ((bcmp(&tmp_entry->wwn, &wwn,
16052 		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16053 			return;
16054 		}
16055 
16056 		tmp_entry = tmp_entry->next;
16057 	}
16058 
16059 	/* add to black list */
16060 	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16061 	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16062 	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16063 	new_entry->lun = lun_id;
16064 	new_entry->masked = 0;
16065 	new_entry->next = *pplun_blacklist;
16066 	*pplun_blacklist = new_entry;
16067 }
16068 
16069 /*
16070  * Check if we should mask the specified lun of this fcp_tgt
16071  */
16072 static int
16073 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16074 	struct fcp_black_list_entry *remote_port;
16075 
16076 	remote_port = fcp_lun_blacklist;
16077 	while (remote_port != NULL) {
16078 		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16079 			if (remote_port->lun == lun_id) {
16080 				remote_port->masked++;
16081 				if (remote_port->masked == 1) {
16082 					fcp_log(CE_NOTE, NULL, "LUN %d of port "
16083 					    "%02x%02x%02x%02x%02x%02x%02x%02x "
16084 					    "is masked due to black listing.\n",
16085 					    lun_id, wwn->raw_wwn[0],
16086 					    wwn->raw_wwn[1], wwn->raw_wwn[2],
16087 					    wwn->raw_wwn[3], wwn->raw_wwn[4],
16088 					    wwn->raw_wwn[5], wwn->raw_wwn[6],
16089 					    wwn->raw_wwn[7]);
16090 				}
16091 				return (TRUE);
16092 			}
16093 		}
16094 		remote_port = remote_port->next;
16095 	}
16096 	return (FALSE);
16097 }
16098 
16099 /*
16100  * Release all allocated resources
16101  */
16102 static void
16103 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16104 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16105 	struct fcp_black_list_entry	*current_entry	= NULL;
16106 
16107 	ASSERT(mutex_owned(&fcp_global_mutex));
16108 	/*
16109 	 * Traverse all luns
16110 	 */
16111 	while (tmp_entry) {
16112 		current_entry = tmp_entry;
16113 		tmp_entry = tmp_entry->next;
16114 		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16115 	}
16116 	*pplun_blacklist = NULL;
16117 }
16118 
16119 /*
16120  * In fcp module,
16121  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16122  */
16123 static struct scsi_pkt *
16124 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16125     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16126     int flags, int (*callback)(), caddr_t arg)
16127 {
16128 	fcp_port_t	*pptr = ADDR2FCP(ap);
16129 	fcp_pkt_t	*cmd  = NULL;
16130 	fc_frame_hdr_t	*hp;
16131 
16132 	/*
16133 	 * First step: get the packet
16134 	 */
16135 	if (pkt == NULL) {
16136 		pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16137 		    tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16138 		    callback, arg);
16139 		if (pkt == NULL) {
16140 			return (NULL);
16141 		}
16142 
16143 		/*
16144 		 * All fields in scsi_pkt will be initialized properly or
16145 		 * set to zero. We need do nothing for scsi_pkt.
16146 		 */
16147 		/*
16148 		 * But it's our responsibility to link other related data
16149 		 * structures. Their initialization will be done, just
16150 		 * before the scsi_pkt will be sent to FCA.
16151 		 */
16152 		cmd		= PKT2CMD(pkt);
16153 		cmd->cmd_pkt	= pkt;
16154 		cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16155 		/*
16156 		 * fc_packet_t
16157 		 */
16158 		cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16159 		cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16160 		    sizeof (struct fcp_pkt));
16161 		cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16162 		cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16163 		cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16164 		cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16165 		/*
16166 		 * Fill in the Fabric Channel Header
16167 		 */
16168 		hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16169 		hp->r_ctl = R_CTL_COMMAND;
16170 		hp->rsvd = 0;
16171 		hp->type = FC_TYPE_SCSI_FCP;
16172 		hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16173 		hp->seq_id = 0;
16174 		hp->df_ctl  = 0;
16175 		hp->seq_cnt = 0;
16176 		hp->ox_id = 0xffff;
16177 		hp->rx_id = 0xffff;
16178 		hp->ro = 0;
16179 	} else {
16180 		/*
16181 		 * We need think if we should reset any elements in
16182 		 * related data structures.
16183 		 */
16184 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
16185 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
16186 		    "reusing pkt, flags %d", flags);
16187 		cmd = PKT2CMD(pkt);
16188 		if (cmd->cmd_fp_pkt->pkt_pd) {
16189 			cmd->cmd_fp_pkt->pkt_pd = NULL;
16190 		}
16191 	}
16192 
16193 	/*
16194 	 * Second step:	 dma allocation/move
16195 	 */
16196 	if (bp && bp->b_bcount != 0) {
16197 		/*
16198 		 * Mark if it's read or write
16199 		 */
16200 		if (bp->b_flags & B_READ) {
16201 			cmd->cmd_flags |= CFLAG_IS_READ;
16202 		} else {
16203 			cmd->cmd_flags &= ~CFLAG_IS_READ;
16204 		}
16205 
16206 		bp_mapin(bp);
16207 		cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16208 		cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16209 		cmd->cmd_fp_pkt->pkt_data_resid = 0;
16210 	} else {
16211 		/*
16212 		 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16213 		 * to send zero-length read/write.
16214 		 */
16215 		cmd->cmd_fp_pkt->pkt_data = NULL;
16216 		cmd->cmd_fp_pkt->pkt_datalen = 0;
16217 	}
16218 
16219 	return (pkt);
16220 }
16221 
16222 static void
16223 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16224 {
16225 	fcp_port_t	*pptr = ADDR2FCP(ap);
16226 
16227 	/*
16228 	 * First we let FCA to uninitilize private part.
16229 	 */
16230 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16231 	    PKT2CMD(pkt)->cmd_fp_pkt);
16232 
16233 	/*
16234 	 * Then we uninitialize fc_packet.
16235 	 */
16236 
16237 	/*
16238 	 * Thirdly, we uninitializae fcp_pkt.
16239 	 */
16240 
16241 	/*
16242 	 * In the end, we free scsi_pkt.
16243 	 */
16244 	scsi_hba_pkt_free(ap, pkt);
16245 }
16246 
16247 static int
16248 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16249 {
16250 	fcp_port_t	*pptr = ADDR2FCP(ap);
16251 	fcp_lun_t	*plun = ADDR2LUN(ap);
16252 	fcp_tgt_t	*ptgt = plun->lun_tgt;
16253 	fcp_pkt_t	*cmd  = PKT2CMD(pkt);
16254 	fcp_cmd_t	*fcmd = &cmd->cmd_fcp_cmd;
16255 	fc_packet_t	*fpkt = cmd->cmd_fp_pkt;
16256 	int		 rval;
16257 
16258 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
16259 	(void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16260 
16261 	/*
16262 	 * Firstly, we need initialize fcp_pkt_t
16263 	 * Secondly, we need initialize fcp_cmd_t.
16264 	 */
16265 	bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16266 	fcmd->fcp_data_len = fpkt->pkt_datalen;
16267 	fcmd->fcp_ent_addr = plun->lun_addr;
16268 	if (pkt->pkt_flags & FLAG_HTAG) {
16269 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16270 	} else if (pkt->pkt_flags & FLAG_OTAG) {
16271 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16272 	} else if (pkt->pkt_flags & FLAG_STAG) {
16273 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16274 	} else {
16275 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16276 	}
16277 
16278 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16279 		fcmd->fcp_cntl.cntl_read_data = 1;
16280 		fcmd->fcp_cntl.cntl_write_data = 0;
16281 	} else {
16282 		fcmd->fcp_cntl.cntl_read_data = 0;
16283 		fcmd->fcp_cntl.cntl_write_data = 1;
16284 	}
16285 
16286 	/*
16287 	 * Then we need initialize fc_packet_t too.
16288 	 */
16289 	fpkt->pkt_timeout = pkt->pkt_time + 2;
16290 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16291 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16292 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16293 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16294 	} else {
16295 		fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16296 	}
16297 
16298 	if (pkt->pkt_flags & FLAG_NOINTR) {
16299 		fpkt->pkt_comp = NULL;
16300 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16301 	} else {
16302 		fpkt->pkt_comp = fcp_cmd_callback;
16303 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16304 		if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16305 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16306 		}
16307 	}
16308 
16309 	/*
16310 	 * Lastly, we need initialize scsi_pkt
16311 	 */
16312 	pkt->pkt_reason = CMD_CMPLT;
16313 	pkt->pkt_state = 0;
16314 	pkt->pkt_statistics = 0;
16315 	pkt->pkt_resid = 0;
16316 
16317 	/*
16318 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
16319 	 * have to do polled I/O
16320 	 */
16321 	if (pkt->pkt_flags & FLAG_NOINTR) {
16322 		return (fcp_dopoll(pptr, cmd));
16323 	}
16324 
16325 	cmd->cmd_state = FCP_PKT_ISSUED;
16326 	rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16327 	if (rval == FC_SUCCESS) {
16328 		return (TRAN_ACCEPT);
16329 	}
16330 
16331 	/*
16332 	 * Need more consideration
16333 	 *
16334 	 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16335 	 */
16336 	cmd->cmd_state = FCP_PKT_IDLE;
16337 	if (rval == FC_TRAN_BUSY) {
16338 		return (TRAN_BUSY);
16339 	} else {
16340 		return (TRAN_FATAL_ERROR);
16341 	}
16342 }
16343 
16344 /*
16345  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16346  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16347  */
16348 static void
16349 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16350 {
16351 	FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16352 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16353 }
16354 
16355 /*
16356  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16357  */
16358 static void
16359 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16360 {
16361 	FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16362 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16363 }
16364