xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/ulp/fcp.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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 /*
28  * Copyright 2023 Oxide Computer Company
29  */
30 
31 #include <sys/scsi/scsi.h>
32 #include <sys/types.h>
33 #include <sys/varargs.h>
34 #include <sys/devctl.h>
35 #include <sys/thread.h>
36 #include <sys/thread.h>
37 #include <sys/open.h>
38 #include <sys/file.h>
39 #include <sys/sunndi.h>
40 #include <sys/console.h>
41 #include <sys/proc.h>
42 #include <sys/time.h>
43 #include <sys/utsname.h>
44 #include <sys/scsi/impl/scsi_reset_notify.h>
45 #include <sys/ndi_impldefs.h>
46 #include <sys/byteorder.h>
47 #include <sys/fs/dv_node.h>
48 #include <sys/ctype.h>
49 #include <sys/sunmdi.h>
50 
51 #include <sys/fibre-channel/fc.h>
52 #include <sys/fibre-channel/impl/fc_ulpif.h>
53 #include <sys/fibre-channel/ulp/fcpvar.h>
54 
55 /*
56  * Discovery Process
57  * =================
58  *
59  *    The discovery process is a major function of FCP.	 In order to help
60  * understand that function a flow diagram is given here.  This diagram
61  * doesn't claim to cover all the cases and the events that can occur during
62  * the discovery process nor the subtleties of the code.  The code paths shown
63  * are simplified.  Its purpose is to help the reader (and potentially bug
64  * fixer) have an overall view of the logic of the code.  For that reason the
65  * diagram covers the simple case of the line coming up cleanly or of a new
66  * port attaching to FCP the link being up.  The reader must keep in mind
67  * that:
68  *
69  *	- There are special cases where bringing devices online and offline
70  *	  is driven by Ioctl.
71  *
72  *	- The behavior of the discovery process can be modified through the
73  *	  .conf file.
74  *
75  *	- The line can go down and come back up at any time during the
76  *	  discovery process which explains some of the complexity of the code.
77  *
78  * ............................................................................
79  *
80  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
81  *
82  *
83  *			+-------------------------+
84  *   fp/fctl module --->|    fcp_port_attach	  |
85  *			+-------------------------+
86  *	   |			     |
87  *	   |			     |
88  *	   |			     v
89  *	   |		+-------------------------+
90  *	   |		| fcp_handle_port_attach  |
91  *	   |		+-------------------------+
92  *	   |				|
93  *	   |				|
94  *	   +--------------------+	|
95  *				|	|
96  *				v	v
97  *			+-------------------------+
98  *			|   fcp_statec_callback	  |
99  *			+-------------------------+
100  *				    |
101  *				    |
102  *				    v
103  *			+-------------------------+
104  *			|    fcp_handle_devices	  |
105  *			+-------------------------+
106  *				    |
107  *				    |
108  *				    v
109  *			+-------------------------+
110  *			|   fcp_handle_mapflags	  |
111  *			+-------------------------+
112  *				    |
113  *				    |
114  *				    v
115  *			+-------------------------+
116  *			|     fcp_send_els	  |
117  *			|			  |
118  *			| PLOGI or PRLI To all the|
119  *			| reachable devices.	  |
120  *			+-------------------------+
121  *
122  *
123  * ............................................................................
124  *
125  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
126  *	   STEP 1 are called (it is actually the same function).
127  *
128  *
129  *			+-------------------------+
130  *			|    fcp_icmd_callback	  |
131  *   fp/fctl module --->|			  |
132  *			| callback for PLOGI and  |
133  *			| PRLI.			  |
134  *			+-------------------------+
135  *				     |
136  *				     |
137  *	    Received PLOGI Accept   /-\	  Received PRLI Accept
138  *		       _ _ _ _ _ _ /   \_ _ _ _ _ _
139  *		      |		   \   /	   |
140  *		      |		    \-/		   |
141  *		      |				   |
142  *		      v				   v
143  *	+-------------------------+	+-------------------------+
144  *	|     fcp_send_els	  |	|     fcp_send_scsi	  |
145  *	|			  |	|			  |
146  *	|	  PRLI		  |	|	REPORT_LUN	  |
147  *	+-------------------------+	+-------------------------+
148  *
149  * ............................................................................
150  *
151  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
152  *	   (It is actually the same function).
153  *
154  *
155  *			    +-------------------------+
156  *   fp/fctl module ------->|	 fcp_scsi_callback    |
157  *			    +-------------------------+
158  *					|
159  *					|
160  *					|
161  *	Receive REPORT_LUN reply       /-\	Receive INQUIRY PAGE83 reply
162  *		  _ _ _ _ _ _ _ _ _ _ /	  \_ _ _ _ _ _ _ _ _ _ _ _
163  *		 |		      \	  /			  |
164  *		 |		       \-/			  |
165  *		 |			|			  |
166  *		 | Receive INQUIRY reply|			  |
167  *		 |			|			  |
168  *		 v			v			  v
169  * +------------------------+ +----------------------+ +----------------------+
170  * |  fcp_handle_reportlun  | |	 fcp_handle_inquiry  | |  fcp_handle_page83   |
171  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
172  * +------------------------+ +----------------------+ +----------------------+
173  *		 |			|			  |
174  *		 |			|			  |
175  *		 |			|			  |
176  *		 v			v			  |
177  *     +-----------------+	+-----------------+		  |
178  *     |  fcp_send_scsi	 |	|  fcp_send_scsi  |		  |
179  *     |		 |	|		  |		  |
180  *     |     INQUIRY	 |	| INQUIRY PAGE83  |		  |
181  *     |  (To each LUN)	 |	+-----------------+		  |
182  *     +-----------------+					  |
183  *								  |
184  *								  v
185  *						      +------------------------+
186  *						      |	 fcp_call_finish_init  |
187  *						      +------------------------+
188  *								  |
189  *								  v
190  *						 +-----------------------------+
191  *						 |  fcp_call_finish_init_held  |
192  *						 +-----------------------------+
193  *								  |
194  *								  |
195  *			   All LUNs scanned			 /-\
196  *			       _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
197  *			      |					\   /
198  *			      |					 \-/
199  *			      v					  |
200  *		     +------------------+			  |
201  *		     |	fcp_finish_tgt	|			  |
202  *		     +------------------+			  |
203  *			      |	  Target Not Offline and	  |
204  *  Target Not Offline and    |	  not marked and tgt_node_state	  |
205  *  marked		     /-\  not FCP_TGT_NODE_ON_DEMAND	  |
206  *		_ _ _ _ _ _ /	\_ _ _ _ _ _ _ _		  |
207  *	       |	    \	/		|		  |
208  *	       |	     \-/		|		  |
209  *	       v				v		  |
210  * +----------------------------+     +-------------------+	  |
211  * |	 fcp_offline_target	|     |	 fcp_create_luns  |	  |
212  * |				|     +-------------------+	  |
213  * | A structure fcp_tgt_elem	|		|		  |
214  * | is created and queued in	|		v		  |
215  * | the FCP port list		|     +-------------------+	  |
216  * | port_offline_tgts.	 It	|     |	 fcp_pass_to_hp	  |	  |
217  * | will be unqueued by the	|     |			  |	  |
218  * | watchdog timer.		|     | Called for each	  |	  |
219  * +----------------------------+     | LUN. Dispatches	  |	  |
220  *		  |		      | fcp_hp_task	  |	  |
221  *		  |		      +-------------------+	  |
222  *		  |				|		  |
223  *		  |				|		  |
224  *		  |				|		  |
225  *		  |				+---------------->|
226  *		  |						  |
227  *		  +---------------------------------------------->|
228  *								  |
229  *								  |
230  *		All the targets (devices) have been scanned	 /-\
231  *				_ _ _ _	_ _ _ _	_ _ _ _ _ _ _ _ /   \
232  *			       |				\   /
233  *			       |				 \-/
234  *	    +-------------------------------------+		  |
235  *	    |		fcp_finish_init		  |		  |
236  *	    |					  |		  |
237  *	    | Signal broadcasts the condition	  |		  |
238  *	    | variable port_config_cv of the FCP  |		  |
239  *	    | port.  One potential code sequence  |		  |
240  *	    | waiting on the condition variable	  |		  |
241  *	    | the code sequence handling	  |		  |
242  *	    | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|		  |
243  *	    | The other is in the function	  |		  |
244  *	    | fcp_reconfig_wait which is called	  |		  |
245  *	    | in the transmit path preventing IOs |		  |
246  *	    | from going through till the disco-  |		  |
247  *	    | very process is over.		  |		  |
248  *	    +-------------------------------------+		  |
249  *			       |				  |
250  *			       |				  |
251  *			       +--------------------------------->|
252  *								  |
253  *								  v
254  *								Return
255  *
256  * ............................................................................
257  *
258  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
259  *
260  *
261  *			+-------------------------+
262  *			|      fcp_hp_task	  |
263  *			+-------------------------+
264  *				     |
265  *				     |
266  *				     v
267  *			+-------------------------+
268  *			|     fcp_trigger_lun	  |
269  *			+-------------------------+
270  *				     |
271  *				     |
272  *				     v
273  *		   Bring offline    /-\	 Bring online
274  *		  _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
275  *		 |		   \   /		   |
276  *		 |		    \-/			   |
277  *		 v					   v
278  *    +---------------------+			+-----------------------+
279  *    |	 fcp_offline_child  |			|      fcp_get_cip	|
280  *    +---------------------+			|			|
281  *						| Creates a dev_info_t	|
282  *						| or a mdi_pathinfo_t	|
283  *						| depending on whether	|
284  *						| mpxio is on or off.	|
285  *						+-----------------------+
286  *							   |
287  *							   |
288  *							   v
289  *						+-----------------------+
290  *						|  fcp_online_child	|
291  *						|			|
292  *						| Set device online	|
293  *						| using NDI or MDI.	|
294  *						+-----------------------+
295  *
296  * ............................................................................
297  *
298  * STEP 5: The watchdog timer expires.	The watch dog timer does much more that
299  *	   what is described here.  We only show the target offline path.
300  *
301  *
302  *			 +--------------------------+
303  *			 |	  fcp_watch	    |
304  *			 +--------------------------+
305  *				       |
306  *				       |
307  *				       v
308  *			 +--------------------------+
309  *			 |  fcp_scan_offline_tgts   |
310  *			 +--------------------------+
311  *				       |
312  *				       |
313  *				       v
314  *			 +--------------------------+
315  *			 |  fcp_offline_target_now  |
316  *			 +--------------------------+
317  *				       |
318  *				       |
319  *				       v
320  *			 +--------------------------+
321  *			 |   fcp_offline_tgt_luns   |
322  *			 +--------------------------+
323  *				       |
324  *				       |
325  *				       v
326  *			 +--------------------------+
327  *			 |     fcp_offline_lun	    |
328  *			 +--------------------------+
329  *				       |
330  *				       |
331  *				       v
332  *		     +----------------------------------+
333  *		     |	     fcp_offline_lun_now	|
334  *		     |					|
335  *		     | A request (or two if mpxio) is	|
336  *		     | sent to the hot plug task using	|
337  *		     | a fcp_hp_elem structure.		|
338  *		     +----------------------------------+
339  */
340 
341 /*
342  * Functions registered with DDI framework
343  */
344 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
345 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
346 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
347 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
348 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
349     cred_t *credp, int *rval);
350 
351 /*
352  * Functions registered with FC Transport framework
353  */
354 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
355     fc_attach_cmd_t cmd,  uint32_t s_id);
356 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
357     fc_detach_cmd_t cmd);
358 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
359     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
360     uint32_t claimed);
361 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
362     fc_unsol_buf_t *buf, uint32_t claimed);
363 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
364     fc_unsol_buf_t *buf, uint32_t claimed);
365 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
366     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
367     uint32_t  dev_cnt, uint32_t port_sid);
368 
369 /*
370  * Functions registered with SCSA framework
371  */
372 static int fcp_phys_tgt_init(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_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
375     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
376 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
377     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
378 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
379 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
380 static int fcp_scsi_reset(struct scsi_address *ap, int level);
381 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
382 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
383     int whom);
384 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
385 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
386     void (*callback)(caddr_t), caddr_t arg);
387 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
388     char *name, ddi_eventcookie_t *event_cookiep);
389 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
390     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
391     ddi_callback_id_t *cb_id);
392 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
393     ddi_callback_id_t cb_id);
394 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
395     ddi_eventcookie_t eventid, void *impldata);
396 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
397     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
398 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
399     ddi_bus_config_op_t op, void *arg);
400 
401 /*
402  * Internal functions
403  */
404 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
405     int mode, int *rval);
406 
407 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
408     int mode, int *rval);
409 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
410     struct fcp_scsi_cmd *fscsi, int mode);
411 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
412     caddr_t base_addr, int mode);
413 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
414 
415 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
416     la_wwn_t *pwwn, int	*ret_val, int *fc_status, int *fc_pkt_state,
417     int *fc_pkt_reason, int *fc_pkt_action);
418 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
419     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
420 static int fcp_tgt_send_prli(struct fcp_tgt	*ptgt, int *fc_status,
421     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
422 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
423 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
424 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
425 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
426 
427 static void fcp_handle_devices(struct fcp_port *pptr,
428     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
429     fcp_map_tag_t *map_tag, int cause);
430 static int fcp_handle_mapflags(struct fcp_port *pptr,
431     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
432     int tgt_cnt, int cause);
433 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
434 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
435     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
436 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
437     int cause);
438 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
439     uint32_t state);
440 static struct fcp_port *fcp_get_port(opaque_t port_handle);
441 static void fcp_unsol_callback(fc_packet_t *fpkt);
442 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
443     uchar_t r_ctl, uchar_t type);
444 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
445 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
446     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
447     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
448 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
449 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
450     int nodma, int flags);
451 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
452 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
453     uchar_t *wwn);
454 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
455     uint32_t d_id);
456 static void fcp_icmd_callback(fc_packet_t *fpkt);
457 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
458     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
459 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
460 static void fcp_scsi_callback(fc_packet_t *fpkt);
461 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
462 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
463 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
464 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
465     uint16_t lun_num);
466 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
467     int link_cnt, int tgt_cnt, int cause);
468 static void fcp_finish_init(struct fcp_port *pptr);
469 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
470     int tgt_cnt, int cause);
471 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
472     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
473 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
474     int link_cnt, int tgt_cnt, int nowait, int flags);
475 static void fcp_offline_target_now(struct fcp_port *pptr,
476     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
477 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
478     int tgt_cnt, int flags);
479 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
480     int nowait, int flags);
481 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
482     int tgt_cnt);
483 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
484     int tgt_cnt, int flags);
485 static void fcp_scan_offline_luns(struct fcp_port *pptr);
486 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
487 static void fcp_update_offline_flags(struct fcp_lun *plun);
488 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
489 static void fcp_abort_commands(struct fcp_pkt *head, struct
490     fcp_port *pptr);
491 static void fcp_cmd_callback(fc_packet_t *fpkt);
492 static void fcp_complete_pkt(fc_packet_t *fpkt);
493 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
494     struct fcp_port *pptr);
495 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
496     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
497 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
498 static void fcp_dealloc_lun(struct fcp_lun *plun);
499 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
500     fc_portmap_t *map_entry, int link_cnt);
501 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
502 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
503 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
504     int internal);
505 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
506 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
507     uint32_t s_id, int instance);
508 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
509     int instance);
510 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
511 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
512     int);
513 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
514 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
515 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
516     int flags);
517 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
518 static int fcp_reset_target(struct scsi_address *ap, int level);
519 static int fcp_commoncap(struct scsi_address *ap, char *cap,
520     int val, int tgtonly, int doset);
521 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
522 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
523 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
524     int sleep);
525 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
526     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
527 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
528 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
529 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
530     int lcount, int tcount);
531 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
532 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
533 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
534     int tgt_cnt);
535 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
536     dev_info_t *pdip, caddr_t name);
537 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
538     int lcount, int tcount, int flags);
539 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
540     int lcount, int tcount, int flags);
541 static void fcp_remove_child(struct fcp_lun *plun);
542 static void fcp_watch(void *arg);
543 static void fcp_check_reset_delay(struct fcp_port *pptr);
544 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
545     struct fcp_lun *rlun, int tgt_cnt);
546 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
547 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
548     uchar_t *wwn, uint16_t lun);
549 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
550     struct fcp_lun *plun);
551 static void fcp_post_callback(struct fcp_pkt *cmd);
552 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
553 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
554 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
555     child_info_t *cip);
556 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
557     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
558     int tgt_cnt, int flags);
559 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
560     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
561     int tgt_cnt, int flags, int wait);
562 static void fcp_retransport_cmd(struct fcp_port *pptr,
563     struct fcp_pkt *cmd);
564 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
565     uint_t statistics);
566 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
567 static void fcp_update_targets(struct fcp_port *pptr,
568     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
569 static int fcp_call_finish_init(struct fcp_port *pptr,
570     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
571 static int fcp_call_finish_init_held(struct fcp_port *pptr,
572     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
573 static void fcp_reconfigure_luns(void * tgt_handle);
574 static void fcp_free_targets(struct fcp_port *pptr);
575 static void fcp_free_target(struct fcp_tgt *ptgt);
576 static int fcp_is_retryable(struct fcp_ipkt *icmd);
577 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
578 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
579 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
580 static void fcp_print_error(fc_packet_t *fpkt);
581 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
582     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
583 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
584 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
585     uint32_t *dev_cnt);
586 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
587 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
588 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
589     struct fcp_ioctl *, struct fcp_port **);
590 static char *fcp_get_lun_path(struct fcp_lun *plun);
591 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
592     int *rval);
593 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
594 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
595 static char *fcp_get_lun_path(struct fcp_lun *plun);
596 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
597     int *rval);
598 static void fcp_reconfig_wait(struct fcp_port *pptr);
599 
600 /*
601  * New functions added for mpxio support
602  */
603 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
604     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
605 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
606     int tcount);
607 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
608     dev_info_t *pdip);
609 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
610 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
611 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
612 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
613 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
614     int what);
615 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
616     fc_packet_t *fpkt);
617 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
618 
619 /*
620  * New functions added for lun masking support
621  */
622 static void fcp_read_blacklist(dev_info_t *dip,
623     struct fcp_black_list_entry **pplun_blacklist);
624 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
625     struct fcp_black_list_entry **pplun_blacklist);
626 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
627     struct fcp_black_list_entry **pplun_blacklist);
628 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
629 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
630 
631 /*
632  * New functions to support software FCA (like fcoei)
633  */
634 static struct scsi_pkt *fcp_pseudo_init_pkt(
635 	struct scsi_address *ap, struct scsi_pkt *pkt,
636 	struct buf *bp, int cmdlen, int statuslen,
637 	int tgtlen, int flags, int (*callback)(), caddr_t arg);
638 static void fcp_pseudo_destroy_pkt(
639 	struct scsi_address *ap, struct scsi_pkt *pkt);
640 static void fcp_pseudo_sync_pkt(
641 	struct scsi_address *ap, struct scsi_pkt *pkt);
642 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
643 static void fcp_pseudo_dmafree(
644 	struct scsi_address *ap, struct scsi_pkt *pkt);
645 
646 extern struct mod_ops	mod_driverops;
647 /*
648  * This variable is defined in modctl.c and set to '1' after the root driver
649  * and fs are loaded.  It serves as an indication that the root filesystem can
650  * be used.
651  */
652 extern int		modrootloaded;
653 /*
654  * This table contains strings associated with the SCSI sense key codes.  It
655  * is used by FCP to print a clear explanation of the code returned in the
656  * sense information by a device.
657  */
658 extern char		*sense_keys[];
659 /*
660  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
661  * under this device that the paths to a physical device are created when
662  * MPxIO is used.
663  */
664 extern dev_info_t	*scsi_vhci_dip;
665 
666 /*
667  * Report lun processing
668  */
669 #define	FCP_LUN_ADDRESSING		0x80
670 #define	FCP_PD_ADDRESSING		0x00
671 #define	FCP_VOLUME_ADDRESSING		0x40
672 
673 #define	FCP_SVE_THROTTLE		0x28 /* Vicom */
674 #define	MAX_INT_DMA			0x7fffffff
675 /*
676  * Property definitions
677  */
678 #define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
679 #define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
680 #define	TARGET_PROP	(char *)fcp_target_prop
681 #define	LUN_PROP	(char *)fcp_lun_prop
682 #define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
683 #define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
684 #define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
685 #define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
686 #define	INIT_PORT_PROP	(char *)fcp_init_port_prop
687 #define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
688 #define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
689 /*
690  * Short hand macros.
691  */
692 #define	LUN_PORT	(plun->lun_tgt->tgt_port)
693 #define	LUN_TGT		(plun->lun_tgt)
694 
695 /*
696  * Driver private macros
697  */
698 #define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
699 			((x) >= 'a' && (x) <= 'f') ?			\
700 			((x) - 'a' + 10) : ((x) - 'A' + 10))
701 
702 #define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
703 
704 #define	FCP_N_NDI_EVENTS						\
705 	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
706 
707 #define	FCP_LINK_STATE_CHANGED(p, c)			\
708 	((p)->port_link_cnt != (c)->ipkt_link_cnt)
709 
710 #define	FCP_TGT_STATE_CHANGED(t, c)			\
711 	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
712 
713 #define	FCP_STATE_CHANGED(p, t, c)		\
714 	(FCP_TGT_STATE_CHANGED(t, c))
715 
716 #define	FCP_MUST_RETRY(fpkt)				\
717 	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
718 	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
719 	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
720 	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
721 	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
722 	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
723 	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
724 	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
725 
726 #define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
727 	((es)->es_key == KEY_UNIT_ATTENTION &&	\
728 	(es)->es_add_code == 0x3f &&		\
729 	(es)->es_qual_code == 0x0e)
730 
731 #define	FCP_SENSE_NO_LUN(es)			\
732 	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
733 	(es)->es_add_code == 0x25 &&		\
734 	(es)->es_qual_code == 0x0)
735 
736 #define	FCP_VERSION		"20091208-1.192"
737 #define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
738 
739 #define	FCP_NUM_ELEMENTS(array)			\
740 	(sizeof (array) / sizeof ((array)[0]))
741 
742 /*
743  * Debugging, Error reporting, and tracing
744  */
745 #define	FCP_LOG_SIZE		1024 * 1024
746 
747 #define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
748 #define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
749 #define	FCP_LEVEL_3		0x00004		/* state change, discovery */
750 #define	FCP_LEVEL_4		0x00008		/* ULP messages */
751 #define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
752 #define	FCP_LEVEL_6		0x00020		/* Transport failures */
753 #define	FCP_LEVEL_7		0x00040
754 #define	FCP_LEVEL_8		0x00080		/* I/O tracing */
755 #define	FCP_LEVEL_9		0x00100		/* I/O tracing */
756 
757 
758 
759 /*
760  * Log contents to system messages file
761  */
762 #define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
763 #define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
764 #define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
765 #define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
766 #define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
767 #define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
768 #define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
769 #define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
770 #define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
771 
772 
773 /*
774  * Log contents to trace buffer
775  */
776 #define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
777 #define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
778 #define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
779 #define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
780 #define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
781 #define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
782 #define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
783 #define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
784 #define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
785 
786 
787 /*
788  * Log contents to both system messages file and trace buffer
789  */
790 #define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
791 				FC_TRACE_LOG_MSG)
792 #define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
793 				FC_TRACE_LOG_MSG)
794 #define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
795 				FC_TRACE_LOG_MSG)
796 #define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
797 				FC_TRACE_LOG_MSG)
798 #define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
799 				FC_TRACE_LOG_MSG)
800 #define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
801 				FC_TRACE_LOG_MSG)
802 #define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
803 				FC_TRACE_LOG_MSG)
804 #define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
805 				FC_TRACE_LOG_MSG)
806 #define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
807 				FC_TRACE_LOG_MSG)
808 #ifdef DEBUG
809 #define	FCP_DTRACE	fc_trace_debug
810 #else
811 #define	FCP_DTRACE
812 #endif
813 
814 #define	FCP_TRACE	fc_trace_debug
815 
816 static struct cb_ops fcp_cb_ops = {
817 	fcp_open,			/* open */
818 	fcp_close,			/* close */
819 	nodev,				/* strategy */
820 	nodev,				/* print */
821 	nodev,				/* dump */
822 	nodev,				/* read */
823 	nodev,				/* write */
824 	fcp_ioctl,			/* ioctl */
825 	nodev,				/* devmap */
826 	nodev,				/* mmap */
827 	nodev,				/* segmap */
828 	nochpoll,			/* chpoll */
829 	ddi_prop_op,			/* cb_prop_op */
830 	0,				/* streamtab */
831 	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
832 	CB_REV,				/* rev */
833 	nodev,				/* aread */
834 	nodev				/* awrite */
835 };
836 
837 
838 static struct dev_ops fcp_ops = {
839 	DEVO_REV,
840 	0,
841 	ddi_getinfo_1to1,
842 	nulldev,		/* identify */
843 	nulldev,		/* probe */
844 	fcp_attach,		/* attach and detach are mandatory */
845 	fcp_detach,
846 	nodev,			/* reset */
847 	&fcp_cb_ops,		/* cb_ops */
848 	NULL,			/* bus_ops */
849 	NULL,			/* power */
850 };
851 
852 
853 char *fcp_version = FCP_NAME_VERSION;
854 
855 static struct modldrv modldrv = {
856 	&mod_driverops,
857 	FCP_NAME_VERSION,
858 	&fcp_ops
859 };
860 
861 
862 static struct modlinkage modlinkage = {
863 	MODREV_1,
864 	&modldrv,
865 	NULL
866 };
867 
868 
869 static fc_ulp_modinfo_t fcp_modinfo = {
870 	&fcp_modinfo,			/* ulp_handle */
871 	FCTL_ULP_MODREV_4,		/* ulp_rev */
872 	FC4_SCSI_FCP,			/* ulp_type */
873 	"fcp",				/* ulp_name */
874 	FCP_STATEC_MASK,		/* ulp_statec_mask */
875 	fcp_port_attach,		/* ulp_port_attach */
876 	fcp_port_detach,		/* ulp_port_detach */
877 	fcp_port_ioctl,			/* ulp_port_ioctl */
878 	fcp_els_callback,		/* ulp_els_callback */
879 	fcp_data_callback,		/* ulp_data_callback */
880 	fcp_statec_callback		/* ulp_statec_callback */
881 };
882 
883 #ifdef	DEBUG
884 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
885 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
886 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
887 				FCP_LEVEL_6 | FCP_LEVEL_7)
888 #else
889 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
890 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
891 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
892 				FCP_LEVEL_6 | FCP_LEVEL_7)
893 #endif
894 
895 /* FCP global variables */
896 int			fcp_bus_config_debug = 0;
897 static int		fcp_log_size = FCP_LOG_SIZE;
898 static int		fcp_trace = FCP_TRACE_DEFAULT;
899 static fc_trace_logq_t	*fcp_logq = NULL;
900 static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
901 /*
902  * The auto-configuration is set by default.  The only way of disabling it is
903  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
904  */
905 static int		fcp_enable_auto_configuration = 1;
906 static int		fcp_max_bus_config_retries	= 4;
907 static int		fcp_lun_ready_retry = 300;
908 /*
909  * The value assigned to the following variable has changed several times due
910  * to a problem with the data underruns reporting of some firmware(s).	The
911  * current value of 50 gives a timeout value of 25 seconds for a max number
912  * of 256 LUNs.
913  */
914 static int		fcp_max_target_retries = 50;
915 /*
916  * Watchdog variables
917  * ------------------
918  *
919  * fcp_watchdog_init
920  *
921  *	Indicates if the watchdog timer is running or not.  This is actually
922  *	a counter of the number of Fibre Channel ports that attached.  When
923  *	the first port attaches the watchdog is started.  When the last port
924  *	detaches the watchdog timer is stopped.
925  *
926  * fcp_watchdog_time
927  *
928  *	This is the watchdog clock counter.  It is incremented by
929  *	fcp_watchdog_time each time the watchdog timer expires.
930  *
931  * fcp_watchdog_timeout
932  *
933  *	Increment value of the variable fcp_watchdog_time as well as the
934  *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
935  *	is strange that this is not a #define	but a variable since the code
936  *	never changes this value.  The reason why it can be said that the
937  *	unit is 1 second is because the number of ticks for the watchdog
938  *	timer is determined like this:
939  *
940  *	    fcp_watchdog_tick = fcp_watchdog_timeout *
941  *				  drv_usectohz(1000000);
942  *
943  *	The value 1000000 is hard coded in the code.
944  *
945  * fcp_watchdog_tick
946  *
947  *	Watchdog timer value in ticks.
948  */
949 static int		fcp_watchdog_init = 0;
950 static int		fcp_watchdog_time = 0;
951 static int		fcp_watchdog_timeout = 1;
952 static int		fcp_watchdog_tick;
953 
954 /*
955  * fcp_offline_delay is a global variable to enable customisation of
956  * the timeout on link offlines or RSCNs. The default value is set
957  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
958  * specified in FCP4 Chapter 11 (see www.t10.org).
959  *
960  * The variable fcp_offline_delay is specified in SECONDS.
961  *
962  * If we made this a static var then the user would not be able to
963  * change it. This variable is set in fcp_attach().
964  */
965 unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
966 
967 static void		*fcp_softstate = NULL; /* for soft state */
968 static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
969 static kmutex_t		fcp_global_mutex;
970 static kmutex_t		fcp_ioctl_mutex;
971 static dev_info_t	*fcp_global_dip = NULL;
972 static timeout_id_t	fcp_watchdog_id;
973 const char		*fcp_lun_prop = "lun";
974 const char		*fcp_sam_lun_prop = "sam-lun";
975 const char		*fcp_target_prop = "target";
976 /*
977  * NOTE: consumers of "node-wwn" property include stmsboot in ON
978  * consolidation.
979  */
980 const char		*fcp_node_wwn_prop = "node-wwn";
981 const char		*fcp_port_wwn_prop = "port-wwn";
982 const char		*fcp_conf_wwn_prop = "fc-port-wwn";
983 const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
984 const char		*fcp_manual_config_only = "manual_configuration_only";
985 const char		*fcp_init_port_prop = "initiator-port";
986 const char		*fcp_tgt_port_prop = "target-port";
987 const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
988 
989 static struct fcp_port	*fcp_port_head = NULL;
990 static ddi_eventcookie_t	fcp_insert_eid;
991 static ddi_eventcookie_t	fcp_remove_eid;
992 
993 static ndi_event_definition_t	fcp_ndi_event_defs[] = {
994 	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
995 	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
996 };
997 
998 /*
999  * List of valid commands for the scsi_ioctl call
1000  */
1001 static uint8_t scsi_ioctl_list[] = {
1002 	SCMD_INQUIRY,
1003 	SCMD_REPORT_LUN,
1004 	SCMD_READ_CAPACITY
1005 };
1006 
1007 /*
1008  * this is used to dummy up a report lun response for cases
1009  * where the target doesn't support it
1010  */
1011 static uchar_t fcp_dummy_lun[] = {
1012 	0x00,		/* MSB length (length = no of luns * 8) */
1013 	0x00,
1014 	0x00,
1015 	0x08,		/* LSB length */
1016 	0x00,		/* MSB reserved */
1017 	0x00,
1018 	0x00,
1019 	0x00,		/* LSB reserved */
1020 	FCP_PD_ADDRESSING,
1021 	0x00,		/* LUN is ZERO at the first level */
1022 	0x00,
1023 	0x00,		/* second level is zero */
1024 	0x00,
1025 	0x00,		/* third level is zero */
1026 	0x00,
1027 	0x00		/* fourth level is zero */
1028 };
1029 
1030 static uchar_t fcp_alpa_to_switch[] = {
1031 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1032 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1033 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1034 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1035 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1036 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1037 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1038 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1039 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1040 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1041 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1042 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1043 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1044 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1045 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1046 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1047 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1048 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1049 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1050 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1051 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1052 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1053 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1054 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1055 };
1056 
1057 static caddr_t pid = "SESS01	      ";
1058 
1059 #if	!defined(lint)
1060 
1061 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1062     fcp_port::fcp_next fcp_watchdog_id))
1063 
1064 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1065 
1066 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1067     fcp_insert_eid
1068     fcp_remove_eid
1069     fcp_watchdog_time))
1070 
1071 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1072     fcp_cb_ops
1073     fcp_ops
1074     callb_cpr))
1075 
1076 #endif /* lint */
1077 
1078 /*
1079  * This table is used to determine whether or not it's safe to copy in
1080  * the target node name for a lun.  Since all luns behind the same target
1081  * have the same wwnn, only tagets that do not support multiple luns are
1082  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1083  */
1084 
1085 char *fcp_symmetric_disk_table[] = {
1086 	"SEAGATE ST",
1087 	"IBM	 DDYFT",
1088 	"SUNW	 SUNWGS",	/* Daktari enclosure */
1089 	"SUN	 SENA",		/* SES device */
1090 	"SUN	 SESS01"	/* VICOM SVE box */
1091 };
1092 
1093 int fcp_symmetric_disk_table_size =
1094 	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1095 
1096 /*
1097  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1098  * will panic if you don't pass this in to the routine, this information.
1099  * Need to determine what the actual impact to the system is by providing
1100  * this information if any. Since dma allocation is done in pkt_init it may
1101  * not have any impact. These values are straight from the Writing Device
1102  * Driver manual.
1103  */
1104 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1105 	DMA_ATTR_V0,	/* ddi_dma_attr version */
1106 	0,		/* low address */
1107 	0xffffffff,	/* high address */
1108 	0x00ffffff,	/* counter upper bound */
1109 	1,		/* alignment requirements */
1110 	0x3f,		/* burst sizes */
1111 	1,		/* minimum DMA access */
1112 	0xffffffff,	/* maximum DMA access */
1113 	(1 << 24) - 1,	/* segment boundary restrictions */
1114 	1,		/* scater/gather list length */
1115 	512,		/* device granularity */
1116 	0		/* DMA flags */
1117 };
1118 
1119 /*
1120  * The _init(9e) return value should be that of mod_install(9f). Under
1121  * some circumstances, a failure may not be related mod_install(9f) and
1122  * one would then require a return value to indicate the failure. Looking
1123  * at mod_install(9f), it is expected to return 0 for success and non-zero
1124  * for failure. mod_install(9f) for device drivers, further goes down the
1125  * calling chain and ends up in ddi_installdrv(), whose return values are
1126  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1127  * calling chain of mod_install(9f) which return values like EINVAL and
1128  * in some even return -1.
1129  *
1130  * To work around the vagaries of the mod_install() calling chain, return
1131  * either 0 or ENODEV depending on the success or failure of mod_install()
1132  */
1133 int
1134 _init(void)
1135 {
1136 	int rval;
1137 
1138 	/*
1139 	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1140 	 * before registering with the transport first.
1141 	 */
1142 	if (ddi_soft_state_init(&fcp_softstate,
1143 	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1144 		return (EINVAL);
1145 	}
1146 
1147 	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1148 	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1149 
1150 	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1151 		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1152 		mutex_destroy(&fcp_global_mutex);
1153 		mutex_destroy(&fcp_ioctl_mutex);
1154 		ddi_soft_state_fini(&fcp_softstate);
1155 		return (ENODEV);
1156 	}
1157 
1158 	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1159 
1160 	if ((rval = mod_install(&modlinkage)) != 0) {
1161 		fc_trace_free_logq(fcp_logq);
1162 		(void) fc_ulp_remove(&fcp_modinfo);
1163 		mutex_destroy(&fcp_global_mutex);
1164 		mutex_destroy(&fcp_ioctl_mutex);
1165 		ddi_soft_state_fini(&fcp_softstate);
1166 		rval = ENODEV;
1167 	}
1168 
1169 	return (rval);
1170 }
1171 
1172 
1173 /*
1174  * the system is done with us as a driver, so clean up
1175  */
1176 int
1177 _fini(void)
1178 {
1179 	int rval;
1180 
1181 	/*
1182 	 * don't start cleaning up until we know that the module remove
1183 	 * has worked  -- if this works, then we know that each instance
1184 	 * has successfully been DDI_DETACHed
1185 	 */
1186 	if ((rval = mod_remove(&modlinkage)) != 0) {
1187 		return (rval);
1188 	}
1189 
1190 	(void) fc_ulp_remove(&fcp_modinfo);
1191 
1192 	ddi_soft_state_fini(&fcp_softstate);
1193 	mutex_destroy(&fcp_global_mutex);
1194 	mutex_destroy(&fcp_ioctl_mutex);
1195 	fc_trace_free_logq(fcp_logq);
1196 
1197 	return (rval);
1198 }
1199 
1200 
1201 int
1202 _info(struct modinfo *modinfop)
1203 {
1204 	return (mod_info(&modlinkage, modinfop));
1205 }
1206 
1207 
1208 /*
1209  * attach the module
1210  */
1211 static int
1212 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1213 {
1214 	int rval = DDI_SUCCESS;
1215 
1216 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1217 	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1218 
1219 	if (cmd == DDI_ATTACH) {
1220 		/* The FCP pseudo device is created here. */
1221 		mutex_enter(&fcp_global_mutex);
1222 		fcp_global_dip = devi;
1223 		mutex_exit(&fcp_global_mutex);
1224 
1225 		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1226 		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1227 			ddi_report_dev(fcp_global_dip);
1228 		} else {
1229 			cmn_err(CE_WARN, "FCP: Cannot create minor node");
1230 			mutex_enter(&fcp_global_mutex);
1231 			fcp_global_dip = NULL;
1232 			mutex_exit(&fcp_global_mutex);
1233 
1234 			rval = DDI_FAILURE;
1235 		}
1236 		/*
1237 		 * We check the fcp_offline_delay property at this
1238 		 * point. This variable is global for the driver,
1239 		 * not specific to an instance.
1240 		 *
1241 		 * We do not recommend setting the value to less
1242 		 * than 10 seconds (RA_TOV_els), or greater than
1243 		 * 60 seconds.
1244 		 */
1245 		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1246 		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1247 		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
1248 		if ((fcp_offline_delay < 10) ||
1249 		    (fcp_offline_delay > 60)) {
1250 			cmn_err(CE_WARN, "Setting fcp_offline_delay "
1251 			    "to %d second(s). This is outside the "
1252 			    "recommended range of 10..60 seconds.",
1253 			    fcp_offline_delay);
1254 		}
1255 	}
1256 
1257 	return (rval);
1258 }
1259 
1260 
1261 /*ARGSUSED*/
1262 static int
1263 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1264 {
1265 	int	res = DDI_SUCCESS;
1266 
1267 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1268 	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
1269 
1270 	if (cmd == DDI_DETACH) {
1271 		/*
1272 		 * Check if there are active ports/threads. If there
1273 		 * are any, we will fail, else we will succeed (there
1274 		 * should not be much to clean up)
1275 		 */
1276 		mutex_enter(&fcp_global_mutex);
1277 		FCP_DTRACE(fcp_logq, "fcp",
1278 		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1279 		    (void *) fcp_port_head);
1280 
1281 		if (fcp_port_head == NULL) {
1282 			ddi_remove_minor_node(fcp_global_dip, NULL);
1283 			fcp_global_dip = NULL;
1284 			mutex_exit(&fcp_global_mutex);
1285 		} else {
1286 			mutex_exit(&fcp_global_mutex);
1287 			res = DDI_FAILURE;
1288 		}
1289 	}
1290 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1291 	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
1292 
1293 	return (res);
1294 }
1295 
1296 
1297 /* ARGSUSED */
1298 static int
1299 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1300 {
1301 	if (otype != OTYP_CHR) {
1302 		return (EINVAL);
1303 	}
1304 
1305 	/*
1306 	 * Allow only root to talk;
1307 	 */
1308 	if (drv_priv(credp)) {
1309 		return (EPERM);
1310 	}
1311 
1312 	mutex_enter(&fcp_global_mutex);
1313 	if (fcp_oflag & FCP_EXCL) {
1314 		mutex_exit(&fcp_global_mutex);
1315 		return (EBUSY);
1316 	}
1317 
1318 	if (flag & FEXCL) {
1319 		if (fcp_oflag & FCP_OPEN) {
1320 			mutex_exit(&fcp_global_mutex);
1321 			return (EBUSY);
1322 		}
1323 		fcp_oflag |= FCP_EXCL;
1324 	}
1325 	fcp_oflag |= FCP_OPEN;
1326 	mutex_exit(&fcp_global_mutex);
1327 
1328 	return (0);
1329 }
1330 
1331 
1332 /* ARGSUSED */
1333 static int
1334 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1335 {
1336 	if (otype != OTYP_CHR) {
1337 		return (EINVAL);
1338 	}
1339 
1340 	mutex_enter(&fcp_global_mutex);
1341 	if (!(fcp_oflag & FCP_OPEN)) {
1342 		mutex_exit(&fcp_global_mutex);
1343 		return (ENODEV);
1344 	}
1345 	fcp_oflag = FCP_IDLE;
1346 	mutex_exit(&fcp_global_mutex);
1347 
1348 	return (0);
1349 }
1350 
1351 
1352 /*
1353  * fcp_ioctl
1354  *	Entry point for the FCP ioctls
1355  *
1356  * Input:
1357  *	See ioctl(9E)
1358  *
1359  * Output:
1360  *	See ioctl(9E)
1361  *
1362  * Returns:
1363  *	See ioctl(9E)
1364  *
1365  * Context:
1366  *	Kernel context.
1367  */
1368 /* ARGSUSED */
1369 static int
1370 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1371     int *rval)
1372 {
1373 	int			ret = 0;
1374 
1375 	mutex_enter(&fcp_global_mutex);
1376 	if (!(fcp_oflag & FCP_OPEN)) {
1377 		mutex_exit(&fcp_global_mutex);
1378 		return (ENXIO);
1379 	}
1380 	mutex_exit(&fcp_global_mutex);
1381 
1382 	switch (cmd) {
1383 	case FCP_TGT_INQUIRY:
1384 	case FCP_TGT_CREATE:
1385 	case FCP_TGT_DELETE:
1386 		ret = fcp_setup_device_data_ioctl(cmd,
1387 		    (struct fcp_ioctl *)data, mode, rval);
1388 		break;
1389 
1390 	case FCP_TGT_SEND_SCSI:
1391 		mutex_enter(&fcp_ioctl_mutex);
1392 		ret = fcp_setup_scsi_ioctl(
1393 		    (struct fcp_scsi_cmd *)data, mode, rval);
1394 		mutex_exit(&fcp_ioctl_mutex);
1395 		break;
1396 
1397 	case FCP_STATE_COUNT:
1398 		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1399 		    mode, rval);
1400 		break;
1401 	case FCP_GET_TARGET_MAPPINGS:
1402 		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1403 		    mode, rval);
1404 		break;
1405 	default:
1406 		fcp_log(CE_WARN, NULL,
1407 		    "!Invalid ioctl opcode = 0x%x", cmd);
1408 		ret	= EINVAL;
1409 	}
1410 
1411 	return (ret);
1412 }
1413 
1414 
1415 /*
1416  * fcp_setup_device_data_ioctl
1417  *	Setup handler for the "device data" style of
1418  *	ioctl for FCP.	See "fcp_util.h" for data structure
1419  *	definition.
1420  *
1421  * Input:
1422  *	cmd	= FCP ioctl command
1423  *	data	= ioctl data
1424  *	mode	= See ioctl(9E)
1425  *
1426  * Output:
1427  *	data	= ioctl data
1428  *	rval	= return value - see ioctl(9E)
1429  *
1430  * Returns:
1431  *	See ioctl(9E)
1432  *
1433  * Context:
1434  *	Kernel context.
1435  */
1436 /* ARGSUSED */
1437 static int
1438 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1439     int *rval)
1440 {
1441 	struct fcp_port	*pptr;
1442 	struct	device_data	*dev_data;
1443 	uint32_t		link_cnt;
1444 	la_wwn_t		*wwn_ptr = NULL;
1445 	struct fcp_tgt		*ptgt = NULL;
1446 	struct fcp_lun		*plun = NULL;
1447 	int			i, error;
1448 	struct fcp_ioctl	fioctl;
1449 
1450 #ifdef	_MULTI_DATAMODEL
1451 	switch (ddi_model_convert_from(mode & FMODELS)) {
1452 	case DDI_MODEL_ILP32: {
1453 		struct fcp32_ioctl f32_ioctl;
1454 
1455 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1456 		    sizeof (struct fcp32_ioctl), mode)) {
1457 			return (EFAULT);
1458 		}
1459 		fioctl.fp_minor = f32_ioctl.fp_minor;
1460 		fioctl.listlen = f32_ioctl.listlen;
1461 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1462 		break;
1463 	}
1464 	case DDI_MODEL_NONE:
1465 		if (ddi_copyin((void *)data, (void *)&fioctl,
1466 		    sizeof (struct fcp_ioctl), mode)) {
1467 			return (EFAULT);
1468 		}
1469 		break;
1470 	}
1471 
1472 #else	/* _MULTI_DATAMODEL */
1473 	if (ddi_copyin((void *)data, (void *)&fioctl,
1474 	    sizeof (struct fcp_ioctl), mode)) {
1475 		return (EFAULT);
1476 	}
1477 #endif	/* _MULTI_DATAMODEL */
1478 
1479 	/*
1480 	 * Right now we can assume that the minor number matches with
1481 	 * this instance of fp. If this changes we will need to
1482 	 * revisit this logic.
1483 	 */
1484 	mutex_enter(&fcp_global_mutex);
1485 	pptr = fcp_port_head;
1486 	while (pptr) {
1487 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1488 			break;
1489 		} else {
1490 			pptr = pptr->port_next;
1491 		}
1492 	}
1493 	mutex_exit(&fcp_global_mutex);
1494 	if (pptr == NULL) {
1495 		return (ENXIO);
1496 	}
1497 	mutex_enter(&pptr->port_mutex);
1498 
1499 
1500 	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1501 	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
1502 		mutex_exit(&pptr->port_mutex);
1503 		return (ENOMEM);
1504 	}
1505 
1506 	if (ddi_copyin(fioctl.list, dev_data,
1507 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1508 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1509 		mutex_exit(&pptr->port_mutex);
1510 		return (EFAULT);
1511 	}
1512 	link_cnt = pptr->port_link_cnt;
1513 
1514 	if (cmd == FCP_TGT_INQUIRY) {
1515 		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1516 		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1517 		    sizeof (wwn_ptr->raw_wwn)) == 0) {
1518 			/* This ioctl is requesting INQ info of local HBA */
1519 			mutex_exit(&pptr->port_mutex);
1520 			dev_data[0].dev0_type = DTYPE_UNKNOWN;
1521 			dev_data[0].dev_status = 0;
1522 			if (ddi_copyout(dev_data, fioctl.list,
1523 			    (sizeof (struct device_data)) * fioctl.listlen,
1524 			    mode)) {
1525 				kmem_free(dev_data,
1526 				    sizeof (*dev_data) * fioctl.listlen);
1527 				return (EFAULT);
1528 			}
1529 			kmem_free(dev_data,
1530 			    sizeof (*dev_data) * fioctl.listlen);
1531 #ifdef	_MULTI_DATAMODEL
1532 			switch (ddi_model_convert_from(mode & FMODELS)) {
1533 			case DDI_MODEL_ILP32: {
1534 				struct fcp32_ioctl f32_ioctl;
1535 				f32_ioctl.fp_minor = fioctl.fp_minor;
1536 				f32_ioctl.listlen = fioctl.listlen;
1537 				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1538 				if (ddi_copyout((void *)&f32_ioctl,
1539 				    (void *)data,
1540 				    sizeof (struct fcp32_ioctl), mode)) {
1541 					return (EFAULT);
1542 				}
1543 				break;
1544 			}
1545 			case DDI_MODEL_NONE:
1546 				if (ddi_copyout((void *)&fioctl, (void *)data,
1547 				    sizeof (struct fcp_ioctl), mode)) {
1548 					return (EFAULT);
1549 				}
1550 				break;
1551 			}
1552 #else	/* _MULTI_DATAMODEL */
1553 			if (ddi_copyout((void *)&fioctl, (void *)data,
1554 			    sizeof (struct fcp_ioctl), mode)) {
1555 				return (EFAULT);
1556 			}
1557 #endif	/* _MULTI_DATAMODEL */
1558 			return (0);
1559 		}
1560 	}
1561 
1562 	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1563 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1564 		mutex_exit(&pptr->port_mutex);
1565 		return (ENXIO);
1566 	}
1567 
1568 	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1569 	    i++) {
1570 		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1571 
1572 		dev_data[i].dev0_type = DTYPE_UNKNOWN;
1573 
1574 
1575 		dev_data[i].dev_status = ENXIO;
1576 
1577 		if ((ptgt = fcp_lookup_target(pptr,
1578 		    (uchar_t *)wwn_ptr)) == NULL) {
1579 			mutex_exit(&pptr->port_mutex);
1580 			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1581 			    wwn_ptr, &error, 0) == NULL) {
1582 				dev_data[i].dev_status = ENODEV;
1583 				mutex_enter(&pptr->port_mutex);
1584 				continue;
1585 			} else {
1586 
1587 				dev_data[i].dev_status = EAGAIN;
1588 
1589 				mutex_enter(&pptr->port_mutex);
1590 				continue;
1591 			}
1592 		} else {
1593 			mutex_enter(&ptgt->tgt_mutex);
1594 			if (ptgt->tgt_state & (FCP_TGT_MARK |
1595 			    FCP_TGT_BUSY)) {
1596 				dev_data[i].dev_status = EAGAIN;
1597 				mutex_exit(&ptgt->tgt_mutex);
1598 				continue;
1599 			}
1600 
1601 			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1602 				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1603 					dev_data[i].dev_status = ENOTSUP;
1604 				} else {
1605 					dev_data[i].dev_status = ENXIO;
1606 				}
1607 				mutex_exit(&ptgt->tgt_mutex);
1608 				continue;
1609 			}
1610 
1611 			switch (cmd) {
1612 			case FCP_TGT_INQUIRY:
1613 				/*
1614 				 * The reason we give device type of
1615 				 * lun 0 only even though in some
1616 				 * cases(like maxstrat) lun 0 device
1617 				 * type may be 0x3f(invalid) is that
1618 				 * for bridge boxes target will appear
1619 				 * as luns and the first lun could be
1620 				 * a device that utility may not care
1621 				 * about (like a tape device).
1622 				 */
1623 				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1624 				dev_data[i].dev_status = 0;
1625 				mutex_exit(&ptgt->tgt_mutex);
1626 
1627 				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1628 					dev_data[i].dev0_type = DTYPE_UNKNOWN;
1629 				} else {
1630 					dev_data[i].dev0_type = plun->lun_type;
1631 				}
1632 				mutex_enter(&ptgt->tgt_mutex);
1633 				break;
1634 
1635 			case FCP_TGT_CREATE:
1636 				mutex_exit(&ptgt->tgt_mutex);
1637 				mutex_exit(&pptr->port_mutex);
1638 
1639 				/*
1640 				 * serialize state change call backs.
1641 				 * only one call back will be handled
1642 				 * at a time.
1643 				 */
1644 				mutex_enter(&fcp_global_mutex);
1645 				if (fcp_oflag & FCP_BUSY) {
1646 					mutex_exit(&fcp_global_mutex);
1647 					if (dev_data) {
1648 						kmem_free(dev_data,
1649 						    sizeof (*dev_data) *
1650 						    fioctl.listlen);
1651 					}
1652 					return (EBUSY);
1653 				}
1654 				fcp_oflag |= FCP_BUSY;
1655 				mutex_exit(&fcp_global_mutex);
1656 
1657 				dev_data[i].dev_status =
1658 				    fcp_create_on_demand(pptr,
1659 				    wwn_ptr->raw_wwn);
1660 
1661 				if (dev_data[i].dev_status != 0) {
1662 					char	buf[25];
1663 
1664 					for (i = 0; i < FC_WWN_SIZE; i++) {
1665 						(void) sprintf(&buf[i << 1],
1666 						    "%02x",
1667 						    wwn_ptr->raw_wwn[i]);
1668 					}
1669 
1670 					fcp_log(CE_WARN, pptr->port_dip,
1671 					    "!Failed to create nodes for"
1672 					    " pwwn=%s; error=%x", buf,
1673 					    dev_data[i].dev_status);
1674 				}
1675 
1676 				/* allow state change call backs again */
1677 				mutex_enter(&fcp_global_mutex);
1678 				fcp_oflag &= ~FCP_BUSY;
1679 				mutex_exit(&fcp_global_mutex);
1680 
1681 				mutex_enter(&pptr->port_mutex);
1682 				mutex_enter(&ptgt->tgt_mutex);
1683 
1684 				break;
1685 
1686 			case FCP_TGT_DELETE:
1687 				break;
1688 
1689 			default:
1690 				fcp_log(CE_WARN, pptr->port_dip,
1691 				    "!Invalid device data ioctl "
1692 				    "opcode = 0x%x", cmd);
1693 			}
1694 			mutex_exit(&ptgt->tgt_mutex);
1695 		}
1696 	}
1697 	mutex_exit(&pptr->port_mutex);
1698 
1699 	if (ddi_copyout(dev_data, fioctl.list,
1700 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1701 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1702 		return (EFAULT);
1703 	}
1704 	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1705 
1706 #ifdef	_MULTI_DATAMODEL
1707 	switch (ddi_model_convert_from(mode & FMODELS)) {
1708 	case DDI_MODEL_ILP32: {
1709 		struct fcp32_ioctl f32_ioctl;
1710 
1711 		f32_ioctl.fp_minor = fioctl.fp_minor;
1712 		f32_ioctl.listlen = fioctl.listlen;
1713 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1714 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1715 		    sizeof (struct fcp32_ioctl), mode)) {
1716 			return (EFAULT);
1717 		}
1718 		break;
1719 	}
1720 	case DDI_MODEL_NONE:
1721 		if (ddi_copyout((void *)&fioctl, (void *)data,
1722 		    sizeof (struct fcp_ioctl), mode)) {
1723 			return (EFAULT);
1724 		}
1725 		break;
1726 	}
1727 #else	/* _MULTI_DATAMODEL */
1728 
1729 	if (ddi_copyout((void *)&fioctl, (void *)data,
1730 	    sizeof (struct fcp_ioctl), mode)) {
1731 		return (EFAULT);
1732 	}
1733 #endif	/* _MULTI_DATAMODEL */
1734 
1735 	return (0);
1736 }
1737 
1738 /*
1739  * Fetch the target mappings (path, etc.) for all LUNs
1740  * on this port.
1741  */
1742 /* ARGSUSED */
1743 static int
1744 fcp_get_target_mappings(struct fcp_ioctl *data,
1745     int mode, int *rval)
1746 {
1747 	struct fcp_port	    *pptr;
1748 	fc_hba_target_mappings_t    *mappings;
1749 	fc_hba_mapping_entry_t	    *map;
1750 	struct fcp_tgt	    *ptgt = NULL;
1751 	struct fcp_lun	    *plun = NULL;
1752 	int			    i, mapIndex, mappingSize;
1753 	int			    listlen;
1754 	struct fcp_ioctl	    fioctl;
1755 	char			    *path;
1756 	fcp_ent_addr_t		    sam_lun_addr;
1757 
1758 #ifdef	_MULTI_DATAMODEL
1759 	switch (ddi_model_convert_from(mode & FMODELS)) {
1760 	case DDI_MODEL_ILP32: {
1761 		struct fcp32_ioctl f32_ioctl;
1762 
1763 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1764 		    sizeof (struct fcp32_ioctl), mode)) {
1765 			return (EFAULT);
1766 		}
1767 		fioctl.fp_minor = f32_ioctl.fp_minor;
1768 		fioctl.listlen = f32_ioctl.listlen;
1769 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1770 		break;
1771 	}
1772 	case DDI_MODEL_NONE:
1773 		if (ddi_copyin((void *)data, (void *)&fioctl,
1774 		    sizeof (struct fcp_ioctl), mode)) {
1775 			return (EFAULT);
1776 		}
1777 		break;
1778 	}
1779 
1780 #else	/* _MULTI_DATAMODEL */
1781 	if (ddi_copyin((void *)data, (void *)&fioctl,
1782 	    sizeof (struct fcp_ioctl), mode)) {
1783 		return (EFAULT);
1784 	}
1785 #endif	/* _MULTI_DATAMODEL */
1786 
1787 	/*
1788 	 * Right now we can assume that the minor number matches with
1789 	 * this instance of fp. If this changes we will need to
1790 	 * revisit this logic.
1791 	 */
1792 	mutex_enter(&fcp_global_mutex);
1793 	pptr = fcp_port_head;
1794 	while (pptr) {
1795 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1796 			break;
1797 		} else {
1798 			pptr = pptr->port_next;
1799 		}
1800 	}
1801 	mutex_exit(&fcp_global_mutex);
1802 	if (pptr == NULL) {
1803 		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1804 		    fioctl.fp_minor);
1805 		return (ENXIO);
1806 	}
1807 
1808 
1809 	/* We use listlen to show the total buffer size */
1810 	mappingSize = fioctl.listlen;
1811 
1812 	/* Now calculate how many mapping entries will fit */
1813 	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1814 	    - sizeof (fc_hba_target_mappings_t);
1815 	if (listlen <= 0) {
1816 		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1817 		return (ENXIO);
1818 	}
1819 	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1820 
1821 	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1822 		return (ENOMEM);
1823 	}
1824 	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1825 
1826 	/* Now get to work */
1827 	mapIndex = 0;
1828 
1829 	mutex_enter(&pptr->port_mutex);
1830 	/* Loop through all targets on this port */
1831 	for (i = 0; i < FCP_NUM_HASH; i++) {
1832 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1833 		    ptgt = ptgt->tgt_next) {
1834 
1835 			mutex_enter(&ptgt->tgt_mutex);
1836 
1837 			/* Loop through all LUNs on this target */
1838 			for (plun = ptgt->tgt_lun; plun != NULL;
1839 			    plun = plun->lun_next) {
1840 				if (plun->lun_state & FCP_LUN_OFFLINE) {
1841 					continue;
1842 				}
1843 
1844 				path = fcp_get_lun_path(plun);
1845 				if (path == NULL) {
1846 					continue;
1847 				}
1848 
1849 				if (mapIndex >= listlen) {
1850 					mapIndex ++;
1851 					kmem_free(path, MAXPATHLEN);
1852 					continue;
1853 				}
1854 				map = &mappings->entries[mapIndex++];
1855 				bcopy(path, map->targetDriver,
1856 				    sizeof (map->targetDriver));
1857 				map->d_id = ptgt->tgt_d_id;
1858 				map->busNumber = 0;
1859 				map->targetNumber = ptgt->tgt_d_id;
1860 				map->osLUN = plun->lun_num;
1861 
1862 				/*
1863 				 * We had swapped lun when we stored it in
1864 				 * lun_addr. We need to swap it back before
1865 				 * returning it to user land
1866 				 */
1867 
1868 				sam_lun_addr.ent_addr_0 =
1869 				    BE_16(plun->lun_addr.ent_addr_0);
1870 				sam_lun_addr.ent_addr_1 =
1871 				    BE_16(plun->lun_addr.ent_addr_1);
1872 				sam_lun_addr.ent_addr_2 =
1873 				    BE_16(plun->lun_addr.ent_addr_2);
1874 				sam_lun_addr.ent_addr_3 =
1875 				    BE_16(plun->lun_addr.ent_addr_3);
1876 
1877 				bcopy(&sam_lun_addr, &map->samLUN,
1878 				    FCP_LUN_SIZE);
1879 				bcopy(ptgt->tgt_node_wwn.raw_wwn,
1880 				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1881 				bcopy(ptgt->tgt_port_wwn.raw_wwn,
1882 				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1883 
1884 				if (plun->lun_guid) {
1885 
1886 					/* convert ascii wwn to bytes */
1887 					fcp_ascii_to_wwn(plun->lun_guid,
1888 					    map->guid, sizeof (map->guid));
1889 
1890 					if ((sizeof (map->guid)) <
1891 					    plun->lun_guid_size / 2) {
1892 						cmn_err(CE_WARN,
1893 						    "fcp_get_target_mappings:"
1894 						    "guid copy space "
1895 						    "insufficient."
1896 						    "Copy Truncation - "
1897 						    "available %d; need %d",
1898 						    (int)sizeof (map->guid),
1899 						    (int)
1900 						    plun->lun_guid_size / 2);
1901 					}
1902 				}
1903 				kmem_free(path, MAXPATHLEN);
1904 			}
1905 			mutex_exit(&ptgt->tgt_mutex);
1906 		}
1907 	}
1908 	mutex_exit(&pptr->port_mutex);
1909 	mappings->numLuns = mapIndex;
1910 
1911 	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1912 		kmem_free(mappings, mappingSize);
1913 		return (EFAULT);
1914 	}
1915 	kmem_free(mappings, mappingSize);
1916 
1917 #ifdef	_MULTI_DATAMODEL
1918 	switch (ddi_model_convert_from(mode & FMODELS)) {
1919 	case DDI_MODEL_ILP32: {
1920 		struct fcp32_ioctl f32_ioctl;
1921 
1922 		f32_ioctl.fp_minor = fioctl.fp_minor;
1923 		f32_ioctl.listlen = fioctl.listlen;
1924 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1925 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1926 		    sizeof (struct fcp32_ioctl), mode)) {
1927 			return (EFAULT);
1928 		}
1929 		break;
1930 	}
1931 	case DDI_MODEL_NONE:
1932 		if (ddi_copyout((void *)&fioctl, (void *)data,
1933 		    sizeof (struct fcp_ioctl), mode)) {
1934 			return (EFAULT);
1935 		}
1936 		break;
1937 	}
1938 #else	/* _MULTI_DATAMODEL */
1939 
1940 	if (ddi_copyout((void *)&fioctl, (void *)data,
1941 	    sizeof (struct fcp_ioctl), mode)) {
1942 		return (EFAULT);
1943 	}
1944 #endif	/* _MULTI_DATAMODEL */
1945 
1946 	return (0);
1947 }
1948 
1949 /*
1950  * fcp_setup_scsi_ioctl
1951  *	Setup handler for the "scsi passthru" style of
1952  *	ioctl for FCP.	See "fcp_util.h" for data structure
1953  *	definition.
1954  *
1955  * Input:
1956  *	u_fscsi	= ioctl data (user address space)
1957  *	mode	= See ioctl(9E)
1958  *
1959  * Output:
1960  *	u_fscsi	= ioctl data (user address space)
1961  *	rval	= return value - see ioctl(9E)
1962  *
1963  * Returns:
1964  *	0	= OK
1965  *	EAGAIN	= See errno.h
1966  *	EBUSY	= See errno.h
1967  *	EFAULT	= See errno.h
1968  *	EINTR	= See errno.h
1969  *	EINVAL	= See errno.h
1970  *	EIO	= See errno.h
1971  *	ENOMEM	= See errno.h
1972  *	ENXIO	= See errno.h
1973  *
1974  * Context:
1975  *	Kernel context.
1976  */
1977 /* ARGSUSED */
1978 static int
1979 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1980     int mode, int *rval)
1981 {
1982 	int			ret		= 0;
1983 	int			temp_ret;
1984 	caddr_t			k_cdbbufaddr	= NULL;
1985 	caddr_t			k_bufaddr	= NULL;
1986 	caddr_t			k_rqbufaddr	= NULL;
1987 	caddr_t			u_cdbbufaddr;
1988 	caddr_t			u_bufaddr;
1989 	caddr_t			u_rqbufaddr;
1990 	struct fcp_scsi_cmd	k_fscsi;
1991 
1992 	/*
1993 	 * Get fcp_scsi_cmd array element from user address space
1994 	 */
1995 	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1996 	    != 0) {
1997 		return (ret);
1998 	}
1999 
2000 
2001 	/*
2002 	 * Even though kmem_alloc() checks the validity of the
2003 	 * buffer length, this check is needed when the
2004 	 * kmem_flags set and the zero buffer length is passed.
2005 	 */
2006 	if ((k_fscsi.scsi_cdblen <= 0) ||
2007 	    (k_fscsi.scsi_buflen <= 0) ||
2008 	    (k_fscsi.scsi_rqlen <= 0)) {
2009 		return (EINVAL);
2010 	}
2011 
2012 	/*
2013 	 * Allocate data for fcp_scsi_cmd pointer fields
2014 	 */
2015 	if (ret == 0) {
2016 		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2017 		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2018 		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2019 
2020 		if (k_cdbbufaddr == NULL ||
2021 		    k_bufaddr	 == NULL ||
2022 		    k_rqbufaddr	 == NULL) {
2023 			ret = ENOMEM;
2024 		}
2025 	}
2026 
2027 	/*
2028 	 * Get fcp_scsi_cmd pointer fields from user
2029 	 * address space
2030 	 */
2031 	if (ret == 0) {
2032 		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2033 		u_bufaddr    = k_fscsi.scsi_bufaddr;
2034 		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2035 
2036 		if (ddi_copyin(u_cdbbufaddr,
2037 		    k_cdbbufaddr,
2038 		    k_fscsi.scsi_cdblen,
2039 		    mode)) {
2040 			ret = EFAULT;
2041 		} else if (ddi_copyin(u_bufaddr,
2042 		    k_bufaddr,
2043 		    k_fscsi.scsi_buflen,
2044 		    mode)) {
2045 			ret = EFAULT;
2046 		} else if (ddi_copyin(u_rqbufaddr,
2047 		    k_rqbufaddr,
2048 		    k_fscsi.scsi_rqlen,
2049 		    mode)) {
2050 			ret = EFAULT;
2051 		}
2052 	}
2053 
2054 	/*
2055 	 * Send scsi command (blocking)
2056 	 */
2057 	if (ret == 0) {
2058 		/*
2059 		 * Prior to sending the scsi command, the
2060 		 * fcp_scsi_cmd data structure must contain kernel,
2061 		 * not user, addresses.
2062 		 */
2063 		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
2064 		k_fscsi.scsi_bufaddr	= k_bufaddr;
2065 		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
2066 
2067 		ret = fcp_send_scsi_ioctl(&k_fscsi);
2068 
2069 		/*
2070 		 * After sending the scsi command, the
2071 		 * fcp_scsi_cmd data structure must contain user,
2072 		 * not kernel, addresses.
2073 		 */
2074 		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
2075 		k_fscsi.scsi_bufaddr	= u_bufaddr;
2076 		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
2077 	}
2078 
2079 	/*
2080 	 * Put fcp_scsi_cmd pointer fields to user address space
2081 	 */
2082 	if (ret == 0) {
2083 		if (ddi_copyout(k_cdbbufaddr,
2084 		    u_cdbbufaddr,
2085 		    k_fscsi.scsi_cdblen,
2086 		    mode)) {
2087 			ret = EFAULT;
2088 		} else if (ddi_copyout(k_bufaddr,
2089 		    u_bufaddr,
2090 		    k_fscsi.scsi_buflen,
2091 		    mode)) {
2092 			ret = EFAULT;
2093 		} else if (ddi_copyout(k_rqbufaddr,
2094 		    u_rqbufaddr,
2095 		    k_fscsi.scsi_rqlen,
2096 		    mode)) {
2097 			ret = EFAULT;
2098 		}
2099 	}
2100 
2101 	/*
2102 	 * Free data for fcp_scsi_cmd pointer fields
2103 	 */
2104 	if (k_cdbbufaddr != NULL) {
2105 		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2106 	}
2107 	if (k_bufaddr != NULL) {
2108 		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2109 	}
2110 	if (k_rqbufaddr != NULL) {
2111 		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2112 	}
2113 
2114 	/*
2115 	 * Put fcp_scsi_cmd array element to user address space
2116 	 */
2117 	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2118 	if (temp_ret != 0) {
2119 		ret = temp_ret;
2120 	}
2121 
2122 	/*
2123 	 * Return status
2124 	 */
2125 	return (ret);
2126 }
2127 
2128 
2129 /*
2130  * fcp_copyin_scsi_cmd
2131  *	Copy in fcp_scsi_cmd data structure from user address space.
2132  *	The data may be in 32 bit or 64 bit modes.
2133  *
2134  * Input:
2135  *	base_addr	= from address (user address space)
2136  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2137  *
2138  * Output:
2139  *	fscsi		= to address (kernel address space)
2140  *
2141  * Returns:
2142  *	0	= OK
2143  *	EFAULT	= Error
2144  *
2145  * Context:
2146  *	Kernel context.
2147  */
2148 static int
2149 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2150 {
2151 #ifdef	_MULTI_DATAMODEL
2152 	struct fcp32_scsi_cmd	f32scsi;
2153 
2154 	switch (ddi_model_convert_from(mode & FMODELS)) {
2155 	case DDI_MODEL_ILP32:
2156 		/*
2157 		 * Copy data from user address space
2158 		 */
2159 		if (ddi_copyin((void *)base_addr,
2160 		    &f32scsi,
2161 		    sizeof (struct fcp32_scsi_cmd),
2162 		    mode)) {
2163 			return (EFAULT);
2164 		}
2165 		/*
2166 		 * Convert from 32 bit to 64 bit
2167 		 */
2168 		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2169 		break;
2170 	case DDI_MODEL_NONE:
2171 		/*
2172 		 * Copy data from user address space
2173 		 */
2174 		if (ddi_copyin((void *)base_addr,
2175 		    fscsi,
2176 		    sizeof (struct fcp_scsi_cmd),
2177 		    mode)) {
2178 			return (EFAULT);
2179 		}
2180 		break;
2181 	}
2182 #else	/* _MULTI_DATAMODEL */
2183 	/*
2184 	 * Copy data from user address space
2185 	 */
2186 	if (ddi_copyin((void *)base_addr,
2187 	    fscsi,
2188 	    sizeof (struct fcp_scsi_cmd),
2189 	    mode)) {
2190 		return (EFAULT);
2191 	}
2192 #endif	/* _MULTI_DATAMODEL */
2193 
2194 	return (0);
2195 }
2196 
2197 
2198 /*
2199  * fcp_copyout_scsi_cmd
2200  *	Copy out fcp_scsi_cmd data structure to user address space.
2201  *	The data may be in 32 bit or 64 bit modes.
2202  *
2203  * Input:
2204  *	fscsi		= to address (kernel address space)
2205  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2206  *
2207  * Output:
2208  *	base_addr	= from address (user address space)
2209  *
2210  * Returns:
2211  *	0	= OK
2212  *	EFAULT	= Error
2213  *
2214  * Context:
2215  *	Kernel context.
2216  */
2217 static int
2218 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2219 {
2220 #ifdef	_MULTI_DATAMODEL
2221 	struct fcp32_scsi_cmd	f32scsi;
2222 
2223 	switch (ddi_model_convert_from(mode & FMODELS)) {
2224 	case DDI_MODEL_ILP32:
2225 		/*
2226 		 * Convert from 64 bit to 32 bit
2227 		 */
2228 		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2229 		/*
2230 		 * Copy data to user address space
2231 		 */
2232 		if (ddi_copyout(&f32scsi,
2233 		    (void *)base_addr,
2234 		    sizeof (struct fcp32_scsi_cmd),
2235 		    mode)) {
2236 			return (EFAULT);
2237 		}
2238 		break;
2239 	case DDI_MODEL_NONE:
2240 		/*
2241 		 * Copy data to user address space
2242 		 */
2243 		if (ddi_copyout(fscsi,
2244 		    (void *)base_addr,
2245 		    sizeof (struct fcp_scsi_cmd),
2246 		    mode)) {
2247 			return (EFAULT);
2248 		}
2249 		break;
2250 	}
2251 #else	/* _MULTI_DATAMODEL */
2252 	/*
2253 	 * Copy data to user address space
2254 	 */
2255 	if (ddi_copyout(fscsi,
2256 	    (void *)base_addr,
2257 	    sizeof (struct fcp_scsi_cmd),
2258 	    mode)) {
2259 		return (EFAULT);
2260 	}
2261 #endif	/* _MULTI_DATAMODEL */
2262 
2263 	return (0);
2264 }
2265 
2266 
2267 /*
2268  * fcp_send_scsi_ioctl
2269  *	Sends the SCSI command in blocking mode.
2270  *
2271  * Input:
2272  *	fscsi		= SCSI command data structure
2273  *
2274  * Output:
2275  *	fscsi		= SCSI command data structure
2276  *
2277  * Returns:
2278  *	0	= OK
2279  *	EAGAIN	= See errno.h
2280  *	EBUSY	= See errno.h
2281  *	EINTR	= See errno.h
2282  *	EINVAL	= See errno.h
2283  *	EIO	= See errno.h
2284  *	ENOMEM	= See errno.h
2285  *	ENXIO	= See errno.h
2286  *
2287  * Context:
2288  *	Kernel context.
2289  */
2290 static int
2291 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2292 {
2293 	struct fcp_lun	*plun		= NULL;
2294 	struct fcp_port	*pptr		= NULL;
2295 	struct fcp_tgt	*ptgt		= NULL;
2296 	fc_packet_t		*fpkt		= NULL;
2297 	struct fcp_ipkt	*icmd		= NULL;
2298 	int			target_created	= FALSE;
2299 	fc_frame_hdr_t		*hp;
2300 	struct fcp_cmd		fcp_cmd;
2301 	struct fcp_cmd		*fcmd;
2302 	union scsi_cdb		*scsi_cdb;
2303 	la_wwn_t		*wwn_ptr;
2304 	int			nodma;
2305 	struct fcp_rsp		*rsp;
2306 	struct fcp_rsp_info	*rsp_info;
2307 	caddr_t			rsp_sense;
2308 	int			buf_len;
2309 	int			info_len;
2310 	int			sense_len;
2311 	struct scsi_extended_sense	*sense_to = NULL;
2312 	timeout_id_t		tid;
2313 	uint8_t			reconfig_lun = FALSE;
2314 	uint8_t			reconfig_pending = FALSE;
2315 	uint8_t			scsi_cmd;
2316 	int			rsp_len;
2317 	int			cmd_index;
2318 	int			fc_status;
2319 	int			pkt_state;
2320 	int			pkt_action;
2321 	int			pkt_reason;
2322 	int			ret, xport_retval = ~FC_SUCCESS;
2323 	int			lcount;
2324 	int			tcount;
2325 	int			reconfig_status;
2326 	int			port_busy = FALSE;
2327 	uchar_t			*lun_string;
2328 
2329 	/*
2330 	 * Check valid SCSI command
2331 	 */
2332 	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2333 	ret = EINVAL;
2334 	for (cmd_index = 0;
2335 	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2336 	    ret != 0;
2337 	    cmd_index++) {
2338 		/*
2339 		 * First byte of CDB is the SCSI command
2340 		 */
2341 		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2342 			ret = 0;
2343 		}
2344 	}
2345 
2346 	/*
2347 	 * Check inputs
2348 	 */
2349 	if (fscsi->scsi_flags != FCP_SCSI_READ) {
2350 		ret = EINVAL;
2351 	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2352 		/* no larger than */
2353 		ret = EINVAL;
2354 	}
2355 
2356 
2357 	/*
2358 	 * Find FC port
2359 	 */
2360 	if (ret == 0) {
2361 		/*
2362 		 * Acquire global mutex
2363 		 */
2364 		mutex_enter(&fcp_global_mutex);
2365 
2366 		pptr = fcp_port_head;
2367 		while (pptr) {
2368 			if (pptr->port_instance ==
2369 			    (uint32_t)fscsi->scsi_fc_port_num) {
2370 				break;
2371 			} else {
2372 				pptr = pptr->port_next;
2373 			}
2374 		}
2375 
2376 		if (pptr == NULL) {
2377 			ret = ENXIO;
2378 		} else {
2379 			/*
2380 			 * fc_ulp_busy_port can raise power
2381 			 *  so, we must not hold any mutexes involved in PM
2382 			 */
2383 			mutex_exit(&fcp_global_mutex);
2384 			ret = fc_ulp_busy_port(pptr->port_fp_handle);
2385 		}
2386 
2387 		if (ret == 0) {
2388 
2389 			/* remember port is busy, so we will release later */
2390 			port_busy = TRUE;
2391 
2392 			/*
2393 			 * If there is a reconfiguration in progress, wait
2394 			 * for it to complete.
2395 			 */
2396 
2397 			fcp_reconfig_wait(pptr);
2398 
2399 			/* reacquire mutexes in order */
2400 			mutex_enter(&fcp_global_mutex);
2401 			mutex_enter(&pptr->port_mutex);
2402 
2403 			/*
2404 			 * Will port accept DMA?
2405 			 */
2406 			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2407 			    ? 1 : 0;
2408 
2409 			/*
2410 			 * If init or offline, device not known
2411 			 *
2412 			 * If we are discovering (onlining), we can
2413 			 * NOT obviously provide reliable data about
2414 			 * devices until it is complete
2415 			 */
2416 			if (pptr->port_state &	  (FCP_STATE_INIT |
2417 			    FCP_STATE_OFFLINE)) {
2418 				ret = ENXIO;
2419 			} else if (pptr->port_state & FCP_STATE_ONLINING) {
2420 				ret = EBUSY;
2421 			} else {
2422 				/*
2423 				 * Find target from pwwn
2424 				 *
2425 				 * The wwn must be put into a local
2426 				 * variable to ensure alignment.
2427 				 */
2428 				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2429 				ptgt = fcp_lookup_target(pptr,
2430 				    (uchar_t *)wwn_ptr);
2431 
2432 				/*
2433 				 * If target not found,
2434 				 */
2435 				if (ptgt == NULL) {
2436 					/*
2437 					 * Note: Still have global &
2438 					 * port mutexes
2439 					 */
2440 					mutex_exit(&pptr->port_mutex);
2441 					ptgt = fcp_port_create_tgt(pptr,
2442 					    wwn_ptr, &ret, &fc_status,
2443 					    &pkt_state, &pkt_action,
2444 					    &pkt_reason);
2445 					mutex_enter(&pptr->port_mutex);
2446 
2447 					fscsi->scsi_fc_status  = fc_status;
2448 					fscsi->scsi_pkt_state  =
2449 					    (uchar_t)pkt_state;
2450 					fscsi->scsi_pkt_reason = pkt_reason;
2451 					fscsi->scsi_pkt_action =
2452 					    (uchar_t)pkt_action;
2453 
2454 					if (ptgt != NULL) {
2455 						target_created = TRUE;
2456 					} else if (ret == 0) {
2457 						ret = ENOMEM;
2458 					}
2459 				}
2460 
2461 				if (ret == 0) {
2462 					/*
2463 					 * Acquire target
2464 					 */
2465 					mutex_enter(&ptgt->tgt_mutex);
2466 
2467 					/*
2468 					 * If target is mark or busy,
2469 					 * then target can not be used
2470 					 */
2471 					if (ptgt->tgt_state &
2472 					    (FCP_TGT_MARK |
2473 					    FCP_TGT_BUSY)) {
2474 						ret = EBUSY;
2475 					} else {
2476 						/*
2477 						 * Mark target as busy
2478 						 */
2479 						ptgt->tgt_state |=
2480 						    FCP_TGT_BUSY;
2481 					}
2482 
2483 					/*
2484 					 * Release target
2485 					 */
2486 					lcount = pptr->port_link_cnt;
2487 					tcount = ptgt->tgt_change_cnt;
2488 					mutex_exit(&ptgt->tgt_mutex);
2489 				}
2490 			}
2491 
2492 			/*
2493 			 * Release port
2494 			 */
2495 			mutex_exit(&pptr->port_mutex);
2496 		}
2497 
2498 		/*
2499 		 * Release global mutex
2500 		 */
2501 		mutex_exit(&fcp_global_mutex);
2502 	}
2503 
2504 	if (ret == 0) {
2505 		uint64_t belun = BE_64(fscsi->scsi_lun);
2506 
2507 		/*
2508 		 * If it's a target device, find lun from pwwn
2509 		 * The wwn must be put into a local
2510 		 * variable to ensure alignment.
2511 		 */
2512 		mutex_enter(&pptr->port_mutex);
2513 		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2514 		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2515 			/* this is not a target */
2516 			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2517 			ret = ENXIO;
2518 		} else if ((belun << 16) != 0) {
2519 			/*
2520 			 * Since fcp only support PD and LU addressing method
2521 			 * so far, the last 6 bytes of a valid LUN are expected
2522 			 * to be filled with 00h.
2523 			 */
2524 			fscsi->scsi_fc_status = FC_INVALID_LUN;
2525 			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2526 			    " method 0x%02x with LUN number 0x%016" PRIx64,
2527 			    (uint8_t)(belun >> 62), belun);
2528 			ret = ENXIO;
2529 		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2530 		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2531 			/*
2532 			 * This is a SCSI target, but no LUN at this
2533 			 * address.
2534 			 *
2535 			 * In the future, we may want to send this to
2536 			 * the target, and let it respond
2537 			 * appropriately
2538 			 */
2539 			ret = ENXIO;
2540 		}
2541 		mutex_exit(&pptr->port_mutex);
2542 	}
2543 
2544 	/*
2545 	 * Finished grabbing external resources
2546 	 * Allocate internal packet (icmd)
2547 	 */
2548 	if (ret == 0) {
2549 		/*
2550 		 * Calc rsp len assuming rsp info included
2551 		 */
2552 		rsp_len = sizeof (struct fcp_rsp) +
2553 		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2554 
2555 		icmd = fcp_icmd_alloc(pptr, ptgt,
2556 		    sizeof (struct fcp_cmd),
2557 		    rsp_len,
2558 		    fscsi->scsi_buflen,
2559 		    nodma,
2560 		    lcount,			/* ipkt_link_cnt */
2561 		    tcount,			/* ipkt_change_cnt */
2562 		    0,				/* cause */
2563 		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
2564 
2565 		if (icmd == NULL) {
2566 			ret = ENOMEM;
2567 		} else {
2568 			/*
2569 			 * Setup internal packet as sema sync
2570 			 */
2571 			fcp_ipkt_sema_init(icmd);
2572 		}
2573 	}
2574 
2575 	if (ret == 0) {
2576 		/*
2577 		 * Init fpkt pointer for use.
2578 		 */
2579 
2580 		fpkt = icmd->ipkt_fpkt;
2581 
2582 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
2583 		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
2584 		fpkt->pkt_timeout	= fscsi->scsi_timeout;
2585 
2586 		/*
2587 		 * Init fcmd pointer for use by SCSI command
2588 		 */
2589 
2590 		if (nodma) {
2591 			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2592 		} else {
2593 			fcmd = &fcp_cmd;
2594 		}
2595 		bzero(fcmd, sizeof (struct fcp_cmd));
2596 		ptgt = plun->lun_tgt;
2597 
2598 		lun_string = (uchar_t *)&fscsi->scsi_lun;
2599 
2600 		fcmd->fcp_ent_addr.ent_addr_0 =
2601 		    BE_16(*(uint16_t *)&(lun_string[0]));
2602 		fcmd->fcp_ent_addr.ent_addr_1 =
2603 		    BE_16(*(uint16_t *)&(lun_string[2]));
2604 		fcmd->fcp_ent_addr.ent_addr_2 =
2605 		    BE_16(*(uint16_t *)&(lun_string[4]));
2606 		fcmd->fcp_ent_addr.ent_addr_3 =
2607 		    BE_16(*(uint16_t *)&(lun_string[6]));
2608 
2609 		/*
2610 		 * Setup internal packet(icmd)
2611 		 */
2612 		icmd->ipkt_lun		= plun;
2613 		icmd->ipkt_restart	= 0;
2614 		icmd->ipkt_retries	= 0;
2615 		icmd->ipkt_opcode	= 0;
2616 
2617 		/*
2618 		 * Init the frame HEADER Pointer for use
2619 		 */
2620 		hp = &fpkt->pkt_cmd_fhdr;
2621 
2622 		hp->s_id	= pptr->port_id;
2623 		hp->d_id	= ptgt->tgt_d_id;
2624 		hp->r_ctl	= R_CTL_COMMAND;
2625 		hp->type	= FC_TYPE_SCSI_FCP;
2626 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2627 		hp->rsvd	= 0;
2628 		hp->seq_id	= 0;
2629 		hp->seq_cnt	= 0;
2630 		hp->ox_id	= 0xffff;
2631 		hp->rx_id	= 0xffff;
2632 		hp->ro		= 0;
2633 
2634 		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
2635 		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
2636 		fcmd->fcp_cntl.cntl_write_data	= 0;
2637 		fcmd->fcp_data_len	= fscsi->scsi_buflen;
2638 
2639 		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2640 		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2641 		    fscsi->scsi_cdblen);
2642 
2643 		if (!nodma) {
2644 			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2645 			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2646 		}
2647 
2648 		/*
2649 		 * Send SCSI command to FC transport
2650 		 */
2651 
2652 		if (ret == 0) {
2653 			mutex_enter(&ptgt->tgt_mutex);
2654 
2655 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2656 				mutex_exit(&ptgt->tgt_mutex);
2657 				fscsi->scsi_fc_status = xport_retval =
2658 				    fc_ulp_transport(pptr->port_fp_handle,
2659 				    fpkt);
2660 				if (fscsi->scsi_fc_status != FC_SUCCESS) {
2661 					ret = EIO;
2662 				}
2663 			} else {
2664 				mutex_exit(&ptgt->tgt_mutex);
2665 				ret = EBUSY;
2666 			}
2667 		}
2668 	}
2669 
2670 	/*
2671 	 * Wait for completion only if fc_ulp_transport was called and it
2672 	 * returned a success. This is the only time callback will happen.
2673 	 * Otherwise, there is no point in waiting
2674 	 */
2675 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2676 		ret = fcp_ipkt_sema_wait(icmd);
2677 	}
2678 
2679 	/*
2680 	 * Copy data to IOCTL data structures
2681 	 */
2682 	rsp = NULL;
2683 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2684 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2685 
2686 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2687 			fcp_log(CE_WARN, pptr->port_dip,
2688 			    "!SCSI command to d_id=0x%x lun=0x%x"
2689 			    " failed, Bad FCP response values:"
2690 			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2691 			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2692 			    ptgt->tgt_d_id, plun->lun_num,
2693 			    rsp->reserved_0, rsp->reserved_1,
2694 			    rsp->fcp_u.fcp_status.reserved_0,
2695 			    rsp->fcp_u.fcp_status.reserved_1,
2696 			    rsp->fcp_response_len, rsp->fcp_sense_len);
2697 
2698 			ret = EIO;
2699 		}
2700 	}
2701 
2702 	if ((ret == 0) && (rsp != NULL)) {
2703 		/*
2704 		 * Calc response lengths
2705 		 */
2706 		sense_len = 0;
2707 		info_len = 0;
2708 
2709 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
2710 			info_len = rsp->fcp_response_len;
2711 		}
2712 
2713 		rsp_info   = (struct fcp_rsp_info *)
2714 		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2715 
2716 		/*
2717 		 * Get SCSI status
2718 		 */
2719 		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2720 		/*
2721 		 * If a lun was just added or removed and the next command
2722 		 * comes through this interface, we need to capture the check
2723 		 * condition so we can discover the new topology.
2724 		 */
2725 		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2726 		    rsp->fcp_u.fcp_status.sense_len_set) {
2727 			sense_len = rsp->fcp_sense_len;
2728 			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2729 			sense_to = (struct scsi_extended_sense *)rsp_sense;
2730 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2731 			    (FCP_SENSE_NO_LUN(sense_to))) {
2732 				reconfig_lun = TRUE;
2733 			}
2734 		}
2735 
2736 		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2737 		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2738 			if (reconfig_lun == FALSE) {
2739 				reconfig_status =
2740 				    fcp_is_reconfig_needed(ptgt, fpkt);
2741 			}
2742 
2743 			if ((reconfig_lun == TRUE) ||
2744 			    (reconfig_status == TRUE)) {
2745 				mutex_enter(&ptgt->tgt_mutex);
2746 				if (ptgt->tgt_tid == NULL) {
2747 					/*
2748 					 * Either we've been notified the
2749 					 * REPORT_LUN data has changed, or
2750 					 * we've determined on our own that
2751 					 * we're out of date.  Kick off
2752 					 * rediscovery.
2753 					 */
2754 					tid = timeout(fcp_reconfigure_luns,
2755 					    (caddr_t)ptgt, drv_usectohz(1));
2756 
2757 					ptgt->tgt_tid = tid;
2758 					ptgt->tgt_state |= FCP_TGT_BUSY;
2759 					ret = EBUSY;
2760 					reconfig_pending = TRUE;
2761 				}
2762 				mutex_exit(&ptgt->tgt_mutex);
2763 			}
2764 		}
2765 
2766 		/*
2767 		 * Calc residuals and buffer lengths
2768 		 */
2769 
2770 		if (ret == 0) {
2771 			buf_len = fscsi->scsi_buflen;
2772 			fscsi->scsi_bufresid	= 0;
2773 			if (rsp->fcp_u.fcp_status.resid_under) {
2774 				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2775 					fscsi->scsi_bufresid = rsp->fcp_resid;
2776 				} else {
2777 					cmn_err(CE_WARN, "fcp: bad residue %x "
2778 					    "for txfer len %x", rsp->fcp_resid,
2779 					    fscsi->scsi_buflen);
2780 					fscsi->scsi_bufresid =
2781 					    fscsi->scsi_buflen;
2782 				}
2783 				buf_len -= fscsi->scsi_bufresid;
2784 			}
2785 			if (rsp->fcp_u.fcp_status.resid_over) {
2786 				fscsi->scsi_bufresid = -rsp->fcp_resid;
2787 			}
2788 
2789 			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
2790 			if (fscsi->scsi_rqlen < sense_len) {
2791 				sense_len = fscsi->scsi_rqlen;
2792 			}
2793 
2794 			fscsi->scsi_fc_rspcode	= 0;
2795 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
2796 				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
2797 			}
2798 			fscsi->scsi_pkt_state	= fpkt->pkt_state;
2799 			fscsi->scsi_pkt_action	= fpkt->pkt_action;
2800 			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
2801 
2802 			/*
2803 			 * Copy data and request sense
2804 			 *
2805 			 * Data must be copied by using the FCP_CP_IN macro.
2806 			 * This will ensure the proper byte order since the data
2807 			 * is being copied directly from the memory mapped
2808 			 * device register.
2809 			 *
2810 			 * The response (and request sense) will be in the
2811 			 * correct byte order.	No special copy is necessary.
2812 			 */
2813 
2814 			if (buf_len) {
2815 				FCP_CP_IN(fpkt->pkt_data,
2816 				    fscsi->scsi_bufaddr,
2817 				    fpkt->pkt_data_acc,
2818 				    buf_len);
2819 			}
2820 			bcopy((void *)rsp_sense,
2821 			    (void *)fscsi->scsi_rqbufaddr,
2822 			    sense_len);
2823 		}
2824 	}
2825 
2826 	/*
2827 	 * Cleanup transport data structures if icmd was alloc-ed
2828 	 * So, cleanup happens in the same thread that icmd was alloc-ed
2829 	 */
2830 	if (icmd != NULL) {
2831 		fcp_ipkt_sema_cleanup(icmd);
2832 	}
2833 
2834 	/* restore pm busy/idle status */
2835 	if (port_busy) {
2836 		fc_ulp_idle_port(pptr->port_fp_handle);
2837 	}
2838 
2839 	/*
2840 	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2841 	 * flag, it'll be cleared when the reconfig is complete.
2842 	 */
2843 	if ((ptgt != NULL) && !reconfig_pending) {
2844 		/*
2845 		 * If target was created,
2846 		 */
2847 		if (target_created) {
2848 			mutex_enter(&ptgt->tgt_mutex);
2849 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2850 			mutex_exit(&ptgt->tgt_mutex);
2851 		} else {
2852 			/*
2853 			 * De-mark target as busy
2854 			 */
2855 			mutex_enter(&ptgt->tgt_mutex);
2856 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2857 			mutex_exit(&ptgt->tgt_mutex);
2858 		}
2859 	}
2860 	return (ret);
2861 }
2862 
2863 
2864 static int
2865 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2866     fc_packet_t	*fpkt)
2867 {
2868 	uchar_t			*lun_string;
2869 	uint16_t		lun_num, i;
2870 	int			num_luns;
2871 	int			actual_luns;
2872 	int			num_masked_luns;
2873 	int			lun_buflen;
2874 	struct fcp_lun	*plun	= NULL;
2875 	struct fcp_reportlun_resp	*report_lun;
2876 	uint8_t			reconfig_needed = FALSE;
2877 	uint8_t			lun_exists = FALSE;
2878 	fcp_port_t			*pptr		 = ptgt->tgt_port;
2879 
2880 	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2881 
2882 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2883 	    fpkt->pkt_datalen);
2884 
2885 	/* get number of luns (which is supplied as LUNS * 8) */
2886 	num_luns = BE_32(report_lun->num_lun) >> 3;
2887 
2888 	/*
2889 	 * Figure out exactly how many lun strings our response buffer
2890 	 * can hold.
2891 	 */
2892 	lun_buflen = (fpkt->pkt_datalen -
2893 	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
2894 
2895 	/*
2896 	 * Is our response buffer full or not? We don't want to
2897 	 * potentially walk beyond the number of luns we have.
2898 	 */
2899 	if (num_luns <= lun_buflen) {
2900 		actual_luns = num_luns;
2901 	} else {
2902 		actual_luns = lun_buflen;
2903 	}
2904 
2905 	mutex_enter(&ptgt->tgt_mutex);
2906 
2907 	/* Scan each lun to see if we have masked it. */
2908 	num_masked_luns = 0;
2909 	if (fcp_lun_blacklist != NULL) {
2910 		for (i = 0; i < actual_luns; i++) {
2911 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2912 			switch (lun_string[0] & 0xC0) {
2913 			case FCP_LUN_ADDRESSING:
2914 			case FCP_PD_ADDRESSING:
2915 			case FCP_VOLUME_ADDRESSING:
2916 				lun_num = ((lun_string[0] & 0x3F) << 8)
2917 				    | lun_string[1];
2918 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
2919 				    lun_num) == TRUE) {
2920 					num_masked_luns++;
2921 				}
2922 				break;
2923 			default:
2924 				break;
2925 			}
2926 		}
2927 	}
2928 
2929 	/*
2930 	 * The quick and easy check.  If the number of LUNs reported
2931 	 * doesn't match the number we currently know about, we need
2932 	 * to reconfigure.
2933 	 */
2934 	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2935 		mutex_exit(&ptgt->tgt_mutex);
2936 		kmem_free(report_lun, fpkt->pkt_datalen);
2937 		return (TRUE);
2938 	}
2939 
2940 	/*
2941 	 * If the quick and easy check doesn't turn up anything, we walk
2942 	 * the list of luns from the REPORT_LUN response and look for
2943 	 * any luns we don't know about.  If we find one, we know we need
2944 	 * to reconfigure. We will skip LUNs that are masked because of the
2945 	 * blacklist.
2946 	 */
2947 	for (i = 0; i < actual_luns; i++) {
2948 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2949 		lun_exists = FALSE;
2950 		switch (lun_string[0] & 0xC0) {
2951 		case FCP_LUN_ADDRESSING:
2952 		case FCP_PD_ADDRESSING:
2953 		case FCP_VOLUME_ADDRESSING:
2954 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2955 
2956 			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2957 			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2958 				lun_exists = TRUE;
2959 				break;
2960 			}
2961 
2962 			for (plun = ptgt->tgt_lun; plun;
2963 			    plun = plun->lun_next) {
2964 				if (plun->lun_num == lun_num) {
2965 					lun_exists = TRUE;
2966 					break;
2967 				}
2968 			}
2969 			break;
2970 		default:
2971 			break;
2972 		}
2973 
2974 		if (lun_exists == FALSE) {
2975 			reconfig_needed = TRUE;
2976 			break;
2977 		}
2978 	}
2979 
2980 	mutex_exit(&ptgt->tgt_mutex);
2981 	kmem_free(report_lun, fpkt->pkt_datalen);
2982 
2983 	return (reconfig_needed);
2984 }
2985 
2986 /*
2987  * This function is called by fcp_handle_page83 and uses inquiry response data
2988  * stored in plun->lun_inq to determine whether or not a device is a member of
2989  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2990  * otherwise 1.
2991  */
2992 static int
2993 fcp_symmetric_device_probe(struct fcp_lun *plun)
2994 {
2995 	struct scsi_inquiry	*stdinq = &plun->lun_inq;
2996 	char			*devidptr;
2997 	int			i, len;
2998 
2999 	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
3000 		devidptr = fcp_symmetric_disk_table[i];
3001 		len = (int)strlen(devidptr);
3002 
3003 		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3004 			return (0);
3005 		}
3006 	}
3007 	return (1);
3008 }
3009 
3010 
3011 /*
3012  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3013  * It basically returns the current count of # of state change callbacks
3014  * i.e the value of tgt_change_cnt.
3015  *
3016  * INPUT:
3017  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3018  *   fcp_ioctl.listlen	-> 1
3019  *   fcp_ioctl.list	-> Pointer to a 32 bit integer
3020  */
3021 /*ARGSUSED2*/
3022 static int
3023 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3024 {
3025 	int			ret;
3026 	uint32_t		link_cnt;
3027 	struct fcp_ioctl	fioctl;
3028 	struct fcp_port	*pptr = NULL;
3029 
3030 	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3031 	    &pptr)) != 0) {
3032 		return (ret);
3033 	}
3034 
3035 	ASSERT(pptr != NULL);
3036 
3037 	if (fioctl.listlen != 1) {
3038 		return (EINVAL);
3039 	}
3040 
3041 	mutex_enter(&pptr->port_mutex);
3042 	if (pptr->port_state & FCP_STATE_OFFLINE) {
3043 		mutex_exit(&pptr->port_mutex);
3044 		return (ENXIO);
3045 	}
3046 
3047 	/*
3048 	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3049 	 * When the fcp initially attaches to the port and there are nothing
3050 	 * hanging out of the port or if there was a repeat offline state change
3051 	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3052 	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3053 	 * will differentiate the 2 cases.
3054 	 */
3055 	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3056 		mutex_exit(&pptr->port_mutex);
3057 		return (ENXIO);
3058 	}
3059 
3060 	link_cnt = pptr->port_link_cnt;
3061 	mutex_exit(&pptr->port_mutex);
3062 
3063 	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3064 		return (EFAULT);
3065 	}
3066 
3067 #ifdef	_MULTI_DATAMODEL
3068 	switch (ddi_model_convert_from(mode & FMODELS)) {
3069 	case DDI_MODEL_ILP32: {
3070 		struct fcp32_ioctl f32_ioctl;
3071 
3072 		f32_ioctl.fp_minor = fioctl.fp_minor;
3073 		f32_ioctl.listlen = fioctl.listlen;
3074 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3075 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3076 		    sizeof (struct fcp32_ioctl), mode)) {
3077 			return (EFAULT);
3078 		}
3079 		break;
3080 	}
3081 	case DDI_MODEL_NONE:
3082 		if (ddi_copyout((void *)&fioctl, (void *)data,
3083 		    sizeof (struct fcp_ioctl), mode)) {
3084 			return (EFAULT);
3085 		}
3086 		break;
3087 	}
3088 #else	/* _MULTI_DATAMODEL */
3089 
3090 	if (ddi_copyout((void *)&fioctl, (void *)data,
3091 	    sizeof (struct fcp_ioctl), mode)) {
3092 		return (EFAULT);
3093 	}
3094 #endif	/* _MULTI_DATAMODEL */
3095 
3096 	return (0);
3097 }
3098 
3099 /*
3100  * This function copies the fcp_ioctl structure passed in from user land
3101  * into kernel land. Handles 32 bit applications.
3102  */
3103 /*ARGSUSED*/
3104 static int
3105 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3106     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3107 {
3108 	struct fcp_port	*t_pptr;
3109 
3110 #ifdef	_MULTI_DATAMODEL
3111 	switch (ddi_model_convert_from(mode & FMODELS)) {
3112 	case DDI_MODEL_ILP32: {
3113 		struct fcp32_ioctl f32_ioctl;
3114 
3115 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3116 		    sizeof (struct fcp32_ioctl), mode)) {
3117 			return (EFAULT);
3118 		}
3119 		fioctl->fp_minor = f32_ioctl.fp_minor;
3120 		fioctl->listlen = f32_ioctl.listlen;
3121 		fioctl->list = (caddr_t)(long)f32_ioctl.list;
3122 		break;
3123 	}
3124 	case DDI_MODEL_NONE:
3125 		if (ddi_copyin((void *)data, (void *)fioctl,
3126 		    sizeof (struct fcp_ioctl), mode)) {
3127 			return (EFAULT);
3128 		}
3129 		break;
3130 	}
3131 
3132 #else	/* _MULTI_DATAMODEL */
3133 	if (ddi_copyin((void *)data, (void *)fioctl,
3134 	    sizeof (struct fcp_ioctl), mode)) {
3135 		return (EFAULT);
3136 	}
3137 #endif	/* _MULTI_DATAMODEL */
3138 
3139 	/*
3140 	 * Right now we can assume that the minor number matches with
3141 	 * this instance of fp. If this changes we will need to
3142 	 * revisit this logic.
3143 	 */
3144 	mutex_enter(&fcp_global_mutex);
3145 	t_pptr = fcp_port_head;
3146 	while (t_pptr) {
3147 		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3148 			break;
3149 		} else {
3150 			t_pptr = t_pptr->port_next;
3151 		}
3152 	}
3153 	*pptr = t_pptr;
3154 	mutex_exit(&fcp_global_mutex);
3155 	if (t_pptr == NULL) {
3156 		return (ENXIO);
3157 	}
3158 
3159 	return (0);
3160 }
3161 
3162 /*
3163  *     Function: fcp_port_create_tgt
3164  *
3165  *  Description: As the name suggest this function creates the target context
3166  *		 specified by the the WWN provided by the caller.  If the
3167  *		 creation goes well and the target is known by fp/fctl a PLOGI
3168  *		 followed by a PRLI are issued.
3169  *
3170  *     Argument: pptr		fcp port structure
3171  *		 pwwn		WWN of the target
3172  *		 ret_val	Address of the return code.  It could be:
3173  *				EIO, ENOMEM or 0.
3174  *		 fc_status	PLOGI or PRLI status completion
3175  *		 fc_pkt_state	PLOGI or PRLI state completion
3176  *		 fc_pkt_reason	PLOGI or PRLI reason completion
3177  *		 fc_pkt_action	PLOGI or PRLI action completion
3178  *
3179  * Return Value: NULL if it failed
3180  *		 Target structure address if it succeeds
3181  */
3182 static struct fcp_tgt *
3183 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3184     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3185 {
3186 	struct fcp_tgt	*ptgt = NULL;
3187 	fc_portmap_t		devlist;
3188 	int			lcount;
3189 	int			error;
3190 
3191 	*ret_val = 0;
3192 
3193 	/*
3194 	 * Check FC port device & get port map
3195 	 */
3196 	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3197 	    &error, 1) == NULL) {
3198 		*ret_val = EIO;
3199 	} else {
3200 		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3201 		    &devlist) != FC_SUCCESS) {
3202 			*ret_val = EIO;
3203 		}
3204 	}
3205 
3206 	/* Set port map flags */
3207 	devlist.map_type = PORT_DEVICE_USER_CREATE;
3208 
3209 	/* Allocate target */
3210 	if (*ret_val == 0) {
3211 		lcount = pptr->port_link_cnt;
3212 		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3213 		if (ptgt == NULL) {
3214 			fcp_log(CE_WARN, pptr->port_dip,
3215 			    "!FC target allocation failed");
3216 			*ret_val = ENOMEM;
3217 		} else {
3218 			/* Setup target */
3219 			mutex_enter(&ptgt->tgt_mutex);
3220 
3221 			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
3222 			ptgt->tgt_tmp_cnt	= 1;
3223 			ptgt->tgt_d_id		= devlist.map_did.port_id;
3224 			ptgt->tgt_hard_addr	=
3225 			    devlist.map_hard_addr.hard_addr;
3226 			ptgt->tgt_pd_handle	= devlist.map_pd;
3227 			ptgt->tgt_fca_dev	= NULL;
3228 
3229 			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3230 			    FC_WWN_SIZE);
3231 			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3232 			    FC_WWN_SIZE);
3233 
3234 			mutex_exit(&ptgt->tgt_mutex);
3235 		}
3236 	}
3237 
3238 	/* Release global mutex for PLOGI and PRLI */
3239 	mutex_exit(&fcp_global_mutex);
3240 
3241 	/* Send PLOGI (If necessary) */
3242 	if (*ret_val == 0) {
3243 		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3244 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3245 	}
3246 
3247 	/* Send PRLI (If necessary) */
3248 	if (*ret_val == 0) {
3249 		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3250 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3251 	}
3252 
3253 	mutex_enter(&fcp_global_mutex);
3254 
3255 	return (ptgt);
3256 }
3257 
3258 /*
3259  *     Function: fcp_tgt_send_plogi
3260  *
3261  *  Description: This function sends a PLOGI to the target specified by the
3262  *		 caller and waits till it completes.
3263  *
3264  *     Argument: ptgt		Target to send the plogi to.
3265  *		 fc_status	Status returned by fp/fctl in the PLOGI request.
3266  *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
3267  *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
3268  *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
3269  *
3270  * Return Value: 0
3271  *		 ENOMEM
3272  *		 EIO
3273  *
3274  *	Context: User context.
3275  */
3276 static int
3277 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3278     int *fc_pkt_reason, int *fc_pkt_action)
3279 {
3280 	struct fcp_port	*pptr;
3281 	struct fcp_ipkt	*icmd;
3282 	struct fc_packet	*fpkt;
3283 	fc_frame_hdr_t		*hp;
3284 	struct la_els_logi	logi;
3285 	int			tcount;
3286 	int			lcount;
3287 	int			ret, login_retval = ~FC_SUCCESS;
3288 
3289 	ret = 0;
3290 
3291 	pptr = ptgt->tgt_port;
3292 
3293 	lcount = pptr->port_link_cnt;
3294 	tcount = ptgt->tgt_change_cnt;
3295 
3296 	/* Alloc internal packet */
3297 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3298 	    sizeof (la_els_logi_t), 0,
3299 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3300 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3301 
3302 	if (icmd == NULL) {
3303 		ret = ENOMEM;
3304 	} else {
3305 		/*
3306 		 * Setup internal packet as sema sync
3307 		 */
3308 		fcp_ipkt_sema_init(icmd);
3309 
3310 		/*
3311 		 * Setup internal packet (icmd)
3312 		 */
3313 		icmd->ipkt_lun		= NULL;
3314 		icmd->ipkt_restart	= 0;
3315 		icmd->ipkt_retries	= 0;
3316 		icmd->ipkt_opcode	= LA_ELS_PLOGI;
3317 
3318 		/*
3319 		 * Setup fc_packet
3320 		 */
3321 		fpkt = icmd->ipkt_fpkt;
3322 
3323 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
3324 		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
3325 		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
3326 
3327 		/*
3328 		 * Setup FC frame header
3329 		 */
3330 		hp = &fpkt->pkt_cmd_fhdr;
3331 
3332 		hp->s_id	= pptr->port_id;	/* source ID */
3333 		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
3334 		hp->r_ctl	= R_CTL_ELS_REQ;
3335 		hp->type	= FC_TYPE_EXTENDED_LS;
3336 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3337 		hp->seq_id	= 0;
3338 		hp->rsvd	= 0;
3339 		hp->df_ctl	= 0;
3340 		hp->seq_cnt	= 0;
3341 		hp->ox_id	= 0xffff;		/* i.e. none */
3342 		hp->rx_id	= 0xffff;		/* i.e. none */
3343 		hp->ro		= 0;
3344 
3345 		/*
3346 		 * Setup PLOGI
3347 		 */
3348 		bzero(&logi, sizeof (struct la_els_logi));
3349 		logi.ls_code.ls_code = LA_ELS_PLOGI;
3350 
3351 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3352 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3353 
3354 		/*
3355 		 * Send PLOGI
3356 		 */
3357 		*fc_status = login_retval =
3358 		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3359 		if (*fc_status != FC_SUCCESS) {
3360 			ret = EIO;
3361 		}
3362 	}
3363 
3364 	/*
3365 	 * Wait for completion
3366 	 */
3367 	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3368 		ret = fcp_ipkt_sema_wait(icmd);
3369 
3370 		*fc_pkt_state	= fpkt->pkt_state;
3371 		*fc_pkt_reason	= fpkt->pkt_reason;
3372 		*fc_pkt_action	= fpkt->pkt_action;
3373 	}
3374 
3375 	/*
3376 	 * Cleanup transport data structures if icmd was alloc-ed AND if there
3377 	 * is going to be no callback (i.e if fc_ulp_login() failed).
3378 	 * Otherwise, cleanup happens in callback routine.
3379 	 */
3380 	if (icmd != NULL) {
3381 		fcp_ipkt_sema_cleanup(icmd);
3382 	}
3383 
3384 	return (ret);
3385 }
3386 
3387 /*
3388  *     Function: fcp_tgt_send_prli
3389  *
3390  *  Description: Does nothing as of today.
3391  *
3392  *     Argument: ptgt		Target to send the prli to.
3393  *		 fc_status	Status returned by fp/fctl in the PRLI request.
3394  *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
3395  *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
3396  *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
3397  *
3398  * Return Value: 0
3399  */
3400 /*ARGSUSED*/
3401 static int
3402 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3403     int *fc_pkt_reason, int *fc_pkt_action)
3404 {
3405 	return (0);
3406 }
3407 
3408 /*
3409  *     Function: fcp_ipkt_sema_init
3410  *
3411  *  Description: Initializes the semaphore contained in the internal packet.
3412  *
3413  *     Argument: icmd	Internal packet the semaphore of which must be
3414  *			initialized.
3415  *
3416  * Return Value: None
3417  *
3418  *	Context: User context only.
3419  */
3420 static void
3421 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3422 {
3423 	struct fc_packet	*fpkt;
3424 
3425 	fpkt = icmd->ipkt_fpkt;
3426 
3427 	/* Create semaphore for sync */
3428 	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3429 
3430 	/* Setup the completion callback */
3431 	fpkt->pkt_comp = fcp_ipkt_sema_callback;
3432 }
3433 
3434 /*
3435  *     Function: fcp_ipkt_sema_wait
3436  *
3437  *  Description: Wait on the semaphore embedded in the internal packet.	 The
3438  *		 semaphore is released in the callback.
3439  *
3440  *     Argument: icmd	Internal packet to wait on for completion.
3441  *
3442  * Return Value: 0
3443  *		 EIO
3444  *		 EBUSY
3445  *		 EAGAIN
3446  *
3447  *	Context: User context only.
3448  *
3449  * This function does a conversion between the field pkt_state of the fc_packet
3450  * embedded in the internal packet (icmd) and the code it returns.
3451  */
3452 static int
3453 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3454 {
3455 	struct fc_packet	*fpkt;
3456 	int	ret;
3457 
3458 	ret = EIO;
3459 	fpkt = icmd->ipkt_fpkt;
3460 
3461 	/*
3462 	 * Wait on semaphore
3463 	 */
3464 	sema_p(&(icmd->ipkt_sema));
3465 
3466 	/*
3467 	 * Check the status of the FC packet
3468 	 */
3469 	switch (fpkt->pkt_state) {
3470 	case FC_PKT_SUCCESS:
3471 		ret = 0;
3472 		break;
3473 	case FC_PKT_LOCAL_RJT:
3474 		switch (fpkt->pkt_reason) {
3475 		case FC_REASON_SEQ_TIMEOUT:
3476 		case FC_REASON_RX_BUF_TIMEOUT:
3477 			ret = EAGAIN;
3478 			break;
3479 		case FC_REASON_PKT_BUSY:
3480 			ret = EBUSY;
3481 			break;
3482 		}
3483 		break;
3484 	case FC_PKT_TIMEOUT:
3485 		ret = EAGAIN;
3486 		break;
3487 	case FC_PKT_LOCAL_BSY:
3488 	case FC_PKT_TRAN_BSY:
3489 	case FC_PKT_NPORT_BSY:
3490 	case FC_PKT_FABRIC_BSY:
3491 		ret = EBUSY;
3492 		break;
3493 	case FC_PKT_LS_RJT:
3494 	case FC_PKT_BA_RJT:
3495 		switch (fpkt->pkt_reason) {
3496 		case FC_REASON_LOGICAL_BSY:
3497 			ret = EBUSY;
3498 			break;
3499 		}
3500 		break;
3501 	case FC_PKT_FS_RJT:
3502 		switch (fpkt->pkt_reason) {
3503 		case FC_REASON_FS_LOGICAL_BUSY:
3504 			ret = EBUSY;
3505 			break;
3506 		}
3507 		break;
3508 	}
3509 
3510 	return (ret);
3511 }
3512 
3513 /*
3514  *     Function: fcp_ipkt_sema_callback
3515  *
3516  *  Description: Registered as the completion callback function for the FC
3517  *		 transport when the ipkt semaphore is used for sync. This will
3518  *		 cleanup the used data structures, if necessary and wake up
3519  *		 the user thread to complete the transaction.
3520  *
3521  *     Argument: fpkt	FC packet (points to the icmd)
3522  *
3523  * Return Value: None
3524  *
3525  *	Context: User context only
3526  */
3527 static void
3528 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3529 {
3530 	struct fcp_ipkt	*icmd;
3531 
3532 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3533 
3534 	/*
3535 	 * Wake up user thread
3536 	 */
3537 	sema_v(&(icmd->ipkt_sema));
3538 }
3539 
3540 /*
3541  *     Function: fcp_ipkt_sema_cleanup
3542  *
3543  *  Description: Called to cleanup (if necessary) the data structures used
3544  *		 when ipkt sema is used for sync.  This function will detect
3545  *		 whether the caller is the last thread (via counter) and
3546  *		 cleanup only if necessary.
3547  *
3548  *     Argument: icmd	Internal command packet
3549  *
3550  * Return Value: None
3551  *
3552  *	Context: User context only
3553  */
3554 static void
3555 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3556 {
3557 	struct fcp_tgt	*ptgt;
3558 	struct fcp_port	*pptr;
3559 
3560 	ptgt = icmd->ipkt_tgt;
3561 	pptr = icmd->ipkt_port;
3562 
3563 	/*
3564 	 * Acquire data structure
3565 	 */
3566 	mutex_enter(&ptgt->tgt_mutex);
3567 
3568 	/*
3569 	 * Destroy semaphore
3570 	 */
3571 	sema_destroy(&(icmd->ipkt_sema));
3572 
3573 	/*
3574 	 * Cleanup internal packet
3575 	 */
3576 	mutex_exit(&ptgt->tgt_mutex);
3577 	fcp_icmd_free(pptr, icmd);
3578 }
3579 
3580 /*
3581  *     Function: fcp_port_attach
3582  *
3583  *  Description: Called by the transport framework to resume, suspend or
3584  *		 attach a new port.
3585  *
3586  *     Argument: ulph		Port handle
3587  *		 *pinfo		Port information
3588  *		 cmd		Command
3589  *		 s_id		Port ID
3590  *
3591  * Return Value: FC_FAILURE or FC_SUCCESS
3592  */
3593 /*ARGSUSED*/
3594 static int
3595 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3596     fc_attach_cmd_t cmd, uint32_t s_id)
3597 {
3598 	int	instance;
3599 	int	res = FC_FAILURE; /* default result */
3600 
3601 	ASSERT(pinfo != NULL);
3602 
3603 	instance = ddi_get_instance(pinfo->port_dip);
3604 
3605 	switch (cmd) {
3606 	case FC_CMD_ATTACH:
3607 		/*
3608 		 * this port instance attaching for the first time (or after
3609 		 * being detached before)
3610 		 */
3611 		if (fcp_handle_port_attach(ulph, pinfo, s_id,
3612 		    instance) == DDI_SUCCESS) {
3613 			res = FC_SUCCESS;
3614 		} else {
3615 			ASSERT(ddi_get_soft_state(fcp_softstate,
3616 			    instance) == NULL);
3617 		}
3618 		break;
3619 
3620 	case FC_CMD_RESUME:
3621 	case FC_CMD_POWER_UP:
3622 		/*
3623 		 * this port instance was attached and the suspended and
3624 		 * will now be resumed
3625 		 */
3626 		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3627 		    instance) == DDI_SUCCESS) {
3628 			res = FC_SUCCESS;
3629 		}
3630 		break;
3631 
3632 	default:
3633 		/* shouldn't happen */
3634 		FCP_TRACE(fcp_logq, "fcp",
3635 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
3636 		    "port_attach: unknown cmdcommand: %d", cmd);
3637 		break;
3638 	}
3639 
3640 	/* return result */
3641 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3642 	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3643 
3644 	return (res);
3645 }
3646 
3647 
3648 /*
3649  * detach or suspend this port instance
3650  *
3651  * acquires and releases the global mutex
3652  *
3653  * acquires and releases the mutex for this port
3654  *
3655  * acquires and releases the hotplug mutex for this port
3656  */
3657 /*ARGSUSED*/
3658 static int
3659 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3660     fc_detach_cmd_t cmd)
3661 {
3662 	int			flag;
3663 	int			instance;
3664 	struct fcp_port		*pptr;
3665 
3666 	instance = ddi_get_instance(info->port_dip);
3667 	pptr = ddi_get_soft_state(fcp_softstate, instance);
3668 
3669 	switch (cmd) {
3670 	case FC_CMD_SUSPEND:
3671 		FCP_DTRACE(fcp_logq, "fcp",
3672 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3673 		    "port suspend called for port %d", instance);
3674 		flag = FCP_STATE_SUSPENDED;
3675 		break;
3676 
3677 	case FC_CMD_POWER_DOWN:
3678 		FCP_DTRACE(fcp_logq, "fcp",
3679 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3680 		    "port power down called for port %d", instance);
3681 		flag = FCP_STATE_POWER_DOWN;
3682 		break;
3683 
3684 	case FC_CMD_DETACH:
3685 		FCP_DTRACE(fcp_logq, "fcp",
3686 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3687 		    "port detach called for port %d", instance);
3688 		flag = FCP_STATE_DETACHING;
3689 		break;
3690 
3691 	default:
3692 		/* shouldn't happen */
3693 		return (FC_FAILURE);
3694 	}
3695 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3696 	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3697 
3698 	return (fcp_handle_port_detach(pptr, flag, instance));
3699 }
3700 
3701 
3702 /*
3703  * called for ioctls on the transport's devctl interface, and the transport
3704  * has passed it to us
3705  *
3706  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3707  *
3708  * return FC_SUCCESS if we decide to claim the ioctl,
3709  * else return FC_UNCLAIMED
3710  *
3711  * *rval is set iff we decide to claim the ioctl
3712  */
3713 /*ARGSUSED*/
3714 static int
3715 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3716     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3717 {
3718 	int			retval = FC_UNCLAIMED;	/* return value */
3719 	struct fcp_port		*pptr = NULL;		/* our soft state */
3720 	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
3721 	dev_info_t		*cdip;
3722 	mdi_pathinfo_t		*pip = NULL;
3723 	char			*ndi_nm;		/* NDI name */
3724 	char			*ndi_addr;		/* NDI addr */
3725 	int			is_mpxio;
3726 	boolean_t		enteredv;
3727 	int			devi_entered = 0;
3728 	clock_t			end_time;
3729 
3730 	ASSERT(rval != NULL);
3731 
3732 	FCP_DTRACE(fcp_logq, "fcp",
3733 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3734 	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3735 
3736 	/* if already claimed then forget it */
3737 	if (claimed) {
3738 		/*
3739 		 * for now, if this ioctl has already been claimed, then
3740 		 * we just ignore it
3741 		 */
3742 		return (retval);
3743 	}
3744 
3745 	/* get our port info */
3746 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
3747 		fcp_log(CE_WARN, NULL,
3748 		    "!fcp:Invalid port handle handle in ioctl");
3749 		*rval = ENXIO;
3750 		return (retval);
3751 	}
3752 	is_mpxio = pptr->port_mpxio;
3753 
3754 	switch (cmd) {
3755 	case DEVCTL_BUS_GETSTATE:
3756 	case DEVCTL_BUS_QUIESCE:
3757 	case DEVCTL_BUS_UNQUIESCE:
3758 	case DEVCTL_BUS_RESET:
3759 	case DEVCTL_BUS_RESETALL:
3760 
3761 	case DEVCTL_BUS_DEV_CREATE:
3762 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3763 			return (retval);
3764 		}
3765 		break;
3766 
3767 	case DEVCTL_DEVICE_GETSTATE:
3768 	case DEVCTL_DEVICE_OFFLINE:
3769 	case DEVCTL_DEVICE_ONLINE:
3770 	case DEVCTL_DEVICE_REMOVE:
3771 	case DEVCTL_DEVICE_RESET:
3772 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3773 			return (retval);
3774 		}
3775 
3776 		ASSERT(dcp != NULL);
3777 
3778 		/* ensure we have a name and address */
3779 		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3780 		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3781 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
3782 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
3783 			    "ioctl: can't get name (%s) or addr (%s)",
3784 			    ndi_nm ? ndi_nm : "<null ptr>",
3785 			    ndi_addr ? ndi_addr : "<null ptr>");
3786 			ndi_dc_freehdl(dcp);
3787 			return (retval);
3788 		}
3789 
3790 
3791 		/* get our child's DIP */
3792 		ASSERT(pptr != NULL);
3793 		if (is_mpxio) {
3794 			mdi_devi_enter(pptr->port_dip, &enteredv);
3795 		} else {
3796 			ndi_devi_enter(pptr->port_dip);
3797 		}
3798 		devi_entered = 1;
3799 
3800 		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3801 		    ndi_addr)) == NULL) {
3802 			/* Look for virtually enumerated devices. */
3803 			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3804 			if (pip == NULL ||
3805 			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3806 				*rval = ENXIO;
3807 				goto out;
3808 			}
3809 		}
3810 		break;
3811 
3812 	default:
3813 		*rval = ENOTTY;
3814 		return (retval);
3815 	}
3816 
3817 	/* this ioctl is ours -- process it */
3818 
3819 	retval = FC_SUCCESS;		/* just means we claim the ioctl */
3820 
3821 	/* we assume it will be a success; else we'll set error value */
3822 	*rval = 0;
3823 
3824 
3825 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3826 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3827 	    "ioctl: claiming this one");
3828 
3829 	/* handle ioctls now */
3830 	switch (cmd) {
3831 	case DEVCTL_DEVICE_GETSTATE:
3832 		ASSERT(cdip != NULL);
3833 		ASSERT(dcp != NULL);
3834 		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3835 			*rval = EFAULT;
3836 		}
3837 		break;
3838 
3839 	case DEVCTL_DEVICE_REMOVE:
3840 	case DEVCTL_DEVICE_OFFLINE: {
3841 		int			flag = 0;
3842 		int			lcount;
3843 		int			tcount;
3844 		struct fcp_pkt	*head = NULL;
3845 		struct fcp_lun	*plun;
3846 		child_info_t		*cip = CIP(cdip);
3847 		int			all = 1;
3848 		struct fcp_lun	*tplun;
3849 		struct fcp_tgt	*ptgt;
3850 
3851 		ASSERT(pptr != NULL);
3852 		ASSERT(cdip != NULL);
3853 
3854 		mutex_enter(&pptr->port_mutex);
3855 		if (pip != NULL) {
3856 			cip = CIP(pip);
3857 		}
3858 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3859 			mutex_exit(&pptr->port_mutex);
3860 			*rval = ENXIO;
3861 			break;
3862 		}
3863 
3864 		head = fcp_scan_commands(plun);
3865 		if (head != NULL) {
3866 			fcp_abort_commands(head, LUN_PORT);
3867 		}
3868 		lcount = pptr->port_link_cnt;
3869 		tcount = plun->lun_tgt->tgt_change_cnt;
3870 		mutex_exit(&pptr->port_mutex);
3871 
3872 		if (cmd == DEVCTL_DEVICE_REMOVE) {
3873 			flag = NDI_DEVI_REMOVE;
3874 		}
3875 
3876 		if (is_mpxio) {
3877 			mdi_devi_exit(pptr->port_dip, enteredv);
3878 		} else {
3879 			ndi_devi_exit(pptr->port_dip);
3880 		}
3881 		devi_entered = 0;
3882 
3883 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3884 		    FCP_OFFLINE, lcount, tcount, flag);
3885 
3886 		if (*rval != NDI_SUCCESS) {
3887 			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3888 			break;
3889 		}
3890 
3891 		fcp_update_offline_flags(plun);
3892 
3893 		ptgt = plun->lun_tgt;
3894 		mutex_enter(&ptgt->tgt_mutex);
3895 		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3896 		    tplun->lun_next) {
3897 			mutex_enter(&tplun->lun_mutex);
3898 			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3899 				all = 0;
3900 			}
3901 			mutex_exit(&tplun->lun_mutex);
3902 		}
3903 
3904 		if (all) {
3905 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3906 			/*
3907 			 * The user is unconfiguring/offlining the device.
3908 			 * If fabric and the auto configuration is set
3909 			 * then make sure the user is the only one who
3910 			 * can reconfigure the device.
3911 			 */
3912 			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3913 			    fcp_enable_auto_configuration) {
3914 				ptgt->tgt_manual_config_only = 1;
3915 			}
3916 		}
3917 		mutex_exit(&ptgt->tgt_mutex);
3918 		break;
3919 	}
3920 
3921 	case DEVCTL_DEVICE_ONLINE: {
3922 		int			lcount;
3923 		int			tcount;
3924 		struct fcp_lun	*plun;
3925 		child_info_t		*cip = CIP(cdip);
3926 
3927 		ASSERT(cdip != NULL);
3928 		ASSERT(pptr != NULL);
3929 
3930 		mutex_enter(&pptr->port_mutex);
3931 		if (pip != NULL) {
3932 			cip = CIP(pip);
3933 		}
3934 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3935 			mutex_exit(&pptr->port_mutex);
3936 			*rval = ENXIO;
3937 			break;
3938 		}
3939 		lcount = pptr->port_link_cnt;
3940 		tcount = plun->lun_tgt->tgt_change_cnt;
3941 		mutex_exit(&pptr->port_mutex);
3942 
3943 		/*
3944 		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3945 		 * to allow the device attach to occur when the device is
3946 		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3947 		 * from the scsi_probe()).
3948 		 */
3949 		mutex_enter(&LUN_TGT->tgt_mutex);
3950 		plun->lun_state |= FCP_LUN_ONLINING;
3951 		mutex_exit(&LUN_TGT->tgt_mutex);
3952 
3953 		if (is_mpxio) {
3954 			mdi_devi_exit(pptr->port_dip, enteredv);
3955 		} else {
3956 			ndi_devi_exit(pptr->port_dip);
3957 		}
3958 		devi_entered = 0;
3959 
3960 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3961 		    FCP_ONLINE, lcount, tcount, 0);
3962 
3963 		if (*rval != NDI_SUCCESS) {
3964 			/* Reset the FCP_LUN_ONLINING bit */
3965 			mutex_enter(&LUN_TGT->tgt_mutex);
3966 			plun->lun_state &= ~FCP_LUN_ONLINING;
3967 			mutex_exit(&LUN_TGT->tgt_mutex);
3968 			*rval = EIO;
3969 			break;
3970 		}
3971 		mutex_enter(&LUN_TGT->tgt_mutex);
3972 		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3973 		    FCP_LUN_ONLINING);
3974 		mutex_exit(&LUN_TGT->tgt_mutex);
3975 		break;
3976 	}
3977 
3978 	case DEVCTL_BUS_DEV_CREATE: {
3979 		uchar_t			*bytes = NULL;
3980 		uint_t			nbytes;
3981 		struct fcp_tgt		*ptgt = NULL;
3982 		struct fcp_lun		*plun = NULL;
3983 		dev_info_t		*useless_dip = NULL;
3984 
3985 		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3986 		    DEVCTL_CONSTRUCT, &useless_dip);
3987 		if (*rval != 0 || useless_dip == NULL) {
3988 			break;
3989 		}
3990 
3991 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3992 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3993 		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3994 			*rval = EINVAL;
3995 			(void) ndi_devi_free(useless_dip);
3996 			if (bytes != NULL) {
3997 				ddi_prop_free(bytes);
3998 			}
3999 			break;
4000 		}
4001 
4002 		*rval = fcp_create_on_demand(pptr, bytes);
4003 		if (*rval == 0) {
4004 			mutex_enter(&pptr->port_mutex);
4005 			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4006 			if (ptgt) {
4007 				/*
4008 				 * We now have a pointer to the target that
4009 				 * was created. Lets point to the first LUN on
4010 				 * this new target.
4011 				 */
4012 				mutex_enter(&ptgt->tgt_mutex);
4013 
4014 				plun = ptgt->tgt_lun;
4015 				/*
4016 				 * There may be stale/offline LUN entries on
4017 				 * this list (this is by design) and so we have
4018 				 * to make sure we point to the first online
4019 				 * LUN
4020 				 */
4021 				while (plun &&
4022 				    plun->lun_state & FCP_LUN_OFFLINE) {
4023 					plun = plun->lun_next;
4024 				}
4025 
4026 				mutex_exit(&ptgt->tgt_mutex);
4027 			}
4028 			mutex_exit(&pptr->port_mutex);
4029 		}
4030 
4031 		if (*rval == 0 && ptgt && plun) {
4032 			mutex_enter(&plun->lun_mutex);
4033 			/*
4034 			 * Allow up to fcp_lun_ready_retry seconds to
4035 			 * configure all the luns behind the target.
4036 			 *
4037 			 * The intent here is to allow targets with long
4038 			 * reboot/reset-recovery times to become available
4039 			 * while limiting the maximum wait time for an
4040 			 * unresponsive target.
4041 			 */
4042 			end_time = ddi_get_lbolt() +
4043 			    SEC_TO_TICK(fcp_lun_ready_retry);
4044 
4045 			while (ddi_get_lbolt() < end_time) {
4046 				retval = FC_SUCCESS;
4047 
4048 				/*
4049 				 * The new ndi interfaces for on-demand creation
4050 				 * are inflexible, Do some more work to pass on
4051 				 * a path name of some LUN (design is broken !)
4052 				 */
4053 				if (plun->lun_cip) {
4054 					if (plun->lun_mpxio == 0) {
4055 						cdip = DIP(plun->lun_cip);
4056 					} else {
4057 						cdip = mdi_pi_get_client(
4058 						    PIP(plun->lun_cip));
4059 					}
4060 					if (cdip == NULL) {
4061 						*rval = ENXIO;
4062 						break;
4063 					}
4064 
4065 					if (!i_ddi_devi_attached(cdip)) {
4066 						mutex_exit(&plun->lun_mutex);
4067 						delay(drv_usectohz(1000000));
4068 						mutex_enter(&plun->lun_mutex);
4069 					} else {
4070 						/*
4071 						 * This Lun is ready, lets
4072 						 * check the next one.
4073 						 */
4074 						mutex_exit(&plun->lun_mutex);
4075 						plun = plun->lun_next;
4076 						while (plun && (plun->lun_state
4077 						    & FCP_LUN_OFFLINE)) {
4078 							plun = plun->lun_next;
4079 						}
4080 						if (!plun) {
4081 							break;
4082 						}
4083 						mutex_enter(&plun->lun_mutex);
4084 					}
4085 				} else {
4086 					/*
4087 					 * lun_cip field for a valid lun
4088 					 * should never be NULL. Fail the
4089 					 * command.
4090 					 */
4091 					*rval = ENXIO;
4092 					break;
4093 				}
4094 			}
4095 			if (plun) {
4096 				mutex_exit(&plun->lun_mutex);
4097 			} else {
4098 				char devnm[MAXNAMELEN];
4099 				int nmlen;
4100 
4101 				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4102 				    ddi_node_name(cdip),
4103 				    ddi_get_name_addr(cdip));
4104 
4105 				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4106 				    0) {
4107 					*rval = EFAULT;
4108 				}
4109 			}
4110 		} else {
4111 			int	i;
4112 			char	buf[25];
4113 
4114 			for (i = 0; i < FC_WWN_SIZE; i++) {
4115 				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4116 			}
4117 
4118 			fcp_log(CE_WARN, pptr->port_dip,
4119 			    "!Failed to create nodes for pwwn=%s; error=%x",
4120 			    buf, *rval);
4121 		}
4122 
4123 		(void) ndi_devi_free(useless_dip);
4124 		ddi_prop_free(bytes);
4125 		break;
4126 	}
4127 
4128 	case DEVCTL_DEVICE_RESET: {
4129 		struct fcp_lun		*plun;
4130 		child_info_t		*cip = CIP(cdip);
4131 
4132 		ASSERT(cdip != NULL);
4133 		ASSERT(pptr != NULL);
4134 		mutex_enter(&pptr->port_mutex);
4135 		if (pip != NULL) {
4136 			cip = CIP(pip);
4137 		}
4138 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4139 			mutex_exit(&pptr->port_mutex);
4140 			*rval = ENXIO;
4141 			break;
4142 		}
4143 		mutex_exit(&pptr->port_mutex);
4144 
4145 		mutex_enter(&plun->lun_tgt->tgt_mutex);
4146 		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4147 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4148 
4149 			*rval = ENXIO;
4150 			break;
4151 		}
4152 
4153 		if (plun->lun_sd == NULL) {
4154 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4155 
4156 			*rval = ENXIO;
4157 			break;
4158 		}
4159 		mutex_exit(&plun->lun_tgt->tgt_mutex);
4160 
4161 		/*
4162 		 * set up ap so that fcp_reset can figure out
4163 		 * which target to reset
4164 		 */
4165 		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4166 		    RESET_TARGET) == FALSE) {
4167 			*rval = EIO;
4168 		}
4169 		break;
4170 	}
4171 
4172 	case DEVCTL_BUS_GETSTATE:
4173 		ASSERT(dcp != NULL);
4174 		ASSERT(pptr != NULL);
4175 		ASSERT(pptr->port_dip != NULL);
4176 		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4177 		    NDI_SUCCESS) {
4178 			*rval = EFAULT;
4179 		}
4180 		break;
4181 
4182 	case DEVCTL_BUS_QUIESCE:
4183 	case DEVCTL_BUS_UNQUIESCE:
4184 		*rval = ENOTSUP;
4185 		break;
4186 
4187 	case DEVCTL_BUS_RESET:
4188 	case DEVCTL_BUS_RESETALL:
4189 		ASSERT(pptr != NULL);
4190 		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4191 		break;
4192 
4193 	default:
4194 		ASSERT(dcp != NULL);
4195 		*rval = ENOTTY;
4196 		break;
4197 	}
4198 
4199 	/* all done -- clean up and return */
4200 out:	if (devi_entered) {
4201 		if (is_mpxio) {
4202 			mdi_devi_exit(pptr->port_dip, enteredv);
4203 		} else {
4204 			ndi_devi_exit(pptr->port_dip);
4205 		}
4206 	}
4207 
4208 	if (dcp != NULL) {
4209 		ndi_dc_freehdl(dcp);
4210 	}
4211 
4212 	return (retval);
4213 }
4214 
4215 
4216 /*ARGSUSED*/
4217 static int
4218 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4219     uint32_t claimed)
4220 {
4221 	uchar_t			r_ctl;
4222 	uchar_t			ls_code;
4223 	struct fcp_port	*pptr;
4224 
4225 	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4226 		return (FC_UNCLAIMED);
4227 	}
4228 
4229 	mutex_enter(&pptr->port_mutex);
4230 	if (pptr->port_state & (FCP_STATE_DETACHING |
4231 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4232 		mutex_exit(&pptr->port_mutex);
4233 		return (FC_UNCLAIMED);
4234 	}
4235 	mutex_exit(&pptr->port_mutex);
4236 
4237 	r_ctl = buf->ub_frame.r_ctl;
4238 
4239 	switch (r_ctl & R_CTL_ROUTING) {
4240 	case R_CTL_EXTENDED_SVC:
4241 		if (r_ctl == R_CTL_ELS_REQ) {
4242 			ls_code = buf->ub_buffer[0];
4243 
4244 			switch (ls_code) {
4245 			case LA_ELS_PRLI:
4246 				/*
4247 				 * We really don't care if something fails.
4248 				 * If the PRLI was not sent out, then the
4249 				 * other end will time it out.
4250 				 */
4251 				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4252 					return (FC_SUCCESS);
4253 				}
4254 				return (FC_UNCLAIMED);
4255 				/* NOTREACHED */
4256 
4257 			default:
4258 				break;
4259 			}
4260 		}
4261 		/* FALLTHROUGH */
4262 
4263 	default:
4264 		return (FC_UNCLAIMED);
4265 	}
4266 }
4267 
4268 
4269 /*ARGSUSED*/
4270 static int
4271 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4272     uint32_t claimed)
4273 {
4274 	return (FC_UNCLAIMED);
4275 }
4276 
4277 /*
4278  *     Function: fcp_statec_callback
4279  *
4280  *  Description: The purpose of this function is to handle a port state change.
4281  *		 It is called from fp/fctl and, in a few instances, internally.
4282  *
4283  *     Argument: ulph		fp/fctl port handle
4284  *		 port_handle	fcp_port structure
4285  *		 port_state	Physical state of the port
4286  *		 port_top	Topology
4287  *		 *devlist	Pointer to the first entry of a table
4288  *				containing the remote ports that can be
4289  *				reached.
4290  *		 dev_cnt	Number of entries pointed by devlist.
4291  *		 port_sid	Port ID of the local port.
4292  *
4293  * Return Value: None
4294  */
4295 /*ARGSUSED*/
4296 static void
4297 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4298     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4299     uint32_t dev_cnt, uint32_t port_sid)
4300 {
4301 	uint32_t		link_count;
4302 	int			map_len = 0;
4303 	struct fcp_port	*pptr;
4304 	fcp_map_tag_t		*map_tag = NULL;
4305 
4306 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
4307 		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4308 		return;			/* nothing to work with! */
4309 	}
4310 
4311 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4312 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
4313 	    "fcp_statec_callback: port state/dev_cnt/top ="
4314 	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4315 	    dev_cnt, port_top);
4316 
4317 	mutex_enter(&pptr->port_mutex);
4318 
4319 	/*
4320 	 * If a thread is in detach, don't do anything.
4321 	 */
4322 	if (pptr->port_state & (FCP_STATE_DETACHING |
4323 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4324 		mutex_exit(&pptr->port_mutex);
4325 		return;
4326 	}
4327 
4328 	/*
4329 	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4330 	 * init_pkt is called, it knows whether or not the target's status
4331 	 * (or pd) might be changing.
4332 	 */
4333 
4334 	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4335 		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4336 	}
4337 
4338 	/*
4339 	 * the transport doesn't allocate or probe unless being
4340 	 * asked to by either the applications or ULPs
4341 	 *
4342 	 * in cases where the port is OFFLINE at the time of port
4343 	 * attach callback and the link comes ONLINE later, for
4344 	 * easier automatic node creation (i.e. without you having to
4345 	 * go out and run the utility to perform LOGINs) the
4346 	 * following conditional is helpful
4347 	 */
4348 	pptr->port_phys_state = port_state;
4349 
4350 	if (dev_cnt) {
4351 		mutex_exit(&pptr->port_mutex);
4352 
4353 		map_len = sizeof (*map_tag) * dev_cnt;
4354 		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4355 		if (map_tag == NULL) {
4356 			fcp_log(CE_WARN, pptr->port_dip,
4357 			    "!fcp%d: failed to allocate for map tags; "
4358 			    " state change will not be processed",
4359 			    pptr->port_instance);
4360 
4361 			mutex_enter(&pptr->port_mutex);
4362 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4363 			mutex_exit(&pptr->port_mutex);
4364 
4365 			return;
4366 		}
4367 
4368 		mutex_enter(&pptr->port_mutex);
4369 	}
4370 
4371 	if (pptr->port_id != port_sid) {
4372 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4373 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4374 		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4375 		    port_sid);
4376 		/*
4377 		 * The local port changed ID. It is the first time a port ID
4378 		 * is assigned or something drastic happened.  We might have
4379 		 * been unplugged and replugged on another loop or fabric port
4380 		 * or somebody grabbed the AL_PA we had or somebody rezoned
4381 		 * the fabric we were plugged into.
4382 		 */
4383 		pptr->port_id = port_sid;
4384 	}
4385 
4386 	switch (FC_PORT_STATE_MASK(port_state)) {
4387 	case FC_STATE_OFFLINE:
4388 	case FC_STATE_RESET_REQUESTED:
4389 		/*
4390 		 * link has gone from online to offline -- just update the
4391 		 * state of this port to BUSY and MARKed to go offline
4392 		 */
4393 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4394 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4395 		    "link went offline");
4396 		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4397 			/*
4398 			 * We were offline a while ago and this one
4399 			 * seems to indicate that the loop has gone
4400 			 * dead forever.
4401 			 */
4402 			pptr->port_tmp_cnt += dev_cnt;
4403 			pptr->port_state &= ~FCP_STATE_OFFLINE;
4404 			pptr->port_state |= FCP_STATE_INIT;
4405 			link_count = pptr->port_link_cnt;
4406 			fcp_handle_devices(pptr, devlist, dev_cnt,
4407 			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4408 		} else {
4409 			pptr->port_link_cnt++;
4410 			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4411 			fcp_update_state(pptr, (FCP_LUN_BUSY |
4412 			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4413 			if (pptr->port_mpxio) {
4414 				fcp_update_mpxio_path_verifybusy(pptr);
4415 			}
4416 			pptr->port_state |= FCP_STATE_OFFLINE;
4417 			pptr->port_state &=
4418 			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4419 			pptr->port_tmp_cnt = 0;
4420 		}
4421 		mutex_exit(&pptr->port_mutex);
4422 		break;
4423 
4424 	case FC_STATE_ONLINE:
4425 	case FC_STATE_LIP:
4426 	case FC_STATE_LIP_LBIT_SET:
4427 		/*
4428 		 * link has gone from offline to online
4429 		 */
4430 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4431 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4432 		    "link went online");
4433 
4434 		pptr->port_link_cnt++;
4435 
4436 		while (pptr->port_ipkt_cnt) {
4437 			mutex_exit(&pptr->port_mutex);
4438 			delay(drv_usectohz(1000000));
4439 			mutex_enter(&pptr->port_mutex);
4440 		}
4441 
4442 		pptr->port_topology = port_top;
4443 
4444 		/*
4445 		 * The state of the targets and luns accessible through this
4446 		 * port is updated.
4447 		 */
4448 		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4449 		    FCP_CAUSE_LINK_CHANGE);
4450 
4451 		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4452 		pptr->port_state |= FCP_STATE_ONLINING;
4453 		pptr->port_tmp_cnt = dev_cnt;
4454 		link_count = pptr->port_link_cnt;
4455 
4456 		pptr->port_deadline = fcp_watchdog_time +
4457 		    FCP_ICMD_DEADLINE;
4458 
4459 		if (!dev_cnt) {
4460 			/*
4461 			 * We go directly to the online state if no remote
4462 			 * ports were discovered.
4463 			 */
4464 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4465 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4466 			    "No remote ports discovered");
4467 
4468 			pptr->port_state &= ~FCP_STATE_ONLINING;
4469 			pptr->port_state |= FCP_STATE_ONLINE;
4470 		}
4471 
4472 		switch (port_top) {
4473 		case FC_TOP_FABRIC:
4474 		case FC_TOP_PUBLIC_LOOP:
4475 		case FC_TOP_PRIVATE_LOOP:
4476 		case FC_TOP_PT_PT:
4477 
4478 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4479 				fcp_retry_ns_registry(pptr, port_sid);
4480 			}
4481 
4482 			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4483 			    map_tag, FCP_CAUSE_LINK_CHANGE);
4484 			break;
4485 
4486 		default:
4487 			/*
4488 			 * We got here because we were provided with an unknown
4489 			 * topology.
4490 			 */
4491 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4492 				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4493 			}
4494 
4495 			pptr->port_tmp_cnt -= dev_cnt;
4496 			fcp_log(CE_WARN, pptr->port_dip,
4497 			    "!unknown/unsupported topology (0x%x)", port_top);
4498 			break;
4499 		}
4500 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4501 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4502 		    "Notify ssd of the reset to reinstate the reservations");
4503 
4504 		scsi_hba_reset_notify_callback(&pptr->port_mutex,
4505 		    &pptr->port_reset_notify_listf);
4506 
4507 		mutex_exit(&pptr->port_mutex);
4508 
4509 		break;
4510 
4511 	case FC_STATE_RESET:
4512 		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4513 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4514 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4515 		    "RESET state, waiting for Offline/Online state_cb");
4516 		mutex_exit(&pptr->port_mutex);
4517 		break;
4518 
4519 	case FC_STATE_DEVICE_CHANGE:
4520 		/*
4521 		 * We come here when an application has requested
4522 		 * Dynamic node creation/deletion in Fabric connectivity.
4523 		 */
4524 		if (pptr->port_state & (FCP_STATE_OFFLINE |
4525 		    FCP_STATE_INIT)) {
4526 			/*
4527 			 * This case can happen when the FCTL is in the
4528 			 * process of giving us on online and the host on
4529 			 * the other side issues a PLOGI/PLOGO. Ideally
4530 			 * the state changes should be serialized unless
4531 			 * they are opposite (online-offline).
4532 			 * The transport will give us a final state change
4533 			 * so we can ignore this for the time being.
4534 			 */
4535 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4536 			mutex_exit(&pptr->port_mutex);
4537 			break;
4538 		}
4539 
4540 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4541 			fcp_retry_ns_registry(pptr, port_sid);
4542 		}
4543 
4544 		/*
4545 		 * Extend the deadline under steady state conditions
4546 		 * to provide more time for the device-change-commands
4547 		 */
4548 		if (!pptr->port_ipkt_cnt) {
4549 			pptr->port_deadline = fcp_watchdog_time +
4550 			    FCP_ICMD_DEADLINE;
4551 		}
4552 
4553 		/*
4554 		 * There is another race condition here, where if we were
4555 		 * in ONLINEING state and a devices in the map logs out,
4556 		 * fp will give another state change as DEVICE_CHANGE
4557 		 * and OLD. This will result in that target being offlined.
4558 		 * The pd_handle is freed. If from the first statec callback
4559 		 * we were going to fire a PLOGI/PRLI, the system will
4560 		 * panic in fc_ulp_transport with invalid pd_handle.
4561 		 * The fix is to check for the link_cnt before issuing
4562 		 * any command down.
4563 		 */
4564 		fcp_update_targets(pptr, devlist, dev_cnt,
4565 		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4566 
4567 		link_count = pptr->port_link_cnt;
4568 
4569 		fcp_handle_devices(pptr, devlist, dev_cnt,
4570 		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4571 
4572 		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4573 
4574 		mutex_exit(&pptr->port_mutex);
4575 		break;
4576 
4577 	case FC_STATE_TARGET_PORT_RESET:
4578 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4579 			fcp_retry_ns_registry(pptr, port_sid);
4580 		}
4581 
4582 		/* Do nothing else */
4583 		mutex_exit(&pptr->port_mutex);
4584 		break;
4585 
4586 	default:
4587 		fcp_log(CE_WARN, pptr->port_dip,
4588 		    "!Invalid state change=0x%x", port_state);
4589 		mutex_exit(&pptr->port_mutex);
4590 		break;
4591 	}
4592 
4593 	if (map_tag) {
4594 		kmem_free(map_tag, map_len);
4595 	}
4596 }
4597 
4598 /*
4599  *     Function: fcp_handle_devices
4600  *
4601  *  Description: This function updates the devices currently known by
4602  *		 walking the list provided by the caller.  The list passed
4603  *		 by the caller is supposed to be the list of reachable
4604  *		 devices.
4605  *
4606  *     Argument: *pptr		Fcp port structure.
4607  *		 *devlist	Pointer to the first entry of a table
4608  *				containing the remote ports that can be
4609  *				reached.
4610  *		 dev_cnt	Number of entries pointed by devlist.
4611  *		 link_cnt	Link state count.
4612  *		 *map_tag	Array of fcp_map_tag_t structures.
4613  *		 cause		What caused this function to be called.
4614  *
4615  * Return Value: None
4616  *
4617  *	  Notes: The pptr->port_mutex must be held.
4618  */
4619 static void
4620 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4621     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4622 {
4623 	int			i;
4624 	int			check_finish_init = 0;
4625 	fc_portmap_t		*map_entry;
4626 	struct fcp_tgt	*ptgt = NULL;
4627 
4628 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4629 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
4630 	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4631 
4632 	if (dev_cnt) {
4633 		ASSERT(map_tag != NULL);
4634 	}
4635 
4636 	/*
4637 	 * The following code goes through the list of remote ports that are
4638 	 * accessible through this (pptr) local port (The list walked is the
4639 	 * one provided by the caller which is the list of the remote ports
4640 	 * currently reachable).  It checks if any of them was already
4641 	 * known by looking for the corresponding target structure based on
4642 	 * the world wide name.	 If a target is part of the list it is tagged
4643 	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4644 	 *
4645 	 * Old comment
4646 	 * -----------
4647 	 * Before we drop port mutex; we MUST get the tags updated; This
4648 	 * two step process is somewhat slow, but more reliable.
4649 	 */
4650 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4651 		map_entry = &(devlist[i]);
4652 
4653 		/*
4654 		 * get ptr to this map entry in our port's
4655 		 * list (if any)
4656 		 */
4657 		ptgt = fcp_lookup_target(pptr,
4658 		    (uchar_t *)&(map_entry->map_pwwn));
4659 
4660 		if (ptgt) {
4661 			map_tag[i] = ptgt->tgt_change_cnt;
4662 			if (cause == FCP_CAUSE_LINK_CHANGE) {
4663 				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4664 			}
4665 		}
4666 	}
4667 
4668 	/*
4669 	 * At this point we know which devices of the new list were already
4670 	 * known (The field tgt_aux_state of the target structure has been
4671 	 * set to FCP_TGT_TAGGED).
4672 	 *
4673 	 * The following code goes through the list of targets currently known
4674 	 * by the local port (the list is actually a hashing table).  If a
4675 	 * target is found and is not tagged, it means the target cannot
4676 	 * be reached anymore through the local port (pptr).  It is offlined.
4677 	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4678 	 */
4679 	for (i = 0; i < FCP_NUM_HASH; i++) {
4680 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4681 		    ptgt = ptgt->tgt_next) {
4682 			mutex_enter(&ptgt->tgt_mutex);
4683 			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4684 			    (cause == FCP_CAUSE_LINK_CHANGE) &&
4685 			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4686 				fcp_offline_target_now(pptr, ptgt,
4687 				    link_cnt, ptgt->tgt_change_cnt, 0);
4688 			}
4689 			mutex_exit(&ptgt->tgt_mutex);
4690 		}
4691 	}
4692 
4693 	/*
4694 	 * At this point, the devices that were known but cannot be reached
4695 	 * anymore, have most likely been offlined.
4696 	 *
4697 	 * The following section of code seems to go through the list of
4698 	 * remote ports that can now be reached.  For every single one it
4699 	 * checks if it is already known or if it is a new port.
4700 	 */
4701 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4702 
4703 		if (check_finish_init) {
4704 			ASSERT(i > 0);
4705 			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4706 			    map_tag[i - 1], cause);
4707 			check_finish_init = 0;
4708 		}
4709 
4710 		/* get a pointer to this map entry */
4711 		map_entry = &(devlist[i]);
4712 
4713 		/*
4714 		 * Check for the duplicate map entry flag. If we have marked
4715 		 * this entry as a duplicate we skip it since the correct
4716 		 * (perhaps even same) state change will be encountered
4717 		 * later in the list.
4718 		 */
4719 		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4720 			continue;
4721 		}
4722 
4723 		/* get ptr to this map entry in our port's list (if any) */
4724 		ptgt = fcp_lookup_target(pptr,
4725 		    (uchar_t *)&(map_entry->map_pwwn));
4726 
4727 		if (ptgt) {
4728 			/*
4729 			 * This device was already known.  The field
4730 			 * tgt_aux_state is reset (was probably set to
4731 			 * FCP_TGT_TAGGED previously in this routine).
4732 			 */
4733 			ptgt->tgt_aux_state = 0;
4734 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4735 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4736 			    "handle_devices: map did/state/type/flags = "
4737 			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4738 			    "tgt_state=%d",
4739 			    map_entry->map_did.port_id, map_entry->map_state,
4740 			    map_entry->map_type, map_entry->map_flags,
4741 			    ptgt->tgt_d_id, ptgt->tgt_state);
4742 		}
4743 
4744 		if (map_entry->map_type == PORT_DEVICE_OLD ||
4745 		    map_entry->map_type == PORT_DEVICE_NEW ||
4746 		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4747 		    map_entry->map_type == PORT_DEVICE_CHANGED) {
4748 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4749 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
4750 			    "map_type=%x, did = %x",
4751 			    map_entry->map_type,
4752 			    map_entry->map_did.port_id);
4753 		}
4754 
4755 		switch (map_entry->map_type) {
4756 		case PORT_DEVICE_NOCHANGE:
4757 		case PORT_DEVICE_USER_CREATE:
4758 		case PORT_DEVICE_USER_LOGIN:
4759 		case PORT_DEVICE_NEW:
4760 		case PORT_DEVICE_REPORTLUN_CHANGED:
4761 			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4762 
4763 			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4764 			    link_cnt, (ptgt) ? map_tag[i] : 0,
4765 			    cause) == TRUE) {
4766 
4767 				FCP_TGT_TRACE(ptgt, map_tag[i],
4768 				    FCP_TGT_TRACE_2);
4769 				check_finish_init++;
4770 			}
4771 			break;
4772 
4773 		case PORT_DEVICE_OLD:
4774 			if (ptgt != NULL) {
4775 				FCP_TGT_TRACE(ptgt, map_tag[i],
4776 				    FCP_TGT_TRACE_3);
4777 
4778 				mutex_enter(&ptgt->tgt_mutex);
4779 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4780 					/*
4781 					 * Must do an in-line wait for I/Os
4782 					 * to get drained
4783 					 */
4784 					mutex_exit(&ptgt->tgt_mutex);
4785 					mutex_exit(&pptr->port_mutex);
4786 
4787 					mutex_enter(&ptgt->tgt_mutex);
4788 					while (ptgt->tgt_ipkt_cnt ||
4789 					    fcp_outstanding_lun_cmds(ptgt)
4790 					    == FC_SUCCESS) {
4791 						mutex_exit(&ptgt->tgt_mutex);
4792 						delay(drv_usectohz(1000000));
4793 						mutex_enter(&ptgt->tgt_mutex);
4794 					}
4795 					mutex_exit(&ptgt->tgt_mutex);
4796 
4797 					mutex_enter(&pptr->port_mutex);
4798 					mutex_enter(&ptgt->tgt_mutex);
4799 
4800 					(void) fcp_offline_target(pptr, ptgt,
4801 					    link_cnt, map_tag[i], 0, 0);
4802 				}
4803 				mutex_exit(&ptgt->tgt_mutex);
4804 			}
4805 			check_finish_init++;
4806 			break;
4807 
4808 		case PORT_DEVICE_USER_DELETE:
4809 		case PORT_DEVICE_USER_LOGOUT:
4810 			if (ptgt != NULL) {
4811 				FCP_TGT_TRACE(ptgt, map_tag[i],
4812 				    FCP_TGT_TRACE_4);
4813 
4814 				mutex_enter(&ptgt->tgt_mutex);
4815 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4816 					(void) fcp_offline_target(pptr, ptgt,
4817 					    link_cnt, map_tag[i], 1, 0);
4818 				}
4819 				mutex_exit(&ptgt->tgt_mutex);
4820 			}
4821 			check_finish_init++;
4822 			break;
4823 
4824 		case PORT_DEVICE_CHANGED:
4825 			if (ptgt != NULL) {
4826 				FCP_TGT_TRACE(ptgt, map_tag[i],
4827 				    FCP_TGT_TRACE_5);
4828 
4829 				if (fcp_device_changed(pptr, ptgt,
4830 				    map_entry, link_cnt, map_tag[i],
4831 				    cause) == TRUE) {
4832 					check_finish_init++;
4833 				}
4834 			} else {
4835 				if (fcp_handle_mapflags(pptr, ptgt,
4836 				    map_entry, link_cnt, 0, cause) == TRUE) {
4837 					check_finish_init++;
4838 				}
4839 			}
4840 			break;
4841 
4842 		default:
4843 			fcp_log(CE_WARN, pptr->port_dip,
4844 			    "!Invalid map_type=0x%x", map_entry->map_type);
4845 			check_finish_init++;
4846 			break;
4847 		}
4848 	}
4849 
4850 	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4851 		ASSERT(i > 0);
4852 		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4853 		    map_tag[i-1], cause);
4854 	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4855 		fcp_offline_all(pptr, link_cnt, cause);
4856 	}
4857 }
4858 
4859 static int
4860 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4861 {
4862 	struct fcp_lun	*plun;
4863 	struct fcp_port *pptr;
4864 	int		 rscn_count;
4865 	int		 lun0_newalloc;
4866 	int		 ret  = TRUE;
4867 
4868 	ASSERT(ptgt);
4869 	pptr = ptgt->tgt_port;
4870 	lun0_newalloc = 0;
4871 	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4872 		/*
4873 		 * no LUN struct for LUN 0 yet exists,
4874 		 * so create one
4875 		 */
4876 		plun = fcp_alloc_lun(ptgt);
4877 		if (plun == NULL) {
4878 			fcp_log(CE_WARN, pptr->port_dip,
4879 			    "!Failed to allocate lun 0 for"
4880 			    " D_ID=%x", ptgt->tgt_d_id);
4881 			return (ret);
4882 		}
4883 		lun0_newalloc = 1;
4884 	}
4885 
4886 	mutex_enter(&ptgt->tgt_mutex);
4887 	/*
4888 	 * consider lun 0 as device not connected if it is
4889 	 * offlined or newly allocated
4890 	 */
4891 	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4892 		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4893 	}
4894 	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4895 	plun->lun_state &= ~FCP_LUN_OFFLINE;
4896 	ptgt->tgt_lun_cnt = 1;
4897 	ptgt->tgt_report_lun_cnt = 0;
4898 	mutex_exit(&ptgt->tgt_mutex);
4899 
4900 	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4901 	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4902 	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4903 	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4904 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4905 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4906 		    "to D_ID=%x", ptgt->tgt_d_id);
4907 	} else {
4908 		ret = FALSE;
4909 	}
4910 
4911 	return (ret);
4912 }
4913 
4914 /*
4915  *     Function: fcp_handle_mapflags
4916  *
4917  *  Description: This function creates a target structure if the ptgt passed
4918  *		 is NULL.  It also kicks off the PLOGI if we are not logged
4919  *		 into the target yet or the PRLI if we are logged into the
4920  *		 target already.  The rest of the treatment is done in the
4921  *		 callbacks of the PLOGI or PRLI.
4922  *
4923  *     Argument: *pptr		FCP Port structure.
4924  *		 *ptgt		Target structure.
4925  *		 *map_entry	Array of fc_portmap_t structures.
4926  *		 link_cnt	Link state count.
4927  *		 tgt_cnt	Target state count.
4928  *		 cause		What caused this function to be called.
4929  *
4930  * Return Value: TRUE	Failed
4931  *		 FALSE	Succeeded
4932  *
4933  *	  Notes: pptr->port_mutex must be owned.
4934  */
4935 static int
4936 fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
4937     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4938 {
4939 	int			lcount;
4940 	int			tcount;
4941 	int			ret = TRUE;
4942 	int			alloc;
4943 	struct fcp_ipkt	*icmd;
4944 	struct fcp_lun	*pseq_lun = NULL;
4945 	uchar_t			opcode;
4946 	int			valid_ptgt_was_passed = FALSE;
4947 
4948 	ASSERT(mutex_owned(&pptr->port_mutex));
4949 
4950 	/*
4951 	 * This case is possible where the FCTL has come up and done discovery
4952 	 * before FCP was loaded and attached. FCTL would have discovered the
4953 	 * devices and later the ULP came online. In this case ULP's would get
4954 	 * PORT_DEVICE_NOCHANGE but target would be NULL.
4955 	 */
4956 	if (ptgt == NULL) {
4957 		/* don't already have a target */
4958 		mutex_exit(&pptr->port_mutex);
4959 		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4960 		mutex_enter(&pptr->port_mutex);
4961 
4962 		if (ptgt == NULL) {
4963 			fcp_log(CE_WARN, pptr->port_dip,
4964 			    "!FC target allocation failed");
4965 			return (ret);
4966 		}
4967 		mutex_enter(&ptgt->tgt_mutex);
4968 		ptgt->tgt_statec_cause = cause;
4969 		ptgt->tgt_tmp_cnt = 1;
4970 		mutex_exit(&ptgt->tgt_mutex);
4971 	} else {
4972 		valid_ptgt_was_passed = TRUE;
4973 	}
4974 
4975 	/*
4976 	 * Copy in the target parameters
4977 	 */
4978 	mutex_enter(&ptgt->tgt_mutex);
4979 	ptgt->tgt_d_id = map_entry->map_did.port_id;
4980 	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4981 	ptgt->tgt_pd_handle = map_entry->map_pd;
4982 	ptgt->tgt_fca_dev = NULL;
4983 
4984 	/* Copy port and node WWNs */
4985 	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4986 	    FC_WWN_SIZE);
4987 	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4988 	    FC_WWN_SIZE);
4989 
4990 	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4991 	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4992 	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4993 	    valid_ptgt_was_passed) {
4994 		/*
4995 		 * determine if there are any tape LUNs on this target
4996 		 */
4997 		for (pseq_lun = ptgt->tgt_lun;
4998 		    pseq_lun != NULL;
4999 		    pseq_lun = pseq_lun->lun_next) {
5000 			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
5001 			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
5002 				fcp_update_tgt_state(ptgt, FCP_RESET,
5003 				    FCP_LUN_MARK);
5004 				mutex_exit(&ptgt->tgt_mutex);
5005 				return (ret);
5006 			}
5007 		}
5008 	}
5009 
5010 	/*
5011 	 * if UA'REPORT_LUN_CHANGED received,
5012 	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
5013 	 */
5014 	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5015 		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5016 		mutex_exit(&ptgt->tgt_mutex);
5017 		mutex_exit(&pptr->port_mutex);
5018 
5019 		ret = fcp_handle_reportlun_changed(ptgt, cause);
5020 
5021 		mutex_enter(&pptr->port_mutex);
5022 		return (ret);
5023 	}
5024 
5025 	/*
5026 	 * If ptgt was NULL when this function was entered, then tgt_node_state
5027 	 * was never specifically initialized but zeroed out which means
5028 	 * FCP_TGT_NODE_NONE.
5029 	 */
5030 	switch (ptgt->tgt_node_state) {
5031 	case FCP_TGT_NODE_NONE:
5032 	case FCP_TGT_NODE_ON_DEMAND:
5033 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5034 		    !fcp_enable_auto_configuration &&
5035 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5036 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5037 		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5038 		    fcp_enable_auto_configuration &&
5039 		    (ptgt->tgt_manual_config_only == 1) &&
5040 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5041 			/*
5042 			 * If auto configuration is set and
5043 			 * the tgt_manual_config_only flag is set then
5044 			 * we only want the user to be able to change
5045 			 * the state through create_on_demand.
5046 			 */
5047 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5048 		} else {
5049 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5050 		}
5051 		break;
5052 
5053 	case FCP_TGT_NODE_PRESENT:
5054 		break;
5055 	}
5056 	/*
5057 	 * If we are booting from a fabric device, make sure we
5058 	 * mark the node state appropriately for this target to be
5059 	 * enumerated
5060 	 */
5061 	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5062 		if (bcmp((caddr_t)pptr->port_boot_wwn,
5063 		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5064 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
5065 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5066 		}
5067 	}
5068 	mutex_exit(&ptgt->tgt_mutex);
5069 
5070 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5071 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
5072 	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5073 	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5074 	    map_entry->map_rscn_info.ulp_rscn_count);
5075 
5076 	mutex_enter(&ptgt->tgt_mutex);
5077 
5078 	/*
5079 	 * Reset target OFFLINE state and mark the target BUSY
5080 	 */
5081 	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5082 	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5083 
5084 	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5085 	lcount = link_cnt;
5086 
5087 	mutex_exit(&ptgt->tgt_mutex);
5088 	mutex_exit(&pptr->port_mutex);
5089 
5090 	/*
5091 	 * if we are already logged in, then we do a PRLI, else
5092 	 * we do a PLOGI first (to get logged in)
5093 	 *
5094 	 * We will not check if we are the PLOGI initiator
5095 	 */
5096 	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5097 	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5098 
5099 	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5100 
5101 	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5102 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5103 	    cause, map_entry->map_rscn_info.ulp_rscn_count);
5104 
5105 	if (icmd == NULL) {
5106 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5107 		/*
5108 		 * We've exited port_mutex before calling fcp_icmd_alloc,
5109 		 * we need to make sure we reacquire it before returning.
5110 		 */
5111 		mutex_enter(&pptr->port_mutex);
5112 		return (FALSE);
5113 	}
5114 
5115 	/* TRUE is only returned while target is intended skipped */
5116 	ret = FALSE;
5117 	/* discover info about this target */
5118 	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5119 	    lcount, tcount, cause)) == DDI_SUCCESS) {
5120 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5121 	} else {
5122 		fcp_icmd_free(pptr, icmd);
5123 		ret = TRUE;
5124 	}
5125 	mutex_enter(&pptr->port_mutex);
5126 
5127 	return (ret);
5128 }
5129 
5130 /*
5131  *     Function: fcp_send_els
5132  *
5133  *  Description: Sends an ELS to the target specified by the caller.  Supports
5134  *		 PLOGI and PRLI.
5135  *
5136  *     Argument: *pptr		Fcp port.
5137  *		 *ptgt		Target to send the ELS to.
5138  *		 *icmd		Internal packet
5139  *		 opcode		ELS opcode
5140  *		 lcount		Link state change counter
5141  *		 tcount		Target state change counter
5142  *		 cause		What caused the call
5143  *
5144  * Return Value: DDI_SUCCESS
5145  *		 Others
5146  */
5147 static int
5148 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5149     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5150 {
5151 	fc_packet_t		*fpkt;
5152 	fc_frame_hdr_t		*hp;
5153 	int			internal = 0;
5154 	int			alloc;
5155 	int			cmd_len;
5156 	int			resp_len;
5157 	int			res = DDI_FAILURE; /* default result */
5158 	int			rval = DDI_FAILURE;
5159 
5160 	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5161 	ASSERT(ptgt->tgt_port == pptr);
5162 
5163 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5164 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5165 	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5166 	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5167 
5168 	if (opcode == LA_ELS_PLOGI) {
5169 		cmd_len = sizeof (la_els_logi_t);
5170 		resp_len = sizeof (la_els_logi_t);
5171 	} else {
5172 		ASSERT(opcode == LA_ELS_PRLI);
5173 		cmd_len = sizeof (la_els_prli_t);
5174 		resp_len = sizeof (la_els_prli_t);
5175 	}
5176 
5177 	if (icmd == NULL) {
5178 		alloc = FCP_MAX(sizeof (la_els_logi_t),
5179 		    sizeof (la_els_prli_t));
5180 		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5181 		    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5182 		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5183 		if (icmd == NULL) {
5184 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5185 			return (res);
5186 		}
5187 		internal++;
5188 	}
5189 	fpkt = icmd->ipkt_fpkt;
5190 
5191 	fpkt->pkt_cmdlen = cmd_len;
5192 	fpkt->pkt_rsplen = resp_len;
5193 	fpkt->pkt_datalen = 0;
5194 	icmd->ipkt_retries = 0;
5195 
5196 	/* fill in fpkt info */
5197 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5198 	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5199 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5200 
5201 	/* get ptr to frame hdr in fpkt */
5202 	hp = &fpkt->pkt_cmd_fhdr;
5203 
5204 	/*
5205 	 * fill in frame hdr
5206 	 */
5207 	hp->r_ctl = R_CTL_ELS_REQ;
5208 	hp->s_id = pptr->port_id;	/* source ID */
5209 	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
5210 	hp->type = FC_TYPE_EXTENDED_LS;
5211 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5212 	hp->seq_id = 0;
5213 	hp->rsvd = 0;
5214 	hp->df_ctl  = 0;
5215 	hp->seq_cnt = 0;
5216 	hp->ox_id = 0xffff;		/* i.e. none */
5217 	hp->rx_id = 0xffff;		/* i.e. none */
5218 	hp->ro = 0;
5219 
5220 	/*
5221 	 * at this point we have a filled in cmd pkt
5222 	 *
5223 	 * fill in the respective info, then use the transport to send
5224 	 * the packet
5225 	 *
5226 	 * for a PLOGI call fc_ulp_login(), and
5227 	 * for a PRLI call fc_ulp_issue_els()
5228 	 */
5229 	switch (opcode) {
5230 	case LA_ELS_PLOGI: {
5231 		struct la_els_logi logi;
5232 
5233 		bzero(&logi, sizeof (struct la_els_logi));
5234 
5235 		hp = &fpkt->pkt_cmd_fhdr;
5236 		hp->r_ctl = R_CTL_ELS_REQ;
5237 		logi.ls_code.ls_code = LA_ELS_PLOGI;
5238 		logi.ls_code.mbz = 0;
5239 
5240 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5241 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5242 
5243 		icmd->ipkt_opcode = LA_ELS_PLOGI;
5244 
5245 		mutex_enter(&pptr->port_mutex);
5246 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5247 
5248 			mutex_exit(&pptr->port_mutex);
5249 
5250 			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5251 			if (rval == FC_SUCCESS) {
5252 				res = DDI_SUCCESS;
5253 				break;
5254 			}
5255 
5256 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5257 
5258 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5259 			    rval, "PLOGI");
5260 		} else {
5261 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5262 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
5263 			    "fcp_send_els1: state change occured"
5264 			    " for D_ID=0x%x", ptgt->tgt_d_id);
5265 			mutex_exit(&pptr->port_mutex);
5266 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5267 		}
5268 		break;
5269 	}
5270 
5271 	case LA_ELS_PRLI: {
5272 		struct la_els_prli	prli;
5273 		struct fcp_prli		*fprli;
5274 
5275 		bzero(&prli, sizeof (struct la_els_prli));
5276 
5277 		hp = &fpkt->pkt_cmd_fhdr;
5278 		hp->r_ctl = R_CTL_ELS_REQ;
5279 
5280 		/* fill in PRLI cmd ELS fields */
5281 		prli.ls_code = LA_ELS_PRLI;
5282 		prli.page_length = 0x10;	/* huh? */
5283 		prli.payload_length = sizeof (struct la_els_prli);
5284 
5285 		icmd->ipkt_opcode = LA_ELS_PRLI;
5286 
5287 		/* get ptr to PRLI service params */
5288 		fprli = (struct fcp_prli *)prli.service_params;
5289 
5290 		/* fill in service params */
5291 		fprli->type = 0x08;
5292 		fprli->resvd1 = 0;
5293 		fprli->orig_process_assoc_valid = 0;
5294 		fprli->resp_process_assoc_valid = 0;
5295 		fprli->establish_image_pair = 1;
5296 		fprli->resvd2 = 0;
5297 		fprli->resvd3 = 0;
5298 		fprli->obsolete_1 = 0;
5299 		fprli->obsolete_2 = 0;
5300 		fprli->data_overlay_allowed = 0;
5301 		fprli->initiator_fn = 1;
5302 		fprli->confirmed_compl_allowed = 1;
5303 
5304 		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5305 			fprli->target_fn = 1;
5306 		} else {
5307 			fprli->target_fn = 0;
5308 		}
5309 
5310 		fprli->retry = 1;
5311 		fprli->read_xfer_rdy_disabled = 1;
5312 		fprli->write_xfer_rdy_disabled = 0;
5313 
5314 		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5315 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5316 
5317 		/* issue the PRLI request */
5318 
5319 		mutex_enter(&pptr->port_mutex);
5320 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5321 
5322 			mutex_exit(&pptr->port_mutex);
5323 
5324 			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5325 			if (rval == FC_SUCCESS) {
5326 				res = DDI_SUCCESS;
5327 				break;
5328 			}
5329 
5330 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5331 
5332 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5333 			    rval, "PRLI");
5334 		} else {
5335 			mutex_exit(&pptr->port_mutex);
5336 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5337 		}
5338 		break;
5339 	}
5340 
5341 	default:
5342 		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5343 		break;
5344 	}
5345 
5346 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5347 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5348 	    "fcp_send_els: returning %d", res);
5349 
5350 	if (res != DDI_SUCCESS) {
5351 		if (internal) {
5352 			fcp_icmd_free(pptr, icmd);
5353 		}
5354 	}
5355 
5356 	return (res);
5357 }
5358 
5359 
5360 /*
5361  * called internally update the state of all of the tgts and each LUN
5362  * for this port (i.e. each target  known to be attached to this port)
5363  * if they are not already offline
5364  *
5365  * must be called with the port mutex owned
5366  *
5367  * acquires and releases the target mutexes for each target attached
5368  * to this port
5369  */
5370 void
5371 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5372 {
5373 	int i;
5374 	struct fcp_tgt *ptgt;
5375 
5376 	ASSERT(mutex_owned(&pptr->port_mutex));
5377 
5378 	for (i = 0; i < FCP_NUM_HASH; i++) {
5379 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5380 		    ptgt = ptgt->tgt_next) {
5381 			mutex_enter(&ptgt->tgt_mutex);
5382 			fcp_update_tgt_state(ptgt, FCP_SET, state);
5383 			ptgt->tgt_change_cnt++;
5384 			ptgt->tgt_statec_cause = cause;
5385 			ptgt->tgt_tmp_cnt = 1;
5386 			ptgt->tgt_done = 0;
5387 			mutex_exit(&ptgt->tgt_mutex);
5388 		}
5389 	}
5390 }
5391 
5392 
5393 static void
5394 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5395 {
5396 	int i;
5397 	int ndevs;
5398 	struct fcp_tgt *ptgt;
5399 
5400 	ASSERT(mutex_owned(&pptr->port_mutex));
5401 
5402 	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5403 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5404 		    ptgt = ptgt->tgt_next) {
5405 			ndevs++;
5406 		}
5407 	}
5408 
5409 	if (ndevs == 0) {
5410 		return;
5411 	}
5412 	pptr->port_tmp_cnt = ndevs;
5413 
5414 	for (i = 0; i < FCP_NUM_HASH; i++) {
5415 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5416 		    ptgt = ptgt->tgt_next) {
5417 			(void) fcp_call_finish_init_held(pptr, ptgt,
5418 			    lcount, ptgt->tgt_change_cnt, cause);
5419 		}
5420 	}
5421 }
5422 
5423 /*
5424  *     Function: fcp_update_tgt_state
5425  *
5426  *  Description: This function updates the field tgt_state of a target.	 That
5427  *		 field is a bitmap and which bit can be set or reset
5428  *		 individually.	The action applied to the target state is also
5429  *		 applied to all the LUNs belonging to the target (provided the
5430  *		 LUN is not offline).  A side effect of applying the state
5431  *		 modification to the target and the LUNs is the field tgt_trace
5432  *		 of the target and lun_trace of the LUNs is set to zero.
5433  *
5434  *
5435  *     Argument: *ptgt	Target structure.
5436  *		 flag	Flag indication what action to apply (set/reset).
5437  *		 state	State bits to update.
5438  *
5439  * Return Value: None
5440  *
5441  *	Context: Interrupt, Kernel or User context.
5442  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5443  *		 calling this function.
5444  */
5445 void
5446 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5447 {
5448 	struct fcp_lun *plun;
5449 
5450 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5451 
5452 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5453 		/* The target is not offline. */
5454 		if (flag == FCP_SET) {
5455 			ptgt->tgt_state |= state;
5456 			ptgt->tgt_trace = 0;
5457 		} else {
5458 			ptgt->tgt_state &= ~state;
5459 		}
5460 
5461 		for (plun = ptgt->tgt_lun; plun != NULL;
5462 		    plun = plun->lun_next) {
5463 			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5464 				/* The LUN is not offline. */
5465 				if (flag == FCP_SET) {
5466 					plun->lun_state |= state;
5467 					plun->lun_trace = 0;
5468 				} else {
5469 					plun->lun_state &= ~state;
5470 				}
5471 			}
5472 		}
5473 	}
5474 }
5475 
5476 /*
5477  *     Function: fcp_update_tgt_state
5478  *
5479  *  Description: This function updates the field lun_state of a LUN.  That
5480  *		 field is a bitmap and which bit can be set or reset
5481  *		 individually.
5482  *
5483  *     Argument: *plun	LUN structure.
5484  *		 flag	Flag indication what action to apply (set/reset).
5485  *		 state	State bits to update.
5486  *
5487  * Return Value: None
5488  *
5489  *	Context: Interrupt, Kernel or User context.
5490  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5491  *		 calling this function.
5492  */
5493 void
5494 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5495 {
5496 	struct fcp_tgt	*ptgt = plun->lun_tgt;
5497 
5498 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5499 
5500 	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5501 		if (flag == FCP_SET) {
5502 			plun->lun_state |= state;
5503 		} else {
5504 			plun->lun_state &= ~state;
5505 		}
5506 	}
5507 }
5508 
5509 /*
5510  *     Function: fcp_get_port
5511  *
5512  *  Description: This function returns the fcp_port structure from the opaque
5513  *		 handle passed by the caller.  That opaque handle is the handle
5514  *		 used by fp/fctl to identify a particular local port.  That
5515  *		 handle has been stored in the corresponding fcp_port
5516  *		 structure.  This function is going to walk the global list of
5517  *		 fcp_port structures till one has a port_fp_handle that matches
5518  *		 the handle passed by the caller.  This function enters the
5519  *		 mutex fcp_global_mutex while walking the global list and then
5520  *		 releases it.
5521  *
5522  *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
5523  *				particular port.
5524  *
5525  * Return Value: NULL		Not found.
5526  *		 Not NULL	Pointer to the fcp_port structure.
5527  *
5528  *	Context: Interrupt, Kernel or User context.
5529  */
5530 static struct fcp_port *
5531 fcp_get_port(opaque_t port_handle)
5532 {
5533 	struct fcp_port *pptr;
5534 
5535 	ASSERT(port_handle != NULL);
5536 
5537 	mutex_enter(&fcp_global_mutex);
5538 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5539 		if (pptr->port_fp_handle == port_handle) {
5540 			break;
5541 		}
5542 	}
5543 	mutex_exit(&fcp_global_mutex);
5544 
5545 	return (pptr);
5546 }
5547 
5548 
5549 static void
5550 fcp_unsol_callback(fc_packet_t *fpkt)
5551 {
5552 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5553 	struct fcp_port *pptr = icmd->ipkt_port;
5554 
5555 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5556 		caddr_t state, reason, action, expln;
5557 
5558 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
5559 		    &action, &expln);
5560 
5561 		fcp_log(CE_WARN, pptr->port_dip,
5562 		    "!couldn't post response to unsolicited request: "
5563 		    " state=%s reason=%s rx_id=%x ox_id=%x",
5564 		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5565 		    fpkt->pkt_cmd_fhdr.rx_id);
5566 	}
5567 	fcp_icmd_free(pptr, icmd);
5568 }
5569 
5570 
5571 /*
5572  * Perform general purpose preparation of a response to an unsolicited request
5573  */
5574 static void
5575 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5576     uchar_t r_ctl, uchar_t type)
5577 {
5578 	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5579 	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5580 	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5581 	pkt->pkt_cmd_fhdr.type = type;
5582 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5583 	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5584 	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5585 	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5586 	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5587 	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5588 	pkt->pkt_cmd_fhdr.ro = 0;
5589 	pkt->pkt_cmd_fhdr.rsvd = 0;
5590 	pkt->pkt_comp = fcp_unsol_callback;
5591 	pkt->pkt_pd = NULL;
5592 	pkt->pkt_ub_resp_token = (opaque_t)buf;
5593 }
5594 
5595 
5596 /*ARGSUSED*/
5597 static int
5598 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5599 {
5600 	fc_packet_t		*fpkt;
5601 	struct la_els_prli	prli;
5602 	struct fcp_prli		*fprli;
5603 	struct fcp_ipkt	*icmd;
5604 	struct la_els_prli	*from;
5605 	struct fcp_prli		*orig;
5606 	struct fcp_tgt	*ptgt;
5607 	int			tcount = 0;
5608 	int			lcount;
5609 
5610 	from = (struct la_els_prli *)buf->ub_buffer;
5611 	orig = (struct fcp_prli *)from->service_params;
5612 	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5613 	    NULL) {
5614 		mutex_enter(&ptgt->tgt_mutex);
5615 		tcount = ptgt->tgt_change_cnt;
5616 		mutex_exit(&ptgt->tgt_mutex);
5617 	}
5618 
5619 	mutex_enter(&pptr->port_mutex);
5620 	lcount = pptr->port_link_cnt;
5621 	mutex_exit(&pptr->port_mutex);
5622 
5623 	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5624 	    sizeof (la_els_prli_t), 0,
5625 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5626 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5627 		return (FC_FAILURE);
5628 	}
5629 
5630 	fpkt = icmd->ipkt_fpkt;
5631 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5632 	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5633 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5634 	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5635 	fpkt->pkt_rsplen = 0;
5636 	fpkt->pkt_datalen = 0;
5637 
5638 	icmd->ipkt_opcode = LA_ELS_PRLI;
5639 
5640 	bzero(&prli, sizeof (struct la_els_prli));
5641 	fprli = (struct fcp_prli *)prli.service_params;
5642 	prli.ls_code = LA_ELS_ACC;
5643 	prli.page_length = 0x10;
5644 	prli.payload_length = sizeof (struct la_els_prli);
5645 
5646 	/* fill in service params */
5647 	fprli->type = 0x08;
5648 	fprli->resvd1 = 0;
5649 	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5650 	fprli->orig_process_associator = orig->orig_process_associator;
5651 	fprli->resp_process_assoc_valid = 0;
5652 	fprli->establish_image_pair = 1;
5653 	fprli->resvd2 = 0;
5654 	fprli->resvd3 = 0;
5655 	fprli->obsolete_1 = 0;
5656 	fprli->obsolete_2 = 0;
5657 	fprli->data_overlay_allowed = 0;
5658 	fprli->initiator_fn = 1;
5659 	fprli->confirmed_compl_allowed = 1;
5660 
5661 	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5662 		fprli->target_fn = 1;
5663 	} else {
5664 		fprli->target_fn = 0;
5665 	}
5666 
5667 	fprli->retry = 1;
5668 	fprli->read_xfer_rdy_disabled = 1;
5669 	fprli->write_xfer_rdy_disabled = 0;
5670 
5671 	/* save the unsol prli payload first */
5672 	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5673 	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5674 
5675 	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5676 	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5677 
5678 	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5679 
5680 	mutex_enter(&pptr->port_mutex);
5681 	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5682 		int rval;
5683 		mutex_exit(&pptr->port_mutex);
5684 
5685 		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5686 		    FC_SUCCESS) {
5687 			if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5688 			    ptgt != NULL) {
5689 				fcp_queue_ipkt(pptr, fpkt);
5690 				return (FC_SUCCESS);
5691 			}
5692 			/* Let it timeout */
5693 			fcp_icmd_free(pptr, icmd);
5694 			return (FC_FAILURE);
5695 		}
5696 	} else {
5697 		mutex_exit(&pptr->port_mutex);
5698 		fcp_icmd_free(pptr, icmd);
5699 		return (FC_FAILURE);
5700 	}
5701 
5702 	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5703 
5704 	return (FC_SUCCESS);
5705 }
5706 
5707 /*
5708  *     Function: fcp_icmd_alloc
5709  *
5710  *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
5711  *		 field is initialized to fcp_icmd_callback.  Sometimes it is
5712  *		 modified by the caller (such as fcp_send_scsi).  The
5713  *		 structure is also tied to the state of the line and of the
5714  *		 target at a particular time.  That link is established by
5715  *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5716  *		 and tcount which came respectively from pptr->link_cnt and
5717  *		 ptgt->tgt_change_cnt.
5718  *
5719  *     Argument: *pptr		Fcp port.
5720  *		 *ptgt		Target (destination of the command).
5721  *		 cmd_len	Length of the command.
5722  *		 resp_len	Length of the expected response.
5723  *		 data_len	Length of the data.
5724  *		 nodma		Indicates weither the command and response.
5725  *				will be transfer through DMA or not.
5726  *		 lcount		Link state change counter.
5727  *		 tcount		Target state change counter.
5728  *		 cause		Reason that lead to this call.
5729  *
5730  * Return Value: NULL		Failed.
5731  *		 Not NULL	Internal packet address.
5732  */
5733 static struct fcp_ipkt *
5734 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5735     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5736     uint32_t rscn_count)
5737 {
5738 	int			dma_setup = 0;
5739 	fc_packet_t		*fpkt;
5740 	struct fcp_ipkt	*icmd = NULL;
5741 
5742 	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5743 	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5744 	    KM_NOSLEEP);
5745 	if (icmd == NULL) {
5746 		fcp_log(CE_WARN, pptr->port_dip,
5747 		    "!internal packet allocation failed");
5748 		return (NULL);
5749 	}
5750 
5751 	/*
5752 	 * initialize the allocated packet
5753 	 */
5754 	icmd->ipkt_nodma = nodma;
5755 	icmd->ipkt_next = icmd->ipkt_prev = NULL;
5756 	icmd->ipkt_lun = NULL;
5757 
5758 	icmd->ipkt_link_cnt = lcount;
5759 	icmd->ipkt_change_cnt = tcount;
5760 	icmd->ipkt_cause = cause;
5761 
5762 	mutex_enter(&pptr->port_mutex);
5763 	icmd->ipkt_port = pptr;
5764 	mutex_exit(&pptr->port_mutex);
5765 
5766 	/* keep track of amt of data to be sent in pkt */
5767 	icmd->ipkt_cmdlen = cmd_len;
5768 	icmd->ipkt_resplen = resp_len;
5769 	icmd->ipkt_datalen = data_len;
5770 
5771 	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5772 	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5773 
5774 	/* set pkt's private ptr to point to cmd pkt */
5775 	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5776 
5777 	/* set FCA private ptr to memory just beyond */
5778 	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5779 	    ((char *)icmd + sizeof (struct fcp_ipkt) +
5780 	    pptr->port_dmacookie_sz);
5781 
5782 	/* get ptr to fpkt substruct and fill it in */
5783 	fpkt = icmd->ipkt_fpkt;
5784 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5785 	    sizeof (struct fcp_ipkt));
5786 
5787 	if (ptgt != NULL) {
5788 		icmd->ipkt_tgt = ptgt;
5789 		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5790 	}
5791 
5792 	fpkt->pkt_comp = fcp_icmd_callback;
5793 	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5794 	fpkt->pkt_cmdlen = cmd_len;
5795 	fpkt->pkt_rsplen = resp_len;
5796 	fpkt->pkt_datalen = data_len;
5797 
5798 	/*
5799 	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5800 	 * rscn_count as fcp knows down to the transport. If a valid count was
5801 	 * passed into this function, we allocate memory to actually pass down
5802 	 * this info.
5803 	 *
5804 	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5805 	 * basically mean that fcp will not be able to help transport
5806 	 * distinguish if a new RSCN has come after fcp was last informed about
5807 	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5808 	 * 5068068 where the device might end up going offline in case of RSCN
5809 	 * storms.
5810 	 */
5811 	fpkt->pkt_ulp_rscn_infop = NULL;
5812 	if (rscn_count != FC_INVALID_RSCN_COUNT) {
5813 		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5814 		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5815 		if (fpkt->pkt_ulp_rscn_infop == NULL) {
5816 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5817 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5818 			    "Failed to alloc memory to pass rscn info");
5819 		}
5820 	}
5821 
5822 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5823 		fc_ulp_rscn_info_t	*rscnp;
5824 
5825 		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5826 		rscnp->ulp_rscn_count = rscn_count;
5827 	}
5828 
5829 	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5830 		goto fail;
5831 	}
5832 	dma_setup++;
5833 
5834 	/*
5835 	 * Must hold target mutex across setting of pkt_pd and call to
5836 	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5837 	 * away while we're not looking.
5838 	 */
5839 	if (ptgt != NULL) {
5840 		mutex_enter(&ptgt->tgt_mutex);
5841 		fpkt->pkt_pd = ptgt->tgt_pd_handle;
5842 
5843 		/* ask transport to do its initialization on this pkt */
5844 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5845 		    != FC_SUCCESS) {
5846 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5847 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5848 			    "fc_ulp_init_packet failed");
5849 			mutex_exit(&ptgt->tgt_mutex);
5850 			goto fail;
5851 		}
5852 		mutex_exit(&ptgt->tgt_mutex);
5853 	} else {
5854 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5855 		    != FC_SUCCESS) {
5856 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5857 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5858 			    "fc_ulp_init_packet failed");
5859 			goto fail;
5860 		}
5861 	}
5862 
5863 	mutex_enter(&pptr->port_mutex);
5864 	if (pptr->port_state & (FCP_STATE_DETACHING |
5865 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5866 		int rval;
5867 
5868 		mutex_exit(&pptr->port_mutex);
5869 
5870 		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5871 		ASSERT(rval == FC_SUCCESS);
5872 
5873 		goto fail;
5874 	}
5875 
5876 	if (ptgt != NULL) {
5877 		mutex_enter(&ptgt->tgt_mutex);
5878 		ptgt->tgt_ipkt_cnt++;
5879 		mutex_exit(&ptgt->tgt_mutex);
5880 	}
5881 
5882 	pptr->port_ipkt_cnt++;
5883 
5884 	mutex_exit(&pptr->port_mutex);
5885 
5886 	return (icmd);
5887 
5888 fail:
5889 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5890 		kmem_free(fpkt->pkt_ulp_rscn_infop,
5891 		    sizeof (fc_ulp_rscn_info_t));
5892 		fpkt->pkt_ulp_rscn_infop = NULL;
5893 	}
5894 
5895 	if (dma_setup) {
5896 		fcp_free_dma(pptr, icmd);
5897 	}
5898 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5899 	    (size_t)pptr->port_dmacookie_sz);
5900 
5901 	return (NULL);
5902 }
5903 
5904 /*
5905  *     Function: fcp_icmd_free
5906  *
5907  *  Description: Frees the internal command passed by the caller.
5908  *
5909  *     Argument: *pptr		Fcp port.
5910  *		 *icmd		Internal packet to free.
5911  *
5912  * Return Value: None
5913  */
5914 static void
5915 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5916 {
5917 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
5918 
5919 	/* Let the underlying layers do their cleanup. */
5920 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5921 	    icmd->ipkt_fpkt);
5922 
5923 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5924 		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5925 		    sizeof (fc_ulp_rscn_info_t));
5926 	}
5927 
5928 	fcp_free_dma(pptr, icmd);
5929 
5930 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5931 	    (size_t)pptr->port_dmacookie_sz);
5932 
5933 	mutex_enter(&pptr->port_mutex);
5934 
5935 	if (ptgt) {
5936 		mutex_enter(&ptgt->tgt_mutex);
5937 		ptgt->tgt_ipkt_cnt--;
5938 		mutex_exit(&ptgt->tgt_mutex);
5939 	}
5940 
5941 	pptr->port_ipkt_cnt--;
5942 	mutex_exit(&pptr->port_mutex);
5943 }
5944 
5945 /*
5946  *     Function: fcp_alloc_dma
5947  *
5948  *  Description: Allocated the DMA resources required for the internal
5949  *		 packet.
5950  *
5951  *     Argument: *pptr	FCP port.
5952  *		 *icmd	Internal FCP packet.
5953  *		 nodma	Indicates if the Cmd and Resp will be DMAed.
5954  *		 flags	Allocation flags (Sleep or NoSleep).
5955  *
5956  * Return Value: FC_SUCCESS
5957  *		 FC_NOMEM
5958  */
5959 static int
5960 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5961     int nodma, int flags)
5962 {
5963 	int		rval;
5964 	size_t		real_size;
5965 	uint_t		ccount;
5966 	int		bound = 0;
5967 	int		cmd_resp = 0;
5968 	fc_packet_t	*fpkt;
5969 	ddi_dma_cookie_t	pkt_data_cookie;
5970 	ddi_dma_cookie_t	*cp;
5971 	uint32_t		cnt;
5972 
5973 	fpkt = &icmd->ipkt_fc_packet;
5974 
5975 	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5976 	    fpkt->pkt_resp_dma == NULL);
5977 
5978 	icmd->ipkt_nodma = nodma;
5979 
5980 	if (nodma) {
5981 		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5982 		if (fpkt->pkt_cmd == NULL) {
5983 			goto fail;
5984 		}
5985 
5986 		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5987 		if (fpkt->pkt_resp == NULL) {
5988 			goto fail;
5989 		}
5990 	} else {
5991 		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5992 
5993 		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5994 		if (rval == FC_FAILURE) {
5995 			ASSERT(fpkt->pkt_cmd_dma == NULL &&
5996 			    fpkt->pkt_resp_dma == NULL);
5997 			goto fail;
5998 		}
5999 		cmd_resp++;
6000 	}
6001 
6002 	if ((fpkt->pkt_datalen != 0) &&
6003 	    !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
6004 		/*
6005 		 * set up DMA handle and memory for the data in this packet
6006 		 */
6007 		if (ddi_dma_alloc_handle(pptr->port_dip,
6008 		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6009 		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6010 			goto fail;
6011 		}
6012 
6013 		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6014 		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6015 		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6016 		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6017 			goto fail;
6018 		}
6019 
6020 		/* was DMA mem size gotten < size asked for/needed ?? */
6021 		if (real_size < fpkt->pkt_datalen) {
6022 			goto fail;
6023 		}
6024 
6025 		/* bind DMA address and handle together */
6026 		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6027 		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6028 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6029 		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6030 			goto fail;
6031 		}
6032 		bound++;
6033 
6034 		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6035 			goto fail;
6036 		}
6037 
6038 		fpkt->pkt_data_cookie_cnt = ccount;
6039 
6040 		cp = fpkt->pkt_data_cookie;
6041 		*cp = pkt_data_cookie;
6042 		cp++;
6043 
6044 		for (cnt = 1; cnt < ccount; cnt++, cp++) {
6045 			ddi_dma_nextcookie(fpkt->pkt_data_dma,
6046 			    &pkt_data_cookie);
6047 			*cp = pkt_data_cookie;
6048 		}
6049 
6050 	} else if (fpkt->pkt_datalen != 0) {
6051 		/*
6052 		 * If it's a pseudo FCA, then it can't support DMA even in
6053 		 * SCSI data phase.
6054 		 */
6055 		fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6056 		if (fpkt->pkt_data == NULL) {
6057 			goto fail;
6058 		}
6059 
6060 	}
6061 
6062 	return (FC_SUCCESS);
6063 
6064 fail:
6065 	if (bound) {
6066 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6067 	}
6068 
6069 	if (fpkt->pkt_data_dma) {
6070 		if (fpkt->pkt_data) {
6071 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6072 		}
6073 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6074 	} else {
6075 		if (fpkt->pkt_data) {
6076 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6077 		}
6078 	}
6079 
6080 	if (nodma) {
6081 		if (fpkt->pkt_cmd) {
6082 			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6083 		}
6084 		if (fpkt->pkt_resp) {
6085 			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6086 		}
6087 	} else {
6088 		if (cmd_resp) {
6089 			fcp_free_cmd_resp(pptr, fpkt);
6090 		}
6091 	}
6092 
6093 	return (FC_NOMEM);
6094 }
6095 
6096 
6097 static void
6098 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6099 {
6100 	fc_packet_t *fpkt = icmd->ipkt_fpkt;
6101 
6102 	if (fpkt->pkt_data_dma) {
6103 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6104 		if (fpkt->pkt_data) {
6105 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6106 		}
6107 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6108 	} else {
6109 		if (fpkt->pkt_data) {
6110 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6111 		}
6112 		/*
6113 		 * Need we reset pkt_* to zero???
6114 		 */
6115 	}
6116 
6117 	if (icmd->ipkt_nodma) {
6118 		if (fpkt->pkt_cmd) {
6119 			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6120 		}
6121 		if (fpkt->pkt_resp) {
6122 			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6123 		}
6124 	} else {
6125 		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6126 
6127 		fcp_free_cmd_resp(pptr, fpkt);
6128 	}
6129 }
6130 
6131 /*
6132  *     Function: fcp_lookup_target
6133  *
6134  *  Description: Finds a target given a WWN.
6135  *
6136  *     Argument: *pptr	FCP port.
6137  *		 *wwn	World Wide Name of the device to look for.
6138  *
6139  * Return Value: NULL		No target found
6140  *		 Not NULL	Target structure
6141  *
6142  *	Context: Interrupt context.
6143  *		 The mutex pptr->port_mutex must be owned.
6144  */
6145 /* ARGSUSED */
6146 static struct fcp_tgt *
6147 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6148 {
6149 	int			hash;
6150 	struct fcp_tgt	*ptgt;
6151 
6152 	ASSERT(mutex_owned(&pptr->port_mutex));
6153 
6154 	hash = FCP_HASH(wwn);
6155 
6156 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6157 	    ptgt = ptgt->tgt_next) {
6158 		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6159 		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6160 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
6161 			break;
6162 		}
6163 	}
6164 
6165 	return (ptgt);
6166 }
6167 
6168 
6169 /*
6170  * Find target structure given a port identifier
6171  */
6172 static struct fcp_tgt *
6173 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6174 {
6175 	fc_portid_t		port_id;
6176 	la_wwn_t		pwwn;
6177 	struct fcp_tgt	*ptgt = NULL;
6178 
6179 	port_id.priv_lilp_posit = 0;
6180 	port_id.port_id = d_id;
6181 	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6182 	    &pwwn) == FC_SUCCESS) {
6183 		mutex_enter(&pptr->port_mutex);
6184 		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6185 		mutex_exit(&pptr->port_mutex);
6186 	}
6187 
6188 	return (ptgt);
6189 }
6190 
6191 
6192 /*
6193  * the packet completion callback routine for info cmd pkts
6194  *
6195  * this means fpkt pts to a response to either a PLOGI or a PRLI
6196  *
6197  * if there is an error an attempt is made to call a routine to resend
6198  * the command that failed
6199  */
6200 static void
6201 fcp_icmd_callback(fc_packet_t *fpkt)
6202 {
6203 	struct fcp_ipkt	*icmd;
6204 	struct fcp_port	*pptr;
6205 	struct fcp_tgt	*ptgt;
6206 	struct la_els_prli	*prli;
6207 	struct la_els_prli	prli_s;
6208 	struct fcp_prli		*fprli;
6209 	struct fcp_lun	*plun;
6210 	int		free_pkt = 1;
6211 	int		rval;
6212 	ls_code_t	resp;
6213 	uchar_t		prli_acc = 0;
6214 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
6215 	int		lun0_newalloc;
6216 
6217 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6218 
6219 	/* get ptrs to the port and target structs for the cmd */
6220 	pptr = icmd->ipkt_port;
6221 	ptgt = icmd->ipkt_tgt;
6222 
6223 	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6224 
6225 	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6226 		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6227 		    sizeof (prli_s));
6228 		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6229 	}
6230 
6231 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6232 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6233 	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
6234 	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6235 	    ptgt->tgt_d_id);
6236 
6237 	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6238 	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6239 
6240 		mutex_enter(&ptgt->tgt_mutex);
6241 		if (ptgt->tgt_pd_handle == NULL) {
6242 			/*
6243 			 * in a fabric environment the port device handles
6244 			 * get created only after successful LOGIN into the
6245 			 * transport, so the transport makes this port
6246 			 * device (pd) handle available in this packet, so
6247 			 * save it now
6248 			 */
6249 			ASSERT(fpkt->pkt_pd != NULL);
6250 			ptgt->tgt_pd_handle = fpkt->pkt_pd;
6251 		}
6252 		mutex_exit(&ptgt->tgt_mutex);
6253 
6254 		/* which ELS cmd is this response for ?? */
6255 		switch (icmd->ipkt_opcode) {
6256 		case LA_ELS_PLOGI:
6257 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6258 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6259 			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6260 			    ptgt->tgt_d_id,
6261 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6262 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6263 
6264 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6265 			    FCP_TGT_TRACE_15);
6266 
6267 			/* Note that we are not allocating a new icmd */
6268 			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6269 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6270 			    icmd->ipkt_cause) != DDI_SUCCESS) {
6271 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6272 				    FCP_TGT_TRACE_16);
6273 				goto fail;
6274 			}
6275 			break;
6276 
6277 		case LA_ELS_PRLI:
6278 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6279 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6280 			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6281 
6282 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6283 			    FCP_TGT_TRACE_17);
6284 
6285 			prli = &prli_s;
6286 
6287 			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6288 			    sizeof (prli_s));
6289 
6290 			fprli = (struct fcp_prli *)prli->service_params;
6291 
6292 			mutex_enter(&ptgt->tgt_mutex);
6293 			ptgt->tgt_icap = fprli->initiator_fn;
6294 			ptgt->tgt_tcap = fprli->target_fn;
6295 			mutex_exit(&ptgt->tgt_mutex);
6296 
6297 			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6298 				/*
6299 				 * this FCP device does not support target mode
6300 				 */
6301 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6302 				    FCP_TGT_TRACE_18);
6303 				goto fail;
6304 			}
6305 			if (fprli->retry == 1) {
6306 				fc_ulp_disable_relogin(pptr->port_fp_handle,
6307 				    &ptgt->tgt_port_wwn);
6308 			}
6309 
6310 			/* target is no longer offline */
6311 			mutex_enter(&pptr->port_mutex);
6312 			mutex_enter(&ptgt->tgt_mutex);
6313 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6314 				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6315 				    FCP_TGT_MARK);
6316 			} else {
6317 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6318 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6319 				    "fcp_icmd_callback,1: state change "
6320 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6321 				mutex_exit(&ptgt->tgt_mutex);
6322 				mutex_exit(&pptr->port_mutex);
6323 				goto fail;
6324 			}
6325 			mutex_exit(&ptgt->tgt_mutex);
6326 			mutex_exit(&pptr->port_mutex);
6327 
6328 			/*
6329 			 * lun 0 should always respond to inquiry, so
6330 			 * get the LUN struct for LUN 0
6331 			 *
6332 			 * Currently we deal with first level of addressing.
6333 			 * If / when we start supporting 0x device types
6334 			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6335 			 * this logic will need revisiting.
6336 			 */
6337 			lun0_newalloc = 0;
6338 			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6339 				/*
6340 				 * no LUN struct for LUN 0 yet exists,
6341 				 * so create one
6342 				 */
6343 				plun = fcp_alloc_lun(ptgt);
6344 				if (plun == NULL) {
6345 					fcp_log(CE_WARN, pptr->port_dip,
6346 					    "!Failed to allocate lun 0 for"
6347 					    " D_ID=%x", ptgt->tgt_d_id);
6348 					goto fail;
6349 				}
6350 				lun0_newalloc = 1;
6351 			}
6352 
6353 			/* fill in LUN info */
6354 			mutex_enter(&ptgt->tgt_mutex);
6355 			/*
6356 			 * consider lun 0 as device not connected if it is
6357 			 * offlined or newly allocated
6358 			 */
6359 			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6360 			    lun0_newalloc) {
6361 				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6362 			}
6363 			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6364 			plun->lun_state &= ~FCP_LUN_OFFLINE;
6365 			ptgt->tgt_lun_cnt = 1;
6366 			ptgt->tgt_report_lun_cnt = 0;
6367 			mutex_exit(&ptgt->tgt_mutex);
6368 
6369 			/* Retrieve the rscn count (if a valid one exists) */
6370 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6371 				rscn_count = ((fc_ulp_rscn_info_t *)
6372 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6373 				    ->ulp_rscn_count;
6374 			} else {
6375 				rscn_count = FC_INVALID_RSCN_COUNT;
6376 			}
6377 
6378 			/* send Report Lun request to target */
6379 			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6380 			    sizeof (struct fcp_reportlun_resp),
6381 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6382 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6383 				mutex_enter(&pptr->port_mutex);
6384 				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6385 					fcp_log(CE_WARN, pptr->port_dip,
6386 					    "!Failed to send REPORT LUN to"
6387 					    "  D_ID=%x", ptgt->tgt_d_id);
6388 				} else {
6389 					FCP_TRACE(fcp_logq,
6390 					    pptr->port_instbuf, fcp_trace,
6391 					    FCP_BUF_LEVEL_5, 0,
6392 					    "fcp_icmd_callback,2:state change"
6393 					    " occured for D_ID=0x%x",
6394 					    ptgt->tgt_d_id);
6395 				}
6396 				mutex_exit(&pptr->port_mutex);
6397 
6398 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6399 				    FCP_TGT_TRACE_19);
6400 
6401 				goto fail;
6402 			} else {
6403 				free_pkt = 0;
6404 				fcp_icmd_free(pptr, icmd);
6405 			}
6406 			break;
6407 
6408 		default:
6409 			fcp_log(CE_WARN, pptr->port_dip,
6410 			    "!fcp_icmd_callback Invalid opcode");
6411 			goto fail;
6412 		}
6413 
6414 		return;
6415 	}
6416 
6417 
6418 	/*
6419 	 * Other PLOGI failures are not retried as the
6420 	 * transport does it already
6421 	 */
6422 	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6423 		if (fcp_is_retryable(icmd) &&
6424 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6425 
6426 			if (FCP_MUST_RETRY(fpkt)) {
6427 				fcp_queue_ipkt(pptr, fpkt);
6428 				return;
6429 			}
6430 
6431 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6432 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6433 			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
6434 			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6435 			    fpkt->pkt_reason);
6436 
6437 			/*
6438 			 * Retry by recalling the routine that
6439 			 * originally queued this packet
6440 			 */
6441 			mutex_enter(&pptr->port_mutex);
6442 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6443 				caddr_t msg;
6444 
6445 				mutex_exit(&pptr->port_mutex);
6446 
6447 				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6448 
6449 				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6450 					fpkt->pkt_timeout +=
6451 					    FCP_TIMEOUT_DELTA;
6452 				}
6453 
6454 				rval = fc_ulp_issue_els(pptr->port_fp_handle,
6455 				    fpkt);
6456 				if (rval == FC_SUCCESS) {
6457 					return;
6458 				}
6459 
6460 				if (rval == FC_STATEC_BUSY ||
6461 				    rval == FC_OFFLINE) {
6462 					fcp_queue_ipkt(pptr, fpkt);
6463 					return;
6464 				}
6465 				(void) fc_ulp_error(rval, &msg);
6466 
6467 				fcp_log(CE_NOTE, pptr->port_dip,
6468 				    "!ELS 0x%x failed to d_id=0x%x;"
6469 				    " %s", icmd->ipkt_opcode,
6470 				    ptgt->tgt_d_id, msg);
6471 			} else {
6472 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6473 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6474 				    "fcp_icmd_callback,3: state change "
6475 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6476 				mutex_exit(&pptr->port_mutex);
6477 			}
6478 		}
6479 	} else {
6480 		if (fcp_is_retryable(icmd) &&
6481 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6482 			if (FCP_MUST_RETRY(fpkt)) {
6483 				fcp_queue_ipkt(pptr, fpkt);
6484 				return;
6485 			}
6486 		}
6487 		mutex_enter(&pptr->port_mutex);
6488 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6489 		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6490 			mutex_exit(&pptr->port_mutex);
6491 			fcp_print_error(fpkt);
6492 		} else {
6493 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6494 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6495 			    "fcp_icmd_callback,4: state change occured"
6496 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6497 			mutex_exit(&pptr->port_mutex);
6498 		}
6499 	}
6500 
6501 fail:
6502 	if (free_pkt) {
6503 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6504 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6505 		fcp_icmd_free(pptr, icmd);
6506 	}
6507 }
6508 
6509 
6510 /*
6511  * called internally to send an info cmd using the transport
6512  *
6513  * sends either an INQ or a REPORT_LUN
6514  *
6515  * when the packet is completed fcp_scsi_callback is called
6516  */
6517 static int
6518 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6519     int lcount, int tcount, int cause, uint32_t rscn_count)
6520 {
6521 	int			nodma;
6522 	struct fcp_ipkt		*icmd;
6523 	struct fcp_tgt		*ptgt;
6524 	struct fcp_port		*pptr;
6525 	fc_frame_hdr_t		*hp;
6526 	fc_packet_t		*fpkt;
6527 	struct fcp_cmd		fcp_cmd;
6528 	struct fcp_cmd		*fcmd;
6529 	union scsi_cdb		*scsi_cdb;
6530 
6531 	ASSERT(plun != NULL);
6532 
6533 	ptgt = plun->lun_tgt;
6534 	ASSERT(ptgt != NULL);
6535 
6536 	pptr = ptgt->tgt_port;
6537 	ASSERT(pptr != NULL);
6538 
6539 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6540 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6541 	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6542 
6543 	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6544 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6545 	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6546 	    rscn_count);
6547 
6548 	if (icmd == NULL) {
6549 		return (DDI_FAILURE);
6550 	}
6551 
6552 	fpkt = icmd->ipkt_fpkt;
6553 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6554 	icmd->ipkt_retries = 0;
6555 	icmd->ipkt_opcode = opcode;
6556 	icmd->ipkt_lun = plun;
6557 
6558 	if (nodma) {
6559 		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6560 	} else {
6561 		fcmd = &fcp_cmd;
6562 	}
6563 	bzero(fcmd, sizeof (struct fcp_cmd));
6564 
6565 	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6566 
6567 	hp = &fpkt->pkt_cmd_fhdr;
6568 
6569 	hp->s_id = pptr->port_id;
6570 	hp->d_id = ptgt->tgt_d_id;
6571 	hp->r_ctl = R_CTL_COMMAND;
6572 	hp->type = FC_TYPE_SCSI_FCP;
6573 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6574 	hp->rsvd = 0;
6575 	hp->seq_id = 0;
6576 	hp->seq_cnt = 0;
6577 	hp->ox_id = 0xffff;
6578 	hp->rx_id = 0xffff;
6579 	hp->ro = 0;
6580 
6581 	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6582 
6583 	/*
6584 	 * Request SCSI target for expedited processing
6585 	 */
6586 
6587 	/*
6588 	 * Set up for untagged queuing because we do not
6589 	 * know if the fibre device supports queuing.
6590 	 */
6591 	fcmd->fcp_cntl.cntl_reserved_0 = 0;
6592 	fcmd->fcp_cntl.cntl_reserved_1 = 0;
6593 	fcmd->fcp_cntl.cntl_reserved_2 = 0;
6594 	fcmd->fcp_cntl.cntl_reserved_3 = 0;
6595 	fcmd->fcp_cntl.cntl_reserved_4 = 0;
6596 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6597 	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6598 
6599 	switch (opcode) {
6600 	case SCMD_INQUIRY_PAGE83:
6601 		/*
6602 		 * Prepare to get the Inquiry VPD page 83 information
6603 		 */
6604 		fcmd->fcp_cntl.cntl_read_data = 1;
6605 		fcmd->fcp_cntl.cntl_write_data = 0;
6606 		fcmd->fcp_data_len = alloc_len;
6607 
6608 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6609 		fpkt->pkt_comp = fcp_scsi_callback;
6610 
6611 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6612 		scsi_cdb->g0_addr2 = 0x01;
6613 		scsi_cdb->g0_addr1 = 0x83;
6614 		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6615 		break;
6616 
6617 	case SCMD_INQUIRY:
6618 		fcmd->fcp_cntl.cntl_read_data = 1;
6619 		fcmd->fcp_cntl.cntl_write_data = 0;
6620 		fcmd->fcp_data_len = alloc_len;
6621 
6622 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6623 		fpkt->pkt_comp = fcp_scsi_callback;
6624 
6625 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6626 		scsi_cdb->g0_count0 = SUN_INQSIZE;
6627 		break;
6628 
6629 	case SCMD_REPORT_LUN: {
6630 		fc_portid_t	d_id;
6631 		opaque_t	fca_dev;
6632 
6633 		ASSERT(alloc_len >= 16);
6634 
6635 		d_id.priv_lilp_posit = 0;
6636 		d_id.port_id = ptgt->tgt_d_id;
6637 
6638 		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6639 
6640 		mutex_enter(&ptgt->tgt_mutex);
6641 		ptgt->tgt_fca_dev = fca_dev;
6642 		mutex_exit(&ptgt->tgt_mutex);
6643 
6644 		fcmd->fcp_cntl.cntl_read_data = 1;
6645 		fcmd->fcp_cntl.cntl_write_data = 0;
6646 		fcmd->fcp_data_len = alloc_len;
6647 
6648 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6649 		fpkt->pkt_comp = fcp_scsi_callback;
6650 
6651 		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6652 		scsi_cdb->scc5_count0 = alloc_len & 0xff;
6653 		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6654 		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6655 		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6656 		break;
6657 	}
6658 
6659 	default:
6660 		fcp_log(CE_WARN, pptr->port_dip,
6661 		    "!fcp_send_scsi Invalid opcode");
6662 		break;
6663 	}
6664 
6665 	if (!nodma) {
6666 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6667 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6668 	}
6669 
6670 	mutex_enter(&pptr->port_mutex);
6671 	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6672 
6673 		mutex_exit(&pptr->port_mutex);
6674 		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6675 		    FC_SUCCESS) {
6676 			fcp_icmd_free(pptr, icmd);
6677 			return (DDI_FAILURE);
6678 		}
6679 		return (DDI_SUCCESS);
6680 	} else {
6681 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6682 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6683 		    "fcp_send_scsi,1: state change occured"
6684 		    " for D_ID=0x%x", ptgt->tgt_d_id);
6685 		mutex_exit(&pptr->port_mutex);
6686 		fcp_icmd_free(pptr, icmd);
6687 		return (DDI_FAILURE);
6688 	}
6689 }
6690 
6691 
6692 /*
6693  * called by fcp_scsi_callback to check to handle the case where
6694  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6695  */
6696 static int
6697 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6698 {
6699 	uchar_t				rqlen;
6700 	int				rval = DDI_FAILURE;
6701 	struct scsi_extended_sense	sense_info, *sense;
6702 	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
6703 	    fpkt->pkt_ulp_private;
6704 	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
6705 	struct fcp_port		*pptr = ptgt->tgt_port;
6706 
6707 	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6708 
6709 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6710 		/*
6711 		 * SCSI-II Reserve Release support. Some older FC drives return
6712 		 * Reservation conflict for Report Luns command.
6713 		 */
6714 		if (icmd->ipkt_nodma) {
6715 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6716 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6717 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6718 		} else {
6719 			fcp_rsp_t	new_resp;
6720 
6721 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6722 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6723 
6724 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6725 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6726 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6727 
6728 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6729 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6730 		}
6731 
6732 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6733 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6734 
6735 		return (DDI_SUCCESS);
6736 	}
6737 
6738 	sense = &sense_info;
6739 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
6740 		/* no need to continue if sense length is not set */
6741 		return (rval);
6742 	}
6743 
6744 	/* casting 64-bit integer to 8-bit */
6745 	rqlen = (uchar_t)min(rsp->fcp_sense_len,
6746 	    sizeof (struct scsi_extended_sense));
6747 
6748 	if (rqlen < 14) {
6749 		/* no need to continue if request length isn't long enough */
6750 		return (rval);
6751 	}
6752 
6753 	if (icmd->ipkt_nodma) {
6754 		/*
6755 		 * We can safely use fcp_response_len here since the
6756 		 * only path that calls fcp_check_reportlun,
6757 		 * fcp_scsi_callback, has already called
6758 		 * fcp_validate_fcp_response.
6759 		 */
6760 		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6761 		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6762 	} else {
6763 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6764 		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6765 		    sizeof (struct scsi_extended_sense));
6766 	}
6767 
6768 	if (!FCP_SENSE_NO_LUN(sense)) {
6769 		mutex_enter(&ptgt->tgt_mutex);
6770 		/* clear the flag if any */
6771 		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6772 		mutex_exit(&ptgt->tgt_mutex);
6773 	}
6774 
6775 	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6776 	    (sense->es_add_code == 0x20)) {
6777 		if (icmd->ipkt_nodma) {
6778 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6779 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6780 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6781 		} else {
6782 			fcp_rsp_t	new_resp;
6783 
6784 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6785 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6786 
6787 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6788 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6789 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6790 
6791 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6792 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6793 		}
6794 
6795 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6796 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6797 
6798 		return (DDI_SUCCESS);
6799 	}
6800 
6801 	/*
6802 	 * This is for the STK library which returns a check condition,
6803 	 * to indicate device is not ready, manual assistance needed.
6804 	 * This is to a report lun command when the door is open.
6805 	 */
6806 	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6807 		if (icmd->ipkt_nodma) {
6808 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6809 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6810 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6811 		} else {
6812 			fcp_rsp_t	new_resp;
6813 
6814 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6815 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6816 
6817 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6818 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6819 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6820 
6821 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6822 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6823 		}
6824 
6825 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6826 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6827 
6828 		return (DDI_SUCCESS);
6829 	}
6830 
6831 	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6832 	    (FCP_SENSE_NO_LUN(sense))) {
6833 		mutex_enter(&ptgt->tgt_mutex);
6834 		if ((FCP_SENSE_NO_LUN(sense)) &&
6835 		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6836 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6837 			mutex_exit(&ptgt->tgt_mutex);
6838 			/*
6839 			 * reconfig was triggred by ILLEGAL REQUEST but
6840 			 * got ILLEGAL REQUEST again
6841 			 */
6842 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6843 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
6844 			    "!FCP: Unable to obtain Report Lun data"
6845 			    " target=%x", ptgt->tgt_d_id);
6846 		} else {
6847 			if (ptgt->tgt_tid == NULL) {
6848 				timeout_id_t	tid;
6849 				/*
6850 				 * REPORT LUN data has changed.	 Kick off
6851 				 * rediscovery
6852 				 */
6853 				tid = timeout(fcp_reconfigure_luns,
6854 				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6855 
6856 				ptgt->tgt_tid = tid;
6857 				ptgt->tgt_state |= FCP_TGT_BUSY;
6858 			}
6859 			if (FCP_SENSE_NO_LUN(sense)) {
6860 				ptgt->tgt_state |= FCP_TGT_ILLREQ;
6861 			}
6862 			mutex_exit(&ptgt->tgt_mutex);
6863 			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6864 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6865 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6866 				    "!FCP:Report Lun Has Changed"
6867 				    " target=%x", ptgt->tgt_d_id);
6868 			} else if (FCP_SENSE_NO_LUN(sense)) {
6869 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6870 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6871 				    "!FCP:LU Not Supported"
6872 				    " target=%x", ptgt->tgt_d_id);
6873 			}
6874 		}
6875 		rval = DDI_SUCCESS;
6876 	}
6877 
6878 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6879 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6880 	    "D_ID=%x, sense=%x, status=%x",
6881 	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6882 	    rsp->fcp_u.fcp_status.scsi_status);
6883 
6884 	return (rval);
6885 }
6886 
6887 /*
6888  *     Function: fcp_scsi_callback
6889  *
6890  *  Description: This is the callback routine set by fcp_send_scsi() after
6891  *		 it calls fcp_icmd_alloc().  The SCSI command completed here
6892  *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
6893  *		 INQUIRY_PAGE83.
6894  *
6895  *     Argument: *fpkt	 FC packet used to convey the command
6896  *
6897  * Return Value: None
6898  */
6899 static void
6900 fcp_scsi_callback(fc_packet_t *fpkt)
6901 {
6902 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
6903 	    fpkt->pkt_ulp_private;
6904 	struct fcp_rsp_info	fcp_rsp_err, *bep;
6905 	struct fcp_port	*pptr;
6906 	struct fcp_tgt	*ptgt;
6907 	struct fcp_lun	*plun;
6908 	struct fcp_rsp		response, *rsp;
6909 
6910 	ptgt = icmd->ipkt_tgt;
6911 	pptr = ptgt->tgt_port;
6912 	plun = icmd->ipkt_lun;
6913 
6914 	if (icmd->ipkt_nodma) {
6915 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6916 	} else {
6917 		rsp = &response;
6918 		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6919 		    sizeof (struct fcp_rsp));
6920 	}
6921 
6922 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6923 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6924 	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
6925 	    "status=%x, lun num=%x",
6926 	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6927 	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6928 
6929 	/*
6930 	 * Pre-init LUN GUID with NWWN if it is not a device that
6931 	 * supports multiple luns and we know it's not page83
6932 	 * compliant.  Although using a NWWN is not lun unique,
6933 	 * we will be fine since there is only one lun behind the taget
6934 	 * in this case.
6935 	 */
6936 	if ((plun->lun_guid_size == 0) &&
6937 	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6938 	    (fcp_symmetric_device_probe(plun) == 0)) {
6939 
6940 		char ascii_wwn[FC_WWN_SIZE*2+1];
6941 		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6942 		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6943 	}
6944 
6945 	/*
6946 	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6947 	 * when thay have more data than what is asked in CDB. An overrun
6948 	 * is really when FCP_DL is smaller than the data length in CDB.
6949 	 * In the case here we know that REPORT LUN command we formed within
6950 	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6951 	 * behavior. In reality this is FC_SUCCESS.
6952 	 */
6953 	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6954 	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6955 	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6956 		fpkt->pkt_state = FC_PKT_SUCCESS;
6957 	}
6958 
6959 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6960 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6961 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6962 		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6963 		    ptgt->tgt_d_id);
6964 
6965 		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6966 			/*
6967 			 * Inquiry VPD page command on A5K SES devices would
6968 			 * result in data CRC errors.
6969 			 */
6970 			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6971 				(void) fcp_handle_page83(fpkt, icmd, 1);
6972 				return;
6973 			}
6974 		}
6975 		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6976 		    FCP_MUST_RETRY(fpkt)) {
6977 			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6978 			fcp_retry_scsi_cmd(fpkt);
6979 			return;
6980 		}
6981 
6982 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6983 		    FCP_TGT_TRACE_20);
6984 
6985 		mutex_enter(&pptr->port_mutex);
6986 		mutex_enter(&ptgt->tgt_mutex);
6987 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6988 			mutex_exit(&ptgt->tgt_mutex);
6989 			mutex_exit(&pptr->port_mutex);
6990 			fcp_print_error(fpkt);
6991 		} else {
6992 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6993 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6994 			    "fcp_scsi_callback,1: state change occured"
6995 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6996 			mutex_exit(&ptgt->tgt_mutex);
6997 			mutex_exit(&pptr->port_mutex);
6998 		}
6999 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7000 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7001 		fcp_icmd_free(pptr, icmd);
7002 		return;
7003 	}
7004 
7005 	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7006 
7007 	mutex_enter(&pptr->port_mutex);
7008 	mutex_enter(&ptgt->tgt_mutex);
7009 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7010 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7011 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7012 		    "fcp_scsi_callback,2: state change occured"
7013 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7014 		mutex_exit(&ptgt->tgt_mutex);
7015 		mutex_exit(&pptr->port_mutex);
7016 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7017 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7018 		fcp_icmd_free(pptr, icmd);
7019 		return;
7020 	}
7021 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7022 
7023 	mutex_exit(&ptgt->tgt_mutex);
7024 	mutex_exit(&pptr->port_mutex);
7025 
7026 	if (icmd->ipkt_nodma) {
7027 		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7028 		    sizeof (struct fcp_rsp));
7029 	} else {
7030 		bep = &fcp_rsp_err;
7031 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7032 		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7033 	}
7034 
7035 	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7036 		fcp_retry_scsi_cmd(fpkt);
7037 		return;
7038 	}
7039 
7040 	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7041 	    FCP_NO_FAILURE) {
7042 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7043 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7044 		    "rsp_code=0x%x, rsp_len_set=0x%x",
7045 		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7046 		fcp_retry_scsi_cmd(fpkt);
7047 		return;
7048 	}
7049 
7050 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7051 	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7052 		fcp_queue_ipkt(pptr, fpkt);
7053 		return;
7054 	}
7055 
7056 	/*
7057 	 * Devices that do not support INQUIRY_PAGE83, return check condition
7058 	 * with illegal request as per SCSI spec.
7059 	 * Crossbridge is one such device and Daktari's SES node is another.
7060 	 * We want to ideally enumerate these devices as a non-mpxio devices.
7061 	 * SES nodes (Daktari only currently) are an exception to this.
7062 	 */
7063 	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7064 	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7065 
7066 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7067 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
7068 		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7069 		    "check condition. May enumerate as non-mpxio device",
7070 		    ptgt->tgt_d_id, plun->lun_type);
7071 
7072 		/*
7073 		 * If we let Daktari's SES be enumerated as a non-mpxio
7074 		 * device, there will be a discrepency in that the other
7075 		 * internal FC disks will get enumerated as mpxio devices.
7076 		 * Applications like luxadm expect this to be consistent.
7077 		 *
7078 		 * So, we put in a hack here to check if this is an SES device
7079 		 * and handle it here.
7080 		 */
7081 		if (plun->lun_type == DTYPE_ESI) {
7082 			/*
7083 			 * Since, pkt_state is actually FC_PKT_SUCCESS
7084 			 * at this stage, we fake a failure here so that
7085 			 * fcp_handle_page83 will create a device path using
7086 			 * the WWN instead of the GUID which is not there anyway
7087 			 */
7088 			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7089 			(void) fcp_handle_page83(fpkt, icmd, 1);
7090 			return;
7091 		}
7092 
7093 		mutex_enter(&ptgt->tgt_mutex);
7094 		plun->lun_state &= ~(FCP_LUN_OFFLINE |
7095 		    FCP_LUN_MARK | FCP_LUN_BUSY);
7096 		mutex_exit(&ptgt->tgt_mutex);
7097 
7098 		(void) fcp_call_finish_init(pptr, ptgt,
7099 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7100 		    icmd->ipkt_cause);
7101 		fcp_icmd_free(pptr, icmd);
7102 		return;
7103 	}
7104 
7105 	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7106 		int rval = DDI_FAILURE;
7107 
7108 		/*
7109 		 * handle cases where report lun isn't supported
7110 		 * by faking up our own REPORT_LUN response or
7111 		 * UNIT ATTENTION
7112 		 */
7113 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7114 			rval = fcp_check_reportlun(rsp, fpkt);
7115 
7116 			/*
7117 			 * fcp_check_reportlun might have modified the
7118 			 * FCP response. Copy it in again to get an updated
7119 			 * FCP response
7120 			 */
7121 			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7122 				rsp = &response;
7123 
7124 				FCP_CP_IN(fpkt->pkt_resp, rsp,
7125 				    fpkt->pkt_resp_acc,
7126 				    sizeof (struct fcp_rsp));
7127 			}
7128 		}
7129 
7130 		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7131 			if (rval == DDI_SUCCESS) {
7132 				(void) fcp_call_finish_init(pptr, ptgt,
7133 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7134 				    icmd->ipkt_cause);
7135 				fcp_icmd_free(pptr, icmd);
7136 			} else {
7137 				fcp_retry_scsi_cmd(fpkt);
7138 			}
7139 
7140 			return;
7141 		}
7142 	} else {
7143 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7144 			mutex_enter(&ptgt->tgt_mutex);
7145 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7146 			mutex_exit(&ptgt->tgt_mutex);
7147 		}
7148 	}
7149 
7150 	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7151 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7152 		(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7153 		    DDI_DMA_SYNC_FORCPU);
7154 	}
7155 
7156 	switch (icmd->ipkt_opcode) {
7157 	case SCMD_INQUIRY:
7158 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7159 		fcp_handle_inquiry(fpkt, icmd);
7160 		break;
7161 
7162 	case SCMD_REPORT_LUN:
7163 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7164 		    FCP_TGT_TRACE_22);
7165 		fcp_handle_reportlun(fpkt, icmd);
7166 		break;
7167 
7168 	case SCMD_INQUIRY_PAGE83:
7169 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7170 		(void) fcp_handle_page83(fpkt, icmd, 0);
7171 		break;
7172 
7173 	default:
7174 		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7175 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7176 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7177 		fcp_icmd_free(pptr, icmd);
7178 		break;
7179 	}
7180 }
7181 
7182 
7183 static void
7184 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7185 {
7186 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
7187 	    fpkt->pkt_ulp_private;
7188 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
7189 	struct fcp_port	*pptr = ptgt->tgt_port;
7190 
7191 	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7192 	    fcp_is_retryable(icmd)) {
7193 		mutex_enter(&pptr->port_mutex);
7194 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7195 			mutex_exit(&pptr->port_mutex);
7196 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7197 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7198 			    "Retrying %s to %x; state=%x, reason=%x",
7199 			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7200 			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7201 			    fpkt->pkt_state, fpkt->pkt_reason);
7202 
7203 			fcp_queue_ipkt(pptr, fpkt);
7204 		} else {
7205 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7206 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7207 			    "fcp_retry_scsi_cmd,1: state change occured"
7208 			    " for D_ID=0x%x", ptgt->tgt_d_id);
7209 			mutex_exit(&pptr->port_mutex);
7210 			(void) fcp_call_finish_init(pptr, ptgt,
7211 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7212 			    icmd->ipkt_cause);
7213 			fcp_icmd_free(pptr, icmd);
7214 		}
7215 	} else {
7216 		fcp_print_error(fpkt);
7217 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7218 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7219 		fcp_icmd_free(pptr, icmd);
7220 	}
7221 }
7222 
7223 /*
7224  *     Function: fcp_handle_page83
7225  *
7226  *  Description: Treats the response to INQUIRY_PAGE83.
7227  *
7228  *     Argument: *fpkt	FC packet used to convey the command.
7229  *		 *icmd	Original fcp_ipkt structure.
7230  *		 ignore_page83_data
7231  *			if it's 1, that means it's a special devices's
7232  *			page83 response, it should be enumerated under mpxio
7233  *
7234  * Return Value: None
7235  */
7236 static void
7237 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7238     int ignore_page83_data)
7239 {
7240 	struct fcp_port	*pptr;
7241 	struct fcp_lun	*plun;
7242 	struct fcp_tgt	*ptgt;
7243 	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7244 	int			fail = 0;
7245 	ddi_devid_t		devid;
7246 	char			*guid = NULL;
7247 	int			ret;
7248 
7249 	ASSERT(icmd != NULL && fpkt != NULL);
7250 
7251 	pptr = icmd->ipkt_port;
7252 	ptgt = icmd->ipkt_tgt;
7253 	plun = icmd->ipkt_lun;
7254 
7255 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7256 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7257 
7258 		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7259 		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
7260 
7261 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7262 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7263 		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7264 		    "dtype=0x%x, lun num=%x",
7265 		    pptr->port_instance, ptgt->tgt_d_id,
7266 		    dev_id_page[0], plun->lun_num);
7267 
7268 		ret = ddi_devid_scsi_encode(
7269 		    DEVID_SCSI_ENCODE_VERSION_LATEST,
7270 		    NULL,		/* driver name */
7271 		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
7272 		    sizeof (plun->lun_inq), /* size of standard inquiry */
7273 		    NULL,		/* page 80 data */
7274 		    0,		/* page 80 len */
7275 		    dev_id_page,	/* page 83 data */
7276 		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7277 		    &devid);
7278 
7279 		if (ret == DDI_SUCCESS) {
7280 
7281 			guid = ddi_devid_to_guid(devid);
7282 
7283 			if (guid) {
7284 				/*
7285 				 * Check our current guid.  If it's non null
7286 				 * and it has changed, we need to copy it into
7287 				 * lun_old_guid since we might still need it.
7288 				 */
7289 				if (plun->lun_guid &&
7290 				    strcmp(guid, plun->lun_guid)) {
7291 					unsigned int len;
7292 
7293 					/*
7294 					 * If the guid of the LUN changes,
7295 					 * reconfiguration should be triggered
7296 					 * to reflect the changes.
7297 					 * i.e. we should offline the LUN with
7298 					 * the old guid, and online the LUN with
7299 					 * the new guid.
7300 					 */
7301 					plun->lun_state |= FCP_LUN_CHANGED;
7302 
7303 					if (plun->lun_old_guid) {
7304 						kmem_free(plun->lun_old_guid,
7305 						    plun->lun_old_guid_size);
7306 					}
7307 
7308 					len = plun->lun_guid_size;
7309 					plun->lun_old_guid_size = len;
7310 
7311 					plun->lun_old_guid = kmem_zalloc(len,
7312 					    KM_NOSLEEP);
7313 
7314 					if (plun->lun_old_guid) {
7315 						/*
7316 						 * The alloc was successful then
7317 						 * let's do the copy.
7318 						 */
7319 						bcopy(plun->lun_guid,
7320 						    plun->lun_old_guid, len);
7321 					} else {
7322 						fail = 1;
7323 						plun->lun_old_guid_size = 0;
7324 					}
7325 				}
7326 				if (!fail) {
7327 					if (fcp_copy_guid_2_lun_block(
7328 					    plun, guid)) {
7329 						fail = 1;
7330 					}
7331 				}
7332 				ddi_devid_free_guid(guid);
7333 
7334 			} else {
7335 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7336 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
7337 				    "fcp_handle_page83: unable to create "
7338 				    "GUID");
7339 
7340 				/* couldn't create good guid from devid */
7341 				fail = 1;
7342 			}
7343 			ddi_devid_free(devid);
7344 
7345 		} else if (ret == DDI_NOT_WELL_FORMED) {
7346 			/* NULL filled data for page 83 */
7347 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7348 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7349 			    "fcp_handle_page83: retry GUID");
7350 
7351 			icmd->ipkt_retries = 0;
7352 			fcp_retry_scsi_cmd(fpkt);
7353 			return;
7354 		} else {
7355 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7356 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7357 			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7358 			    ret);
7359 			/*
7360 			 * Since the page83 validation
7361 			 * introduced late, we are being
7362 			 * tolerant to the existing devices
7363 			 * that already found to be working
7364 			 * under mpxio, like A5200's SES device,
7365 			 * its page83 response will not be standard-compliant,
7366 			 * but we still want it to be enumerated under mpxio.
7367 			 */
7368 			if (fcp_symmetric_device_probe(plun) != 0) {
7369 				fail = 1;
7370 			}
7371 		}
7372 
7373 	} else {
7374 		/* bad packet state */
7375 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7376 
7377 		/*
7378 		 * For some special devices (A5K SES and Daktari's SES devices),
7379 		 * they should be enumerated under mpxio
7380 		 * or "luxadm dis" will fail
7381 		 */
7382 		if (ignore_page83_data) {
7383 			fail = 0;
7384 		} else {
7385 			fail = 1;
7386 		}
7387 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7388 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7389 		    "!Devid page cmd failed. "
7390 		    "fpkt_state: %x fpkt_reason: %x",
7391 		    "ignore_page83: %d",
7392 		    fpkt->pkt_state, fpkt->pkt_reason,
7393 		    ignore_page83_data);
7394 	}
7395 
7396 	mutex_enter(&pptr->port_mutex);
7397 	mutex_enter(&plun->lun_mutex);
7398 	/*
7399 	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7400 	 * mismatch between lun_cip and lun_mpxio.
7401 	 */
7402 	if (plun->lun_cip == NULL) {
7403 		/*
7404 		 * If we don't have a guid for this lun it's because we were
7405 		 * unable to glean one from the page 83 response.  Set the
7406 		 * control flag to 0 here to make sure that we don't attempt to
7407 		 * enumerate it under mpxio.
7408 		 */
7409 		if (fail || pptr->port_mpxio == 0) {
7410 			plun->lun_mpxio = 0;
7411 		} else {
7412 			plun->lun_mpxio = 1;
7413 		}
7414 	}
7415 	mutex_exit(&plun->lun_mutex);
7416 	mutex_exit(&pptr->port_mutex);
7417 
7418 	mutex_enter(&ptgt->tgt_mutex);
7419 	plun->lun_state &=
7420 	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7421 	mutex_exit(&ptgt->tgt_mutex);
7422 
7423 	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7424 	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7425 
7426 	fcp_icmd_free(pptr, icmd);
7427 }
7428 
7429 /*
7430  *     Function: fcp_handle_inquiry
7431  *
7432  *  Description: Called by fcp_scsi_callback to handle the response to an
7433  *		 INQUIRY request.
7434  *
7435  *     Argument: *fpkt	FC packet used to convey the command.
7436  *		 *icmd	Original fcp_ipkt structure.
7437  *
7438  * Return Value: None
7439  */
7440 static void
7441 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7442 {
7443 	struct fcp_port	*pptr;
7444 	struct fcp_lun	*plun;
7445 	struct fcp_tgt	*ptgt;
7446 	uchar_t		dtype;
7447 	uchar_t		pqual;
7448 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
7449 
7450 	ASSERT(icmd != NULL && fpkt != NULL);
7451 
7452 	pptr = icmd->ipkt_port;
7453 	ptgt = icmd->ipkt_tgt;
7454 	plun = icmd->ipkt_lun;
7455 
7456 	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7457 	    sizeof (struct scsi_inquiry));
7458 
7459 	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7460 	pqual = plun->lun_inq.inq_dtype >> 5;
7461 
7462 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7463 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7464 	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7465 	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7466 	    plun->lun_num, dtype, pqual);
7467 
7468 	if (pqual != 0) {
7469 		/*
7470 		 * Non-zero peripheral qualifier
7471 		 */
7472 		fcp_log(CE_CONT, pptr->port_dip,
7473 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7474 		    "Device type=0x%x Peripheral qual=0x%x\n",
7475 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7476 
7477 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7478 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7479 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7480 		    "Device type=0x%x Peripheral qual=0x%x\n",
7481 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7482 
7483 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7484 
7485 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7486 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7487 		fcp_icmd_free(pptr, icmd);
7488 		return;
7489 	}
7490 
7491 	/*
7492 	 * If the device is already initialized, check the dtype
7493 	 * for a change. If it has changed then update the flags
7494 	 * so the create_luns will offline the old device and
7495 	 * create the new device. Refer to bug: 4764752
7496 	 */
7497 	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7498 		plun->lun_state |= FCP_LUN_CHANGED;
7499 	}
7500 	plun->lun_type = plun->lun_inq.inq_dtype;
7501 
7502 	/*
7503 	 * This code is setting/initializing the throttling in the FCA
7504 	 * driver.
7505 	 */
7506 	mutex_enter(&pptr->port_mutex);
7507 	if (!pptr->port_notify) {
7508 		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7509 			uint32_t cmd = 0;
7510 			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7511 			    ((cmd & 0xFFFFFF00 >> 8) |
7512 			    FCP_SVE_THROTTLE << 8));
7513 			pptr->port_notify = 1;
7514 			mutex_exit(&pptr->port_mutex);
7515 			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7516 			mutex_enter(&pptr->port_mutex);
7517 		}
7518 	}
7519 
7520 	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7521 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7522 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7523 		    "fcp_handle_inquiry,1:state change occured"
7524 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7525 		mutex_exit(&pptr->port_mutex);
7526 
7527 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7528 		(void) fcp_call_finish_init(pptr, ptgt,
7529 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7530 		    icmd->ipkt_cause);
7531 		fcp_icmd_free(pptr, icmd);
7532 		return;
7533 	}
7534 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7535 	mutex_exit(&pptr->port_mutex);
7536 
7537 	/* Retrieve the rscn count (if a valid one exists) */
7538 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7539 		rscn_count = ((fc_ulp_rscn_info_t *)
7540 		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7541 	} else {
7542 		rscn_count = FC_INVALID_RSCN_COUNT;
7543 	}
7544 
7545 	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7546 	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
7547 	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7548 	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7549 		fcp_log(CE_WARN, NULL, "!failed to send page 83");
7550 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7551 		(void) fcp_call_finish_init(pptr, ptgt,
7552 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7553 		    icmd->ipkt_cause);
7554 	}
7555 
7556 	/*
7557 	 * Read Inquiry VPD Page 0x83 to uniquely
7558 	 * identify this logical unit.
7559 	 */
7560 	fcp_icmd_free(pptr, icmd);
7561 }
7562 
7563 /*
7564  *     Function: fcp_handle_reportlun
7565  *
7566  *  Description: Called by fcp_scsi_callback to handle the response to a
7567  *		 REPORT_LUN request.
7568  *
7569  *     Argument: *fpkt	FC packet used to convey the command.
7570  *		 *icmd	Original fcp_ipkt structure.
7571  *
7572  * Return Value: None
7573  */
7574 static void
7575 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7576 {
7577 	int				i;
7578 	int				nluns_claimed;
7579 	int				nluns_bufmax;
7580 	int				len;
7581 	uint16_t			lun_num;
7582 	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
7583 	struct fcp_port			*pptr;
7584 	struct fcp_tgt			*ptgt;
7585 	struct fcp_lun			*plun;
7586 	struct fcp_reportlun_resp	*report_lun;
7587 
7588 	pptr = icmd->ipkt_port;
7589 	ptgt = icmd->ipkt_tgt;
7590 	len = fpkt->pkt_datalen;
7591 
7592 	if ((len < FCP_LUN_HEADER) ||
7593 	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7594 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7595 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7596 		fcp_icmd_free(pptr, icmd);
7597 		return;
7598 	}
7599 
7600 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7601 	    fpkt->pkt_datalen);
7602 
7603 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7604 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7605 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7606 	    pptr->port_instance, ptgt->tgt_d_id);
7607 
7608 	/*
7609 	 * Get the number of luns (which is supplied as LUNS * 8) the
7610 	 * device claims it has.
7611 	 */
7612 	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7613 
7614 	/*
7615 	 * Get the maximum number of luns the buffer submitted can hold.
7616 	 */
7617 	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7618 
7619 	/*
7620 	 * Due to limitations of certain hardware, we support only 16 bit LUNs
7621 	 */
7622 	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7623 		kmem_free(report_lun, len);
7624 
7625 		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7626 		    " 0x%x number of LUNs for target=%x", nluns_claimed,
7627 		    ptgt->tgt_d_id);
7628 
7629 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7630 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7631 		fcp_icmd_free(pptr, icmd);
7632 		return;
7633 	}
7634 
7635 	/*
7636 	 * If there are more LUNs than we have allocated memory for,
7637 	 * allocate more space and send down yet another report lun if
7638 	 * the maximum number of attempts hasn't been reached.
7639 	 */
7640 	mutex_enter(&ptgt->tgt_mutex);
7641 
7642 	if ((nluns_claimed > nluns_bufmax) &&
7643 	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7644 
7645 		struct fcp_lun *plun;
7646 
7647 		ptgt->tgt_report_lun_cnt++;
7648 		plun = ptgt->tgt_lun;
7649 		ASSERT(plun != NULL);
7650 		mutex_exit(&ptgt->tgt_mutex);
7651 
7652 		kmem_free(report_lun, len);
7653 
7654 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7655 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7656 		    "!Dynamically discovered %d LUNs for D_ID=%x",
7657 		    nluns_claimed, ptgt->tgt_d_id);
7658 
7659 		/* Retrieve the rscn count (if a valid one exists) */
7660 		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7661 			rscn_count = ((fc_ulp_rscn_info_t *)
7662 			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7663 			    ulp_rscn_count;
7664 		} else {
7665 			rscn_count = FC_INVALID_RSCN_COUNT;
7666 		}
7667 
7668 		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7669 		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7670 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7671 		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7672 			(void) fcp_call_finish_init(pptr, ptgt,
7673 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7674 			    icmd->ipkt_cause);
7675 		}
7676 
7677 		fcp_icmd_free(pptr, icmd);
7678 		return;
7679 	}
7680 
7681 	if (nluns_claimed > nluns_bufmax) {
7682 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7683 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7684 		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7685 		    "	 Number of LUNs lost=%x",
7686 		    ptgt->tgt_port_wwn.raw_wwn[0],
7687 		    ptgt->tgt_port_wwn.raw_wwn[1],
7688 		    ptgt->tgt_port_wwn.raw_wwn[2],
7689 		    ptgt->tgt_port_wwn.raw_wwn[3],
7690 		    ptgt->tgt_port_wwn.raw_wwn[4],
7691 		    ptgt->tgt_port_wwn.raw_wwn[5],
7692 		    ptgt->tgt_port_wwn.raw_wwn[6],
7693 		    ptgt->tgt_port_wwn.raw_wwn[7],
7694 		    nluns_claimed - nluns_bufmax);
7695 
7696 		nluns_claimed = nluns_bufmax;
7697 	}
7698 	ptgt->tgt_lun_cnt = nluns_claimed;
7699 
7700 	/*
7701 	 * Identify missing LUNs and print warning messages
7702 	 */
7703 	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7704 		int offline;
7705 		int exists = 0;
7706 
7707 		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7708 
7709 		for (i = 0; i < nluns_claimed && exists == 0; i++) {
7710 			uchar_t		*lun_string;
7711 
7712 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7713 
7714 			switch (lun_string[0] & 0xC0) {
7715 			case FCP_LUN_ADDRESSING:
7716 			case FCP_PD_ADDRESSING:
7717 			case FCP_VOLUME_ADDRESSING:
7718 				lun_num = ((lun_string[0] & 0x3F) << 8) |
7719 				    lun_string[1];
7720 				if (plun->lun_num == lun_num) {
7721 					exists++;
7722 					break;
7723 				}
7724 				break;
7725 
7726 			default:
7727 				break;
7728 			}
7729 		}
7730 
7731 		if (!exists && !offline) {
7732 			mutex_exit(&ptgt->tgt_mutex);
7733 
7734 			mutex_enter(&pptr->port_mutex);
7735 			mutex_enter(&ptgt->tgt_mutex);
7736 			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7737 				/*
7738 				 * set disappear flag when device was connected
7739 				 */
7740 				if (!(plun->lun_state &
7741 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7742 					plun->lun_state |= FCP_LUN_DISAPPEARED;
7743 				}
7744 				mutex_exit(&ptgt->tgt_mutex);
7745 				mutex_exit(&pptr->port_mutex);
7746 				if (!(plun->lun_state &
7747 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7748 					fcp_log(CE_NOTE, pptr->port_dip,
7749 					    "!Lun=%x for target=%x disappeared",
7750 					    plun->lun_num, ptgt->tgt_d_id);
7751 				}
7752 				mutex_enter(&ptgt->tgt_mutex);
7753 			} else {
7754 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7755 				    fcp_trace, FCP_BUF_LEVEL_5, 0,
7756 				    "fcp_handle_reportlun,1: state change"
7757 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
7758 				mutex_exit(&ptgt->tgt_mutex);
7759 				mutex_exit(&pptr->port_mutex);
7760 				kmem_free(report_lun, len);
7761 				(void) fcp_call_finish_init(pptr, ptgt,
7762 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7763 				    icmd->ipkt_cause);
7764 				fcp_icmd_free(pptr, icmd);
7765 				return;
7766 			}
7767 		} else if (exists) {
7768 			/*
7769 			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7770 			 * actually exists in REPORT_LUN response
7771 			 */
7772 			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7773 				plun->lun_state &=
7774 				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
7775 			}
7776 			if (offline || plun->lun_num == 0) {
7777 				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7778 					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7779 					mutex_exit(&ptgt->tgt_mutex);
7780 					fcp_log(CE_NOTE, pptr->port_dip,
7781 					    "!Lun=%x for target=%x reappeared",
7782 					    plun->lun_num, ptgt->tgt_d_id);
7783 					mutex_enter(&ptgt->tgt_mutex);
7784 				}
7785 			}
7786 		}
7787 	}
7788 
7789 	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7790 	mutex_exit(&ptgt->tgt_mutex);
7791 
7792 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7793 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7794 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7795 	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7796 
7797 	/* scan each lun */
7798 	for (i = 0; i < nluns_claimed; i++) {
7799 		uchar_t	*lun_string;
7800 
7801 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7802 
7803 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7804 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7805 		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7806 		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7807 		    lun_string[0]);
7808 
7809 		switch (lun_string[0] & 0xC0) {
7810 		case FCP_LUN_ADDRESSING:
7811 		case FCP_PD_ADDRESSING:
7812 		case FCP_VOLUME_ADDRESSING:
7813 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7814 
7815 			/* We will skip masked LUNs because of the blacklist. */
7816 			if (fcp_lun_blacklist != NULL) {
7817 				mutex_enter(&ptgt->tgt_mutex);
7818 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
7819 				    lun_num) == TRUE) {
7820 					ptgt->tgt_lun_cnt--;
7821 					mutex_exit(&ptgt->tgt_mutex);
7822 					break;
7823 				}
7824 				mutex_exit(&ptgt->tgt_mutex);
7825 			}
7826 
7827 			/* see if this LUN is already allocated */
7828 			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7829 				plun = fcp_alloc_lun(ptgt);
7830 				if (plun == NULL) {
7831 					fcp_log(CE_NOTE, pptr->port_dip,
7832 					    "!Lun allocation failed"
7833 					    " target=%x lun=%x",
7834 					    ptgt->tgt_d_id, lun_num);
7835 					break;
7836 				}
7837 			}
7838 
7839 			mutex_enter(&plun->lun_tgt->tgt_mutex);
7840 			/* convert to LUN */
7841 			plun->lun_addr.ent_addr_0 =
7842 			    BE_16(*(uint16_t *)&(lun_string[0]));
7843 			plun->lun_addr.ent_addr_1 =
7844 			    BE_16(*(uint16_t *)&(lun_string[2]));
7845 			plun->lun_addr.ent_addr_2 =
7846 			    BE_16(*(uint16_t *)&(lun_string[4]));
7847 			plun->lun_addr.ent_addr_3 =
7848 			    BE_16(*(uint16_t *)&(lun_string[6]));
7849 
7850 			plun->lun_num = lun_num;
7851 			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7852 			plun->lun_state &= ~FCP_LUN_OFFLINE;
7853 			mutex_exit(&plun->lun_tgt->tgt_mutex);
7854 
7855 			/* Retrieve the rscn count (if a valid one exists) */
7856 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7857 				rscn_count = ((fc_ulp_rscn_info_t *)
7858 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7859 				    ulp_rscn_count;
7860 			} else {
7861 				rscn_count = FC_INVALID_RSCN_COUNT;
7862 			}
7863 
7864 			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7865 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7866 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7867 				mutex_enter(&pptr->port_mutex);
7868 				mutex_enter(&plun->lun_tgt->tgt_mutex);
7869 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7870 					fcp_log(CE_NOTE, pptr->port_dip,
7871 					    "!failed to send INQUIRY"
7872 					    " target=%x lun=%x",
7873 					    ptgt->tgt_d_id, plun->lun_num);
7874 				} else {
7875 					FCP_TRACE(fcp_logq,
7876 					    pptr->port_instbuf, fcp_trace,
7877 					    FCP_BUF_LEVEL_5, 0,
7878 					    "fcp_handle_reportlun,2: state"
7879 					    " change occured for D_ID=0x%x",
7880 					    ptgt->tgt_d_id);
7881 				}
7882 				mutex_exit(&plun->lun_tgt->tgt_mutex);
7883 				mutex_exit(&pptr->port_mutex);
7884 			} else {
7885 				continue;
7886 			}
7887 			break;
7888 
7889 		default:
7890 			fcp_log(CE_WARN, NULL,
7891 			    "!Unsupported LUN Addressing method %x "
7892 			    "in response to REPORT_LUN", lun_string[0]);
7893 			break;
7894 		}
7895 
7896 		/*
7897 		 * each time through this loop we should decrement
7898 		 * the tmp_cnt by one -- since we go through this loop
7899 		 * one time for each LUN, the tmp_cnt should never be <=0
7900 		 */
7901 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7902 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7903 	}
7904 
7905 	if (i == 0) {
7906 		fcp_log(CE_WARN, pptr->port_dip,
7907 		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7908 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7909 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7910 	}
7911 
7912 	kmem_free(report_lun, len);
7913 	fcp_icmd_free(pptr, icmd);
7914 }
7915 
7916 
7917 /*
7918  * called internally to return a LUN given a target and a LUN number
7919  */
7920 static struct fcp_lun *
7921 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7922 {
7923 	struct fcp_lun	*plun;
7924 
7925 	mutex_enter(&ptgt->tgt_mutex);
7926 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7927 		if (plun->lun_num == lun_num) {
7928 			mutex_exit(&ptgt->tgt_mutex);
7929 			return (plun);
7930 		}
7931 	}
7932 	mutex_exit(&ptgt->tgt_mutex);
7933 
7934 	return (NULL);
7935 }
7936 
7937 
7938 /*
7939  * handle finishing one target for fcp_finish_init
7940  *
7941  * return true (non-zero) if we want finish_init to continue with the
7942  * next target
7943  *
7944  * called with the port mutex held
7945  */
7946 /*ARGSUSED*/
7947 static int
7948 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7949     int link_cnt, int tgt_cnt, int cause)
7950 {
7951 	int	rval = 1;
7952 	ASSERT(pptr != NULL);
7953 	ASSERT(ptgt != NULL);
7954 
7955 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7956 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7957 	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7958 	    ptgt->tgt_state);
7959 
7960 	ASSERT(mutex_owned(&pptr->port_mutex));
7961 
7962 	if ((pptr->port_link_cnt != link_cnt) ||
7963 	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7964 		/*
7965 		 * oh oh -- another link reset or target change
7966 		 * must have occurred while we are in here
7967 		 */
7968 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7969 
7970 		return (0);
7971 	} else {
7972 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7973 	}
7974 
7975 	mutex_enter(&ptgt->tgt_mutex);
7976 
7977 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7978 		/*
7979 		 * tgt is not offline -- is it marked (i.e. needs
7980 		 * to be offlined) ??
7981 		 */
7982 		if (ptgt->tgt_state & FCP_TGT_MARK) {
7983 			/*
7984 			 * this target not offline *and*
7985 			 * marked
7986 			 */
7987 			ptgt->tgt_state &= ~FCP_TGT_MARK;
7988 			rval = fcp_offline_target(pptr, ptgt, link_cnt,
7989 			    tgt_cnt, 0, 0);
7990 		} else {
7991 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
7992 
7993 			/* create the LUNs */
7994 			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7995 				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7996 				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7997 				    cause);
7998 				ptgt->tgt_device_created = 1;
7999 			} else {
8000 				fcp_update_tgt_state(ptgt, FCP_RESET,
8001 				    FCP_LUN_BUSY);
8002 			}
8003 		}
8004 	}
8005 
8006 	mutex_exit(&ptgt->tgt_mutex);
8007 
8008 	return (rval);
8009 }
8010 
8011 
8012 /*
8013  * this routine is called to finish port initialization
8014  *
8015  * Each port has a "temp" counter -- when a state change happens (e.g.
8016  * port online), the temp count is set to the number of devices in the map.
8017  * Then, as each device gets "discovered", the temp counter is decremented
8018  * by one.  When this count reaches zero we know that all of the devices
8019  * in the map have been discovered (or an error has occurred), so we can
8020  * then finish initialization -- which is done by this routine (well, this
8021  * and fcp-finish_tgt())
8022  *
8023  * acquires and releases the global mutex
8024  *
8025  * called with the port mutex owned
8026  */
8027 static void
8028 fcp_finish_init(struct fcp_port *pptr)
8029 {
8030 #ifdef	DEBUG
8031 	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8032 	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8033 	    FCP_STACK_DEPTH);
8034 #endif /* DEBUG */
8035 
8036 	ASSERT(mutex_owned(&pptr->port_mutex));
8037 
8038 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8039 	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8040 	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8041 
8042 	if ((pptr->port_state & FCP_STATE_ONLINING) &&
8043 	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
8044 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8045 		pptr->port_state &= ~FCP_STATE_ONLINING;
8046 		pptr->port_state |= FCP_STATE_ONLINE;
8047 	}
8048 
8049 	/* Wake up threads waiting on config done */
8050 	cv_broadcast(&pptr->port_config_cv);
8051 }
8052 
8053 
8054 /*
8055  * called from fcp_finish_init to create the LUNs for a target
8056  *
8057  * called with the port mutex owned
8058  */
8059 static void
8060 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8061 {
8062 	struct fcp_lun	*plun;
8063 	struct fcp_port	*pptr;
8064 	child_info_t		*cip = NULL;
8065 
8066 	ASSERT(ptgt != NULL);
8067 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8068 
8069 	pptr = ptgt->tgt_port;
8070 
8071 	ASSERT(pptr != NULL);
8072 
8073 	/* scan all LUNs for this target */
8074 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8075 		if (plun->lun_state & FCP_LUN_OFFLINE) {
8076 			continue;
8077 		}
8078 
8079 		if (plun->lun_state & FCP_LUN_MARK) {
8080 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8081 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8082 			    "fcp_create_luns: offlining marked LUN!");
8083 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8084 			continue;
8085 		}
8086 
8087 		plun->lun_state &= ~FCP_LUN_BUSY;
8088 
8089 		/*
8090 		 * There are conditions in which FCP_LUN_INIT flag is cleared
8091 		 * but we have a valid plun->lun_cip. To cover this case also
8092 		 * CLEAR_BUSY whenever we have a valid lun_cip.
8093 		 */
8094 		if (plun->lun_mpxio && plun->lun_cip &&
8095 		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8096 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8097 		    0, 0))) {
8098 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8099 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8100 			    "fcp_create_luns: enable lun %p failed!",
8101 			    plun);
8102 		}
8103 
8104 		if (plun->lun_state & FCP_LUN_INIT &&
8105 		    !(plun->lun_state & FCP_LUN_CHANGED)) {
8106 			continue;
8107 		}
8108 
8109 		if (cause == FCP_CAUSE_USER_CREATE) {
8110 			continue;
8111 		}
8112 
8113 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
8114 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
8115 		    "create_luns: passing ONLINE elem to HP thread");
8116 
8117 		/*
8118 		 * If lun has changed, prepare for offlining the old path.
8119 		 * Do not offline the old path right now, since it may be
8120 		 * still opened.
8121 		 */
8122 		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8123 			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8124 		}
8125 
8126 		/* pass an ONLINE element to the hotplug thread */
8127 		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8128 		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8129 
8130 			/*
8131 			 * We can not synchronous attach (i.e pass
8132 			 * NDI_ONLINE_ATTACH) here as we might be
8133 			 * coming from an interrupt or callback
8134 			 * thread.
8135 			 */
8136 			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8137 			    link_cnt, tgt_cnt, 0, 0)) {
8138 				fcp_log(CE_CONT, pptr->port_dip,
8139 				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8140 				    plun->lun_tgt->tgt_d_id, plun->lun_num);
8141 			}
8142 		}
8143 	}
8144 }
8145 
8146 
8147 /*
8148  * function to online/offline devices
8149  */
8150 static int
8151 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8152     int online, int lcount, int tcount, int flags)
8153 {
8154 	int			rval = NDI_FAILURE;
8155 	boolean_t		enteredv;
8156 	child_info_t		*ccip;
8157 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
8158 	int			is_mpxio = pptr->port_mpxio;
8159 	dev_info_t		*cdip, *pdip;
8160 	char			*devname;
8161 
8162 	if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8163 		/*
8164 		 * When this event gets serviced, lun_cip and lun_mpxio
8165 		 * has changed, so it should be invalidated now.
8166 		 */
8167 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8168 		    FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8169 		    "plun: %p, cip: %p, what:%d", plun, cip, online);
8170 		return (rval);
8171 	}
8172 
8173 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8174 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
8175 	    "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8176 	    "flags=%x mpxio=%x\n",
8177 	    plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8178 	    plun->lun_mpxio);
8179 
8180 	/*
8181 	 * lun_mpxio needs checking here because we can end up in a race
8182 	 * condition where this task has been dispatched while lun_mpxio is
8183 	 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8184 	 * enable MPXIO for the LUN, but was unable to, and hence cleared
8185 	 * the flag. We rely on the serialization of the tasks here. We return
8186 	 * NDI_SUCCESS so any callers continue without reporting spurious
8187 	 * errors, and the still think we're an MPXIO LUN.
8188 	 */
8189 
8190 	if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8191 	    online == FCP_MPXIO_PATH_SET_BUSY) {
8192 		if (plun->lun_mpxio) {
8193 			rval = fcp_update_mpxio_path(plun, cip, online);
8194 		} else {
8195 			rval = NDI_SUCCESS;
8196 		}
8197 		return (rval);
8198 	}
8199 
8200 	/*
8201 	 * Explicit devfs_clean() due to ndi_devi_offline() not
8202 	 * executing devfs_clean() if parent lock is held.
8203 	 */
8204 	ASSERT(!servicing_interrupt());
8205 	if (online == FCP_OFFLINE) {
8206 		if (plun->lun_mpxio == 0) {
8207 			if (plun->lun_cip == cip) {
8208 				cdip = DIP(plun->lun_cip);
8209 			} else {
8210 				cdip = DIP(cip);
8211 			}
8212 		} else if ((plun->lun_cip == cip) && plun->lun_cip) {
8213 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8214 		} else if ((plun->lun_cip != cip) && cip) {
8215 			/*
8216 			 * This means a DTYPE/GUID change, we shall get the
8217 			 * dip of the old cip instead of the current lun_cip.
8218 			 */
8219 			cdip = mdi_pi_get_client(PIP(cip));
8220 		}
8221 		if (cdip) {
8222 			if (i_ddi_devi_attached(cdip)) {
8223 				pdip = ddi_get_parent(cdip);
8224 				devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8225 				ndi_devi_enter(pdip);
8226 				(void) ddi_deviname(cdip, devname);
8227 				/*
8228 				 * Release parent lock before calling
8229 				 * devfs_clean().
8230 				 */
8231 				ndi_devi_exit(pdip);
8232 				(void) devfs_clean(pdip, devname + 1,
8233 				    DV_CLEAN_FORCE);
8234 				kmem_free(devname, MAXNAMELEN + 1);
8235 			}
8236 		}
8237 	}
8238 
8239 	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8240 		return (NDI_FAILURE);
8241 	}
8242 
8243 	if (is_mpxio) {
8244 		mdi_devi_enter(pptr->port_dip, &enteredv);
8245 	} else {
8246 		ndi_devi_enter(pptr->port_dip);
8247 	}
8248 
8249 	mutex_enter(&pptr->port_mutex);
8250 	mutex_enter(&plun->lun_mutex);
8251 
8252 	if (online == FCP_ONLINE) {
8253 		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8254 		if (ccip == NULL) {
8255 			goto fail;
8256 		}
8257 	} else {
8258 		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8259 			goto fail;
8260 		}
8261 		ccip = cip;
8262 	}
8263 
8264 	if (online == FCP_ONLINE) {
8265 		rval = fcp_online_child(plun, ccip, lcount, tcount, flags);
8266 		fc_ulp_log_device_event(pptr->port_fp_handle,
8267 		    FC_ULP_DEVICE_ONLINE);
8268 	} else {
8269 		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags);
8270 		fc_ulp_log_device_event(pptr->port_fp_handle,
8271 		    FC_ULP_DEVICE_OFFLINE);
8272 	}
8273 
8274 fail:	mutex_exit(&plun->lun_mutex);
8275 	mutex_exit(&pptr->port_mutex);
8276 
8277 	if (is_mpxio) {
8278 		mdi_devi_exit(pptr->port_dip, enteredv);
8279 	} else {
8280 		ndi_devi_exit(pptr->port_dip);
8281 	}
8282 
8283 	fc_ulp_idle_port(pptr->port_fp_handle);
8284 
8285 	return (rval);
8286 }
8287 
8288 
8289 /*
8290  * take a target offline by taking all of its LUNs offline
8291  */
8292 /*ARGSUSED*/
8293 static int
8294 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8295     int link_cnt, int tgt_cnt, int nowait, int flags)
8296 {
8297 	struct fcp_tgt_elem	*elem;
8298 
8299 	ASSERT(mutex_owned(&pptr->port_mutex));
8300 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8301 
8302 	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8303 
8304 	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8305 	    ptgt->tgt_change_cnt)) {
8306 		mutex_exit(&ptgt->tgt_mutex);
8307 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8308 		mutex_enter(&ptgt->tgt_mutex);
8309 
8310 		return (0);
8311 	}
8312 
8313 	ptgt->tgt_pd_handle = NULL;
8314 	mutex_exit(&ptgt->tgt_mutex);
8315 	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8316 	mutex_enter(&ptgt->tgt_mutex);
8317 
8318 	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8319 
8320 	if (ptgt->tgt_tcap &&
8321 	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8322 		elem->flags = flags;
8323 		elem->time = fcp_watchdog_time;
8324 		if (nowait == 0) {
8325 			elem->time += fcp_offline_delay;
8326 		}
8327 		elem->ptgt = ptgt;
8328 		elem->link_cnt = link_cnt;
8329 		elem->tgt_cnt = tgt_cnt;
8330 		elem->next = pptr->port_offline_tgts;
8331 		pptr->port_offline_tgts = elem;
8332 	} else {
8333 		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8334 	}
8335 
8336 	return (1);
8337 }
8338 
8339 
8340 static void
8341 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8342     int link_cnt, int tgt_cnt, int flags)
8343 {
8344 	ASSERT(mutex_owned(&pptr->port_mutex));
8345 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8346 
8347 	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8348 	ptgt->tgt_state = FCP_TGT_OFFLINE;
8349 	ptgt->tgt_pd_handle = NULL;
8350 	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8351 }
8352 
8353 
8354 static void
8355 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8356     int flags)
8357 {
8358 	struct	fcp_lun	*plun;
8359 
8360 	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8361 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8362 
8363 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8364 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8365 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8366 		}
8367 	}
8368 }
8369 
8370 
8371 /*
8372  * take a LUN offline
8373  *
8374  * enters and leaves with the target mutex held, releasing it in the process
8375  *
8376  * allocates memory in non-sleep mode
8377  */
8378 static void
8379 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8380     int nowait, int flags)
8381 {
8382 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8383 	struct fcp_lun_elem	*elem;
8384 
8385 	ASSERT(plun != NULL);
8386 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8387 
8388 	if (nowait) {
8389 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8390 		return;
8391 	}
8392 
8393 	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8394 		elem->flags = flags;
8395 		elem->time = fcp_watchdog_time;
8396 		if (nowait == 0) {
8397 			elem->time += fcp_offline_delay;
8398 		}
8399 		elem->plun = plun;
8400 		elem->link_cnt = link_cnt;
8401 		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8402 		elem->next = pptr->port_offline_luns;
8403 		pptr->port_offline_luns = elem;
8404 	} else {
8405 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8406 	}
8407 }
8408 
8409 
8410 static void
8411 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8412 {
8413 	struct fcp_pkt	*head = NULL;
8414 
8415 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8416 
8417 	mutex_exit(&LUN_TGT->tgt_mutex);
8418 
8419 	head = fcp_scan_commands(plun);
8420 	if (head != NULL) {
8421 		fcp_abort_commands(head, LUN_PORT);
8422 	}
8423 
8424 	mutex_enter(&LUN_TGT->tgt_mutex);
8425 
8426 	if (plun->lun_cip && plun->lun_mpxio) {
8427 		/*
8428 		 * Intimate MPxIO lun busy is cleared
8429 		 */
8430 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8431 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8432 		    0, 0)) {
8433 			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8434 			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8435 			    LUN_TGT->tgt_d_id, plun->lun_num);
8436 		}
8437 		/*
8438 		 * Intimate MPxIO that the lun is now marked for offline
8439 		 */
8440 		mutex_exit(&LUN_TGT->tgt_mutex);
8441 		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8442 		mutex_enter(&LUN_TGT->tgt_mutex);
8443 	}
8444 }
8445 
8446 static void
8447 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8448     int flags)
8449 {
8450 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8451 
8452 	mutex_exit(&LUN_TGT->tgt_mutex);
8453 	fcp_update_offline_flags(plun);
8454 	mutex_enter(&LUN_TGT->tgt_mutex);
8455 
8456 	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8457 
8458 	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8459 	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8460 	    "offline_lun: passing OFFLINE elem to HP thread");
8461 
8462 	if (plun->lun_cip) {
8463 		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8464 		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8465 		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8466 		    LUN_TGT->tgt_trace);
8467 
8468 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8469 		    link_cnt, tgt_cnt, flags, 0)) {
8470 			fcp_log(CE_CONT, LUN_PORT->port_dip,
8471 			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8472 			    LUN_TGT->tgt_d_id, plun->lun_num);
8473 		}
8474 	}
8475 }
8476 
8477 static void
8478 fcp_scan_offline_luns(struct fcp_port *pptr)
8479 {
8480 	struct fcp_lun_elem	*elem;
8481 	struct fcp_lun_elem	*prev;
8482 	struct fcp_lun_elem	*next;
8483 
8484 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8485 
8486 	prev = NULL;
8487 	elem = pptr->port_offline_luns;
8488 	while (elem) {
8489 		next = elem->next;
8490 		if (elem->time <= fcp_watchdog_time) {
8491 			int			changed = 1;
8492 			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8493 
8494 			mutex_enter(&ptgt->tgt_mutex);
8495 			if (pptr->port_link_cnt == elem->link_cnt &&
8496 			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8497 				changed = 0;
8498 			}
8499 
8500 			if (!changed &&
8501 			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8502 				fcp_offline_lun_now(elem->plun,
8503 				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8504 			}
8505 			mutex_exit(&ptgt->tgt_mutex);
8506 
8507 			kmem_free(elem, sizeof (*elem));
8508 
8509 			if (prev) {
8510 				prev->next = next;
8511 			} else {
8512 				pptr->port_offline_luns = next;
8513 			}
8514 		} else {
8515 			prev = elem;
8516 		}
8517 		elem = next;
8518 	}
8519 }
8520 
8521 
8522 static void
8523 fcp_scan_offline_tgts(struct fcp_port *pptr)
8524 {
8525 	struct fcp_tgt_elem	*elem;
8526 	struct fcp_tgt_elem	*prev;
8527 	struct fcp_tgt_elem	*next;
8528 
8529 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8530 
8531 	prev = NULL;
8532 	elem = pptr->port_offline_tgts;
8533 	while (elem) {
8534 		next = elem->next;
8535 		if (elem->time <= fcp_watchdog_time) {
8536 			int		outdated = 1;
8537 			struct fcp_tgt	*ptgt = elem->ptgt;
8538 
8539 			mutex_enter(&ptgt->tgt_mutex);
8540 
8541 			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8542 				/* No change on tgt since elem was created. */
8543 				outdated = 0;
8544 			} else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8545 			    pptr->port_link_cnt == elem->link_cnt + 1 &&
8546 			    ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8547 				/*
8548 				 * Exactly one thing happened to the target
8549 				 * inbetween: the local port went offline.
8550 				 * For fp the remote port is already gone so
8551 				 * it will not tell us again to offline the
8552 				 * target. We must offline it now.
8553 				 */
8554 				outdated = 0;
8555 			}
8556 
8557 			if (!outdated && !(ptgt->tgt_state &
8558 			    FCP_TGT_OFFLINE)) {
8559 				fcp_offline_target_now(pptr,
8560 				    ptgt, elem->link_cnt, elem->tgt_cnt,
8561 				    elem->flags);
8562 			}
8563 
8564 			mutex_exit(&ptgt->tgt_mutex);
8565 
8566 			kmem_free(elem, sizeof (*elem));
8567 
8568 			if (prev) {
8569 				prev->next = next;
8570 			} else {
8571 				pptr->port_offline_tgts = next;
8572 			}
8573 		} else {
8574 			prev = elem;
8575 		}
8576 		elem = next;
8577 	}
8578 }
8579 
8580 
8581 static void
8582 fcp_update_offline_flags(struct fcp_lun *plun)
8583 {
8584 	struct fcp_port	*pptr = LUN_PORT;
8585 	ASSERT(plun != NULL);
8586 
8587 	mutex_enter(&LUN_TGT->tgt_mutex);
8588 	plun->lun_state |= FCP_LUN_OFFLINE;
8589 	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8590 
8591 	mutex_enter(&plun->lun_mutex);
8592 	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8593 		dev_info_t *cdip = NULL;
8594 
8595 		mutex_exit(&LUN_TGT->tgt_mutex);
8596 
8597 		if (plun->lun_mpxio == 0) {
8598 			cdip = DIP(plun->lun_cip);
8599 		} else if (plun->lun_cip) {
8600 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8601 		}
8602 
8603 		mutex_exit(&plun->lun_mutex);
8604 		if (cdip) {
8605 			(void) ndi_event_retrieve_cookie(
8606 			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8607 			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8608 			(void) ndi_event_run_callbacks(
8609 			    pptr->port_ndi_event_hdl, cdip,
8610 			    fcp_remove_eid, NULL);
8611 		}
8612 	} else {
8613 		mutex_exit(&plun->lun_mutex);
8614 		mutex_exit(&LUN_TGT->tgt_mutex);
8615 	}
8616 }
8617 
8618 
8619 /*
8620  * Scan all of the command pkts for this port, moving pkts that
8621  * match our LUN onto our own list (headed by "head")
8622  */
8623 static struct fcp_pkt *
8624 fcp_scan_commands(struct fcp_lun *plun)
8625 {
8626 	struct fcp_port	*pptr = LUN_PORT;
8627 
8628 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8629 	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8630 	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8631 
8632 	struct fcp_pkt	*head = NULL;	/* head of our list */
8633 	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8634 
8635 	int			cmds_found = 0;
8636 
8637 	mutex_enter(&pptr->port_pkt_mutex);
8638 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8639 		struct fcp_lun *tlun =
8640 		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8641 
8642 		ncmd = cmd->cmd_next;	/* set next command */
8643 
8644 		/*
8645 		 * if this pkt is for a different LUN  or the
8646 		 * command is sent down, skip it.
8647 		 */
8648 		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8649 		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8650 			pcmd = cmd;
8651 			continue;
8652 		}
8653 		cmds_found++;
8654 		if (pcmd != NULL) {
8655 			ASSERT(pptr->port_pkt_head != cmd);
8656 			pcmd->cmd_next = cmd->cmd_next;
8657 		} else {
8658 			ASSERT(cmd == pptr->port_pkt_head);
8659 			pptr->port_pkt_head = cmd->cmd_next;
8660 		}
8661 
8662 		if (cmd == pptr->port_pkt_tail) {
8663 			pptr->port_pkt_tail = pcmd;
8664 			if (pcmd) {
8665 				pcmd->cmd_next = NULL;
8666 			}
8667 		}
8668 
8669 		if (head == NULL) {
8670 			head = tail = cmd;
8671 		} else {
8672 			ASSERT(tail != NULL);
8673 
8674 			tail->cmd_next = cmd;
8675 			tail = cmd;
8676 		}
8677 		cmd->cmd_next = NULL;
8678 	}
8679 	mutex_exit(&pptr->port_pkt_mutex);
8680 
8681 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8682 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8683 	    "scan commands: %d cmd(s) found", cmds_found);
8684 
8685 	return (head);
8686 }
8687 
8688 
8689 /*
8690  * Abort all the commands in the command queue
8691  */
8692 static void
8693 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8694 {
8695 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8696 	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8697 
8698 	ASSERT(mutex_owned(&pptr->port_mutex));
8699 
8700 	/* scan through the pkts and invalid them */
8701 	for (cmd = head; cmd != NULL; cmd = ncmd) {
8702 		struct scsi_pkt *pkt = cmd->cmd_pkt;
8703 
8704 		ncmd = cmd->cmd_next;
8705 		ASSERT(pkt != NULL);
8706 
8707 		/*
8708 		 * The lun is going to be marked offline. Indicate
8709 		 * the target driver not to requeue or retry this command
8710 		 * as the device is going to be offlined pretty soon.
8711 		 */
8712 		pkt->pkt_reason = CMD_DEV_GONE;
8713 		pkt->pkt_statistics = 0;
8714 		pkt->pkt_state = 0;
8715 
8716 		/* reset cmd flags/state */
8717 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8718 		cmd->cmd_state = FCP_PKT_IDLE;
8719 
8720 		/*
8721 		 * ensure we have a packet completion routine,
8722 		 * then call it.
8723 		 */
8724 		ASSERT(pkt->pkt_comp != NULL);
8725 
8726 		mutex_exit(&pptr->port_mutex);
8727 		fcp_post_callback(cmd);
8728 		mutex_enter(&pptr->port_mutex);
8729 	}
8730 }
8731 
8732 
8733 /*
8734  * the pkt_comp callback for command packets
8735  */
8736 static void
8737 fcp_cmd_callback(fc_packet_t *fpkt)
8738 {
8739 	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8740 	struct scsi_pkt *pkt = cmd->cmd_pkt;
8741 	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8742 
8743 	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8744 
8745 	if (cmd->cmd_state == FCP_PKT_IDLE) {
8746 		cmn_err(CE_PANIC, "Packet already completed %p",
8747 		    (void *)cmd);
8748 	}
8749 
8750 	/*
8751 	 * Watch thread should be freeing the packet, ignore the pkt.
8752 	 */
8753 	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8754 		fcp_log(CE_CONT, pptr->port_dip,
8755 		    "!FCP: Pkt completed while aborting\n");
8756 		return;
8757 	}
8758 	cmd->cmd_state = FCP_PKT_IDLE;
8759 
8760 	fcp_complete_pkt(fpkt);
8761 
8762 #ifdef	DEBUG
8763 	mutex_enter(&pptr->port_pkt_mutex);
8764 	pptr->port_npkts--;
8765 	mutex_exit(&pptr->port_pkt_mutex);
8766 #endif /* DEBUG */
8767 
8768 	fcp_post_callback(cmd);
8769 }
8770 
8771 
8772 static void
8773 fcp_complete_pkt(fc_packet_t *fpkt)
8774 {
8775 	int			error = 0;
8776 	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8777 	    fpkt->pkt_ulp_private;
8778 	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8779 	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8780 	struct fcp_lun	*plun;
8781 	struct fcp_tgt	*ptgt;
8782 	struct fcp_rsp		*rsp;
8783 	struct scsi_address	save;
8784 
8785 #ifdef	DEBUG
8786 	save = pkt->pkt_address;
8787 #endif /* DEBUG */
8788 
8789 	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8790 
8791 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8792 		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8793 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8794 			    sizeof (struct fcp_rsp));
8795 		}
8796 
8797 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8798 		    STATE_SENT_CMD | STATE_GOT_STATUS;
8799 
8800 		pkt->pkt_resid = 0;
8801 
8802 		if (fpkt->pkt_datalen) {
8803 			pkt->pkt_state |= STATE_XFERRED_DATA;
8804 			if (fpkt->pkt_data_resid) {
8805 				error++;
8806 			}
8807 		}
8808 
8809 		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8810 		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8811 			/*
8812 			 * The next two checks make sure that if there
8813 			 * is no sense data or a valid response and
8814 			 * the command came back with check condition,
8815 			 * the command should be retried.
8816 			 */
8817 			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8818 			    !rsp->fcp_u.fcp_status.sense_len_set) {
8819 				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8820 				pkt->pkt_resid = cmd->cmd_dmacount;
8821 			}
8822 		}
8823 
8824 		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8825 			return;
8826 		}
8827 
8828 		plun = ADDR2LUN(&pkt->pkt_address);
8829 		ptgt = plun->lun_tgt;
8830 		ASSERT(ptgt != NULL);
8831 
8832 		/*
8833 		 * Update the transfer resid, if appropriate
8834 		 */
8835 		if (rsp->fcp_u.fcp_status.resid_over ||
8836 		    rsp->fcp_u.fcp_status.resid_under) {
8837 			pkt->pkt_resid = rsp->fcp_resid;
8838 		}
8839 
8840 		/*
8841 		 * First see if we got a FCP protocol error.
8842 		 */
8843 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8844 			struct fcp_rsp_info	*bep;
8845 			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8846 			    sizeof (struct fcp_rsp));
8847 
8848 			if (fcp_validate_fcp_response(rsp, pptr) !=
8849 			    FC_SUCCESS) {
8850 				pkt->pkt_reason = CMD_CMPLT;
8851 				*(pkt->pkt_scbp) = STATUS_CHECK;
8852 
8853 				fcp_log(CE_WARN, pptr->port_dip,
8854 				    "!SCSI command to d_id=0x%x lun=0x%x"
8855 				    " failed, Bad FCP response values:"
8856 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8857 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8858 				    ptgt->tgt_d_id, plun->lun_num,
8859 				    rsp->reserved_0, rsp->reserved_1,
8860 				    rsp->fcp_u.fcp_status.reserved_0,
8861 				    rsp->fcp_u.fcp_status.reserved_1,
8862 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8863 
8864 				return;
8865 			}
8866 
8867 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8868 				FCP_CP_IN(fpkt->pkt_resp +
8869 				    sizeof (struct fcp_rsp), bep,
8870 				    fpkt->pkt_resp_acc,
8871 				    sizeof (struct fcp_rsp_info));
8872 			}
8873 
8874 			if (bep->rsp_code != FCP_NO_FAILURE) {
8875 				child_info_t	*cip;
8876 
8877 				pkt->pkt_reason = CMD_TRAN_ERR;
8878 
8879 				mutex_enter(&plun->lun_mutex);
8880 				cip = plun->lun_cip;
8881 				mutex_exit(&plun->lun_mutex);
8882 
8883 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8884 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8885 				    "FCP response error on cmd=%p"
8886 				    " target=0x%x, cip=%p", cmd,
8887 				    ptgt->tgt_d_id, cip);
8888 			}
8889 		}
8890 
8891 		/*
8892 		 * See if we got a SCSI error with sense data
8893 		 */
8894 		if (rsp->fcp_u.fcp_status.sense_len_set) {
8895 			uchar_t				rqlen;
8896 			caddr_t				sense_from;
8897 			child_info_t			*cip;
8898 			timeout_id_t			tid;
8899 			struct scsi_arq_status		*arq;
8900 			struct scsi_extended_sense	*sense_to;
8901 
8902 			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8903 			sense_to = &arq->sts_sensedata;
8904 
8905 			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8906 			    sizeof (struct scsi_extended_sense));
8907 
8908 			sense_from = (caddr_t)fpkt->pkt_resp +
8909 			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8910 
8911 			if (fcp_validate_fcp_response(rsp, pptr) !=
8912 			    FC_SUCCESS) {
8913 				pkt->pkt_reason = CMD_CMPLT;
8914 				*(pkt->pkt_scbp) = STATUS_CHECK;
8915 
8916 				fcp_log(CE_WARN, pptr->port_dip,
8917 				    "!SCSI command to d_id=0x%x lun=0x%x"
8918 				    " failed, Bad FCP response values:"
8919 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8920 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8921 				    ptgt->tgt_d_id, plun->lun_num,
8922 				    rsp->reserved_0, rsp->reserved_1,
8923 				    rsp->fcp_u.fcp_status.reserved_0,
8924 				    rsp->fcp_u.fcp_status.reserved_1,
8925 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8926 
8927 				return;
8928 			}
8929 
8930 			/*
8931 			 * copy in sense information
8932 			 */
8933 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8934 				FCP_CP_IN(sense_from, sense_to,
8935 				    fpkt->pkt_resp_acc, rqlen);
8936 			} else {
8937 				bcopy(sense_from, sense_to, rqlen);
8938 			}
8939 
8940 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8941 			    (FCP_SENSE_NO_LUN(sense_to))) {
8942 				mutex_enter(&ptgt->tgt_mutex);
8943 				if (ptgt->tgt_tid == NULL) {
8944 					/*
8945 					 * Kick off rediscovery
8946 					 */
8947 					tid = timeout(fcp_reconfigure_luns,
8948 					    (caddr_t)ptgt, drv_usectohz(1));
8949 
8950 					ptgt->tgt_tid = tid;
8951 					ptgt->tgt_state |= FCP_TGT_BUSY;
8952 				}
8953 				mutex_exit(&ptgt->tgt_mutex);
8954 				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8955 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8956 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8957 					    "!FCP: Report Lun Has Changed"
8958 					    " target=%x", ptgt->tgt_d_id);
8959 				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8960 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8961 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8962 					    "!FCP: LU Not Supported"
8963 					    " target=%x", ptgt->tgt_d_id);
8964 				}
8965 			}
8966 			ASSERT(pkt->pkt_scbp != NULL);
8967 
8968 			pkt->pkt_state |= STATE_ARQ_DONE;
8969 
8970 			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8971 
8972 			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8973 			arq->sts_rqpkt_reason = 0;
8974 			arq->sts_rqpkt_statistics = 0;
8975 
8976 			arq->sts_rqpkt_state = STATE_GOT_BUS |
8977 			    STATE_GOT_TARGET | STATE_SENT_CMD |
8978 			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8979 			    STATE_XFERRED_DATA;
8980 
8981 			mutex_enter(&plun->lun_mutex);
8982 			cip = plun->lun_cip;
8983 			mutex_exit(&plun->lun_mutex);
8984 
8985 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8986 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
8987 			    "SCSI Check condition on cmd=%p target=0x%x"
8988 			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
8989 			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
8990 			    cmd->cmd_fcp_cmd.fcp_cdb[0],
8991 			    rsp->fcp_u.fcp_status.scsi_status,
8992 			    sense_to->es_key, sense_to->es_add_code,
8993 			    sense_to->es_qual_code);
8994 		}
8995 	} else {
8996 		plun = ADDR2LUN(&pkt->pkt_address);
8997 		ptgt = plun->lun_tgt;
8998 		ASSERT(ptgt != NULL);
8999 
9000 		/*
9001 		 * Work harder to translate errors into target driver
9002 		 * understandable ones. Note with despair that the target
9003 		 * drivers don't decode pkt_state and pkt_reason exhaustively
9004 		 * They resort to using the big hammer most often, which
9005 		 * may not get fixed in the life time of this driver.
9006 		 */
9007 		pkt->pkt_state = 0;
9008 		pkt->pkt_statistics = 0;
9009 
9010 		switch (fpkt->pkt_state) {
9011 		case FC_PKT_TRAN_ERROR:
9012 			switch (fpkt->pkt_reason) {
9013 			case FC_REASON_OVERRUN:
9014 				pkt->pkt_reason = CMD_CMD_OVR;
9015 				pkt->pkt_statistics |= STAT_ABORTED;
9016 				break;
9017 
9018 			case FC_REASON_XCHG_BSY: {
9019 				caddr_t ptr;
9020 
9021 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9022 
9023 				ptr = (caddr_t)pkt->pkt_scbp;
9024 				if (ptr) {
9025 					*ptr = STATUS_BUSY;
9026 				}
9027 				break;
9028 			}
9029 
9030 			case FC_REASON_ABORTED:
9031 				pkt->pkt_reason = CMD_TRAN_ERR;
9032 				pkt->pkt_statistics |= STAT_ABORTED;
9033 				break;
9034 
9035 			case FC_REASON_ABORT_FAILED:
9036 				pkt->pkt_reason = CMD_ABORT_FAIL;
9037 				break;
9038 
9039 			case FC_REASON_NO_SEQ_INIT:
9040 			case FC_REASON_CRC_ERROR:
9041 				pkt->pkt_reason = CMD_TRAN_ERR;
9042 				pkt->pkt_statistics |= STAT_ABORTED;
9043 				break;
9044 			default:
9045 				pkt->pkt_reason = CMD_TRAN_ERR;
9046 				break;
9047 			}
9048 			break;
9049 
9050 		case FC_PKT_PORT_OFFLINE: {
9051 			dev_info_t	*cdip = NULL;
9052 			caddr_t		ptr;
9053 
9054 			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9055 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9056 				    fcp_trace, FCP_BUF_LEVEL_8, 0,
9057 				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9058 				    ptgt->tgt_d_id);
9059 			}
9060 
9061 			mutex_enter(&plun->lun_mutex);
9062 			if (plun->lun_mpxio == 0) {
9063 				cdip = DIP(plun->lun_cip);
9064 			} else if (plun->lun_cip) {
9065 				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9066 			}
9067 
9068 			mutex_exit(&plun->lun_mutex);
9069 
9070 			if (cdip) {
9071 				(void) ndi_event_retrieve_cookie(
9072 				    pptr->port_ndi_event_hdl, cdip,
9073 				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9074 				    NDI_EVENT_NOPASS);
9075 				(void) ndi_event_run_callbacks(
9076 				    pptr->port_ndi_event_hdl, cdip,
9077 				    fcp_remove_eid, NULL);
9078 			}
9079 
9080 			/*
9081 			 * If the link goes off-line for a lip,
9082 			 * this will cause a error to the ST SG
9083 			 * SGEN drivers. By setting BUSY we will
9084 			 * give the drivers the chance to retry
9085 			 * before it blows of the job. ST will
9086 			 * remember how many times it has retried.
9087 			 */
9088 
9089 			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9090 			    (plun->lun_type == DTYPE_CHANGER)) {
9091 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9092 				ptr = (caddr_t)pkt->pkt_scbp;
9093 				if (ptr) {
9094 					*ptr = STATUS_BUSY;
9095 				}
9096 			} else {
9097 				pkt->pkt_reason = CMD_TRAN_ERR;
9098 				pkt->pkt_statistics |= STAT_BUS_RESET;
9099 			}
9100 			break;
9101 		}
9102 
9103 		case FC_PKT_TRAN_BSY:
9104 			/*
9105 			 * Use the ssd Qfull handling here.
9106 			 */
9107 			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9108 			pkt->pkt_state = STATE_GOT_BUS;
9109 			break;
9110 
9111 		case FC_PKT_TIMEOUT:
9112 			pkt->pkt_reason = CMD_TIMEOUT;
9113 			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9114 				pkt->pkt_statistics |= STAT_TIMEOUT;
9115 			} else {
9116 				pkt->pkt_statistics |= STAT_ABORTED;
9117 			}
9118 			break;
9119 
9120 		case FC_PKT_LOCAL_RJT:
9121 			switch (fpkt->pkt_reason) {
9122 			case FC_REASON_OFFLINE: {
9123 				dev_info_t	*cdip = NULL;
9124 
9125 				mutex_enter(&plun->lun_mutex);
9126 				if (plun->lun_mpxio == 0) {
9127 					cdip = DIP(plun->lun_cip);
9128 				} else if (plun->lun_cip) {
9129 					cdip = mdi_pi_get_client(
9130 					    PIP(plun->lun_cip));
9131 				}
9132 				mutex_exit(&plun->lun_mutex);
9133 
9134 				if (cdip) {
9135 					(void) ndi_event_retrieve_cookie(
9136 					    pptr->port_ndi_event_hdl, cdip,
9137 					    FCAL_REMOVE_EVENT,
9138 					    &fcp_remove_eid,
9139 					    NDI_EVENT_NOPASS);
9140 					(void) ndi_event_run_callbacks(
9141 					    pptr->port_ndi_event_hdl,
9142 					    cdip, fcp_remove_eid, NULL);
9143 				}
9144 
9145 				pkt->pkt_reason = CMD_TRAN_ERR;
9146 				pkt->pkt_statistics |= STAT_BUS_RESET;
9147 
9148 				break;
9149 			}
9150 
9151 			case FC_REASON_NOMEM:
9152 			case FC_REASON_QFULL: {
9153 				caddr_t ptr;
9154 
9155 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9156 				ptr = (caddr_t)pkt->pkt_scbp;
9157 				if (ptr) {
9158 					*ptr = STATUS_BUSY;
9159 				}
9160 				break;
9161 			}
9162 
9163 			case FC_REASON_DMA_ERROR:
9164 				pkt->pkt_reason = CMD_DMA_DERR;
9165 				pkt->pkt_statistics |= STAT_ABORTED;
9166 				break;
9167 
9168 			case FC_REASON_CRC_ERROR:
9169 			case FC_REASON_UNDERRUN: {
9170 				uchar_t		status;
9171 				/*
9172 				 * Work around for Bugid: 4240945.
9173 				 * IB on A5k doesn't set the Underrun bit
9174 				 * in the fcp status, when it is transferring
9175 				 * less than requested amount of data. Work
9176 				 * around the ses problem to keep luxadm
9177 				 * happy till ibfirmware is fixed.
9178 				 */
9179 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9180 					FCP_CP_IN(fpkt->pkt_resp, rsp,
9181 					    fpkt->pkt_resp_acc,
9182 					    sizeof (struct fcp_rsp));
9183 				}
9184 				status = rsp->fcp_u.fcp_status.scsi_status;
9185 				if (((plun->lun_type & DTYPE_MASK) ==
9186 				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9187 					pkt->pkt_reason = CMD_CMPLT;
9188 					*pkt->pkt_scbp = status;
9189 					pkt->pkt_resid = 0;
9190 				} else {
9191 					pkt->pkt_reason = CMD_TRAN_ERR;
9192 					pkt->pkt_statistics |= STAT_ABORTED;
9193 				}
9194 				break;
9195 			}
9196 
9197 			case FC_REASON_NO_CONNECTION:
9198 			case FC_REASON_UNSUPPORTED:
9199 			case FC_REASON_ILLEGAL_REQ:
9200 			case FC_REASON_BAD_SID:
9201 			case FC_REASON_DIAG_BUSY:
9202 			case FC_REASON_FCAL_OPN_FAIL:
9203 			case FC_REASON_BAD_XID:
9204 			default:
9205 				pkt->pkt_reason = CMD_TRAN_ERR;
9206 				pkt->pkt_statistics |= STAT_ABORTED;
9207 				break;
9208 
9209 			}
9210 			break;
9211 
9212 		case FC_PKT_NPORT_RJT:
9213 		case FC_PKT_FABRIC_RJT:
9214 		case FC_PKT_NPORT_BSY:
9215 		case FC_PKT_FABRIC_BSY:
9216 		default:
9217 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9218 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9219 			    "FC Status 0x%x, reason 0x%x",
9220 			    fpkt->pkt_state, fpkt->pkt_reason);
9221 			pkt->pkt_reason = CMD_TRAN_ERR;
9222 			pkt->pkt_statistics |= STAT_ABORTED;
9223 			break;
9224 		}
9225 
9226 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9227 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9228 		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9229 		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9230 		    fpkt->pkt_reason);
9231 	}
9232 
9233 	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9234 }
9235 
9236 
9237 static int
9238 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9239 {
9240 	if (rsp->reserved_0 || rsp->reserved_1 ||
9241 	    rsp->fcp_u.fcp_status.reserved_0 ||
9242 	    rsp->fcp_u.fcp_status.reserved_1) {
9243 		/*
9244 		 * These reserved fields should ideally be zero. FCP-2 does say
9245 		 * that the recipient need not check for reserved fields to be
9246 		 * zero. If they are not zero, we will not make a fuss about it
9247 		 * - just log it (in debug to both trace buffer and messages
9248 		 * file and to trace buffer only in non-debug) and move on.
9249 		 *
9250 		 * Non-zero reserved fields were seen with minnows.
9251 		 *
9252 		 * qlc takes care of some of this but we cannot assume that all
9253 		 * FCAs will do so.
9254 		 */
9255 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9256 		    FCP_BUF_LEVEL_5, 0,
9257 		    "Got fcp response packet with non-zero reserved fields "
9258 		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9259 		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9260 		    rsp->reserved_0, rsp->reserved_1,
9261 		    rsp->fcp_u.fcp_status.reserved_0,
9262 		    rsp->fcp_u.fcp_status.reserved_1);
9263 	}
9264 
9265 	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9266 	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9267 		return (FC_FAILURE);
9268 	}
9269 
9270 	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9271 	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9272 	    sizeof (struct fcp_rsp))) {
9273 		return (FC_FAILURE);
9274 	}
9275 
9276 	return (FC_SUCCESS);
9277 }
9278 
9279 
9280 /*
9281  * This is called when there is a change the in device state. The case we're
9282  * handling here is, if the d_id s does not match, offline this tgt and online
9283  * a new tgt with the new d_id.	 called from fcp_handle_devices with
9284  * port_mutex held.
9285  */
9286 static int
9287 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9288     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9289 {
9290 	ASSERT(mutex_owned(&pptr->port_mutex));
9291 
9292 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9293 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9294 	    "Starting fcp_device_changed...");
9295 
9296 	/*
9297 	 * The two cases where the port_device_changed is called is
9298 	 * either it changes it's d_id or it's hard address.
9299 	 */
9300 	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9301 	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9302 	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9303 
9304 		/* offline this target */
9305 		mutex_enter(&ptgt->tgt_mutex);
9306 		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9307 			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9308 			    0, 1, NDI_DEVI_REMOVE);
9309 		}
9310 		mutex_exit(&ptgt->tgt_mutex);
9311 
9312 		fcp_log(CE_NOTE, pptr->port_dip,
9313 		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9314 		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9315 		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9316 		    map_entry->map_hard_addr.hard_addr);
9317 	}
9318 
9319 	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9320 	    link_cnt, tgt_cnt, cause));
9321 }
9322 
9323 /*
9324  *     Function: fcp_alloc_lun
9325  *
9326  *  Description: Creates a new lun structure and adds it to the list
9327  *		 of luns of the target.
9328  *
9329  *     Argument: ptgt		Target the lun will belong to.
9330  *
9331  * Return Value: NULL		Failed
9332  *		 Not NULL	Succeeded
9333  *
9334  *	Context: Kernel context
9335  */
9336 static struct fcp_lun *
9337 fcp_alloc_lun(struct fcp_tgt *ptgt)
9338 {
9339 	struct fcp_lun *plun;
9340 
9341 	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9342 	if (plun != NULL) {
9343 		/*
9344 		 * Initialize the mutex before putting in the target list
9345 		 * especially before releasing the target mutex.
9346 		 */
9347 		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9348 		plun->lun_tgt = ptgt;
9349 
9350 		mutex_enter(&ptgt->tgt_mutex);
9351 		plun->lun_next = ptgt->tgt_lun;
9352 		ptgt->tgt_lun = plun;
9353 		plun->lun_old_guid = NULL;
9354 		plun->lun_old_guid_size = 0;
9355 		mutex_exit(&ptgt->tgt_mutex);
9356 	}
9357 
9358 	return (plun);
9359 }
9360 
9361 /*
9362  *     Function: fcp_dealloc_lun
9363  *
9364  *  Description: Frees the LUN structure passed by the caller.
9365  *
9366  *     Argument: plun		LUN structure to free.
9367  *
9368  * Return Value: None
9369  *
9370  *	Context: Kernel context.
9371  */
9372 static void
9373 fcp_dealloc_lun(struct fcp_lun *plun)
9374 {
9375 	mutex_enter(&plun->lun_mutex);
9376 	if (plun->lun_cip) {
9377 		fcp_remove_child(plun);
9378 	}
9379 	mutex_exit(&plun->lun_mutex);
9380 
9381 	mutex_destroy(&plun->lun_mutex);
9382 	if (plun->lun_guid) {
9383 		kmem_free(plun->lun_guid, plun->lun_guid_size);
9384 	}
9385 	if (plun->lun_old_guid) {
9386 		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9387 	}
9388 	kmem_free(plun, sizeof (*plun));
9389 }
9390 
9391 /*
9392  *     Function: fcp_alloc_tgt
9393  *
9394  *  Description: Creates a new target structure and adds it to the port
9395  *		 hash list.
9396  *
9397  *     Argument: pptr		fcp port structure
9398  *		 *map_entry	entry describing the target to create
9399  *		 link_cnt	Link state change counter
9400  *
9401  * Return Value: NULL		Failed
9402  *		 Not NULL	Succeeded
9403  *
9404  *	Context: Kernel context.
9405  */
9406 static struct fcp_tgt *
9407 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9408 {
9409 	int			hash;
9410 	uchar_t			*wwn;
9411 	struct fcp_tgt	*ptgt;
9412 
9413 	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9414 	if (ptgt != NULL) {
9415 		mutex_enter(&pptr->port_mutex);
9416 		if (link_cnt != pptr->port_link_cnt) {
9417 			/*
9418 			 * oh oh -- another link reset
9419 			 * in progress -- give up
9420 			 */
9421 			mutex_exit(&pptr->port_mutex);
9422 			kmem_free(ptgt, sizeof (*ptgt));
9423 			ptgt = NULL;
9424 		} else {
9425 			/*
9426 			 * initialize the mutex before putting in the port
9427 			 * wwn list, especially before releasing the port
9428 			 * mutex.
9429 			 */
9430 			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9431 
9432 			/* add new target entry to the port's hash list */
9433 			wwn = (uchar_t *)&map_entry->map_pwwn;
9434 			hash = FCP_HASH(wwn);
9435 
9436 			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9437 			pptr->port_tgt_hash_table[hash] = ptgt;
9438 
9439 			/* save cross-ptr */
9440 			ptgt->tgt_port = pptr;
9441 
9442 			ptgt->tgt_change_cnt = 1;
9443 
9444 			/* initialize the target manual_config_only flag */
9445 			if (fcp_enable_auto_configuration) {
9446 				ptgt->tgt_manual_config_only = 0;
9447 			} else {
9448 				ptgt->tgt_manual_config_only = 1;
9449 			}
9450 
9451 			mutex_exit(&pptr->port_mutex);
9452 		}
9453 	}
9454 
9455 	return (ptgt);
9456 }
9457 
9458 /*
9459  *     Function: fcp_dealloc_tgt
9460  *
9461  *  Description: Frees the target structure passed by the caller.
9462  *
9463  *     Argument: ptgt		Target structure to free.
9464  *
9465  * Return Value: None
9466  *
9467  *	Context: Kernel context.
9468  */
9469 static void
9470 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9471 {
9472 	mutex_destroy(&ptgt->tgt_mutex);
9473 	kmem_free(ptgt, sizeof (*ptgt));
9474 }
9475 
9476 
9477 /*
9478  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9479  *
9480  *	Device discovery commands will not be retried for-ever as
9481  *	this will have repercussions on other devices that need to
9482  *	be submitted to the hotplug thread. After a quick glance
9483  *	at the SCSI-3 spec, it was found that the spec doesn't
9484  *	mandate a forever retry, rather recommends a delayed retry.
9485  *
9486  *	Since Photon IB is single threaded, STATUS_BUSY is common
9487  *	in a 4+initiator environment. Make sure the total time
9488  *	spent on retries (including command timeout) does not
9489  *	60 seconds
9490  */
9491 static void
9492 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9493 {
9494 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9495 	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9496 
9497 	mutex_enter(&pptr->port_mutex);
9498 	mutex_enter(&ptgt->tgt_mutex);
9499 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9500 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9501 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9502 		    "fcp_queue_ipkt,1:state change occured"
9503 		    " for D_ID=0x%x", ptgt->tgt_d_id);
9504 		mutex_exit(&ptgt->tgt_mutex);
9505 		mutex_exit(&pptr->port_mutex);
9506 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9507 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9508 		fcp_icmd_free(pptr, icmd);
9509 		return;
9510 	}
9511 	mutex_exit(&ptgt->tgt_mutex);
9512 
9513 	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9514 
9515 	if (pptr->port_ipkt_list != NULL) {
9516 		/* add pkt to front of doubly-linked list */
9517 		pptr->port_ipkt_list->ipkt_prev = icmd;
9518 		icmd->ipkt_next = pptr->port_ipkt_list;
9519 		pptr->port_ipkt_list = icmd;
9520 		icmd->ipkt_prev = NULL;
9521 	} else {
9522 		/* this is the first/only pkt on the list */
9523 		pptr->port_ipkt_list = icmd;
9524 		icmd->ipkt_next = NULL;
9525 		icmd->ipkt_prev = NULL;
9526 	}
9527 	mutex_exit(&pptr->port_mutex);
9528 }
9529 
9530 /*
9531  *     Function: fcp_transport
9532  *
9533  *  Description: This function submits the Fibre Channel packet to the transort
9534  *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9535  *		 fails the submission, the treatment depends on the value of
9536  *		 the variable internal.
9537  *
9538  *     Argument: port_handle	fp/fctl port handle.
9539  *		 *fpkt		Packet to submit to the transport layer.
9540  *		 internal	Not zero when it's an internal packet.
9541  *
9542  * Return Value: FC_TRAN_BUSY
9543  *		 FC_STATEC_BUSY
9544  *		 FC_OFFLINE
9545  *		 FC_LOGINREQ
9546  *		 FC_DEVICE_BUSY
9547  *		 FC_SUCCESS
9548  */
9549 static int
9550 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9551 {
9552 	int	rval;
9553 
9554 	rval = fc_ulp_transport(port_handle, fpkt);
9555 	if (rval == FC_SUCCESS) {
9556 		return (rval);
9557 	}
9558 
9559 	/*
9560 	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9561 	 * a command, if the underlying modules see that there is a state
9562 	 * change, or if a port is OFFLINE, that means, that state change
9563 	 * hasn't reached FCP yet, so re-queue the command for deferred
9564 	 * submission.
9565 	 */
9566 	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9567 	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9568 	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9569 		/*
9570 		 * Defer packet re-submission. Life hang is possible on
9571 		 * internal commands if the port driver sends FC_STATEC_BUSY
9572 		 * for ever, but that shouldn't happen in a good environment.
9573 		 * Limiting re-transport for internal commands is probably a
9574 		 * good idea..
9575 		 * A race condition can happen when a port sees barrage of
9576 		 * link transitions offline to online. If the FCTL has
9577 		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9578 		 * internal commands should be queued to do the discovery.
9579 		 * The race condition is when an online comes and FCP starts
9580 		 * its internal discovery and the link goes offline. It is
9581 		 * possible that the statec_callback has not reached FCP
9582 		 * and FCP is carrying on with its internal discovery.
9583 		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9584 		 * that the link has gone offline. At this point FCP should
9585 		 * drop all the internal commands and wait for the
9586 		 * statec_callback. It will be facilitated by incrementing
9587 		 * port_link_cnt.
9588 		 *
9589 		 * For external commands, the (FC)pkt_timeout is decremented
9590 		 * by the QUEUE Delay added by our driver, Care is taken to
9591 		 * ensure that it doesn't become zero (zero means no timeout)
9592 		 * If the time expires right inside driver queue itself,
9593 		 * the watch thread will return it to the original caller
9594 		 * indicating that the command has timed-out.
9595 		 */
9596 		if (internal) {
9597 			char			*op;
9598 			struct fcp_ipkt	*icmd;
9599 
9600 			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9601 			switch (icmd->ipkt_opcode) {
9602 			case SCMD_REPORT_LUN:
9603 				op = "REPORT LUN";
9604 				break;
9605 
9606 			case SCMD_INQUIRY:
9607 				op = "INQUIRY";
9608 				break;
9609 
9610 			case SCMD_INQUIRY_PAGE83:
9611 				op = "INQUIRY-83";
9612 				break;
9613 
9614 			default:
9615 				op = "Internal SCSI COMMAND";
9616 				break;
9617 			}
9618 
9619 			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9620 			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9621 				rval = FC_SUCCESS;
9622 			}
9623 		} else {
9624 			struct fcp_pkt *cmd;
9625 			struct fcp_port *pptr;
9626 
9627 			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9628 			cmd->cmd_state = FCP_PKT_IDLE;
9629 			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9630 
9631 			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9632 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9633 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9634 				    "fcp_transport: xport busy for pkt %p",
9635 				    cmd->cmd_pkt);
9636 				rval = FC_TRAN_BUSY;
9637 			} else {
9638 				fcp_queue_pkt(pptr, cmd);
9639 				rval = FC_SUCCESS;
9640 			}
9641 		}
9642 	}
9643 
9644 	return (rval);
9645 }
9646 
9647 /*VARARGS3*/
9648 static void
9649 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9650 {
9651 	char		buf[256];
9652 	va_list		ap;
9653 
9654 	if (dip == NULL) {
9655 		dip = fcp_global_dip;
9656 	}
9657 
9658 	va_start(ap, fmt);
9659 	(void) vsprintf(buf, fmt, ap);
9660 	va_end(ap);
9661 
9662 	scsi_log(dip, "fcp", level, buf);
9663 }
9664 
9665 /*
9666  * This function retries NS registry of FC4 type.
9667  * It assumes that fcp_mutex is held.
9668  * The function does nothing if topology is not fabric
9669  * So, the topology has to be set before this function can be called
9670  */
9671 static void
9672 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9673 {
9674 	int	rval;
9675 
9676 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9677 
9678 	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9679 	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9680 	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9681 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9682 			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9683 		}
9684 		return;
9685 	}
9686 	mutex_exit(&pptr->port_mutex);
9687 	rval = fcp_do_ns_registry(pptr, s_id);
9688 	mutex_enter(&pptr->port_mutex);
9689 
9690 	if (rval == 0) {
9691 		/* Registry successful. Reset flag */
9692 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9693 	}
9694 }
9695 
9696 /*
9697  * This function registers the ULP with the switch by calling transport i/f
9698  */
9699 static int
9700 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9701 {
9702 	fc_ns_cmd_t		ns_cmd;
9703 	ns_rfc_type_t		rfc;
9704 	uint32_t		types[8];
9705 
9706 	/*
9707 	 * Prepare the Name server structure to
9708 	 * register with the transport in case of
9709 	 * Fabric configuration.
9710 	 */
9711 	bzero(&rfc, sizeof (rfc));
9712 	bzero(types, sizeof (types));
9713 
9714 	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9715 	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9716 
9717 	rfc.rfc_port_id.port_id = s_id;
9718 	bcopy(types, rfc.rfc_types, sizeof (types));
9719 
9720 	ns_cmd.ns_flags = 0;
9721 	ns_cmd.ns_cmd = NS_RFT_ID;
9722 	ns_cmd.ns_req_len = sizeof (rfc);
9723 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9724 	ns_cmd.ns_resp_len = 0;
9725 	ns_cmd.ns_resp_payload = NULL;
9726 
9727 	/*
9728 	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9729 	 */
9730 	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9731 		fcp_log(CE_WARN, pptr->port_dip,
9732 		    "!ns_registry: failed name server registration");
9733 		return (1);
9734 	}
9735 
9736 	return (0);
9737 }
9738 
9739 /*
9740  *     Function: fcp_handle_port_attach
9741  *
9742  *  Description: This function is called from fcp_port_attach() to attach a
9743  *		 new port. This routine does the following:
9744  *
9745  *		1) Allocates an fcp_port structure and initializes it.
9746  *		2) Tries to register the new FC-4 (FCP) capablity with the name
9747  *		   server.
9748  *		3) Kicks off the enumeration of the targets/luns visible
9749  *		   through this new port.  That is done by calling
9750  *		   fcp_statec_callback() if the port is online.
9751  *
9752  *     Argument: ulph		fp/fctl port handle.
9753  *		 *pinfo		Port information.
9754  *		 s_id		Port ID.
9755  *		 instance	Device instance number for the local port
9756  *				(returned by ddi_get_instance()).
9757  *
9758  * Return Value: DDI_SUCCESS
9759  *		 DDI_FAILURE
9760  *
9761  *	Context: User and Kernel context.
9762  */
9763 /*ARGSUSED*/
9764 int
9765 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9766     uint32_t s_id, int instance)
9767 {
9768 	int			res = DDI_FAILURE;
9769 	scsi_hba_tran_t		*tran;
9770 	int			mutex_initted = FALSE;
9771 	int			hba_attached = FALSE;
9772 	int			soft_state_linked = FALSE;
9773 	int			event_bind = FALSE;
9774 	struct fcp_port		*pptr;
9775 	fc_portmap_t		*tmp_list = NULL;
9776 	uint32_t		max_cnt, alloc_cnt;
9777 	uchar_t			*boot_wwn = NULL;
9778 	uint_t			nbytes;
9779 	int			manual_cfg;
9780 
9781 	/*
9782 	 * this port instance attaching for the first time (or after
9783 	 * being detached before)
9784 	 */
9785 	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9786 	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9787 
9788 	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9789 		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9790 		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9791 		    instance);
9792 		return (res);
9793 	}
9794 
9795 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9796 		/* this shouldn't happen */
9797 		ddi_soft_state_free(fcp_softstate, instance);
9798 		cmn_err(CE_WARN, "fcp: bad soft state");
9799 		return (res);
9800 	}
9801 
9802 	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9803 
9804 	/*
9805 	 * Make a copy of ulp_port_info as fctl allocates
9806 	 * a temp struct.
9807 	 */
9808 	(void) fcp_cp_pinfo(pptr, pinfo);
9809 
9810 	/*
9811 	 * Check for manual_configuration_only property.
9812 	 * Enable manual configurtion if the property is
9813 	 * set to 1, otherwise disable manual configuration.
9814 	 */
9815 	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9816 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9817 	    MANUAL_CFG_ONLY,
9818 	    -1)) != -1) {
9819 		if (manual_cfg == 1) {
9820 			char	*pathname;
9821 			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9822 			(void) ddi_pathname(pptr->port_dip, pathname);
9823 			cmn_err(CE_NOTE,
9824 			    "%s (%s%d) %s is enabled via %s.conf.",
9825 			    pathname,
9826 			    ddi_driver_name(pptr->port_dip),
9827 			    ddi_get_instance(pptr->port_dip),
9828 			    MANUAL_CFG_ONLY,
9829 			    ddi_driver_name(pptr->port_dip));
9830 			fcp_enable_auto_configuration = 0;
9831 			kmem_free(pathname, MAXPATHLEN);
9832 		}
9833 	}
9834 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9835 	pptr->port_link_cnt = 1;
9836 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9837 	pptr->port_id = s_id;
9838 	pptr->port_instance = instance;
9839 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9840 	pptr->port_state = FCP_STATE_INIT;
9841 	if (pinfo->port_acc_attr == NULL) {
9842 		/*
9843 		 * The corresponding FCA doesn't support DMA at all
9844 		 */
9845 		pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9846 	}
9847 
9848 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9849 
9850 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9851 		/*
9852 		 * If FCA supports DMA in SCSI data phase, we need preallocate
9853 		 * dma cookie, so stash the cookie size
9854 		 */
9855 		pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9856 		    pptr->port_data_dma_attr.dma_attr_sgllen;
9857 	}
9858 
9859 	/*
9860 	 * The two mutexes of fcp_port are initialized.	 The variable
9861 	 * mutex_initted is incremented to remember that fact.	That variable
9862 	 * is checked when the routine fails and the mutexes have to be
9863 	 * destroyed.
9864 	 */
9865 	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9866 	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9867 	mutex_initted++;
9868 
9869 	/*
9870 	 * The SCSI tran structure is allocate and initialized now.
9871 	 */
9872 	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9873 		fcp_log(CE_WARN, pptr->port_dip,
9874 		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9875 		goto fail;
9876 	}
9877 
9878 	/* link in the transport structure then fill it in */
9879 	pptr->port_tran = tran;
9880 	tran->tran_hba_private		= pptr;
9881 	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9882 	tran->tran_tgt_probe		= NULL;
9883 	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9884 	tran->tran_start		= fcp_scsi_start;
9885 	tran->tran_reset		= fcp_scsi_reset;
9886 	tran->tran_abort		= fcp_scsi_abort;
9887 	tran->tran_getcap		= fcp_scsi_getcap;
9888 	tran->tran_setcap		= fcp_scsi_setcap;
9889 	tran->tran_init_pkt		= NULL;
9890 	tran->tran_destroy_pkt		= NULL;
9891 	tran->tran_dmafree		= NULL;
9892 	tran->tran_sync_pkt		= NULL;
9893 	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9894 	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9895 	tran->tran_get_name		= fcp_scsi_get_name;
9896 	tran->tran_clear_aca		= NULL;
9897 	tran->tran_clear_task_set	= NULL;
9898 	tran->tran_terminate_task	= NULL;
9899 	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9900 	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9901 	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9902 	tran->tran_post_event		= fcp_scsi_bus_post_event;
9903 	tran->tran_quiesce		= NULL;
9904 	tran->tran_unquiesce		= NULL;
9905 	tran->tran_bus_reset		= NULL;
9906 	tran->tran_bus_config		= fcp_scsi_bus_config;
9907 	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9908 	tran->tran_bus_power		= NULL;
9909 	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9910 
9911 	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9912 	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9913 	tran->tran_setup_pkt		= fcp_pkt_setup;
9914 	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9915 	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9916 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9917 	if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9918 		/*
9919 		 * If FCA don't support DMA, then we use different vectors to
9920 		 * minimize the effects on DMA code flow path
9921 		 */
9922 		tran->tran_start	   = fcp_pseudo_start;
9923 		tran->tran_init_pkt	   = fcp_pseudo_init_pkt;
9924 		tran->tran_destroy_pkt	   = fcp_pseudo_destroy_pkt;
9925 		tran->tran_sync_pkt	   = fcp_pseudo_sync_pkt;
9926 		tran->tran_dmafree	   = fcp_pseudo_dmafree;
9927 		tran->tran_setup_pkt	   = NULL;
9928 		tran->tran_teardown_pkt	   = NULL;
9929 		tran->tran_pkt_constructor = NULL;
9930 		tran->tran_pkt_destructor  = NULL;
9931 		pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9932 	}
9933 
9934 	/*
9935 	 * Allocate an ndi event handle
9936 	 */
9937 	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9938 	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9939 
9940 	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9941 	    sizeof (fcp_ndi_event_defs));
9942 
9943 	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9944 	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9945 
9946 	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9947 	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9948 	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9949 
9950 	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9951 	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9952 	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9953 		goto fail;
9954 	}
9955 	event_bind++;	/* Checked in fail case */
9956 
9957 	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9958 	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9959 	    != DDI_SUCCESS) {
9960 		fcp_log(CE_WARN, pptr->port_dip,
9961 		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9962 		goto fail;
9963 	}
9964 	hba_attached++;	/* Checked in fail case */
9965 
9966 	pptr->port_mpxio = 0;
9967 	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9968 	    MDI_SUCCESS) {
9969 		pptr->port_mpxio++;
9970 	}
9971 
9972 	/*
9973 	 * The following code is putting the new port structure in the global
9974 	 * list of ports and, if it is the first port to attach, it start the
9975 	 * fcp_watchdog_tick.
9976 	 *
9977 	 * Why put this new port in the global before we are done attaching it?
9978 	 * We are actually making the structure globally known before we are
9979 	 * done attaching it.  The reason for that is: because of the code that
9980 	 * follows.  At this point the resources to handle the port are
9981 	 * allocated.  This function is now going to do the following:
9982 	 *
9983 	 *   1) It is going to try to register with the name server advertizing
9984 	 *	the new FCP capability of the port.
9985 	 *   2) It is going to play the role of the fp/fctl layer by building
9986 	 *	a list of worlwide names reachable through this port and call
9987 	 *	itself on fcp_statec_callback().  That requires the port to
9988 	 *	be part of the global list.
9989 	 */
9990 	mutex_enter(&fcp_global_mutex);
9991 	if (fcp_port_head == NULL) {
9992 		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
9993 	}
9994 	pptr->port_next = fcp_port_head;
9995 	fcp_port_head = pptr;
9996 	soft_state_linked++;
9997 
9998 	if (fcp_watchdog_init++ == 0) {
9999 		fcp_watchdog_tick = fcp_watchdog_timeout *
10000 		    drv_usectohz(1000000);
10001 		fcp_watchdog_id = timeout(fcp_watch, NULL,
10002 		    fcp_watchdog_tick);
10003 	}
10004 	mutex_exit(&fcp_global_mutex);
10005 
10006 	/*
10007 	 * Here an attempt is made to register with the name server, the new
10008 	 * FCP capability.  That is done using an RTF_ID to the name server.
10009 	 * It is done synchronously.  The function fcp_do_ns_registry()
10010 	 * doesn't return till the name server responded.
10011 	 * On failures, just ignore it for now and it will get retried during
10012 	 * state change callbacks. We'll set a flag to show this failure
10013 	 */
10014 	if (fcp_do_ns_registry(pptr, s_id)) {
10015 		mutex_enter(&pptr->port_mutex);
10016 		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10017 		mutex_exit(&pptr->port_mutex);
10018 	} else {
10019 		mutex_enter(&pptr->port_mutex);
10020 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10021 		mutex_exit(&pptr->port_mutex);
10022 	}
10023 
10024 	/*
10025 	 * Lookup for boot WWN property
10026 	 */
10027 	if (modrootloaded != 1) {
10028 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10029 		    ddi_get_parent(pinfo->port_dip),
10030 		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10031 		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10032 		    (nbytes == FC_WWN_SIZE)) {
10033 			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10034 		}
10035 		if (boot_wwn) {
10036 			ddi_prop_free(boot_wwn);
10037 		}
10038 	}
10039 
10040 	/*
10041 	 * Handle various topologies and link states.
10042 	 */
10043 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10044 	case FC_STATE_OFFLINE:
10045 
10046 		/*
10047 		 * we're attaching a port where the link is offline
10048 		 *
10049 		 * Wait for ONLINE, at which time a state
10050 		 * change will cause a statec_callback
10051 		 *
10052 		 * in the mean time, do not do anything
10053 		 */
10054 		res = DDI_SUCCESS;
10055 		pptr->port_state |= FCP_STATE_OFFLINE;
10056 		break;
10057 
10058 	case FC_STATE_ONLINE: {
10059 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
10060 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10061 			res = DDI_SUCCESS;
10062 			break;
10063 		}
10064 		/*
10065 		 * discover devices and create nodes (a private
10066 		 * loop or point-to-point)
10067 		 */
10068 		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10069 
10070 		/*
10071 		 * At this point we are going to build a list of all the ports
10072 		 * that	can be reached through this local port.	 It looks like
10073 		 * we cannot handle more than FCP_MAX_DEVICES per local port
10074 		 * (128).
10075 		 */
10076 		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10077 		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10078 		    KM_NOSLEEP)) == NULL) {
10079 			fcp_log(CE_WARN, pptr->port_dip,
10080 			    "!fcp%d: failed to allocate portmap",
10081 			    instance);
10082 			goto fail;
10083 		}
10084 
10085 		/*
10086 		 * fc_ulp_getportmap() is going to provide us with the list of
10087 		 * remote ports in the buffer we just allocated.  The way the
10088 		 * list is going to be retrieved depends on the topology.
10089 		 * However, if we are connected to a Fabric, a name server
10090 		 * request may be sent to get the list of FCP capable ports.
10091 		 * It should be noted that is the case the request is
10092 		 * synchronous.	 This means we are stuck here till the name
10093 		 * server replies.  A lot of things can change during that time
10094 		 * and including, may be, being called on
10095 		 * fcp_statec_callback() for different reasons. I'm not sure
10096 		 * the code can handle that.
10097 		 */
10098 		max_cnt = FCP_MAX_DEVICES;
10099 		alloc_cnt = FCP_MAX_DEVICES;
10100 		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10101 		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10102 		    FC_SUCCESS) {
10103 			caddr_t msg;
10104 
10105 			(void) fc_ulp_error(res, &msg);
10106 
10107 			/*
10108 			 * this	 just means the transport is
10109 			 * busy perhaps building a portmap so,
10110 			 * for now, succeed this port attach
10111 			 * when the transport has a new map,
10112 			 * it'll send us a state change then
10113 			 */
10114 			fcp_log(CE_WARN, pptr->port_dip,
10115 			    "!failed to get port map : %s", msg);
10116 
10117 			res = DDI_SUCCESS;
10118 			break;	/* go return result */
10119 		}
10120 		if (max_cnt > alloc_cnt) {
10121 			alloc_cnt = max_cnt;
10122 		}
10123 
10124 		/*
10125 		 * We are now going to call fcp_statec_callback() ourselves.
10126 		 * By issuing this call we are trying to kick off the enumera-
10127 		 * tion process.
10128 		 */
10129 		/*
10130 		 * let the state change callback do the SCSI device
10131 		 * discovery and create the devinfos
10132 		 */
10133 		fcp_statec_callback(ulph, pptr->port_fp_handle,
10134 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10135 		    max_cnt, pptr->port_id);
10136 
10137 		res = DDI_SUCCESS;
10138 		break;
10139 	}
10140 
10141 	default:
10142 		/* unknown port state */
10143 		fcp_log(CE_WARN, pptr->port_dip,
10144 		    "!fcp%d: invalid port state at attach=0x%x",
10145 		    instance, pptr->port_phys_state);
10146 
10147 		mutex_enter(&pptr->port_mutex);
10148 		pptr->port_phys_state = FCP_STATE_OFFLINE;
10149 		mutex_exit(&pptr->port_mutex);
10150 
10151 		res = DDI_SUCCESS;
10152 		break;
10153 	}
10154 
10155 	/* free temp list if used */
10156 	if (tmp_list != NULL) {
10157 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10158 	}
10159 
10160 	/* note the attach time */
10161 	pptr->port_attach_time = ddi_get_lbolt64();
10162 
10163 	/* all done */
10164 	return (res);
10165 
10166 	/* a failure we have to clean up after */
10167 fail:
10168 	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10169 
10170 	if (soft_state_linked) {
10171 		/* remove this fcp_port from the linked list */
10172 		(void) fcp_soft_state_unlink(pptr);
10173 	}
10174 
10175 	/* unbind and free event set */
10176 	if (pptr->port_ndi_event_hdl) {
10177 		if (event_bind) {
10178 			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10179 			    &pptr->port_ndi_events, NDI_SLEEP);
10180 		}
10181 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10182 	}
10183 
10184 	if (pptr->port_ndi_event_defs) {
10185 		(void) kmem_free(pptr->port_ndi_event_defs,
10186 		    sizeof (fcp_ndi_event_defs));
10187 	}
10188 
10189 	/*
10190 	 * Clean up mpxio stuff
10191 	 */
10192 	if (pptr->port_mpxio) {
10193 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10194 		pptr->port_mpxio--;
10195 	}
10196 
10197 	/* undo SCSI HBA setup */
10198 	if (hba_attached) {
10199 		(void) scsi_hba_detach(pptr->port_dip);
10200 	}
10201 	if (pptr->port_tran != NULL) {
10202 		scsi_hba_tran_free(pptr->port_tran);
10203 	}
10204 
10205 	mutex_enter(&fcp_global_mutex);
10206 
10207 	/*
10208 	 * We check soft_state_linked, because it is incremented right before
10209 	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10210 	 * soft_state_linked is still FALSE, we do not want to decrement
10211 	 * fcp_watchdog_init or possibly call untimeout.
10212 	 */
10213 
10214 	if (soft_state_linked) {
10215 		if (--fcp_watchdog_init == 0) {
10216 			timeout_id_t	tid = fcp_watchdog_id;
10217 
10218 			mutex_exit(&fcp_global_mutex);
10219 			(void) untimeout(tid);
10220 		} else {
10221 			mutex_exit(&fcp_global_mutex);
10222 		}
10223 	} else {
10224 		mutex_exit(&fcp_global_mutex);
10225 	}
10226 
10227 	if (mutex_initted) {
10228 		mutex_destroy(&pptr->port_mutex);
10229 		mutex_destroy(&pptr->port_pkt_mutex);
10230 	}
10231 
10232 	if (tmp_list != NULL) {
10233 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10234 	}
10235 
10236 	/* this makes pptr invalid */
10237 	ddi_soft_state_free(fcp_softstate, instance);
10238 
10239 	return (DDI_FAILURE);
10240 }
10241 
10242 
10243 static int
10244 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10245 {
10246 	int count = 0;
10247 
10248 	mutex_enter(&pptr->port_mutex);
10249 
10250 	/*
10251 	 * if the port is powered down or suspended, nothing else
10252 	 * to do; just return.
10253 	 */
10254 	if (flag != FCP_STATE_DETACHING) {
10255 		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10256 		    FCP_STATE_SUSPENDED)) {
10257 			pptr->port_state |= flag;
10258 			mutex_exit(&pptr->port_mutex);
10259 			return (FC_SUCCESS);
10260 		}
10261 	}
10262 
10263 	if (pptr->port_state & FCP_STATE_IN_MDI) {
10264 		mutex_exit(&pptr->port_mutex);
10265 		return (FC_FAILURE);
10266 	}
10267 
10268 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10269 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10270 	    "fcp_handle_port_detach: port is detaching");
10271 
10272 	pptr->port_state |= flag;
10273 
10274 	/*
10275 	 * Wait for any ongoing reconfig/ipkt to complete, that
10276 	 * ensures the freeing to targets/luns is safe.
10277 	 * No more ref to this port should happen from statec/ioctl
10278 	 * after that as it was removed from the global port list.
10279 	 */
10280 	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10281 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10282 		/*
10283 		 * Let's give sufficient time for reconfig/ipkt
10284 		 * to complete.
10285 		 */
10286 		if (count++ >= FCP_ICMD_DEADLINE) {
10287 			break;
10288 		}
10289 		mutex_exit(&pptr->port_mutex);
10290 		delay(drv_usectohz(1000000));
10291 		mutex_enter(&pptr->port_mutex);
10292 	}
10293 
10294 	/*
10295 	 * if the driver is still busy then fail to
10296 	 * suspend/power down.
10297 	 */
10298 	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10299 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10300 		pptr->port_state &= ~flag;
10301 		mutex_exit(&pptr->port_mutex);
10302 		return (FC_FAILURE);
10303 	}
10304 
10305 	if (flag == FCP_STATE_DETACHING) {
10306 		pptr = fcp_soft_state_unlink(pptr);
10307 		ASSERT(pptr != NULL);
10308 	}
10309 
10310 	pptr->port_link_cnt++;
10311 	pptr->port_state |= FCP_STATE_OFFLINE;
10312 	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10313 
10314 	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10315 	    FCP_CAUSE_LINK_DOWN);
10316 	mutex_exit(&pptr->port_mutex);
10317 
10318 	/* kill watch dog timer if we're the last */
10319 	mutex_enter(&fcp_global_mutex);
10320 	if (--fcp_watchdog_init == 0) {
10321 		timeout_id_t	tid = fcp_watchdog_id;
10322 		mutex_exit(&fcp_global_mutex);
10323 		(void) untimeout(tid);
10324 	} else {
10325 		mutex_exit(&fcp_global_mutex);
10326 	}
10327 
10328 	/* clean up the port structures */
10329 	if (flag == FCP_STATE_DETACHING) {
10330 		fcp_cleanup_port(pptr, instance);
10331 	}
10332 
10333 	return (FC_SUCCESS);
10334 }
10335 
10336 
10337 static void
10338 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10339 {
10340 	ASSERT(pptr != NULL);
10341 
10342 	/* unbind and free event set */
10343 	if (pptr->port_ndi_event_hdl) {
10344 		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10345 		    &pptr->port_ndi_events, NDI_SLEEP);
10346 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10347 	}
10348 
10349 	if (pptr->port_ndi_event_defs) {
10350 		(void) kmem_free(pptr->port_ndi_event_defs,
10351 		    sizeof (fcp_ndi_event_defs));
10352 	}
10353 
10354 	/* free the lun/target structures and devinfos */
10355 	fcp_free_targets(pptr);
10356 
10357 	/*
10358 	 * Clean up mpxio stuff
10359 	 */
10360 	if (pptr->port_mpxio) {
10361 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10362 		pptr->port_mpxio--;
10363 	}
10364 
10365 	/* clean up SCSA stuff */
10366 	(void) scsi_hba_detach(pptr->port_dip);
10367 	if (pptr->port_tran != NULL) {
10368 		scsi_hba_tran_free(pptr->port_tran);
10369 	}
10370 
10371 #ifdef	KSTATS_CODE
10372 	/* clean up kstats */
10373 	if (pptr->fcp_ksp != NULL) {
10374 		kstat_delete(pptr->fcp_ksp);
10375 	}
10376 #endif
10377 
10378 	/* clean up soft state mutexes/condition variables */
10379 	mutex_destroy(&pptr->port_mutex);
10380 	mutex_destroy(&pptr->port_pkt_mutex);
10381 
10382 	/* all done with soft state */
10383 	ddi_soft_state_free(fcp_softstate, instance);
10384 }
10385 
10386 /*
10387  *     Function: fcp_kmem_cache_constructor
10388  *
10389  *  Description: This function allocates and initializes the resources required
10390  *		 to build a scsi_pkt structure the target driver.  The result
10391  *		 of the allocation and initialization will be cached in the
10392  *		 memory cache.	As DMA resources may be allocated here, that
10393  *		 means DMA resources will be tied up in the cache manager.
10394  *		 This is a tradeoff that has been made for performance reasons.
10395  *
10396  *     Argument: *buf		Memory to preinitialize.
10397  *		 *arg		FCP port structure (fcp_port).
10398  *		 kmflags	Value passed to kmem_cache_alloc() and
10399  *				propagated to the constructor.
10400  *
10401  * Return Value: 0	Allocation/Initialization was successful.
10402  *		 -1	Allocation or Initialization failed.
10403  *
10404  *
10405  * If the returned value is 0, the buffer is initialized like this:
10406  *
10407  *		    +================================+
10408  *	     +----> |	      struct scsi_pkt	     |
10409  *	     |	    |				     |
10410  *	     | +--- | pkt_ha_private		     |
10411  *	     | |    |				     |
10412  *	     | |    +================================+
10413  *	     | |
10414  *	     | |    +================================+
10415  *	     | +--> |	    struct fcp_pkt	     | <---------+
10416  *	     |	    |				     |		 |
10417  *	     +----- | cmd_pkt			     |		 |
10418  *		    |			  cmd_fp_pkt | ---+	 |
10419  *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10420  *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10421  *	  |    |    |--------------------------------|	  |	 |
10422  *	  |    |    |	      struct fc_packet	     | <--+	 |
10423  *	  |    |    |				     |		 |
10424  *	  |    |    |		     pkt_ulp_private | ----------+
10425  *	  |    |    |		     pkt_fca_private | -----+
10426  *	  |    |    |		     pkt_data_cookie | ---+ |
10427  *	  |    |    | pkt_cmdlen		     |	  | |
10428  *	  |    |(a) | pkt_rsplen		     |	  | |
10429  *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10430  *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10431  *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10432  *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10433  *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10434  *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10435  *		    +================================+	  | |  |   |   |    |
10436  *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10437  *		    |				     |	    |  |   |   |    |
10438  *		    +================================+	    |  |   |   |    |
10439  *		    |	      fca_private	     | <----+  |   |   |    |
10440  *		    |				     |	       |   |   |    |
10441  *		    +================================+	       |   |   |    |
10442  *							       |   |   |    |
10443  *							       |   |   |    |
10444  *		    +================================+	 (d)   |   |   |    |
10445  *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10446  *		    |				     |		   |   |    |
10447  *		    +================================+		   |   |    |
10448  *								   |   |    |
10449  *		    +================================+	 (d)	   |   |    |
10450  *		    |		fcp_resp	     | <-----------+   |    |
10451  *		    |	(DMA resources associated)   |		       |    |
10452  *		    +================================+		       |    |
10453  *								       |    |
10454  *								       |    |
10455  *								       |    |
10456  *		    +================================+	 (c)	       |    |
10457  *		    |	     fcp_cmd cookies	     | <---------------+    |
10458  *		    |				     |			    |
10459  *		    +================================+			    |
10460  *									    |
10461  *		    +================================+	 (c)		    |
10462  *		    |		 fcp_cmd	     | <--------------------+
10463  *		    |	(DMA resources associated)   |
10464  *		    +================================+
10465  *
10466  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10467  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10468  * (c) Only if DMA is used for the FCP_CMD buffer.
10469  * (d) Only if DMA is used for the FCP_RESP buffer
10470  */
10471 static int
10472 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10473     int kmflags)
10474 {
10475 	struct fcp_pkt	*cmd;
10476 	struct fcp_port	*pptr;
10477 	fc_packet_t	*fpkt;
10478 
10479 	pptr = (struct fcp_port *)tran->tran_hba_private;
10480 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10481 	bzero(cmd, tran->tran_hba_len);
10482 
10483 	cmd->cmd_pkt = pkt;
10484 	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10485 	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10486 	cmd->cmd_fp_pkt = fpkt;
10487 
10488 	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10489 	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10490 	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10491 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10492 
10493 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10494 	    sizeof (struct fcp_pkt));
10495 
10496 	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10497 	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10498 
10499 	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10500 		/*
10501 		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10502 		 * fcp_resp.  The transfer of information will be done by
10503 		 * bcopy.
10504 		 * The naming of the flags (that is actually a value) is
10505 		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10506 		 * DMA" but instead "NO DMA".
10507 		 */
10508 		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10509 		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10510 		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10511 	} else {
10512 		/*
10513 		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10514 		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10515 		 * interfaces.
10516 		 */
10517 		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10518 			return (-1);
10519 		}
10520 	}
10521 
10522 	return (0);
10523 }
10524 
10525 /*
10526  *     Function: fcp_kmem_cache_destructor
10527  *
10528  *  Description: Called by the destructor of the cache managed by SCSA.
10529  *		 All the resources pre-allocated in fcp_pkt_constructor
10530  *		 and the data also pre-initialized in fcp_pkt_constructor
10531  *		 are freed and uninitialized here.
10532  *
10533  *     Argument: *buf		Memory to uninitialize.
10534  *		 *arg		FCP port structure (fcp_port).
10535  *
10536  * Return Value: None
10537  *
10538  *	Context: kernel
10539  */
10540 static void
10541 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10542 {
10543 	struct fcp_pkt	*cmd;
10544 	struct fcp_port	*pptr;
10545 
10546 	pptr = (struct fcp_port *)(tran->tran_hba_private);
10547 	cmd = pkt->pkt_ha_private;
10548 
10549 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10550 		/*
10551 		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10552 		 * buffer and DMA resources allocated to do so are released.
10553 		 */
10554 		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10555 	}
10556 }
10557 
10558 /*
10559  *     Function: fcp_alloc_cmd_resp
10560  *
10561  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10562  *		 will be DMAed by the HBA.  The buffer is allocated applying
10563  *		 the DMA requirements for the HBA.  The buffers allocated will
10564  *		 also be bound.	 DMA resources are allocated in the process.
10565  *		 They will be released by fcp_free_cmd_resp().
10566  *
10567  *     Argument: *pptr	FCP port.
10568  *		 *fpkt	fc packet for which the cmd and resp packet should be
10569  *			allocated.
10570  *		 flags	Allocation flags.
10571  *
10572  * Return Value: FC_FAILURE
10573  *		 FC_SUCCESS
10574  *
10575  *	Context: User or Kernel context only if flags == KM_SLEEP.
10576  *		 Interrupt context if the KM_SLEEP is not specified.
10577  */
10578 static int
10579 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10580 {
10581 	int			rval;
10582 	int			cmd_len;
10583 	int			resp_len;
10584 	ulong_t			real_len;
10585 	int			(*cb) (caddr_t);
10586 	ddi_dma_cookie_t	pkt_cookie;
10587 	ddi_dma_cookie_t	*cp;
10588 	uint32_t		cnt;
10589 
10590 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10591 
10592 	cmd_len = fpkt->pkt_cmdlen;
10593 	resp_len = fpkt->pkt_rsplen;
10594 
10595 	ASSERT(fpkt->pkt_cmd_dma == NULL);
10596 
10597 	/* Allocation of a DMA handle used in subsequent calls. */
10598 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10599 	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10600 		return (FC_FAILURE);
10601 	}
10602 
10603 	/* A buffer is allocated that satisfies the DMA requirements. */
10604 	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10605 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10606 	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10607 
10608 	if (rval != DDI_SUCCESS) {
10609 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10610 		return (FC_FAILURE);
10611 	}
10612 
10613 	if (real_len < cmd_len) {
10614 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10615 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10616 		return (FC_FAILURE);
10617 	}
10618 
10619 	/* The buffer allocated is DMA bound. */
10620 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10621 	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10622 	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10623 
10624 	if (rval != DDI_DMA_MAPPED) {
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 	if (fpkt->pkt_cmd_cookie_cnt >
10631 	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10632 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10633 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10634 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10635 		return (FC_FAILURE);
10636 	}
10637 
10638 	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10639 
10640 	/*
10641 	 * The buffer where the scatter/gather list is going to be built is
10642 	 * allocated.
10643 	 */
10644 	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10645 	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10646 	    KM_NOSLEEP);
10647 
10648 	if (cp == NULL) {
10649 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10650 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10651 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10652 		return (FC_FAILURE);
10653 	}
10654 
10655 	/*
10656 	 * The scatter/gather list for the buffer we just allocated is built
10657 	 * here.
10658 	 */
10659 	*cp = pkt_cookie;
10660 	cp++;
10661 
10662 	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10663 		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10664 		    &pkt_cookie);
10665 		*cp = pkt_cookie;
10666 	}
10667 
10668 	ASSERT(fpkt->pkt_resp_dma == NULL);
10669 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10670 	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10671 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10672 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10673 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10674 		return (FC_FAILURE);
10675 	}
10676 
10677 	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10678 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10679 	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10680 	    &fpkt->pkt_resp_acc);
10681 
10682 	if (rval != DDI_SUCCESS) {
10683 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10684 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10685 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10686 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10687 		kmem_free(fpkt->pkt_cmd_cookie,
10688 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10689 		return (FC_FAILURE);
10690 	}
10691 
10692 	if (real_len < resp_len) {
10693 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
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 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10704 	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10705 	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10706 
10707 	if (rval != DDI_DMA_MAPPED) {
10708 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10709 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10710 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10711 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10712 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10713 		kmem_free(fpkt->pkt_cmd_cookie,
10714 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10715 		return (FC_FAILURE);
10716 	}
10717 
10718 	if (fpkt->pkt_resp_cookie_cnt >
10719 	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10720 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10721 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10722 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10723 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10724 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10725 		kmem_free(fpkt->pkt_cmd_cookie,
10726 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10727 		return (FC_FAILURE);
10728 	}
10729 
10730 	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10731 
10732 	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10733 	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10734 	    KM_NOSLEEP);
10735 
10736 	if (cp == NULL) {
10737 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10738 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10739 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10740 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10741 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10742 		kmem_free(fpkt->pkt_cmd_cookie,
10743 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10744 		return (FC_FAILURE);
10745 	}
10746 
10747 	*cp = pkt_cookie;
10748 	cp++;
10749 
10750 	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10751 		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10752 		    &pkt_cookie);
10753 		*cp = pkt_cookie;
10754 	}
10755 
10756 	return (FC_SUCCESS);
10757 }
10758 
10759 /*
10760  *     Function: fcp_free_cmd_resp
10761  *
10762  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10763  *		 allocated by fcp_alloc_cmd_resp() and all the resources
10764  *		 associated with them.	That includes the DMA resources and the
10765  *		 buffer allocated for the cookies of each one of them.
10766  *
10767  *     Argument: *pptr		FCP port context.
10768  *		 *fpkt		fc packet containing the cmd and resp packet
10769  *				to be released.
10770  *
10771  * Return Value: None
10772  *
10773  *	Context: Interrupt, User and Kernel context.
10774  */
10775 /* ARGSUSED */
10776 static void
10777 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10778 {
10779 	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10780 
10781 	if (fpkt->pkt_resp_dma) {
10782 		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10783 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10784 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10785 	}
10786 
10787 	if (fpkt->pkt_resp_cookie) {
10788 		kmem_free(fpkt->pkt_resp_cookie,
10789 		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10790 		fpkt->pkt_resp_cookie = NULL;
10791 	}
10792 
10793 	if (fpkt->pkt_cmd_dma) {
10794 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10795 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10796 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10797 	}
10798 
10799 	if (fpkt->pkt_cmd_cookie) {
10800 		kmem_free(fpkt->pkt_cmd_cookie,
10801 		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10802 		fpkt->pkt_cmd_cookie = NULL;
10803 	}
10804 }
10805 
10806 
10807 /*
10808  * called by the transport to do our own target initialization
10809  *
10810  * can acquire and release the global mutex
10811  */
10812 /* ARGSUSED */
10813 static int
10814 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10815     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10816 {
10817 	uchar_t			*bytes;
10818 	uint_t			nbytes;
10819 	uint16_t		lun_num;
10820 	struct fcp_tgt	*ptgt;
10821 	struct fcp_lun	*plun;
10822 	struct fcp_port	*pptr = (struct fcp_port *)
10823 	    hba_tran->tran_hba_private;
10824 
10825 	ASSERT(pptr != NULL);
10826 
10827 	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10828 	    FCP_BUF_LEVEL_8, 0,
10829 	    "fcp_phys_tgt_init: called for %s (instance %d)",
10830 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10831 
10832 	/* get our port WWN property */
10833 	bytes = NULL;
10834 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10835 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10836 	    (nbytes != FC_WWN_SIZE)) {
10837 		/* no port WWN property */
10838 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10839 		    FCP_BUF_LEVEL_8, 0,
10840 		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10841 		    " for %s (instance %d): bytes=%p nbytes=%x",
10842 		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10843 		    nbytes);
10844 
10845 		if (bytes != NULL) {
10846 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10847 		}
10848 
10849 		return (DDI_NOT_WELL_FORMED);
10850 	}
10851 	ASSERT(bytes != NULL);
10852 
10853 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10854 	    LUN_PROP, 0xFFFF);
10855 	if (lun_num == 0xFFFF) {
10856 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10857 		    FCP_BUF_LEVEL_8, 0,
10858 		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10859 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10860 		    ddi_get_instance(tgt_dip));
10861 
10862 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10863 		return (DDI_NOT_WELL_FORMED);
10864 	}
10865 
10866 	mutex_enter(&pptr->port_mutex);
10867 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10868 		mutex_exit(&pptr->port_mutex);
10869 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10870 		    FCP_BUF_LEVEL_8, 0,
10871 		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10872 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10873 		    ddi_get_instance(tgt_dip));
10874 
10875 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10876 		return (DDI_FAILURE);
10877 	}
10878 
10879 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10880 	    FC_WWN_SIZE) == 0);
10881 	ASSERT(plun->lun_num == lun_num);
10882 
10883 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10884 
10885 	ptgt = plun->lun_tgt;
10886 
10887 	mutex_enter(&ptgt->tgt_mutex);
10888 	plun->lun_tgt_count++;
10889 	scsi_device_hba_private_set(sd, plun);
10890 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10891 	plun->lun_sd = sd;
10892 	mutex_exit(&ptgt->tgt_mutex);
10893 	mutex_exit(&pptr->port_mutex);
10894 
10895 	return (DDI_SUCCESS);
10896 }
10897 
10898 /*ARGSUSED*/
10899 static int
10900 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10901     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10902 {
10903 	uchar_t			*bytes;
10904 	uint_t			nbytes;
10905 	uint16_t		lun_num;
10906 	struct fcp_tgt	*ptgt;
10907 	struct fcp_lun	*plun;
10908 	struct fcp_port	*pptr = (struct fcp_port *)
10909 	    hba_tran->tran_hba_private;
10910 	child_info_t		*cip;
10911 
10912 	ASSERT(pptr != NULL);
10913 
10914 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10915 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10916 	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10917 	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10918 	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10919 
10920 	cip = (child_info_t *)sd->sd_pathinfo;
10921 	if (cip == NULL) {
10922 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10923 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10924 		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10925 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10926 		    ddi_get_instance(tgt_dip));
10927 
10928 		return (DDI_NOT_WELL_FORMED);
10929 	}
10930 
10931 	/* get our port WWN property */
10932 	bytes = NULL;
10933 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10934 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10935 	    (nbytes != FC_WWN_SIZE)) {
10936 		if (bytes) {
10937 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10938 		}
10939 		return (DDI_NOT_WELL_FORMED);
10940 	}
10941 
10942 	ASSERT(bytes != NULL);
10943 
10944 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10945 	    LUN_PROP, 0xFFFF);
10946 	if (lun_num == 0xFFFF) {
10947 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10948 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10949 		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10950 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10951 		    ddi_get_instance(tgt_dip));
10952 
10953 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10954 		return (DDI_NOT_WELL_FORMED);
10955 	}
10956 
10957 	mutex_enter(&pptr->port_mutex);
10958 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10959 		mutex_exit(&pptr->port_mutex);
10960 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10961 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10962 		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10963 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10964 		    ddi_get_instance(tgt_dip));
10965 
10966 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10967 		return (DDI_FAILURE);
10968 	}
10969 
10970 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10971 	    FC_WWN_SIZE) == 0);
10972 	ASSERT(plun->lun_num == lun_num);
10973 
10974 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10975 
10976 	ptgt = plun->lun_tgt;
10977 
10978 	mutex_enter(&ptgt->tgt_mutex);
10979 	plun->lun_tgt_count++;
10980 	scsi_device_hba_private_set(sd, plun);
10981 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10982 	plun->lun_sd = sd;
10983 	mutex_exit(&ptgt->tgt_mutex);
10984 	mutex_exit(&pptr->port_mutex);
10985 
10986 	return (DDI_SUCCESS);
10987 }
10988 
10989 
10990 /*
10991  * called by the transport to do our own target initialization
10992  *
10993  * can acquire and release the global mutex
10994  */
10995 /* ARGSUSED */
10996 static int
10997 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10998     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10999 {
11000 	struct fcp_port	*pptr = (struct fcp_port *)
11001 	    hba_tran->tran_hba_private;
11002 	int			rval;
11003 
11004 	ASSERT(pptr != NULL);
11005 
11006 	/*
11007 	 * Child node is getting initialized.  Look at the mpxio component
11008 	 * type on the child device to see if this device is mpxio managed
11009 	 * or not.
11010 	 */
11011 	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11012 		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11013 	} else {
11014 		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11015 	}
11016 
11017 	return (rval);
11018 }
11019 
11020 
11021 /* ARGSUSED */
11022 static void
11023 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11024     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11025 {
11026 	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
11027 	struct fcp_tgt	*ptgt;
11028 
11029 	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11030 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
11031 	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11032 	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11033 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11034 
11035 	if (plun == NULL) {
11036 		return;
11037 	}
11038 	ptgt = plun->lun_tgt;
11039 
11040 	ASSERT(ptgt != NULL);
11041 
11042 	mutex_enter(&ptgt->tgt_mutex);
11043 	ASSERT(plun->lun_tgt_count > 0);
11044 
11045 	if (--plun->lun_tgt_count == 0) {
11046 		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11047 	}
11048 	plun->lun_sd = NULL;
11049 	mutex_exit(&ptgt->tgt_mutex);
11050 }
11051 
11052 /*
11053  *     Function: fcp_scsi_start
11054  *
11055  *  Description: This function is called by the target driver to request a
11056  *		 command to be sent.
11057  *
11058  *     Argument: *ap		SCSI address of the device.
11059  *		 *pkt		SCSI packet containing the cmd to send.
11060  *
11061  * Return Value: TRAN_ACCEPT
11062  *		 TRAN_BUSY
11063  *		 TRAN_BADPKT
11064  *		 TRAN_FATAL_ERROR
11065  */
11066 static int
11067 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11068 {
11069 	struct fcp_port	*pptr = ADDR2FCP(ap);
11070 	struct fcp_lun	*plun = ADDR2LUN(ap);
11071 	struct fcp_pkt	*cmd = PKT2CMD(pkt);
11072 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11073 	int			rval;
11074 
11075 	/* ensure command isn't already issued */
11076 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11077 
11078 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11079 	    fcp_trace, FCP_BUF_LEVEL_9, 0,
11080 	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11081 
11082 	/*
11083 	 * It is strange that we enter the fcp_port mutex and the target
11084 	 * mutex to check the lun state (which has a mutex of its own).
11085 	 */
11086 	mutex_enter(&pptr->port_mutex);
11087 	mutex_enter(&ptgt->tgt_mutex);
11088 
11089 	/*
11090 	 * If the device is offline and is not in the process of coming
11091 	 * online, fail the request.
11092 	 */
11093 
11094 	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11095 	    !(plun->lun_state & FCP_LUN_ONLINING)) {
11096 		mutex_exit(&ptgt->tgt_mutex);
11097 		mutex_exit(&pptr->port_mutex);
11098 
11099 		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11100 			pkt->pkt_reason = CMD_DEV_GONE;
11101 		}
11102 
11103 		return (TRAN_FATAL_ERROR);
11104 	}
11105 	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11106 
11107 	/*
11108 	 * If we are suspended, kernel is trying to dump, so don't
11109 	 * block, fail or defer requests - send them down right away.
11110 	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11111 	 * assume we have been suspended.  There is hardware such as
11112 	 * the v880 that doesn't do PM.	 Thus, the check for
11113 	 * ddi_in_panic.
11114 	 *
11115 	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11116 	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11117 	 * either the device will have gone away or changed and we can fail
11118 	 * the request, or we can proceed if the device didn't change.
11119 	 *
11120 	 * If the pd in the target or the packet is NULL it's probably
11121 	 * because the device has gone away, we allow the request to be
11122 	 * put on the internal queue here in case the device comes back within
11123 	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11124 	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11125 	 * could be NULL because the device was disappearing during or since
11126 	 * packet initialization.
11127 	 */
11128 
11129 	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11130 	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11131 	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11132 	    (ptgt->tgt_pd_handle == NULL) ||
11133 	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11134 		/*
11135 		 * If ((LUN is busy AND
11136 		 *	LUN not suspended AND
11137 		 *	The system is not in panic state) OR
11138 		 *	(The port is coming up))
11139 		 *
11140 		 * We check to see if the any of the flags FLAG_NOINTR or
11141 		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11142 		 * returned will be TRAN_BUSY.	If not, the request is queued.
11143 		 */
11144 		mutex_exit(&ptgt->tgt_mutex);
11145 		mutex_exit(&pptr->port_mutex);
11146 
11147 		/* see if using interrupts is allowed (so queueing'll work) */
11148 		if (pkt->pkt_flags & FLAG_NOINTR) {
11149 			pkt->pkt_resid = 0;
11150 			return (TRAN_BUSY);
11151 		}
11152 		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11153 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11154 			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11155 			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11156 			return (TRAN_BUSY);
11157 		}
11158 #ifdef	DEBUG
11159 		mutex_enter(&pptr->port_pkt_mutex);
11160 		pptr->port_npkts++;
11161 		mutex_exit(&pptr->port_pkt_mutex);
11162 #endif /* DEBUG */
11163 
11164 		/* got queue up the pkt for later */
11165 		fcp_queue_pkt(pptr, cmd);
11166 		return (TRAN_ACCEPT);
11167 	}
11168 	cmd->cmd_state = FCP_PKT_ISSUED;
11169 
11170 	mutex_exit(&ptgt->tgt_mutex);
11171 	mutex_exit(&pptr->port_mutex);
11172 
11173 	/*
11174 	 * Now that we released the mutexes, what was protected by them can
11175 	 * change.
11176 	 */
11177 
11178 	/*
11179 	 * If there is a reconfiguration in progress, wait for it to complete.
11180 	 */
11181 	fcp_reconfig_wait(pptr);
11182 
11183 	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11184 	    pkt->pkt_time : 0;
11185 
11186 	/* prepare the packet */
11187 
11188 	fcp_prepare_pkt(pptr, cmd, plun);
11189 
11190 	if (cmd->cmd_pkt->pkt_time) {
11191 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11192 	} else {
11193 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11194 	}
11195 
11196 	/*
11197 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11198 	 * have to do polled I/O
11199 	 */
11200 	if (pkt->pkt_flags & FLAG_NOINTR) {
11201 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11202 		return (fcp_dopoll(pptr, cmd));
11203 	}
11204 
11205 #ifdef	DEBUG
11206 	mutex_enter(&pptr->port_pkt_mutex);
11207 	pptr->port_npkts++;
11208 	mutex_exit(&pptr->port_pkt_mutex);
11209 #endif /* DEBUG */
11210 
11211 	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11212 	if (rval == FC_SUCCESS) {
11213 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11214 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11215 		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11216 		return (TRAN_ACCEPT);
11217 	}
11218 
11219 	cmd->cmd_state = FCP_PKT_IDLE;
11220 
11221 #ifdef	DEBUG
11222 	mutex_enter(&pptr->port_pkt_mutex);
11223 	pptr->port_npkts--;
11224 	mutex_exit(&pptr->port_pkt_mutex);
11225 #endif /* DEBUG */
11226 
11227 	/*
11228 	 * For lack of clearer definitions, choose
11229 	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11230 	 */
11231 
11232 	if (rval == FC_TRAN_BUSY) {
11233 		pkt->pkt_resid = 0;
11234 		rval = TRAN_BUSY;
11235 	} else {
11236 		mutex_enter(&ptgt->tgt_mutex);
11237 		if (plun->lun_state & FCP_LUN_OFFLINE) {
11238 			child_info_t	*cip;
11239 
11240 			mutex_enter(&plun->lun_mutex);
11241 			cip = plun->lun_cip;
11242 			mutex_exit(&plun->lun_mutex);
11243 
11244 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11245 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11246 			    "fcp_transport failed 2 for %x: %x; dip=%p",
11247 			    plun->lun_tgt->tgt_d_id, rval, cip);
11248 
11249 			rval = TRAN_FATAL_ERROR;
11250 		} else {
11251 			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11252 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11253 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11254 				    "fcp_scsi_start: FC_BUSY for pkt %p",
11255 				    pkt);
11256 				rval = TRAN_BUSY;
11257 			} else {
11258 				rval = TRAN_ACCEPT;
11259 				fcp_queue_pkt(pptr, cmd);
11260 			}
11261 		}
11262 		mutex_exit(&ptgt->tgt_mutex);
11263 	}
11264 
11265 	return (rval);
11266 }
11267 
11268 /*
11269  * called by the transport to abort a packet
11270  */
11271 /*ARGSUSED*/
11272 static int
11273 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11274 {
11275 	int tgt_cnt;
11276 	struct fcp_port		*pptr = ADDR2FCP(ap);
11277 	struct fcp_lun	*plun = ADDR2LUN(ap);
11278 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11279 
11280 	if (pkt == NULL) {
11281 		if (ptgt) {
11282 			mutex_enter(&ptgt->tgt_mutex);
11283 			tgt_cnt = ptgt->tgt_change_cnt;
11284 			mutex_exit(&ptgt->tgt_mutex);
11285 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11286 			return (TRUE);
11287 		}
11288 	}
11289 	return (FALSE);
11290 }
11291 
11292 
11293 /*
11294  * Perform reset
11295  */
11296 int
11297 fcp_scsi_reset(struct scsi_address *ap, int level)
11298 {
11299 	int			rval = 0;
11300 	struct fcp_port		*pptr = ADDR2FCP(ap);
11301 	struct fcp_lun	*plun = ADDR2LUN(ap);
11302 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11303 
11304 	if (level == RESET_ALL) {
11305 		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11306 			rval = 1;
11307 		}
11308 	} else if (level == RESET_TARGET || level == RESET_LUN) {
11309 		/*
11310 		 * If we are in the middle of discovery, return
11311 		 * SUCCESS as this target will be rediscovered
11312 		 * anyway
11313 		 */
11314 		mutex_enter(&ptgt->tgt_mutex);
11315 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11316 			mutex_exit(&ptgt->tgt_mutex);
11317 			return (1);
11318 		}
11319 		mutex_exit(&ptgt->tgt_mutex);
11320 
11321 		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11322 			rval = 1;
11323 		}
11324 	}
11325 	return (rval);
11326 }
11327 
11328 
11329 /*
11330  * called by the framework to get a SCSI capability
11331  */
11332 static int
11333 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11334 {
11335 	return (fcp_commoncap(ap, cap, 0, whom, 0));
11336 }
11337 
11338 
11339 /*
11340  * called by the framework to set a SCSI capability
11341  */
11342 static int
11343 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11344 {
11345 	return (fcp_commoncap(ap, cap, value, whom, 1));
11346 }
11347 
11348 /*
11349  *     Function: fcp_pkt_setup
11350  *
11351  *  Description: This function sets up the scsi_pkt structure passed by the
11352  *		 caller. This function assumes fcp_pkt_constructor has been
11353  *		 called previously for the packet passed by the caller.	 If
11354  *		 successful this call will have the following results:
11355  *
11356  *		   - The resources needed that will be constant through out
11357  *		     the whole transaction are allocated.
11358  *		   - The fields that will be constant through out the whole
11359  *		     transaction are initialized.
11360  *		   - The scsi packet will be linked to the LUN structure
11361  *		     addressed by the transaction.
11362  *
11363  *     Argument:
11364  *		 *pkt		Pointer to a scsi_pkt structure.
11365  *		 callback
11366  *		 arg
11367  *
11368  * Return Value: 0	Success
11369  *		 !0	Failure
11370  *
11371  *	Context: Kernel context or interrupt context
11372  */
11373 /* ARGSUSED */
11374 static int
11375 fcp_pkt_setup(struct scsi_pkt *pkt,
11376     int (*callback)(caddr_t arg),
11377     caddr_t arg)
11378 {
11379 	struct fcp_pkt	*cmd;
11380 	struct fcp_port	*pptr;
11381 	struct fcp_lun	*plun;
11382 	struct fcp_tgt	*ptgt;
11383 	int		kf;
11384 	fc_packet_t	*fpkt;
11385 	fc_frame_hdr_t	*hp;
11386 
11387 	pptr = ADDR2FCP(&pkt->pkt_address);
11388 	plun = ADDR2LUN(&pkt->pkt_address);
11389 	ptgt = plun->lun_tgt;
11390 
11391 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11392 	fpkt = cmd->cmd_fp_pkt;
11393 
11394 	/*
11395 	 * this request is for dma allocation only
11396 	 */
11397 	/*
11398 	 * First step of fcp_scsi_init_pkt: pkt allocation
11399 	 * We determine if the caller is willing to wait for the
11400 	 * resources.
11401 	 */
11402 	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11403 
11404 	/*
11405 	 * Selective zeroing of the pkt.
11406 	 */
11407 	cmd->cmd_back = NULL;
11408 	cmd->cmd_next = NULL;
11409 
11410 	/*
11411 	 * Zero out fcp command
11412 	 */
11413 	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11414 
11415 	cmd->cmd_state = FCP_PKT_IDLE;
11416 
11417 	fpkt = cmd->cmd_fp_pkt;
11418 	fpkt->pkt_data_acc = NULL;
11419 
11420 	/*
11421 	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11422 	 * could be destroyed.	We need fail pkt_setup.
11423 	 */
11424 	if (pptr->port_state & FCP_STATE_OFFLINE) {
11425 		return (-1);
11426 	}
11427 
11428 	mutex_enter(&ptgt->tgt_mutex);
11429 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11430 
11431 	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11432 	    != FC_SUCCESS) {
11433 		mutex_exit(&ptgt->tgt_mutex);
11434 		return (-1);
11435 	}
11436 
11437 	mutex_exit(&ptgt->tgt_mutex);
11438 
11439 	/* Fill in the Fabric Channel Header */
11440 	hp = &fpkt->pkt_cmd_fhdr;
11441 	hp->r_ctl = R_CTL_COMMAND;
11442 	hp->rsvd = 0;
11443 	hp->type = FC_TYPE_SCSI_FCP;
11444 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11445 	hp->seq_id = 0;
11446 	hp->df_ctl  = 0;
11447 	hp->seq_cnt = 0;
11448 	hp->ox_id = 0xffff;
11449 	hp->rx_id = 0xffff;
11450 	hp->ro = 0;
11451 
11452 	/*
11453 	 * A doubly linked list (cmd_forw, cmd_back) is built
11454 	 * out of every allocated packet on a per-lun basis
11455 	 *
11456 	 * The packets are maintained in the list so as to satisfy
11457 	 * scsi_abort() requests. At present (which is unlikely to
11458 	 * change in the future) nobody performs a real scsi_abort
11459 	 * in the SCSI target drivers (as they don't keep the packets
11460 	 * after doing scsi_transport - so they don't know how to
11461 	 * abort a packet other than sending a NULL to abort all
11462 	 * outstanding packets)
11463 	 */
11464 	mutex_enter(&plun->lun_mutex);
11465 	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11466 		plun->lun_pkt_head->cmd_back = cmd;
11467 	} else {
11468 		plun->lun_pkt_tail = cmd;
11469 	}
11470 	plun->lun_pkt_head = cmd;
11471 	mutex_exit(&plun->lun_mutex);
11472 	return (0);
11473 }
11474 
11475 /*
11476  *     Function: fcp_pkt_teardown
11477  *
11478  *  Description: This function releases a scsi_pkt structure and all the
11479  *		 resources attached to it.
11480  *
11481  *     Argument: *pkt		Pointer to a scsi_pkt structure.
11482  *
11483  * Return Value: None
11484  *
11485  *	Context: User, Kernel or Interrupt context.
11486  */
11487 static void
11488 fcp_pkt_teardown(struct scsi_pkt *pkt)
11489 {
11490 	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11491 	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11492 	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11493 
11494 	/*
11495 	 * Remove the packet from the per-lun list
11496 	 */
11497 	mutex_enter(&plun->lun_mutex);
11498 	if (cmd->cmd_back) {
11499 		ASSERT(cmd != plun->lun_pkt_head);
11500 		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11501 	} else {
11502 		ASSERT(cmd == plun->lun_pkt_head);
11503 		plun->lun_pkt_head = cmd->cmd_forw;
11504 	}
11505 
11506 	if (cmd->cmd_forw) {
11507 		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11508 	} else {
11509 		ASSERT(cmd == plun->lun_pkt_tail);
11510 		plun->lun_pkt_tail = cmd->cmd_back;
11511 	}
11512 
11513 	mutex_exit(&plun->lun_mutex);
11514 
11515 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11516 }
11517 
11518 /*
11519  * Routine for reset notification setup, to register or cancel.
11520  * This function is called by SCSA
11521  */
11522 /*ARGSUSED*/
11523 static int
11524 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11525     void (*callback)(caddr_t), caddr_t arg)
11526 {
11527 	struct fcp_port *pptr = ADDR2FCP(ap);
11528 
11529 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11530 	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11531 }
11532 
11533 
11534 static int
11535 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11536     ddi_eventcookie_t *event_cookiep)
11537 {
11538 	struct fcp_port *pptr = fcp_dip2port(dip);
11539 
11540 	if (pptr == NULL) {
11541 		return (DDI_FAILURE);
11542 	}
11543 
11544 	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11545 	    event_cookiep, NDI_EVENT_NOPASS));
11546 }
11547 
11548 
11549 static int
11550 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11551     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11552     ddi_callback_id_t *cb_id)
11553 {
11554 	struct fcp_port *pptr = fcp_dip2port(dip);
11555 
11556 	if (pptr == NULL) {
11557 		return (DDI_FAILURE);
11558 	}
11559 
11560 	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11561 	    eventid, callback, arg, NDI_SLEEP, cb_id));
11562 }
11563 
11564 
11565 static int
11566 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11567 {
11568 
11569 	struct fcp_port *pptr = fcp_dip2port(dip);
11570 
11571 	if (pptr == NULL) {
11572 		return (DDI_FAILURE);
11573 	}
11574 	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11575 }
11576 
11577 
11578 /*
11579  * called by the transport to post an event
11580  */
11581 static int
11582 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11583     ddi_eventcookie_t eventid, void *impldata)
11584 {
11585 	struct fcp_port *pptr = fcp_dip2port(dip);
11586 
11587 	if (pptr == NULL) {
11588 		return (DDI_FAILURE);
11589 	}
11590 
11591 	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11592 	    eventid, impldata));
11593 }
11594 
11595 
11596 /*
11597  * A target in in many cases in Fibre Channel has a one to one relation
11598  * with a port identifier (which is also known as D_ID and also as AL_PA
11599  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11600  * will most likely result in resetting all LUNs (which means a reset will
11601  * occur on all the SCSI devices connected at the other end of the bridge)
11602  * That is the latest favorite topic for discussion, for, one can debate as
11603  * hot as one likes and come up with arguably a best solution to one's
11604  * satisfaction
11605  *
11606  * To stay on track and not digress much, here are the problems stated
11607  * briefly:
11608  *
11609  *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11610  *	target drivers use RESET_TARGET even if their instance is on a
11611  *	LUN. Doesn't that sound a bit broken ?
11612  *
11613  *	FCP SCSI (the current spec) only defines RESET TARGET in the
11614  *	control fields of an FCP_CMND structure. It should have been
11615  *	fixed right there, giving flexibility to the initiators to
11616  *	minimize havoc that could be caused by resetting a target.
11617  */
11618 static int
11619 fcp_reset_target(struct scsi_address *ap, int level)
11620 {
11621 	int			rval = FC_FAILURE;
11622 	char			lun_id[25];
11623 	struct fcp_port		*pptr = ADDR2FCP(ap);
11624 	struct fcp_lun	*plun = ADDR2LUN(ap);
11625 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11626 	struct scsi_pkt		*pkt;
11627 	struct fcp_pkt	*cmd;
11628 	struct fcp_rsp		*rsp;
11629 	uint32_t		tgt_cnt;
11630 	struct fcp_rsp_info	*rsp_info;
11631 	struct fcp_reset_elem	*p;
11632 	int			bval;
11633 
11634 	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11635 	    KM_NOSLEEP)) == NULL) {
11636 		return (rval);
11637 	}
11638 
11639 	mutex_enter(&ptgt->tgt_mutex);
11640 	if (level == RESET_TARGET) {
11641 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11642 			mutex_exit(&ptgt->tgt_mutex);
11643 			kmem_free(p, sizeof (struct fcp_reset_elem));
11644 			return (rval);
11645 		}
11646 		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11647 		(void) strcpy(lun_id, " ");
11648 	} else {
11649 		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11650 			mutex_exit(&ptgt->tgt_mutex);
11651 			kmem_free(p, sizeof (struct fcp_reset_elem));
11652 			return (rval);
11653 		}
11654 		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11655 
11656 		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11657 	}
11658 	tgt_cnt = ptgt->tgt_change_cnt;
11659 
11660 	mutex_exit(&ptgt->tgt_mutex);
11661 
11662 	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11663 	    0, 0, NULL, 0)) == NULL) {
11664 		kmem_free(p, sizeof (struct fcp_reset_elem));
11665 		mutex_enter(&ptgt->tgt_mutex);
11666 		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11667 		mutex_exit(&ptgt->tgt_mutex);
11668 		return (rval);
11669 	}
11670 	pkt->pkt_time = FCP_POLL_TIMEOUT;
11671 
11672 	/* fill in cmd part of packet */
11673 	cmd = PKT2CMD(pkt);
11674 	if (level == RESET_TARGET) {
11675 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11676 	} else {
11677 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11678 	}
11679 	cmd->cmd_fp_pkt->pkt_comp = NULL;
11680 	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11681 
11682 	/* prepare a packet for transport */
11683 	fcp_prepare_pkt(pptr, cmd, plun);
11684 
11685 	if (cmd->cmd_pkt->pkt_time) {
11686 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11687 	} else {
11688 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11689 	}
11690 
11691 	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11692 	bval = fcp_dopoll(pptr, cmd);
11693 	fc_ulp_idle_port(pptr->port_fp_handle);
11694 
11695 	/* submit the packet */
11696 	if (bval == TRAN_ACCEPT) {
11697 		int error = 3;
11698 
11699 		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11700 		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11701 		    sizeof (struct fcp_rsp));
11702 
11703 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11704 			if (fcp_validate_fcp_response(rsp, pptr) ==
11705 			    FC_SUCCESS) {
11706 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11707 					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11708 					    sizeof (struct fcp_rsp), rsp_info,
11709 					    cmd->cmd_fp_pkt->pkt_resp_acc,
11710 					    sizeof (struct fcp_rsp_info));
11711 				}
11712 				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11713 					rval = FC_SUCCESS;
11714 					error = 0;
11715 				} else {
11716 					error = 1;
11717 				}
11718 			} else {
11719 				error = 2;
11720 			}
11721 		}
11722 
11723 		switch (error) {
11724 		case 0:
11725 			fcp_log(CE_WARN, pptr->port_dip,
11726 			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11727 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11728 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11729 			break;
11730 
11731 		case 1:
11732 			fcp_log(CE_WARN, pptr->port_dip,
11733 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11734 			    " response code=%x",
11735 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11736 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11737 			    rsp_info->rsp_code);
11738 			break;
11739 
11740 		case 2:
11741 			fcp_log(CE_WARN, pptr->port_dip,
11742 			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11743 			    " Bad FCP response values: rsvd1=%x,"
11744 			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11745 			    " rsplen=%x, senselen=%x",
11746 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11747 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11748 			    rsp->reserved_0, rsp->reserved_1,
11749 			    rsp->fcp_u.fcp_status.reserved_0,
11750 			    rsp->fcp_u.fcp_status.reserved_1,
11751 			    rsp->fcp_response_len, rsp->fcp_sense_len);
11752 			break;
11753 
11754 		default:
11755 			fcp_log(CE_WARN, pptr->port_dip,
11756 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11757 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11758 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11759 			break;
11760 		}
11761 	}
11762 	scsi_destroy_pkt(pkt);
11763 
11764 	if (rval == FC_FAILURE) {
11765 		mutex_enter(&ptgt->tgt_mutex);
11766 		if (level == RESET_TARGET) {
11767 			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11768 		} else {
11769 			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11770 		}
11771 		mutex_exit(&ptgt->tgt_mutex);
11772 		kmem_free(p, sizeof (struct fcp_reset_elem));
11773 		return (rval);
11774 	}
11775 
11776 	mutex_enter(&pptr->port_mutex);
11777 	if (level == RESET_TARGET) {
11778 		p->tgt = ptgt;
11779 		p->lun = NULL;
11780 	} else {
11781 		p->tgt = NULL;
11782 		p->lun = plun;
11783 	}
11784 	p->tgt = ptgt;
11785 	p->tgt_cnt = tgt_cnt;
11786 	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11787 	p->next = pptr->port_reset_list;
11788 	pptr->port_reset_list = p;
11789 
11790 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11791 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11792 	    "Notify ssd of the reset to reinstate the reservations");
11793 
11794 	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11795 	    &pptr->port_reset_notify_listf);
11796 
11797 	mutex_exit(&pptr->port_mutex);
11798 
11799 	return (rval);
11800 }
11801 
11802 
11803 /*
11804  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11805  * SCSI capabilities
11806  */
11807 /* ARGSUSED */
11808 static int
11809 fcp_commoncap(struct scsi_address *ap, char *cap,
11810     int val, int tgtonly, int doset)
11811 {
11812 	struct fcp_port		*pptr = ADDR2FCP(ap);
11813 	struct fcp_lun	*plun = ADDR2LUN(ap);
11814 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11815 	int			cidx;
11816 	int			rval = FALSE;
11817 
11818 	if (cap == (char *)0) {
11819 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11820 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11821 		    "fcp_commoncap: invalid arg");
11822 		return (rval);
11823 	}
11824 
11825 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11826 		return (UNDEFINED);
11827 	}
11828 
11829 	/*
11830 	 * Process setcap request.
11831 	 */
11832 	if (doset) {
11833 		/*
11834 		 * At present, we can only set binary (0/1) values
11835 		 */
11836 		switch (cidx) {
11837 		case SCSI_CAP_ARQ:
11838 			if (val == 0) {
11839 				rval = FALSE;
11840 			} else {
11841 				rval = TRUE;
11842 			}
11843 			break;
11844 
11845 		case SCSI_CAP_LUN_RESET:
11846 			if (val) {
11847 				plun->lun_cap |= FCP_LUN_CAP_RESET;
11848 			} else {
11849 				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11850 			}
11851 			rval = TRUE;
11852 			break;
11853 
11854 		case SCSI_CAP_SECTOR_SIZE:
11855 			rval = TRUE;
11856 			break;
11857 		default:
11858 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11859 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11860 			    "fcp_setcap: unsupported %d", cidx);
11861 			rval = UNDEFINED;
11862 			break;
11863 		}
11864 
11865 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11866 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11867 		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11868 		    "0x%x/0x%x/0x%x/%d",
11869 		    cap, val, tgtonly, doset, rval);
11870 
11871 	} else {
11872 		/*
11873 		 * Process getcap request.
11874 		 */
11875 		switch (cidx) {
11876 		case SCSI_CAP_DMA_MAX:
11877 			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11878 
11879 			/*
11880 			 * Need to make an adjustment qlc is uint_t 64
11881 			 * st is int, so we will make the adjustment here
11882 			 * being as nobody wants to touch this.
11883 			 * It still leaves the max single block length
11884 			 * of 2 gig. This should last .
11885 			 */
11886 
11887 			if (rval == -1) {
11888 				rval = MAX_INT_DMA;
11889 			}
11890 
11891 			break;
11892 
11893 		case SCSI_CAP_INITIATOR_ID:
11894 			rval = pptr->port_id;
11895 			break;
11896 
11897 		case SCSI_CAP_ARQ:
11898 		case SCSI_CAP_RESET_NOTIFICATION:
11899 		case SCSI_CAP_TAGGED_QING:
11900 			rval = TRUE;
11901 			break;
11902 
11903 		case SCSI_CAP_SCSI_VERSION:
11904 			rval = 3;
11905 			break;
11906 
11907 		case SCSI_CAP_INTERCONNECT_TYPE:
11908 			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11909 			    (ptgt->tgt_hard_addr == 0)) {
11910 				rval = INTERCONNECT_FABRIC;
11911 			} else {
11912 				rval = INTERCONNECT_FIBRE;
11913 			}
11914 			break;
11915 
11916 		case SCSI_CAP_LUN_RESET:
11917 			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11918 			    TRUE : FALSE;
11919 			break;
11920 
11921 		default:
11922 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11923 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11924 			    "fcp_getcap: unsupported %d", cidx);
11925 			rval = UNDEFINED;
11926 			break;
11927 		}
11928 
11929 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11930 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11931 		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11932 		    "0x%x/0x%x/0x%x/%d",
11933 		    cap, val, tgtonly, doset, rval);
11934 	}
11935 
11936 	return (rval);
11937 }
11938 
11939 /*
11940  * called by the transport to get the port-wwn and lun
11941  * properties of this device, and to create a "name" based on them
11942  *
11943  * these properties don't exist on sun4m
11944  *
11945  * return 1 for success else return 0
11946  */
11947 /* ARGSUSED */
11948 static int
11949 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11950 {
11951 	int			i;
11952 	int			*lun;
11953 	int			numChars;
11954 	uint_t			nlun;
11955 	uint_t			count;
11956 	uint_t			nbytes;
11957 	uchar_t			*bytes;
11958 	uint16_t		lun_num;
11959 	uint32_t		tgt_id;
11960 	char			**conf_wwn;
11961 	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11962 	uchar_t			barray[FC_WWN_SIZE];
11963 	dev_info_t		*tgt_dip;
11964 	struct fcp_tgt	*ptgt;
11965 	struct fcp_port	*pptr;
11966 	struct fcp_lun	*plun;
11967 
11968 	ASSERT(sd != NULL);
11969 	ASSERT(name != NULL);
11970 
11971 	tgt_dip = sd->sd_dev;
11972 	pptr = ddi_get_soft_state(fcp_softstate,
11973 	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11974 	if (pptr == NULL) {
11975 		return (0);
11976 	}
11977 
11978 	ASSERT(tgt_dip != NULL);
11979 
11980 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11981 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11982 	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11983 		name[0] = '\0';
11984 		return (0);
11985 	}
11986 
11987 	if (nlun == 0) {
11988 		ddi_prop_free(lun);
11989 		return (0);
11990 	}
11991 
11992 	lun_num = lun[0];
11993 	ddi_prop_free(lun);
11994 
11995 	/*
11996 	 * Lookup for .conf WWN property
11997 	 */
11998 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
11999 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12000 	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12001 		ASSERT(count >= 1);
12002 
12003 		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12004 		ddi_prop_free(conf_wwn);
12005 		mutex_enter(&pptr->port_mutex);
12006 		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12007 			mutex_exit(&pptr->port_mutex);
12008 			return (0);
12009 		}
12010 		ptgt = plun->lun_tgt;
12011 		mutex_exit(&pptr->port_mutex);
12012 
12013 		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12014 		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12015 
12016 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12017 		    ptgt->tgt_hard_addr != 0) {
12018 			tgt_id = (uint32_t)fcp_alpa_to_switch[
12019 			    ptgt->tgt_hard_addr];
12020 		} else {
12021 			tgt_id = ptgt->tgt_d_id;
12022 		}
12023 
12024 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12025 		    TARGET_PROP, tgt_id);
12026 	}
12027 
12028 	/* get the our port-wwn property */
12029 	bytes = NULL;
12030 	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12031 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12032 	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12033 		if (bytes != NULL) {
12034 			ddi_prop_free(bytes);
12035 		}
12036 		return (0);
12037 	}
12038 
12039 	for (i = 0; i < FC_WWN_SIZE; i++) {
12040 		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12041 	}
12042 
12043 	/* Stick in the address of the form "wWWN,LUN" */
12044 	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12045 
12046 	ASSERT(numChars < len);
12047 	if (numChars >= len) {
12048 		fcp_log(CE_WARN, pptr->port_dip,
12049 		    "!fcp_scsi_get_name: "
12050 		    "name parameter length too small, it needs to be %d",
12051 		    numChars+1);
12052 	}
12053 
12054 	ddi_prop_free(bytes);
12055 
12056 	return (1);
12057 }
12058 
12059 
12060 /*
12061  * called by the transport to get the SCSI target id value, returning
12062  * it in "name"
12063  *
12064  * this isn't needed/used on sun4m
12065  *
12066  * return 1 for success else return 0
12067  */
12068 /* ARGSUSED */
12069 static int
12070 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12071 {
12072 	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
12073 	struct fcp_tgt	*ptgt;
12074 	int    numChars;
12075 
12076 	if (plun == NULL) {
12077 		return (0);
12078 	}
12079 
12080 	if ((ptgt = plun->lun_tgt) == NULL) {
12081 		return (0);
12082 	}
12083 
12084 	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12085 
12086 	ASSERT(numChars < len);
12087 	if (numChars >= len) {
12088 		fcp_log(CE_WARN, NULL,
12089 		    "!fcp_scsi_get_bus_addr: "
12090 		    "name parameter length too small, it needs to be %d",
12091 		    numChars+1);
12092 	}
12093 
12094 	return (1);
12095 }
12096 
12097 
12098 /*
12099  * called internally to reset the link where the specified port lives
12100  */
12101 static int
12102 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12103 {
12104 	la_wwn_t		wwn;
12105 	struct fcp_lun	*plun;
12106 	struct fcp_tgt	*ptgt;
12107 
12108 	/* disable restart of lip if we're suspended */
12109 	mutex_enter(&pptr->port_mutex);
12110 
12111 	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12112 	    FCP_STATE_POWER_DOWN)) {
12113 		mutex_exit(&pptr->port_mutex);
12114 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12115 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12116 		    "fcp_linkreset, fcp%d: link reset "
12117 		    "disabled due to DDI_SUSPEND",
12118 		    ddi_get_instance(pptr->port_dip));
12119 		return (FC_FAILURE);
12120 	}
12121 
12122 	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12123 		mutex_exit(&pptr->port_mutex);
12124 		return (FC_SUCCESS);
12125 	}
12126 
12127 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12128 	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12129 
12130 	/*
12131 	 * If ap == NULL assume local link reset.
12132 	 */
12133 	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12134 		plun = ADDR2LUN(ap);
12135 		ptgt = plun->lun_tgt;
12136 		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12137 	} else {
12138 		bzero((caddr_t)&wwn, sizeof (wwn));
12139 	}
12140 	mutex_exit(&pptr->port_mutex);
12141 
12142 	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12143 }
12144 
12145 
12146 /*
12147  * called from fcp_port_attach() to resume a port
12148  * return DDI_* success/failure status
12149  * acquires and releases the global mutex
12150  * acquires and releases the port mutex
12151  */
12152 /*ARGSUSED*/
12153 
12154 static int
12155 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12156     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12157 {
12158 	int			res = DDI_FAILURE; /* default result */
12159 	struct fcp_port	*pptr;		/* port state ptr */
12160 	uint32_t		alloc_cnt;
12161 	uint32_t		max_cnt;
12162 	fc_portmap_t		*tmp_list = NULL;
12163 
12164 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12165 	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12166 	    instance);
12167 
12168 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12169 		cmn_err(CE_WARN, "fcp: bad soft state");
12170 		return (res);
12171 	}
12172 
12173 	mutex_enter(&pptr->port_mutex);
12174 	switch (cmd) {
12175 	case FC_CMD_RESUME:
12176 		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12177 		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12178 		break;
12179 
12180 	case FC_CMD_POWER_UP:
12181 		/*
12182 		 * If the port is DDI_SUSPENded, defer rediscovery
12183 		 * until DDI_RESUME occurs
12184 		 */
12185 		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12186 			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12187 			mutex_exit(&pptr->port_mutex);
12188 			return (DDI_SUCCESS);
12189 		}
12190 		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12191 	}
12192 	pptr->port_id = s_id;
12193 	pptr->port_state = FCP_STATE_INIT;
12194 	mutex_exit(&pptr->port_mutex);
12195 
12196 	/*
12197 	 * Make a copy of ulp_port_info as fctl allocates
12198 	 * a temp struct.
12199 	 */
12200 	(void) fcp_cp_pinfo(pptr, pinfo);
12201 
12202 	mutex_enter(&fcp_global_mutex);
12203 	if (fcp_watchdog_init++ == 0) {
12204 		fcp_watchdog_tick = fcp_watchdog_timeout *
12205 		    drv_usectohz(1000000);
12206 		fcp_watchdog_id = timeout(fcp_watch,
12207 		    NULL, fcp_watchdog_tick);
12208 	}
12209 	mutex_exit(&fcp_global_mutex);
12210 
12211 	/*
12212 	 * Handle various topologies and link states.
12213 	 */
12214 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12215 	case FC_STATE_OFFLINE:
12216 		/*
12217 		 * Wait for ONLINE, at which time a state
12218 		 * change will cause a statec_callback
12219 		 */
12220 		res = DDI_SUCCESS;
12221 		break;
12222 
12223 	case FC_STATE_ONLINE:
12224 
12225 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12226 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12227 			res = DDI_SUCCESS;
12228 			break;
12229 		}
12230 
12231 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12232 		    !fcp_enable_auto_configuration) {
12233 			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12234 			if (tmp_list == NULL) {
12235 				if (!alloc_cnt) {
12236 					res = DDI_SUCCESS;
12237 				}
12238 				break;
12239 			}
12240 			max_cnt = alloc_cnt;
12241 		} else {
12242 			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12243 
12244 			alloc_cnt = FCP_MAX_DEVICES;
12245 
12246 			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12247 			    (sizeof (fc_portmap_t)) * alloc_cnt,
12248 			    KM_NOSLEEP)) == NULL) {
12249 				fcp_log(CE_WARN, pptr->port_dip,
12250 				    "!fcp%d: failed to allocate portmap",
12251 				    instance);
12252 				break;
12253 			}
12254 
12255 			max_cnt = alloc_cnt;
12256 			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12257 			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12258 			    FC_SUCCESS) {
12259 				caddr_t msg;
12260 
12261 				(void) fc_ulp_error(res, &msg);
12262 
12263 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12264 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12265 				    "resume failed getportmap: reason=0x%x",
12266 				    res);
12267 
12268 				fcp_log(CE_WARN, pptr->port_dip,
12269 				    "!failed to get port map : %s", msg);
12270 				break;
12271 			}
12272 			if (max_cnt > alloc_cnt) {
12273 				alloc_cnt = max_cnt;
12274 			}
12275 		}
12276 
12277 		/*
12278 		 * do the SCSI device discovery and create
12279 		 * the devinfos
12280 		 */
12281 		fcp_statec_callback(ulph, pptr->port_fp_handle,
12282 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12283 		    max_cnt, pptr->port_id);
12284 
12285 		res = DDI_SUCCESS;
12286 		break;
12287 
12288 	default:
12289 		fcp_log(CE_WARN, pptr->port_dip,
12290 		    "!fcp%d: invalid port state at attach=0x%x",
12291 		    instance, pptr->port_phys_state);
12292 
12293 		mutex_enter(&pptr->port_mutex);
12294 		pptr->port_phys_state = FCP_STATE_OFFLINE;
12295 		mutex_exit(&pptr->port_mutex);
12296 		res = DDI_SUCCESS;
12297 
12298 		break;
12299 	}
12300 
12301 	if (tmp_list != NULL) {
12302 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12303 	}
12304 
12305 	return (res);
12306 }
12307 
12308 
12309 static void
12310 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12311 {
12312 	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12313 	pptr->port_dip = pinfo->port_dip;
12314 	pptr->port_fp_handle = pinfo->port_handle;
12315 	if (pinfo->port_acc_attr != NULL) {
12316 		/*
12317 		 * FCA supports DMA
12318 		 */
12319 		pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12320 		pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12321 		pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12322 		pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12323 	}
12324 	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12325 	pptr->port_max_exch = pinfo->port_fca_max_exch;
12326 	pptr->port_phys_state = pinfo->port_state;
12327 	pptr->port_topology = pinfo->port_flags;
12328 	pptr->port_reset_action = pinfo->port_reset_action;
12329 	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12330 	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12331 	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12332 	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12333 
12334 	/* Clear FMA caps to avoid fm-capability ereport */
12335 	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12336 		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12337 	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12338 		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12339 	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12340 		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12341 }
12342 
12343 /*
12344  * If the elements wait field is set to 1 then
12345  * another thread is waiting for the operation to complete. Once
12346  * it is complete, the waiting thread is signaled and the element is
12347  * freed by the waiting thread. If the elements wait field is set to 0
12348  * the element is freed.
12349  */
12350 static void
12351 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12352 {
12353 	ASSERT(elem != NULL);
12354 	mutex_enter(&elem->mutex);
12355 	elem->result = result;
12356 	if (elem->wait) {
12357 		elem->wait = 0;
12358 		cv_signal(&elem->cv);
12359 		mutex_exit(&elem->mutex);
12360 	} else {
12361 		mutex_exit(&elem->mutex);
12362 		cv_destroy(&elem->cv);
12363 		mutex_destroy(&elem->mutex);
12364 		kmem_free(elem, sizeof (struct fcp_hp_elem));
12365 	}
12366 }
12367 
12368 /*
12369  * This function is invoked from the taskq thread to allocate
12370  * devinfo nodes and to online/offline them.
12371  */
12372 static void
12373 fcp_hp_task(void *arg)
12374 {
12375 	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12376 	struct fcp_lun	*plun = elem->lun;
12377 	struct fcp_port		*pptr = elem->port;
12378 	int			result;
12379 
12380 	ASSERT(elem->what == FCP_ONLINE ||
12381 	    elem->what == FCP_OFFLINE ||
12382 	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12383 	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12384 
12385 	mutex_enter(&pptr->port_mutex);
12386 	mutex_enter(&plun->lun_mutex);
12387 	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12388 	    plun->lun_event_count != elem->event_cnt) ||
12389 	    pptr->port_state & (FCP_STATE_SUSPENDED |
12390 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12391 		mutex_exit(&plun->lun_mutex);
12392 		mutex_exit(&pptr->port_mutex);
12393 		fcp_process_elem(elem, NDI_FAILURE);
12394 		return;
12395 	}
12396 	mutex_exit(&plun->lun_mutex);
12397 	mutex_exit(&pptr->port_mutex);
12398 
12399 	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12400 	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12401 	fcp_process_elem(elem, result);
12402 }
12403 
12404 
12405 static child_info_t *
12406 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12407     int tcount)
12408 {
12409 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12410 
12411 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12412 		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12413 
12414 		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12415 		/*
12416 		 * Child has not been created yet. Create the child device
12417 		 * based on the per-Lun flags.
12418 		 */
12419 		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12420 			plun->lun_cip =
12421 			    CIP(fcp_create_dip(plun, lcount, tcount));
12422 			plun->lun_mpxio = 0;
12423 		} else {
12424 			plun->lun_cip =
12425 			    CIP(fcp_create_pip(plun, lcount, tcount));
12426 			plun->lun_mpxio = 1;
12427 		}
12428 	} else {
12429 		plun->lun_cip = cip;
12430 	}
12431 
12432 	return (plun->lun_cip);
12433 }
12434 
12435 
12436 static int
12437 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12438 {
12439 	int		rval = FC_FAILURE;
12440 	dev_info_t	*pdip;
12441 	struct dev_info	*dip;
12442 
12443 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12444 
12445 	pdip = plun->lun_tgt->tgt_port->port_dip;
12446 
12447 	if (plun->lun_cip == NULL) {
12448 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12449 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12450 		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12451 		    "plun: %p lun state: %x num: %d target state: %x",
12452 		    plun, plun->lun_state, plun->lun_num,
12453 		    plun->lun_tgt->tgt_port->port_state);
12454 		return (rval);
12455 	}
12456 	ndi_devi_enter(pdip);
12457 	dip = DEVI(pdip)->devi_child;
12458 	while (dip) {
12459 		if (dip == DEVI(cdip)) {
12460 			rval = FC_SUCCESS;
12461 			break;
12462 		}
12463 		dip = dip->devi_sibling;
12464 	}
12465 	ndi_devi_exit(pdip);
12466 	return (rval);
12467 }
12468 
12469 static int
12470 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12471 {
12472 	int		rval = FC_FAILURE;
12473 
12474 	ASSERT(plun != NULL);
12475 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12476 
12477 	if (plun->lun_mpxio == 0) {
12478 		rval = fcp_is_dip_present(plun, DIP(cip));
12479 	} else {
12480 		rval = fcp_is_pip_present(plun, PIP(cip));
12481 	}
12482 
12483 	return (rval);
12484 }
12485 
12486 /*
12487  *     Function: fcp_create_dip
12488  *
12489  *  Description: Creates a dev_info_t structure for the LUN specified by the
12490  *		 caller.
12491  *
12492  *     Argument: plun		Lun structure
12493  *		 link_cnt	Link state count.
12494  *		 tgt_cnt	Target state change count.
12495  *
12496  * Return Value: NULL if it failed
12497  *		 dev_info_t structure address if it succeeded
12498  *
12499  *	Context: Kernel context
12500  */
12501 static dev_info_t *
12502 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12503 {
12504 	int			failure = 0;
12505 	uint32_t		tgt_id;
12506 	uint64_t		sam_lun;
12507 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12508 	struct fcp_port	*pptr = ptgt->tgt_port;
12509 	dev_info_t		*pdip = pptr->port_dip;
12510 	dev_info_t		*cdip = NULL;
12511 	dev_info_t		*old_dip = DIP(plun->lun_cip);
12512 	char			*nname = NULL;
12513 	char			**compatible = NULL;
12514 	int			ncompatible;
12515 	char			*scsi_binding_set;
12516 	char			t_pwwn[17];
12517 
12518 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12519 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12520 
12521 	/* get the 'scsi-binding-set' property */
12522 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12523 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12524 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12525 		scsi_binding_set = NULL;
12526 	}
12527 
12528 	/* determine the node name and compatible */
12529 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12530 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12531 	if (scsi_binding_set) {
12532 		ddi_prop_free(scsi_binding_set);
12533 	}
12534 
12535 	if (nname == NULL) {
12536 #ifdef	DEBUG
12537 		cmn_err(CE_WARN, "%s%d: no driver for "
12538 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12539 		    "	 compatible: %s",
12540 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12541 		    ptgt->tgt_port_wwn.raw_wwn[0],
12542 		    ptgt->tgt_port_wwn.raw_wwn[1],
12543 		    ptgt->tgt_port_wwn.raw_wwn[2],
12544 		    ptgt->tgt_port_wwn.raw_wwn[3],
12545 		    ptgt->tgt_port_wwn.raw_wwn[4],
12546 		    ptgt->tgt_port_wwn.raw_wwn[5],
12547 		    ptgt->tgt_port_wwn.raw_wwn[6],
12548 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12549 		    *compatible);
12550 #endif	/* DEBUG */
12551 		failure++;
12552 		goto end_of_fcp_create_dip;
12553 	}
12554 
12555 	cdip = fcp_find_existing_dip(plun, pdip, nname);
12556 
12557 	/*
12558 	 * if the old_dip does not match the cdip, that means there is
12559 	 * some property change. since we'll be using the cdip, we need
12560 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12561 	 * then the dtype for the device has been updated. Offline the
12562 	 * the old device and create a new device with the new device type
12563 	 * Refer to bug: 4764752
12564 	 */
12565 	if (old_dip && (cdip != old_dip ||
12566 	    plun->lun_state & FCP_LUN_CHANGED)) {
12567 		plun->lun_state &= ~(FCP_LUN_INIT);
12568 		mutex_exit(&plun->lun_mutex);
12569 		mutex_exit(&pptr->port_mutex);
12570 
12571 		mutex_enter(&ptgt->tgt_mutex);
12572 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12573 		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12574 		mutex_exit(&ptgt->tgt_mutex);
12575 
12576 #ifdef DEBUG
12577 		if (cdip != NULL) {
12578 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12579 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12580 			    "Old dip=%p; New dip=%p don't match", old_dip,
12581 			    cdip);
12582 		} else {
12583 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12584 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12585 			    "Old dip=%p; New dip=NULL don't match", old_dip);
12586 		}
12587 #endif
12588 
12589 		mutex_enter(&pptr->port_mutex);
12590 		mutex_enter(&plun->lun_mutex);
12591 	}
12592 
12593 	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12594 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12595 		if (ndi_devi_alloc(pptr->port_dip, nname,
12596 		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12597 			failure++;
12598 			goto end_of_fcp_create_dip;
12599 		}
12600 	}
12601 
12602 	/*
12603 	 * Previously all the properties for the devinfo were destroyed here
12604 	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12605 	 * the devid property (and other properties established by the target
12606 	 * driver or framework) which the code does not always recreate, this
12607 	 * call was removed.
12608 	 * This opens a theoretical possibility that we may return with a
12609 	 * stale devid on the node if the scsi entity behind the fibre channel
12610 	 * lun has changed.
12611 	 */
12612 
12613 	/* decorate the node with compatible */
12614 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12615 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12616 		failure++;
12617 		goto end_of_fcp_create_dip;
12618 	}
12619 
12620 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12621 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12622 		failure++;
12623 		goto end_of_fcp_create_dip;
12624 	}
12625 
12626 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12627 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12628 		failure++;
12629 		goto end_of_fcp_create_dip;
12630 	}
12631 
12632 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12633 	t_pwwn[16] = '\0';
12634 	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12635 	    != DDI_PROP_SUCCESS) {
12636 		failure++;
12637 		goto end_of_fcp_create_dip;
12638 	}
12639 
12640 	/*
12641 	 * If there is no hard address - We might have to deal with
12642 	 * that by using WWN - Having said that it is important to
12643 	 * recognize this problem early so ssd can be informed of
12644 	 * the right interconnect type.
12645 	 */
12646 	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12647 		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12648 	} else {
12649 		tgt_id = ptgt->tgt_d_id;
12650 	}
12651 
12652 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12653 	    tgt_id) != DDI_PROP_SUCCESS) {
12654 		failure++;
12655 		goto end_of_fcp_create_dip;
12656 	}
12657 
12658 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12659 	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12660 		failure++;
12661 		goto end_of_fcp_create_dip;
12662 	}
12663 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12664 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12665 	    sam_lun) != DDI_PROP_SUCCESS) {
12666 		failure++;
12667 		goto end_of_fcp_create_dip;
12668 	}
12669 
12670 end_of_fcp_create_dip:
12671 	scsi_hba_nodename_compatible_free(nname, compatible);
12672 
12673 	if (cdip != NULL && failure) {
12674 		(void) ndi_prop_remove_all(cdip);
12675 		(void) ndi_devi_free(cdip);
12676 		cdip = NULL;
12677 	}
12678 
12679 	return (cdip);
12680 }
12681 
12682 /*
12683  *     Function: fcp_create_pip
12684  *
12685  *  Description: Creates a Path Id for the LUN specified by the caller.
12686  *
12687  *     Argument: plun		Lun structure
12688  *		 link_cnt	Link state count.
12689  *		 tgt_cnt	Target state count.
12690  *
12691  * Return Value: NULL if it failed
12692  *		 mdi_pathinfo_t structure address if it succeeded
12693  *
12694  *	Context: Kernel context
12695  */
12696 static mdi_pathinfo_t *
12697 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12698 {
12699 	int			i;
12700 	char			buf[MAXNAMELEN];
12701 	char			uaddr[MAXNAMELEN];
12702 	int			failure = 0;
12703 	uint32_t		tgt_id;
12704 	uint64_t		sam_lun;
12705 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12706 	struct fcp_port	*pptr = ptgt->tgt_port;
12707 	dev_info_t		*pdip = pptr->port_dip;
12708 	mdi_pathinfo_t		*pip = NULL;
12709 	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12710 	char			*nname = NULL;
12711 	char			**compatible = NULL;
12712 	int			ncompatible;
12713 	char			*scsi_binding_set;
12714 	char			t_pwwn[17];
12715 
12716 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12717 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12718 
12719 	scsi_binding_set = "vhci";
12720 
12721 	/* determine the node name and compatible */
12722 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12723 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12724 
12725 	if (nname == NULL) {
12726 #ifdef	DEBUG
12727 		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12728 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12729 		    "	 compatible: %s",
12730 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12731 		    ptgt->tgt_port_wwn.raw_wwn[0],
12732 		    ptgt->tgt_port_wwn.raw_wwn[1],
12733 		    ptgt->tgt_port_wwn.raw_wwn[2],
12734 		    ptgt->tgt_port_wwn.raw_wwn[3],
12735 		    ptgt->tgt_port_wwn.raw_wwn[4],
12736 		    ptgt->tgt_port_wwn.raw_wwn[5],
12737 		    ptgt->tgt_port_wwn.raw_wwn[6],
12738 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12739 		    *compatible);
12740 #endif	/* DEBUG */
12741 		failure++;
12742 		goto end_of_fcp_create_pip;
12743 	}
12744 
12745 	pip = fcp_find_existing_pip(plun, pdip);
12746 
12747 	/*
12748 	 * if the old_dip does not match the cdip, that means there is
12749 	 * some property change. since we'll be using the cdip, we need
12750 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12751 	 * then the dtype for the device has been updated. Offline the
12752 	 * the old device and create a new device with the new device type
12753 	 * Refer to bug: 4764752
12754 	 */
12755 	if (old_pip && (pip != old_pip ||
12756 	    plun->lun_state & FCP_LUN_CHANGED)) {
12757 		plun->lun_state &= ~(FCP_LUN_INIT);
12758 		mutex_exit(&plun->lun_mutex);
12759 		mutex_exit(&pptr->port_mutex);
12760 
12761 		mutex_enter(&ptgt->tgt_mutex);
12762 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12763 		    FCP_OFFLINE, lcount, tcount,
12764 		    NDI_DEVI_REMOVE, 0);
12765 		mutex_exit(&ptgt->tgt_mutex);
12766 
12767 		if (pip != NULL) {
12768 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12769 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12770 			    "Old pip=%p; New pip=%p don't match",
12771 			    old_pip, pip);
12772 		} else {
12773 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12774 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12775 			    "Old pip=%p; New pip=NULL don't match",
12776 			    old_pip);
12777 		}
12778 
12779 		mutex_enter(&pptr->port_mutex);
12780 		mutex_enter(&plun->lun_mutex);
12781 	}
12782 
12783 	/*
12784 	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12785 	 * lun_guid_size which is dependent on the target, I don't
12786 	 * believe the same trancation happens here UNLESS the standards
12787 	 * change the FC_WWN_SIZE value to something larger than
12788 	 * MAXNAMELEN(currently 255 bytes).
12789 	 */
12790 
12791 	for (i = 0; i < FC_WWN_SIZE; i++) {
12792 		(void) sprintf(&buf[i << 1], "%02x",
12793 		    ptgt->tgt_port_wwn.raw_wwn[i]);
12794 	}
12795 
12796 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12797 	    buf, plun->lun_num);
12798 
12799 	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12800 		/*
12801 		 * Release the locks before calling into
12802 		 * mdi_pi_alloc_compatible() since this can result in a
12803 		 * callback into fcp which can result in a deadlock
12804 		 * (see bug # 4870272).
12805 		 *
12806 		 * Basically, what we are trying to avoid is the scenario where
12807 		 * one thread does ndi_devi_enter() and tries to grab
12808 		 * fcp_mutex and another does it the other way round.
12809 		 *
12810 		 * But before we do that, make sure that nobody releases the
12811 		 * port in the meantime. We can do this by setting a flag.
12812 		 */
12813 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12814 		pptr->port_state |= FCP_STATE_IN_MDI;
12815 		mutex_exit(&plun->lun_mutex);
12816 		mutex_exit(&pptr->port_mutex);
12817 		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12818 		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12819 			fcp_log(CE_WARN, pptr->port_dip,
12820 			    "!path alloc failed:0x%x", plun);
12821 			mutex_enter(&pptr->port_mutex);
12822 			mutex_enter(&plun->lun_mutex);
12823 			pptr->port_state &= ~FCP_STATE_IN_MDI;
12824 			failure++;
12825 			goto end_of_fcp_create_pip;
12826 		}
12827 		mutex_enter(&pptr->port_mutex);
12828 		mutex_enter(&plun->lun_mutex);
12829 		pptr->port_state &= ~FCP_STATE_IN_MDI;
12830 	} else {
12831 		(void) mdi_prop_remove(pip, NULL);
12832 	}
12833 
12834 	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12835 
12836 	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12837 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12838 	    != DDI_PROP_SUCCESS) {
12839 		failure++;
12840 		goto end_of_fcp_create_pip;
12841 	}
12842 
12843 	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12844 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12845 	    != DDI_PROP_SUCCESS) {
12846 		failure++;
12847 		goto end_of_fcp_create_pip;
12848 	}
12849 
12850 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12851 	t_pwwn[16] = '\0';
12852 	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12853 	    != DDI_PROP_SUCCESS) {
12854 		failure++;
12855 		goto end_of_fcp_create_pip;
12856 	}
12857 
12858 	/*
12859 	 * If there is no hard address - We might have to deal with
12860 	 * that by using WWN - Having said that it is important to
12861 	 * recognize this problem early so ssd can be informed of
12862 	 * the right interconnect type.
12863 	 */
12864 	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12865 	    ptgt->tgt_hard_addr != 0) {
12866 		tgt_id = (uint32_t)
12867 		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12868 	} else {
12869 		tgt_id = ptgt->tgt_d_id;
12870 	}
12871 
12872 	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12873 	    != DDI_PROP_SUCCESS) {
12874 		failure++;
12875 		goto end_of_fcp_create_pip;
12876 	}
12877 
12878 	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12879 	    != DDI_PROP_SUCCESS) {
12880 		failure++;
12881 		goto end_of_fcp_create_pip;
12882 	}
12883 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12884 	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12885 	    != DDI_PROP_SUCCESS) {
12886 		failure++;
12887 		goto end_of_fcp_create_pip;
12888 	}
12889 
12890 end_of_fcp_create_pip:
12891 	scsi_hba_nodename_compatible_free(nname, compatible);
12892 
12893 	if (pip != NULL && failure) {
12894 		(void) mdi_prop_remove(pip, NULL);
12895 		mutex_exit(&plun->lun_mutex);
12896 		mutex_exit(&pptr->port_mutex);
12897 		(void) mdi_pi_free(pip, 0);
12898 		mutex_enter(&pptr->port_mutex);
12899 		mutex_enter(&plun->lun_mutex);
12900 		pip = NULL;
12901 	}
12902 
12903 	return (pip);
12904 }
12905 
12906 static dev_info_t *
12907 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12908 {
12909 	uint_t			nbytes;
12910 	uchar_t			*bytes;
12911 	uint_t			nwords;
12912 	uint32_t		tgt_id;
12913 	int			*words;
12914 	dev_info_t		*cdip;
12915 	dev_info_t		*ndip;
12916 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12917 	struct fcp_port	*pptr = ptgt->tgt_port;
12918 
12919 	ndi_devi_enter(pdip);
12920 
12921 	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12922 	while ((cdip = ndip) != NULL) {
12923 		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12924 
12925 		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12926 			continue;
12927 		}
12928 
12929 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12930 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12931 		    &nbytes) != DDI_PROP_SUCCESS) {
12932 			continue;
12933 		}
12934 
12935 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12936 			if (bytes != NULL) {
12937 				ddi_prop_free(bytes);
12938 			}
12939 			continue;
12940 		}
12941 		ASSERT(bytes != NULL);
12942 
12943 		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12944 			ddi_prop_free(bytes);
12945 			continue;
12946 		}
12947 
12948 		ddi_prop_free(bytes);
12949 
12950 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12951 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12952 		    &nbytes) != DDI_PROP_SUCCESS) {
12953 			continue;
12954 		}
12955 
12956 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12957 			if (bytes != NULL) {
12958 				ddi_prop_free(bytes);
12959 			}
12960 			continue;
12961 		}
12962 		ASSERT(bytes != NULL);
12963 
12964 		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12965 			ddi_prop_free(bytes);
12966 			continue;
12967 		}
12968 
12969 		ddi_prop_free(bytes);
12970 
12971 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12972 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12973 		    &nwords) != DDI_PROP_SUCCESS) {
12974 			continue;
12975 		}
12976 
12977 		if (nwords != 1 || words == NULL) {
12978 			if (words != NULL) {
12979 				ddi_prop_free(words);
12980 			}
12981 			continue;
12982 		}
12983 		ASSERT(words != NULL);
12984 
12985 		/*
12986 		 * If there is no hard address - We might have to deal with
12987 		 * that by using WWN - Having said that it is important to
12988 		 * recognize this problem early so ssd can be informed of
12989 		 * the right interconnect type.
12990 		 */
12991 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12992 		    ptgt->tgt_hard_addr != 0) {
12993 			tgt_id =
12994 			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12995 		} else {
12996 			tgt_id = ptgt->tgt_d_id;
12997 		}
12998 
12999 		if (tgt_id != (uint32_t)*words) {
13000 			ddi_prop_free(words);
13001 			continue;
13002 		}
13003 		ddi_prop_free(words);
13004 
13005 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13006 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13007 		    &nwords) != DDI_PROP_SUCCESS) {
13008 			continue;
13009 		}
13010 
13011 		if (nwords != 1 || words == NULL) {
13012 			if (words != NULL) {
13013 				ddi_prop_free(words);
13014 			}
13015 			continue;
13016 		}
13017 		ASSERT(words != NULL);
13018 
13019 		if (plun->lun_num == (uint16_t)*words) {
13020 			ddi_prop_free(words);
13021 			break;
13022 		}
13023 		ddi_prop_free(words);
13024 	}
13025 	ndi_devi_exit(pdip);
13026 
13027 	return (cdip);
13028 }
13029 
13030 
13031 static int
13032 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13033 {
13034 	dev_info_t	*pdip;
13035 	char		buf[MAXNAMELEN];
13036 	char		uaddr[MAXNAMELEN];
13037 	int		rval = FC_FAILURE;
13038 
13039 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13040 
13041 	pdip = plun->lun_tgt->tgt_port->port_dip;
13042 
13043 	/*
13044 	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13045 	 * non-NULL even when the LUN is not there as in the case when a LUN is
13046 	 * configured and then deleted on the device end (for T3/T4 case). In
13047 	 * such cases, pip will be NULL.
13048 	 *
13049 	 * If the device generates an RSCN, it will end up getting offlined when
13050 	 * it disappeared and a new LUN will get created when it is rediscovered
13051 	 * on the device. If we check for lun_cip here, the LUN will not end
13052 	 * up getting onlined since this function will end up returning a
13053 	 * FC_SUCCESS.
13054 	 *
13055 	 * The behavior is different on other devices. For instance, on a HDS,
13056 	 * there was no RSCN generated by the device but the next I/O generated
13057 	 * a check condition and rediscovery got triggered that way. So, in
13058 	 * such cases, this path will not be exercised
13059 	 */
13060 	if (pip == NULL) {
13061 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13062 		    fcp_trace, FCP_BUF_LEVEL_4, 0,
13063 		    "fcp_is_pip_present: plun->lun_cip is NULL: "
13064 		    "plun: %p lun state: %x num: %d target state: %x",
13065 		    plun, plun->lun_state, plun->lun_num,
13066 		    plun->lun_tgt->tgt_port->port_state);
13067 		return (rval);
13068 	}
13069 
13070 	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13071 
13072 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13073 
13074 	if (plun->lun_old_guid) {
13075 		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13076 			rval = FC_SUCCESS;
13077 		}
13078 	} else {
13079 		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13080 			rval = FC_SUCCESS;
13081 		}
13082 	}
13083 	return (rval);
13084 }
13085 
13086 static mdi_pathinfo_t *
13087 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13088 {
13089 	char			buf[MAXNAMELEN];
13090 	char			uaddr[MAXNAMELEN];
13091 	mdi_pathinfo_t		*pip;
13092 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13093 	struct fcp_port	*pptr = ptgt->tgt_port;
13094 
13095 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13096 
13097 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13098 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13099 
13100 	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13101 
13102 	return (pip);
13103 }
13104 
13105 
13106 static int
13107 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13108     int tcount, int flags)
13109 {
13110 	int			rval;
13111 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13112 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13113 	dev_info_t		*cdip = NULL;
13114 
13115 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13116 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13117 
13118 	if (plun->lun_cip == NULL) {
13119 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13120 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13121 		    "fcp_online_child: plun->lun_cip is NULL: "
13122 		    "plun: %p state: %x num: %d target state: %x",
13123 		    plun, plun->lun_state, plun->lun_num,
13124 		    plun->lun_tgt->tgt_port->port_state);
13125 		return (NDI_FAILURE);
13126 	}
13127 again:
13128 	if (plun->lun_mpxio == 0) {
13129 		cdip = DIP(cip);
13130 		mutex_exit(&plun->lun_mutex);
13131 		mutex_exit(&pptr->port_mutex);
13132 
13133 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13134 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13135 		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13136 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13137 
13138 		/*
13139 		 * We could check for FCP_LUN_INIT here but chances
13140 		 * of getting here when it's already in FCP_LUN_INIT
13141 		 * is rare and a duplicate ndi_devi_online wouldn't
13142 		 * hurt either (as the node would already have been
13143 		 * in CF2)
13144 		 */
13145 		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13146 			rval = ndi_devi_bind_driver(cdip, flags);
13147 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13148 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13149 			    "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13150 		} else {
13151 			rval = ndi_devi_online(cdip, flags);
13152 		}
13153 
13154 		/*
13155 		 * We log the message into trace buffer if the device
13156 		 * is "ses" and into syslog for any other device
13157 		 * type. This is to prevent the ndi_devi_online failure
13158 		 * message that appears for V880/A5K ses devices.
13159 		 */
13160 		if (rval == NDI_SUCCESS) {
13161 			mutex_enter(&ptgt->tgt_mutex);
13162 			plun->lun_state |= FCP_LUN_INIT;
13163 			mutex_exit(&ptgt->tgt_mutex);
13164 		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13165 			fcp_log(CE_NOTE, pptr->port_dip,
13166 			    "!ndi_devi_online:"
13167 			    " failed for %s: target=%x lun=%x %x",
13168 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13169 			    plun->lun_num, rval);
13170 		} else {
13171 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13172 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13173 			    " !ndi_devi_online:"
13174 			    " failed for %s: target=%x lun=%x %x",
13175 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13176 			    plun->lun_num, rval);
13177 		}
13178 	} else {
13179 		cdip = mdi_pi_get_client(PIP(cip));
13180 		mutex_exit(&plun->lun_mutex);
13181 		mutex_exit(&pptr->port_mutex);
13182 
13183 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13184 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13185 		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13186 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13187 
13188 		/*
13189 		 * Hold path and exit phci to avoid deadlock with power
13190 		 * management code during mdi_pi_online.
13191 		 */
13192 		mdi_hold_path(PIP(cip));
13193 		mdi_devi_exit_phci(pptr->port_dip);
13194 
13195 		rval = mdi_pi_online(PIP(cip), flags);
13196 
13197 		mdi_devi_enter_phci(pptr->port_dip);
13198 		mdi_rele_path(PIP(cip));
13199 
13200 		if (rval == MDI_SUCCESS) {
13201 			mutex_enter(&ptgt->tgt_mutex);
13202 			plun->lun_state |= FCP_LUN_INIT;
13203 			mutex_exit(&ptgt->tgt_mutex);
13204 
13205 			/*
13206 			 * Clear MPxIO path permanent disable in case
13207 			 * fcp hotplug dropped the offline event.
13208 			 */
13209 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13210 
13211 		} else if (rval == MDI_NOT_SUPPORTED) {
13212 			child_info_t	*old_cip = cip;
13213 
13214 			/*
13215 			 * MPxIO does not support this device yet.
13216 			 * Enumerate in legacy mode.
13217 			 */
13218 			mutex_enter(&pptr->port_mutex);
13219 			mutex_enter(&plun->lun_mutex);
13220 			plun->lun_mpxio = 0;
13221 			plun->lun_cip = NULL;
13222 			cdip = fcp_create_dip(plun, lcount, tcount);
13223 			plun->lun_cip = cip = CIP(cdip);
13224 			if (cip == NULL) {
13225 				fcp_log(CE_WARN, pptr->port_dip,
13226 				    "!fcp_online_child: "
13227 				    "Create devinfo failed for LU=%p", plun);
13228 				mutex_exit(&plun->lun_mutex);
13229 
13230 				mutex_enter(&ptgt->tgt_mutex);
13231 				plun->lun_state |= FCP_LUN_OFFLINE;
13232 				mutex_exit(&ptgt->tgt_mutex);
13233 
13234 				mutex_exit(&pptr->port_mutex);
13235 
13236 				/*
13237 				 * free the mdi_pathinfo node
13238 				 */
13239 				(void) mdi_pi_free(PIP(old_cip), 0);
13240 			} else {
13241 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13242 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13243 				    "fcp_online_child: creating devinfo "
13244 				    "node 0x%p for plun 0x%p",
13245 				    cip, plun);
13246 				mutex_exit(&plun->lun_mutex);
13247 				mutex_exit(&pptr->port_mutex);
13248 				/*
13249 				 * free the mdi_pathinfo node
13250 				 */
13251 				(void) mdi_pi_free(PIP(old_cip), 0);
13252 				mutex_enter(&pptr->port_mutex);
13253 				mutex_enter(&plun->lun_mutex);
13254 				goto again;
13255 			}
13256 		} else {
13257 			if (cdip) {
13258 				fcp_log(CE_NOTE, pptr->port_dip,
13259 				    "!fcp_online_child: mdi_pi_online:"
13260 				    " failed for %s: target=%x lun=%x %x",
13261 				    ddi_get_name(cdip), ptgt->tgt_d_id,
13262 				    plun->lun_num, rval);
13263 			}
13264 		}
13265 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13266 	}
13267 
13268 	if (rval == NDI_SUCCESS) {
13269 		if (cdip) {
13270 			(void) ndi_event_retrieve_cookie(
13271 			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13272 			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13273 			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13274 			    cdip, fcp_insert_eid, NULL);
13275 		}
13276 	}
13277 	mutex_enter(&pptr->port_mutex);
13278 	mutex_enter(&plun->lun_mutex);
13279 	return (rval);
13280 }
13281 
13282 /* ARGSUSED */
13283 static int
13284 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13285     int tcount, int flags)
13286 {
13287 	int		rval;
13288 	int		lun_mpxio;
13289 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
13290 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13291 	dev_info_t	*cdip;
13292 
13293 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13294 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13295 
13296 	if (plun->lun_cip == NULL) {
13297 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13298 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13299 		    "fcp_offline_child: plun->lun_cip is NULL: "
13300 		    "plun: %p lun state: %x num: %d target state: %x",
13301 		    plun, plun->lun_state, plun->lun_num,
13302 		    plun->lun_tgt->tgt_port->port_state);
13303 		return (NDI_FAILURE);
13304 	}
13305 
13306 	/*
13307 	 * We will use this value twice. Make a copy to be sure we use
13308 	 * the same value in both places.
13309 	 */
13310 	lun_mpxio = plun->lun_mpxio;
13311 
13312 	if (lun_mpxio == 0) {
13313 		cdip = DIP(cip);
13314 		mutex_exit(&plun->lun_mutex);
13315 		mutex_exit(&pptr->port_mutex);
13316 		rval = ndi_devi_offline(DIP(cip), flags);
13317 		if (rval != NDI_SUCCESS) {
13318 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13319 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13320 			    "fcp_offline_child: ndi_devi_offline failed "
13321 			    "rval=%x cip=%p", rval, cip);
13322 		}
13323 	} else {
13324 		cdip = mdi_pi_get_client(PIP(cip));
13325 		mutex_exit(&plun->lun_mutex);
13326 		mutex_exit(&pptr->port_mutex);
13327 
13328 		/*
13329 		 * Exit phci to avoid deadlock with power management code
13330 		 * during mdi_pi_offline
13331 		 */
13332 		mdi_hold_path(PIP(cip));
13333 		mdi_devi_exit_phci(pptr->port_dip);
13334 
13335 		rval = mdi_pi_offline(PIP(cip), flags);
13336 
13337 		mdi_devi_enter_phci(pptr->port_dip);
13338 		mdi_rele_path(PIP(cip));
13339 
13340 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13341 	}
13342 
13343 	mutex_enter(&ptgt->tgt_mutex);
13344 	plun->lun_state &= ~FCP_LUN_INIT;
13345 	mutex_exit(&ptgt->tgt_mutex);
13346 
13347 	if (rval == NDI_SUCCESS) {
13348 		cdip = NULL;
13349 		if (flags & NDI_DEVI_REMOVE) {
13350 			mutex_enter(&plun->lun_mutex);
13351 			/*
13352 			 * If the guid of the LUN changes, lun_cip will not
13353 			 * equal to cip, and after offlining the LUN with the
13354 			 * old guid, we should keep lun_cip since it's the cip
13355 			 * of the LUN with the new guid.
13356 			 * Otherwise remove our reference to child node.
13357 			 *
13358 			 * This must be done before the child node is freed,
13359 			 * otherwise other threads could see a stale lun_cip
13360 			 * pointer.
13361 			 */
13362 			if (plun->lun_cip == cip) {
13363 				plun->lun_cip = NULL;
13364 			}
13365 			if (plun->lun_old_guid) {
13366 				kmem_free(plun->lun_old_guid,
13367 				    plun->lun_old_guid_size);
13368 				plun->lun_old_guid = NULL;
13369 				plun->lun_old_guid_size = 0;
13370 			}
13371 			mutex_exit(&plun->lun_mutex);
13372 		}
13373 	}
13374 
13375 	if (lun_mpxio != 0) {
13376 		if (rval == NDI_SUCCESS) {
13377 			/*
13378 			 * Clear MPxIO path permanent disable as the path is
13379 			 * already offlined.
13380 			 */
13381 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13382 
13383 			if (flags & NDI_DEVI_REMOVE) {
13384 				(void) mdi_pi_free(PIP(cip), 0);
13385 			}
13386 		} else {
13387 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13388 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13389 			    "fcp_offline_child: mdi_pi_offline failed "
13390 			    "rval=%x cip=%p", rval, cip);
13391 		}
13392 	}
13393 
13394 	mutex_enter(&pptr->port_mutex);
13395 	mutex_enter(&plun->lun_mutex);
13396 
13397 	if (cdip) {
13398 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13399 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13400 		    " target=%x lun=%x", "ndi_offline",
13401 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13402 	}
13403 
13404 	return (rval);
13405 }
13406 
13407 static void
13408 fcp_remove_child(struct fcp_lun *plun)
13409 {
13410 	child_info_t *cip;
13411 	boolean_t enteredv;
13412 
13413 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13414 
13415 	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13416 		if (plun->lun_mpxio == 0) {
13417 			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13418 			(void) ndi_devi_free(DIP(plun->lun_cip));
13419 			plun->lun_cip = NULL;
13420 		} else {
13421 			/*
13422 			 * Clear reference to the child node in the lun.
13423 			 * This must be done before freeing it with mdi_pi_free
13424 			 * and with lun_mutex held so that other threads always
13425 			 * see either valid lun_cip or NULL when holding
13426 			 * lun_mutex. We keep a copy in cip.
13427 			 */
13428 			cip = plun->lun_cip;
13429 			plun->lun_cip = NULL;
13430 
13431 			mutex_exit(&plun->lun_mutex);
13432 			mutex_exit(&plun->lun_tgt->tgt_mutex);
13433 			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13434 
13435 			mdi_devi_enter(
13436 			    plun->lun_tgt->tgt_port->port_dip, &enteredv);
13437 
13438 			/*
13439 			 * Exit phci to avoid deadlock with power management
13440 			 * code during mdi_pi_offline
13441 			 */
13442 			mdi_hold_path(PIP(cip));
13443 			mdi_devi_exit_phci(
13444 			    plun->lun_tgt->tgt_port->port_dip);
13445 			(void) mdi_pi_offline(PIP(cip),
13446 			    NDI_DEVI_REMOVE);
13447 			mdi_devi_enter_phci(
13448 			    plun->lun_tgt->tgt_port->port_dip);
13449 			mdi_rele_path(PIP(cip));
13450 
13451 			mdi_devi_exit(
13452 			    plun->lun_tgt->tgt_port->port_dip, enteredv);
13453 
13454 			FCP_TRACE(fcp_logq,
13455 			    plun->lun_tgt->tgt_port->port_instbuf,
13456 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13457 			    "lun=%p pip freed %p", plun, cip);
13458 
13459 			(void) mdi_prop_remove(PIP(cip), NULL);
13460 			(void) mdi_pi_free(PIP(cip), 0);
13461 
13462 			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13463 			mutex_enter(&plun->lun_tgt->tgt_mutex);
13464 			mutex_enter(&plun->lun_mutex);
13465 		}
13466 	} else {
13467 		plun->lun_cip = NULL;
13468 	}
13469 }
13470 
13471 /*
13472  * called when a timeout occurs
13473  *
13474  * can be scheduled during an attach or resume (if not already running)
13475  *
13476  * one timeout is set up for all ports
13477  *
13478  * acquires and releases the global mutex
13479  */
13480 /*ARGSUSED*/
13481 static void
13482 fcp_watch(void *arg)
13483 {
13484 	struct fcp_port	*pptr;
13485 	struct fcp_ipkt	*icmd;
13486 	struct fcp_ipkt	*nicmd;
13487 	struct fcp_pkt	*cmd;
13488 	struct fcp_pkt	*ncmd;
13489 	struct fcp_pkt	*tail;
13490 	struct fcp_pkt	*pcmd;
13491 	struct fcp_pkt	*save_head;
13492 	struct fcp_port	*save_port;
13493 
13494 	/* increment global watchdog time */
13495 	fcp_watchdog_time += fcp_watchdog_timeout;
13496 
13497 	mutex_enter(&fcp_global_mutex);
13498 
13499 	/* scan each port in our list */
13500 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13501 		save_port = fcp_port_head;
13502 		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13503 		mutex_exit(&fcp_global_mutex);
13504 
13505 		mutex_enter(&pptr->port_mutex);
13506 		if (pptr->port_ipkt_list == NULL &&
13507 		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13508 		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13509 			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13510 			mutex_exit(&pptr->port_mutex);
13511 			mutex_enter(&fcp_global_mutex);
13512 			goto end_of_watchdog;
13513 		}
13514 
13515 		/*
13516 		 * We check if a list of targets need to be offlined.
13517 		 */
13518 		if (pptr->port_offline_tgts) {
13519 			fcp_scan_offline_tgts(pptr);
13520 		}
13521 
13522 		/*
13523 		 * We check if a list of luns need to be offlined.
13524 		 */
13525 		if (pptr->port_offline_luns) {
13526 			fcp_scan_offline_luns(pptr);
13527 		}
13528 
13529 		/*
13530 		 * We check if a list of targets or luns need to be reset.
13531 		 */
13532 		if (pptr->port_reset_list) {
13533 			fcp_check_reset_delay(pptr);
13534 		}
13535 
13536 		mutex_exit(&pptr->port_mutex);
13537 
13538 		/*
13539 		 * This is where the pending commands (pkt) are checked for
13540 		 * timeout.
13541 		 */
13542 		mutex_enter(&pptr->port_pkt_mutex);
13543 		tail = pptr->port_pkt_tail;
13544 
13545 		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13546 		    cmd != NULL; cmd = ncmd) {
13547 			ncmd = cmd->cmd_next;
13548 			/*
13549 			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13550 			 * must be set.
13551 			 */
13552 			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13553 			/*
13554 			 * FCP_INVALID_TIMEOUT will be set for those
13555 			 * command that need to be failed. Mostly those
13556 			 * cmds that could not be queued down for the
13557 			 * "timeout" value. cmd->cmd_timeout is used
13558 			 * to try and requeue the command regularly.
13559 			 */
13560 			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13561 				/*
13562 				 * This command hasn't timed out yet.  Let's
13563 				 * go to the next one.
13564 				 */
13565 				pcmd = cmd;
13566 				goto end_of_loop;
13567 			}
13568 
13569 			if (cmd == pptr->port_pkt_head) {
13570 				ASSERT(pcmd == NULL);
13571 				pptr->port_pkt_head = cmd->cmd_next;
13572 			} else {
13573 				ASSERT(pcmd != NULL);
13574 				pcmd->cmd_next = cmd->cmd_next;
13575 			}
13576 
13577 			if (cmd == pptr->port_pkt_tail) {
13578 				ASSERT(cmd->cmd_next == NULL);
13579 				pptr->port_pkt_tail = pcmd;
13580 				if (pcmd) {
13581 					pcmd->cmd_next = NULL;
13582 				}
13583 			}
13584 			cmd->cmd_next = NULL;
13585 
13586 			/*
13587 			 * save the current head before dropping the
13588 			 * mutex - If the head doesn't remain the
13589 			 * same after re acquiring the mutex, just
13590 			 * bail out and revisit on next tick.
13591 			 *
13592 			 * PS: The tail pointer can change as the commands
13593 			 * get requeued after failure to retransport
13594 			 */
13595 			save_head = pptr->port_pkt_head;
13596 			mutex_exit(&pptr->port_pkt_mutex);
13597 
13598 			if (cmd->cmd_fp_pkt->pkt_timeout ==
13599 			    FCP_INVALID_TIMEOUT) {
13600 				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13601 				struct fcp_lun	*plun;
13602 				struct fcp_tgt	*ptgt;
13603 
13604 				plun = ADDR2LUN(&pkt->pkt_address);
13605 				ptgt = plun->lun_tgt;
13606 
13607 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13608 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13609 				    "SCSI cmd 0x%x to D_ID=%x timed out",
13610 				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13611 
13612 				cmd->cmd_state == FCP_PKT_ABORTING ?
13613 				    fcp_fail_cmd(cmd, CMD_RESET,
13614 				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13615 				    CMD_TIMEOUT, STAT_ABORTED);
13616 			} else {
13617 				fcp_retransport_cmd(pptr, cmd);
13618 			}
13619 			mutex_enter(&pptr->port_pkt_mutex);
13620 			if (save_head && save_head != pptr->port_pkt_head) {
13621 				/*
13622 				 * Looks like linked list got changed (mostly
13623 				 * happens when an an OFFLINE LUN code starts
13624 				 * returning overflow queue commands in
13625 				 * parallel. So bail out and revisit during
13626 				 * next tick
13627 				 */
13628 				break;
13629 			}
13630 		end_of_loop:
13631 			/*
13632 			 * Scan only upto the previously known tail pointer
13633 			 * to avoid excessive processing - lots of new packets
13634 			 * could have been added to the tail or the old ones
13635 			 * re-queued.
13636 			 */
13637 			if (cmd == tail) {
13638 				break;
13639 			}
13640 		}
13641 		mutex_exit(&pptr->port_pkt_mutex);
13642 
13643 		mutex_enter(&pptr->port_mutex);
13644 		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13645 			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13646 
13647 			nicmd = icmd->ipkt_next;
13648 			if ((icmd->ipkt_restart != 0) &&
13649 			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13650 				/* packet has not timed out */
13651 				continue;
13652 			}
13653 
13654 			/* time for packet re-transport */
13655 			if (icmd == pptr->port_ipkt_list) {
13656 				pptr->port_ipkt_list = icmd->ipkt_next;
13657 				if (pptr->port_ipkt_list) {
13658 					pptr->port_ipkt_list->ipkt_prev =
13659 					    NULL;
13660 				}
13661 			} else {
13662 				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13663 				if (icmd->ipkt_next) {
13664 					icmd->ipkt_next->ipkt_prev =
13665 					    icmd->ipkt_prev;
13666 				}
13667 			}
13668 			icmd->ipkt_next = NULL;
13669 			icmd->ipkt_prev = NULL;
13670 			mutex_exit(&pptr->port_mutex);
13671 
13672 			if (fcp_is_retryable(icmd)) {
13673 				fc_ulp_rscn_info_t *rscnp =
13674 				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13675 				    pkt_ulp_rscn_infop;
13676 
13677 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13678 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13679 				    "%x to D_ID=%x Retrying..",
13680 				    icmd->ipkt_opcode,
13681 				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13682 
13683 				/*
13684 				 * Update the RSCN count in the packet
13685 				 * before resending.
13686 				 */
13687 
13688 				if (rscnp != NULL) {
13689 					rscnp->ulp_rscn_count =
13690 					    fc_ulp_get_rscn_count(pptr->
13691 					    port_fp_handle);
13692 				}
13693 
13694 				mutex_enter(&pptr->port_mutex);
13695 				mutex_enter(&ptgt->tgt_mutex);
13696 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13697 					mutex_exit(&ptgt->tgt_mutex);
13698 					mutex_exit(&pptr->port_mutex);
13699 					switch (icmd->ipkt_opcode) {
13700 						int rval;
13701 					case LA_ELS_PLOGI:
13702 						if ((rval = fc_ulp_login(
13703 						    pptr->port_fp_handle,
13704 						    &icmd->ipkt_fpkt, 1)) ==
13705 						    FC_SUCCESS) {
13706 							mutex_enter(
13707 							    &pptr->port_mutex);
13708 							continue;
13709 						}
13710 						if (fcp_handle_ipkt_errors(
13711 						    pptr, ptgt, icmd, rval,
13712 						    "PLOGI") == DDI_SUCCESS) {
13713 							mutex_enter(
13714 							    &pptr->port_mutex);
13715 							continue;
13716 						}
13717 						break;
13718 
13719 					case LA_ELS_PRLI:
13720 						if ((rval = fc_ulp_issue_els(
13721 						    pptr->port_fp_handle,
13722 						    icmd->ipkt_fpkt)) ==
13723 						    FC_SUCCESS) {
13724 							mutex_enter(
13725 							    &pptr->port_mutex);
13726 							continue;
13727 						}
13728 						if (fcp_handle_ipkt_errors(
13729 						    pptr, ptgt, icmd, rval,
13730 						    "PRLI") == DDI_SUCCESS) {
13731 							mutex_enter(
13732 							    &pptr->port_mutex);
13733 							continue;
13734 						}
13735 						break;
13736 
13737 					default:
13738 						if ((rval = fcp_transport(
13739 						    pptr->port_fp_handle,
13740 						    icmd->ipkt_fpkt, 1)) ==
13741 						    FC_SUCCESS) {
13742 							mutex_enter(
13743 							    &pptr->port_mutex);
13744 							continue;
13745 						}
13746 						if (fcp_handle_ipkt_errors(
13747 						    pptr, ptgt, icmd, rval,
13748 						    "PRLI") == DDI_SUCCESS) {
13749 							mutex_enter(
13750 							    &pptr->port_mutex);
13751 							continue;
13752 						}
13753 						break;
13754 					}
13755 				} else {
13756 					mutex_exit(&ptgt->tgt_mutex);
13757 					mutex_exit(&pptr->port_mutex);
13758 				}
13759 			} else {
13760 				fcp_print_error(icmd->ipkt_fpkt);
13761 			}
13762 
13763 			(void) fcp_call_finish_init(pptr, ptgt,
13764 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13765 			    icmd->ipkt_cause);
13766 			fcp_icmd_free(pptr, icmd);
13767 			mutex_enter(&pptr->port_mutex);
13768 		}
13769 
13770 		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13771 		mutex_exit(&pptr->port_mutex);
13772 		mutex_enter(&fcp_global_mutex);
13773 
13774 	end_of_watchdog:
13775 		/*
13776 		 * Bail out early before getting into trouble
13777 		 */
13778 		if (save_port != fcp_port_head) {
13779 			break;
13780 		}
13781 	}
13782 
13783 	if (fcp_watchdog_init > 0) {
13784 		/* reschedule timeout to go again */
13785 		fcp_watchdog_id =
13786 		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13787 	}
13788 	mutex_exit(&fcp_global_mutex);
13789 }
13790 
13791 
13792 static void
13793 fcp_check_reset_delay(struct fcp_port *pptr)
13794 {
13795 	uint32_t		tgt_cnt;
13796 	int			level;
13797 	struct fcp_tgt	*ptgt;
13798 	struct fcp_lun	*plun;
13799 	struct fcp_reset_elem *cur = NULL;
13800 	struct fcp_reset_elem *next = NULL;
13801 	struct fcp_reset_elem *prev = NULL;
13802 
13803 	ASSERT(mutex_owned(&pptr->port_mutex));
13804 
13805 	next = pptr->port_reset_list;
13806 	while ((cur = next) != NULL) {
13807 		next = cur->next;
13808 
13809 		if (cur->timeout < fcp_watchdog_time) {
13810 			prev = cur;
13811 			continue;
13812 		}
13813 
13814 		ptgt = cur->tgt;
13815 		plun = cur->lun;
13816 		tgt_cnt = cur->tgt_cnt;
13817 
13818 		if (ptgt) {
13819 			level = RESET_TARGET;
13820 		} else {
13821 			ASSERT(plun != NULL);
13822 			level = RESET_LUN;
13823 			ptgt = plun->lun_tgt;
13824 		}
13825 		if (prev) {
13826 			prev->next = next;
13827 		} else {
13828 			/*
13829 			 * Because we drop port mutex while doing aborts for
13830 			 * packets, we can't rely on reset_list pointing to
13831 			 * our head
13832 			 */
13833 			if (cur == pptr->port_reset_list) {
13834 				pptr->port_reset_list = next;
13835 			} else {
13836 				struct fcp_reset_elem *which;
13837 
13838 				which = pptr->port_reset_list;
13839 				while (which && which->next != cur) {
13840 					which = which->next;
13841 				}
13842 				ASSERT(which != NULL);
13843 
13844 				which->next = next;
13845 				prev = which;
13846 			}
13847 		}
13848 
13849 		kmem_free(cur, sizeof (*cur));
13850 
13851 		if (tgt_cnt == ptgt->tgt_change_cnt) {
13852 			mutex_enter(&ptgt->tgt_mutex);
13853 			if (level == RESET_TARGET) {
13854 				fcp_update_tgt_state(ptgt,
13855 				    FCP_RESET, FCP_LUN_BUSY);
13856 			} else {
13857 				fcp_update_lun_state(plun,
13858 				    FCP_RESET, FCP_LUN_BUSY);
13859 			}
13860 			mutex_exit(&ptgt->tgt_mutex);
13861 
13862 			mutex_exit(&pptr->port_mutex);
13863 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13864 			mutex_enter(&pptr->port_mutex);
13865 		}
13866 	}
13867 }
13868 
13869 
13870 static void
13871 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13872     struct fcp_lun *rlun, int tgt_cnt)
13873 {
13874 	int			rval;
13875 	struct fcp_lun	*tlun, *nlun;
13876 	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13877 	    *cmd = NULL, *head = NULL,
13878 	    *tail = NULL;
13879 
13880 	mutex_enter(&pptr->port_pkt_mutex);
13881 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13882 		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13883 		struct fcp_tgt *ptgt = plun->lun_tgt;
13884 
13885 		ncmd = cmd->cmd_next;
13886 
13887 		if (ptgt != ttgt && plun != rlun) {
13888 			pcmd = cmd;
13889 			continue;
13890 		}
13891 
13892 		if (pcmd != NULL) {
13893 			ASSERT(pptr->port_pkt_head != cmd);
13894 			pcmd->cmd_next = ncmd;
13895 		} else {
13896 			ASSERT(cmd == pptr->port_pkt_head);
13897 			pptr->port_pkt_head = ncmd;
13898 		}
13899 		if (pptr->port_pkt_tail == cmd) {
13900 			ASSERT(cmd->cmd_next == NULL);
13901 			pptr->port_pkt_tail = pcmd;
13902 			if (pcmd != NULL) {
13903 				pcmd->cmd_next = NULL;
13904 			}
13905 		}
13906 
13907 		if (head == NULL) {
13908 			head = tail = cmd;
13909 		} else {
13910 			ASSERT(tail != NULL);
13911 			tail->cmd_next = cmd;
13912 			tail = cmd;
13913 		}
13914 		cmd->cmd_next = NULL;
13915 	}
13916 	mutex_exit(&pptr->port_pkt_mutex);
13917 
13918 	for (cmd = head; cmd != NULL; cmd = ncmd) {
13919 		struct scsi_pkt *pkt = cmd->cmd_pkt;
13920 
13921 		ncmd = cmd->cmd_next;
13922 		ASSERT(pkt != NULL);
13923 
13924 		mutex_enter(&pptr->port_mutex);
13925 		if (ttgt->tgt_change_cnt == tgt_cnt) {
13926 			mutex_exit(&pptr->port_mutex);
13927 			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13928 			pkt->pkt_reason = CMD_RESET;
13929 			pkt->pkt_statistics |= STAT_DEV_RESET;
13930 			cmd->cmd_state = FCP_PKT_IDLE;
13931 			fcp_post_callback(cmd);
13932 		} else {
13933 			mutex_exit(&pptr->port_mutex);
13934 		}
13935 	}
13936 
13937 	/*
13938 	 * If the FCA will return all the commands in its queue then our
13939 	 * work is easy, just return.
13940 	 */
13941 
13942 	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13943 		return;
13944 	}
13945 
13946 	/*
13947 	 * For RESET_LUN get hold of target pointer
13948 	 */
13949 	if (ttgt == NULL) {
13950 		ASSERT(rlun != NULL);
13951 
13952 		ttgt = rlun->lun_tgt;
13953 
13954 		ASSERT(ttgt != NULL);
13955 	}
13956 
13957 	/*
13958 	 * There are some severe race conditions here.
13959 	 * While we are trying to abort the pkt, it might be completing
13960 	 * so mark it aborted and if the abort does not succeed then
13961 	 * handle it in the watch thread.
13962 	 */
13963 	mutex_enter(&ttgt->tgt_mutex);
13964 	nlun = ttgt->tgt_lun;
13965 	mutex_exit(&ttgt->tgt_mutex);
13966 	while ((tlun = nlun) != NULL) {
13967 		int restart = 0;
13968 		if (rlun && rlun != tlun) {
13969 			mutex_enter(&ttgt->tgt_mutex);
13970 			nlun = tlun->lun_next;
13971 			mutex_exit(&ttgt->tgt_mutex);
13972 			continue;
13973 		}
13974 		mutex_enter(&tlun->lun_mutex);
13975 		cmd = tlun->lun_pkt_head;
13976 		while (cmd != NULL) {
13977 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13978 				struct scsi_pkt *pkt;
13979 
13980 				restart = 1;
13981 				cmd->cmd_state = FCP_PKT_ABORTING;
13982 				mutex_exit(&tlun->lun_mutex);
13983 				rval = fc_ulp_abort(pptr->port_fp_handle,
13984 				    cmd->cmd_fp_pkt, KM_SLEEP);
13985 				if (rval == FC_SUCCESS) {
13986 					pkt = cmd->cmd_pkt;
13987 					pkt->pkt_reason = CMD_RESET;
13988 					pkt->pkt_statistics |= STAT_DEV_RESET;
13989 					cmd->cmd_state = FCP_PKT_IDLE;
13990 					fcp_post_callback(cmd);
13991 				} else {
13992 					caddr_t msg;
13993 
13994 					(void) fc_ulp_error(rval, &msg);
13995 
13996 					/*
13997 					 * This part is tricky. The abort
13998 					 * failed and now the command could
13999 					 * be completing.  The cmd_state ==
14000 					 * FCP_PKT_ABORTING should save
14001 					 * us in fcp_cmd_callback. If we
14002 					 * are already aborting ignore the
14003 					 * command in fcp_cmd_callback.
14004 					 * Here we leave this packet for 20
14005 					 * sec to be aborted in the
14006 					 * fcp_watch thread.
14007 					 */
14008 					fcp_log(CE_WARN, pptr->port_dip,
14009 					    "!Abort failed after reset %s",
14010 					    msg);
14011 
14012 					cmd->cmd_timeout =
14013 					    fcp_watchdog_time +
14014 					    cmd->cmd_pkt->pkt_time +
14015 					    FCP_FAILED_DELAY;
14016 
14017 					cmd->cmd_fp_pkt->pkt_timeout =
14018 					    FCP_INVALID_TIMEOUT;
14019 					/*
14020 					 * This is a hack, cmd is put in the
14021 					 * overflow queue so that it can be
14022 					 * timed out finally
14023 					 */
14024 					cmd->cmd_flags |= CFLAG_IN_QUEUE;
14025 
14026 					mutex_enter(&pptr->port_pkt_mutex);
14027 					if (pptr->port_pkt_head) {
14028 						ASSERT(pptr->port_pkt_tail
14029 						    != NULL);
14030 						pptr->port_pkt_tail->cmd_next
14031 						    = cmd;
14032 						pptr->port_pkt_tail = cmd;
14033 					} else {
14034 						ASSERT(pptr->port_pkt_tail
14035 						    == NULL);
14036 						pptr->port_pkt_head =
14037 						    pptr->port_pkt_tail
14038 						    = cmd;
14039 					}
14040 					cmd->cmd_next = NULL;
14041 					mutex_exit(&pptr->port_pkt_mutex);
14042 				}
14043 				mutex_enter(&tlun->lun_mutex);
14044 				cmd = tlun->lun_pkt_head;
14045 			} else {
14046 				cmd = cmd->cmd_forw;
14047 			}
14048 		}
14049 		mutex_exit(&tlun->lun_mutex);
14050 
14051 		mutex_enter(&ttgt->tgt_mutex);
14052 		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14053 		mutex_exit(&ttgt->tgt_mutex);
14054 
14055 		mutex_enter(&pptr->port_mutex);
14056 		if (tgt_cnt != ttgt->tgt_change_cnt) {
14057 			mutex_exit(&pptr->port_mutex);
14058 			return;
14059 		} else {
14060 			mutex_exit(&pptr->port_mutex);
14061 		}
14062 	}
14063 }
14064 
14065 
14066 /*
14067  * unlink the soft state, returning the soft state found (if any)
14068  *
14069  * acquires and releases the global mutex
14070  */
14071 struct fcp_port *
14072 fcp_soft_state_unlink(struct fcp_port *pptr)
14073 {
14074 	struct fcp_port	*hptr;		/* ptr index */
14075 	struct fcp_port	*tptr;		/* prev hptr */
14076 
14077 	mutex_enter(&fcp_global_mutex);
14078 	for (hptr = fcp_port_head, tptr = NULL;
14079 	    hptr != NULL;
14080 	    tptr = hptr, hptr = hptr->port_next) {
14081 		if (hptr == pptr) {
14082 			/* we found a match -- remove this item */
14083 			if (tptr == NULL) {
14084 				/* we're at the head of the list */
14085 				fcp_port_head = hptr->port_next;
14086 			} else {
14087 				tptr->port_next = hptr->port_next;
14088 			}
14089 			break;			/* success */
14090 		}
14091 	}
14092 	if (fcp_port_head == NULL) {
14093 		fcp_cleanup_blacklist(&fcp_lun_blacklist);
14094 	}
14095 	mutex_exit(&fcp_global_mutex);
14096 	return (hptr);
14097 }
14098 
14099 
14100 /*
14101  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14102  * WWN and a LUN number
14103  */
14104 /* ARGSUSED */
14105 static struct fcp_lun *
14106 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14107 {
14108 	int hash;
14109 	struct fcp_tgt *ptgt;
14110 	struct fcp_lun *plun;
14111 
14112 	ASSERT(mutex_owned(&pptr->port_mutex));
14113 
14114 	hash = FCP_HASH(wwn);
14115 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14116 	    ptgt = ptgt->tgt_next) {
14117 		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14118 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
14119 			mutex_enter(&ptgt->tgt_mutex);
14120 			for (plun = ptgt->tgt_lun;
14121 			    plun != NULL;
14122 			    plun = plun->lun_next) {
14123 				if (plun->lun_num == lun) {
14124 					mutex_exit(&ptgt->tgt_mutex);
14125 					return (plun);
14126 				}
14127 			}
14128 			mutex_exit(&ptgt->tgt_mutex);
14129 			return (NULL);
14130 		}
14131 	}
14132 	return (NULL);
14133 }
14134 
14135 /*
14136  *     Function: fcp_prepare_pkt
14137  *
14138  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14139  *		 for fcp_start(). It binds the data or partially maps it.
14140  *		 Builds the FCP header and starts the initialization of the
14141  *		 Fibre Channel header.
14142  *
14143  *     Argument: *pptr		FCP port.
14144  *		 *cmd		FCP packet.
14145  *		 *plun		LUN the command will be sent to.
14146  *
14147  *	Context: User, Kernel and Interrupt context.
14148  */
14149 static void
14150 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14151     struct fcp_lun *plun)
14152 {
14153 	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
14154 	struct fcp_tgt		*ptgt = plun->lun_tgt;
14155 	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
14156 
14157 	ASSERT(cmd->cmd_pkt->pkt_comp ||
14158 	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14159 
14160 	if (cmd->cmd_pkt->pkt_numcookies) {
14161 		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14162 			fcmd->fcp_cntl.cntl_read_data = 1;
14163 			fcmd->fcp_cntl.cntl_write_data = 0;
14164 			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14165 		} else {
14166 			fcmd->fcp_cntl.cntl_read_data = 0;
14167 			fcmd->fcp_cntl.cntl_write_data = 1;
14168 			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14169 		}
14170 
14171 		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14172 
14173 		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14174 		ASSERT(fpkt->pkt_data_cookie_cnt <=
14175 		    pptr->port_data_dma_attr.dma_attr_sgllen);
14176 
14177 		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14178 
14179 		/* FCA needs pkt_datalen to be set */
14180 		fpkt->pkt_datalen = cmd->cmd_dmacount;
14181 		fcmd->fcp_data_len = cmd->cmd_dmacount;
14182 	} else {
14183 		fcmd->fcp_cntl.cntl_read_data = 0;
14184 		fcmd->fcp_cntl.cntl_write_data = 0;
14185 		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14186 		fpkt->pkt_datalen = 0;
14187 		fcmd->fcp_data_len = 0;
14188 	}
14189 
14190 	/* set up the Tagged Queuing type */
14191 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14192 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14193 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14194 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14195 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14196 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14197 	} else {
14198 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14199 	}
14200 
14201 	fcmd->fcp_ent_addr = plun->lun_addr;
14202 
14203 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14204 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14205 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14206 	} else {
14207 		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14208 	}
14209 
14210 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14211 	cmd->cmd_pkt->pkt_state = 0;
14212 	cmd->cmd_pkt->pkt_statistics = 0;
14213 	cmd->cmd_pkt->pkt_resid = 0;
14214 
14215 	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14216 
14217 	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14218 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14219 		fpkt->pkt_comp = NULL;
14220 	} else {
14221 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14222 		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14223 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14224 		}
14225 		fpkt->pkt_comp = fcp_cmd_callback;
14226 	}
14227 
14228 	mutex_enter(&pptr->port_mutex);
14229 	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14230 		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14231 	}
14232 	mutex_exit(&pptr->port_mutex);
14233 
14234 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14235 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14236 
14237 	/*
14238 	 * Save a few kernel cycles here
14239 	 */
14240 #ifndef	__lock_lint
14241 	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14242 #endif /* __lock_lint */
14243 }
14244 
14245 static void
14246 fcp_post_callback(struct fcp_pkt *cmd)
14247 {
14248 	scsi_hba_pkt_comp(cmd->cmd_pkt);
14249 }
14250 
14251 
14252 /*
14253  * called to do polled I/O by fcp_start()
14254  *
14255  * return a transport status value, i.e. TRAN_ACCECPT for success
14256  */
14257 static int
14258 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14259 {
14260 	int	rval;
14261 
14262 #ifdef	DEBUG
14263 	mutex_enter(&pptr->port_pkt_mutex);
14264 	pptr->port_npkts++;
14265 	mutex_exit(&pptr->port_pkt_mutex);
14266 #endif /* DEBUG */
14267 
14268 	if (cmd->cmd_fp_pkt->pkt_timeout) {
14269 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14270 	} else {
14271 		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14272 	}
14273 
14274 	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14275 
14276 	cmd->cmd_state = FCP_PKT_ISSUED;
14277 
14278 	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14279 
14280 #ifdef	DEBUG
14281 	mutex_enter(&pptr->port_pkt_mutex);
14282 	pptr->port_npkts--;
14283 	mutex_exit(&pptr->port_pkt_mutex);
14284 #endif /* DEBUG */
14285 
14286 	cmd->cmd_state = FCP_PKT_IDLE;
14287 
14288 	switch (rval) {
14289 	case FC_SUCCESS:
14290 		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14291 			fcp_complete_pkt(cmd->cmd_fp_pkt);
14292 			rval = TRAN_ACCEPT;
14293 		} else {
14294 			rval = TRAN_FATAL_ERROR;
14295 		}
14296 		break;
14297 
14298 	case FC_TRAN_BUSY:
14299 		rval = TRAN_BUSY;
14300 		cmd->cmd_pkt->pkt_resid = 0;
14301 		break;
14302 
14303 	case FC_BADPACKET:
14304 		rval = TRAN_BADPKT;
14305 		break;
14306 
14307 	default:
14308 		rval = TRAN_FATAL_ERROR;
14309 		break;
14310 	}
14311 
14312 	return (rval);
14313 }
14314 
14315 
14316 /*
14317  * called by some of the following transport-called routines to convert
14318  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14319  */
14320 static struct fcp_port *
14321 fcp_dip2port(dev_info_t *dip)
14322 {
14323 	int	instance;
14324 
14325 	instance = ddi_get_instance(dip);
14326 	return (ddi_get_soft_state(fcp_softstate, instance));
14327 }
14328 
14329 
14330 /*
14331  * called internally to return a LUN given a dip
14332  */
14333 struct fcp_lun *
14334 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14335 {
14336 	struct fcp_tgt *ptgt;
14337 	struct fcp_lun *plun;
14338 	int i;
14339 
14340 
14341 	ASSERT(mutex_owned(&pptr->port_mutex));
14342 
14343 	for (i = 0; i < FCP_NUM_HASH; i++) {
14344 		for (ptgt = pptr->port_tgt_hash_table[i];
14345 		    ptgt != NULL;
14346 		    ptgt = ptgt->tgt_next) {
14347 			mutex_enter(&ptgt->tgt_mutex);
14348 			for (plun = ptgt->tgt_lun; plun != NULL;
14349 			    plun = plun->lun_next) {
14350 				mutex_enter(&plun->lun_mutex);
14351 				if (plun->lun_cip == cip) {
14352 					mutex_exit(&plun->lun_mutex);
14353 					mutex_exit(&ptgt->tgt_mutex);
14354 					return (plun); /* match found */
14355 				}
14356 				mutex_exit(&plun->lun_mutex);
14357 			}
14358 			mutex_exit(&ptgt->tgt_mutex);
14359 		}
14360 	}
14361 	return (NULL);				/* no LUN found */
14362 }
14363 
14364 /*
14365  * pass an element to the hotplug list, kick the hotplug thread
14366  * and wait for the element to get processed by the hotplug thread.
14367  * on return the element is freed.
14368  *
14369  * return zero success and non-zero on failure
14370  *
14371  * acquires/releases the target mutex
14372  *
14373  */
14374 static int
14375 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14376     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14377 {
14378 	struct fcp_hp_elem	*elem;
14379 	int			rval;
14380 
14381 	mutex_enter(&plun->lun_tgt->tgt_mutex);
14382 	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14383 	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14384 		mutex_exit(&plun->lun_tgt->tgt_mutex);
14385 		fcp_log(CE_CONT, pptr->port_dip,
14386 		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14387 		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14388 		return (NDI_FAILURE);
14389 	}
14390 	mutex_exit(&plun->lun_tgt->tgt_mutex);
14391 	mutex_enter(&elem->mutex);
14392 	if (elem->wait) {
14393 		while (elem->wait) {
14394 			cv_wait(&elem->cv, &elem->mutex);
14395 		}
14396 	}
14397 	rval = (elem->result);
14398 	mutex_exit(&elem->mutex);
14399 	mutex_destroy(&elem->mutex);
14400 	cv_destroy(&elem->cv);
14401 	kmem_free(elem, sizeof (struct fcp_hp_elem));
14402 	return (rval);
14403 }
14404 
14405 /*
14406  * pass an element to the hotplug list, and then
14407  * kick the hotplug thread
14408  *
14409  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14410  *
14411  * acquires/releases the hotplug mutex
14412  *
14413  * called with the target mutex owned
14414  *
14415  * memory acquired in NOSLEEP mode
14416  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14417  *	 for the hp daemon to process the request and is responsible for
14418  *	 freeing the element
14419  */
14420 static struct fcp_hp_elem *
14421 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14422     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14423 {
14424 	struct fcp_hp_elem	*elem;
14425 	dev_info_t *pdip;
14426 
14427 	ASSERT(pptr != NULL);
14428 	ASSERT(plun != NULL);
14429 	ASSERT(plun->lun_tgt != NULL);
14430 	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14431 
14432 	/* create space for a hotplug element */
14433 	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14434 	    == NULL) {
14435 		fcp_log(CE_WARN, NULL,
14436 		    "!can't allocate memory for hotplug element");
14437 		return (NULL);
14438 	}
14439 
14440 	/* fill in hotplug element */
14441 	elem->port = pptr;
14442 	elem->lun = plun;
14443 	elem->cip = cip;
14444 	elem->old_lun_mpxio = plun->lun_mpxio;
14445 	elem->what = what;
14446 	elem->flags = flags;
14447 	elem->link_cnt = link_cnt;
14448 	elem->tgt_cnt = tgt_cnt;
14449 	elem->wait = wait;
14450 	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14451 	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14452 
14453 	/* schedule the hotplug task */
14454 	pdip = pptr->port_dip;
14455 	mutex_enter(&plun->lun_mutex);
14456 	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14457 		plun->lun_event_count++;
14458 		elem->event_cnt = plun->lun_event_count;
14459 	}
14460 	mutex_exit(&plun->lun_mutex);
14461 	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14462 	    (void *)elem, KM_NOSLEEP) == TASKQID_INVALID) {
14463 		mutex_enter(&plun->lun_mutex);
14464 		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14465 			plun->lun_event_count--;
14466 		}
14467 		mutex_exit(&plun->lun_mutex);
14468 		kmem_free(elem, sizeof (*elem));
14469 		return (0);
14470 	}
14471 
14472 	return (elem);
14473 }
14474 
14475 
14476 static void
14477 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14478 {
14479 	int			rval;
14480 	struct scsi_address	*ap;
14481 	struct fcp_lun	*plun;
14482 	struct fcp_tgt	*ptgt;
14483 	fc_packet_t	*fpkt;
14484 
14485 	ap = &cmd->cmd_pkt->pkt_address;
14486 	plun = ADDR2LUN(ap);
14487 	ptgt = plun->lun_tgt;
14488 
14489 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14490 
14491 	cmd->cmd_state = FCP_PKT_IDLE;
14492 
14493 	mutex_enter(&pptr->port_mutex);
14494 	mutex_enter(&ptgt->tgt_mutex);
14495 	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14496 	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14497 		fc_ulp_rscn_info_t *rscnp;
14498 
14499 		cmd->cmd_state = FCP_PKT_ISSUED;
14500 
14501 		/*
14502 		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14503 		 * originally NULL, hence we try to set it to the pd pointed
14504 		 * to by the SCSI device we're trying to get to.
14505 		 */
14506 
14507 		fpkt = cmd->cmd_fp_pkt;
14508 		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14509 			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14510 			/*
14511 			 * We need to notify the transport that we now have a
14512 			 * reference to the remote port handle.
14513 			 */
14514 			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14515 		}
14516 
14517 		mutex_exit(&ptgt->tgt_mutex);
14518 		mutex_exit(&pptr->port_mutex);
14519 
14520 		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14521 
14522 		/* prepare the packet */
14523 
14524 		fcp_prepare_pkt(pptr, cmd, plun);
14525 
14526 		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14527 		    pkt_ulp_rscn_infop;
14528 
14529 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14530 		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14531 
14532 		if (rscnp != NULL) {
14533 			rscnp->ulp_rscn_count =
14534 			    fc_ulp_get_rscn_count(pptr->
14535 			    port_fp_handle);
14536 		}
14537 
14538 		rval = fcp_transport(pptr->port_fp_handle,
14539 		    cmd->cmd_fp_pkt, 0);
14540 
14541 		if (rval == FC_SUCCESS) {
14542 			return;
14543 		}
14544 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14545 	} else {
14546 		mutex_exit(&ptgt->tgt_mutex);
14547 		mutex_exit(&pptr->port_mutex);
14548 	}
14549 
14550 	fcp_queue_pkt(pptr, cmd);
14551 }
14552 
14553 
14554 static void
14555 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14556 {
14557 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14558 
14559 	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14560 	cmd->cmd_state = FCP_PKT_IDLE;
14561 
14562 	cmd->cmd_pkt->pkt_reason = reason;
14563 	cmd->cmd_pkt->pkt_state = 0;
14564 	cmd->cmd_pkt->pkt_statistics = statistics;
14565 
14566 	fcp_post_callback(cmd);
14567 }
14568 
14569 /*
14570  *     Function: fcp_queue_pkt
14571  *
14572  *  Description: This function queues the packet passed by the caller into
14573  *		 the list of packets of the FCP port.
14574  *
14575  *     Argument: *pptr		FCP port.
14576  *		 *cmd		FCP packet to queue.
14577  *
14578  * Return Value: None
14579  *
14580  *	Context: User, Kernel and Interrupt context.
14581  */
14582 static void
14583 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14584 {
14585 	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == 0);
14586 
14587 	mutex_enter(&pptr->port_pkt_mutex);
14588 	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14589 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14590 	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14591 
14592 	/*
14593 	 * zero pkt_time means hang around for ever
14594 	 */
14595 	if (cmd->cmd_pkt->pkt_time) {
14596 		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14597 			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14598 		} else {
14599 			/*
14600 			 * Indicate the watch thread to fail the
14601 			 * command by setting it to highest value
14602 			 */
14603 			cmd->cmd_timeout = fcp_watchdog_time;
14604 			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14605 		}
14606 	}
14607 
14608 	if (pptr->port_pkt_head) {
14609 		ASSERT(pptr->port_pkt_tail != NULL);
14610 
14611 		pptr->port_pkt_tail->cmd_next = cmd;
14612 		pptr->port_pkt_tail = cmd;
14613 	} else {
14614 		ASSERT(pptr->port_pkt_tail == NULL);
14615 
14616 		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14617 	}
14618 	cmd->cmd_next = NULL;
14619 	mutex_exit(&pptr->port_pkt_mutex);
14620 }
14621 
14622 /*
14623  *     Function: fcp_update_targets
14624  *
14625  *  Description: This function applies the specified change of state to all
14626  *		 the targets listed.  The operation applied is 'set'.
14627  *
14628  *     Argument: *pptr		FCP port.
14629  *		 *dev_list	Array of fc_portmap_t structures.
14630  *		 count		Length of dev_list.
14631  *		 state		State bits to update.
14632  *		 cause		Reason for the update.
14633  *
14634  * Return Value: None
14635  *
14636  *	Context: User, Kernel and Interrupt context.
14637  *		 The mutex pptr->port_mutex must be held.
14638  */
14639 static void
14640 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14641     uint32_t count, uint32_t state, int cause)
14642 {
14643 	fc_portmap_t		*map_entry;
14644 	struct fcp_tgt	*ptgt;
14645 
14646 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14647 
14648 	while (count--) {
14649 		map_entry = &(dev_list[count]);
14650 		ptgt = fcp_lookup_target(pptr,
14651 		    (uchar_t *)&(map_entry->map_pwwn));
14652 		if (ptgt == NULL) {
14653 			continue;
14654 		}
14655 
14656 		mutex_enter(&ptgt->tgt_mutex);
14657 		ptgt->tgt_trace = 0;
14658 		ptgt->tgt_change_cnt++;
14659 		ptgt->tgt_statec_cause = cause;
14660 		ptgt->tgt_tmp_cnt = 1;
14661 		fcp_update_tgt_state(ptgt, FCP_SET, state);
14662 		mutex_exit(&ptgt->tgt_mutex);
14663 	}
14664 }
14665 
14666 static int
14667 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14668     int lcount, int tcount, int cause)
14669 {
14670 	int rval;
14671 
14672 	mutex_enter(&pptr->port_mutex);
14673 	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14674 	mutex_exit(&pptr->port_mutex);
14675 
14676 	return (rval);
14677 }
14678 
14679 
14680 static int
14681 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14682     int lcount, int tcount, int cause)
14683 {
14684 	int	finish_init = 0;
14685 	int	finish_tgt = 0;
14686 	int	do_finish_init = 0;
14687 	int	rval = FCP_NO_CHANGE;
14688 
14689 	if (cause == FCP_CAUSE_LINK_CHANGE ||
14690 	    cause == FCP_CAUSE_LINK_DOWN) {
14691 		do_finish_init = 1;
14692 	}
14693 
14694 	if (ptgt != NULL) {
14695 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14696 		    FCP_BUF_LEVEL_2, 0,
14697 		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14698 		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14699 		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14700 		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14701 		    ptgt->tgt_d_id, ptgt->tgt_done);
14702 
14703 		mutex_enter(&ptgt->tgt_mutex);
14704 
14705 		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14706 			rval = FCP_DEV_CHANGE;
14707 			if (do_finish_init && ptgt->tgt_done == 0) {
14708 				ptgt->tgt_done++;
14709 				finish_init = 1;
14710 			}
14711 		} else {
14712 			if (--ptgt->tgt_tmp_cnt <= 0) {
14713 				ptgt->tgt_tmp_cnt = 0;
14714 				finish_tgt = 1;
14715 
14716 				if (do_finish_init) {
14717 					finish_init = 1;
14718 				}
14719 			}
14720 		}
14721 		mutex_exit(&ptgt->tgt_mutex);
14722 	} else {
14723 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14724 		    FCP_BUF_LEVEL_2, 0,
14725 		    "Call Finish Init for NO target");
14726 
14727 		if (do_finish_init) {
14728 			finish_init = 1;
14729 		}
14730 	}
14731 
14732 	if (finish_tgt) {
14733 		ASSERT(ptgt != NULL);
14734 
14735 		mutex_enter(&ptgt->tgt_mutex);
14736 #ifdef	DEBUG
14737 		bzero(ptgt->tgt_tmp_cnt_stack,
14738 		    sizeof (ptgt->tgt_tmp_cnt_stack));
14739 
14740 		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14741 		    FCP_STACK_DEPTH);
14742 #endif /* DEBUG */
14743 		mutex_exit(&ptgt->tgt_mutex);
14744 
14745 		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14746 	}
14747 
14748 	if (finish_init && lcount == pptr->port_link_cnt) {
14749 		ASSERT(pptr->port_tmp_cnt > 0);
14750 		if (--pptr->port_tmp_cnt == 0) {
14751 			fcp_finish_init(pptr);
14752 		}
14753 	} else if (lcount != pptr->port_link_cnt) {
14754 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14755 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14756 		    "fcp_call_finish_init_held,1: state change occured"
14757 		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14758 	}
14759 
14760 	return (rval);
14761 }
14762 
14763 static void
14764 fcp_reconfigure_luns(void * tgt_handle)
14765 {
14766 	uint32_t		dev_cnt;
14767 	fc_portmap_t		*devlist;
14768 	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14769 	struct fcp_port		*pptr = ptgt->tgt_port;
14770 
14771 	/*
14772 	 * If the timer that fires this off got canceled too late, the
14773 	 * target could have been destroyed.
14774 	 */
14775 
14776 	if (ptgt->tgt_tid == NULL) {
14777 		return;
14778 	}
14779 
14780 	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14781 	if (devlist == NULL) {
14782 		fcp_log(CE_WARN, pptr->port_dip,
14783 		    "!fcp%d: failed to allocate for portmap",
14784 		    pptr->port_instance);
14785 		return;
14786 	}
14787 
14788 	dev_cnt = 1;
14789 	devlist->map_pd = ptgt->tgt_pd_handle;
14790 	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14791 	devlist->map_did.port_id = ptgt->tgt_d_id;
14792 
14793 	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14794 	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14795 
14796 	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14797 	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14798 	devlist->map_flags = 0;
14799 
14800 	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14801 	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14802 
14803 	/*
14804 	 * Clear the tgt_tid after no more references to
14805 	 * the fcp_tgt
14806 	 */
14807 	mutex_enter(&ptgt->tgt_mutex);
14808 	ptgt->tgt_tid = NULL;
14809 	mutex_exit(&ptgt->tgt_mutex);
14810 
14811 	kmem_free(devlist, sizeof (*devlist));
14812 }
14813 
14814 
14815 static void
14816 fcp_free_targets(struct fcp_port *pptr)
14817 {
14818 	int			i;
14819 	struct fcp_tgt	*ptgt;
14820 
14821 	mutex_enter(&pptr->port_mutex);
14822 	for (i = 0; i < FCP_NUM_HASH; i++) {
14823 		ptgt = pptr->port_tgt_hash_table[i];
14824 		while (ptgt != NULL) {
14825 			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14826 
14827 			fcp_free_target(ptgt);
14828 			ptgt = next_tgt;
14829 		}
14830 	}
14831 	mutex_exit(&pptr->port_mutex);
14832 }
14833 
14834 
14835 static void
14836 fcp_free_target(struct fcp_tgt *ptgt)
14837 {
14838 	struct fcp_lun	*plun;
14839 	timeout_id_t		tid;
14840 
14841 	mutex_enter(&ptgt->tgt_mutex);
14842 	tid = ptgt->tgt_tid;
14843 
14844 	/*
14845 	 * Cancel any pending timeouts for this target.
14846 	 */
14847 
14848 	if (tid != NULL) {
14849 		/*
14850 		 * Set tgt_tid to NULL first to avoid a race in the callback.
14851 		 * If tgt_tid is NULL, the callback will simply return.
14852 		 */
14853 		ptgt->tgt_tid = NULL;
14854 		mutex_exit(&ptgt->tgt_mutex);
14855 		(void) untimeout(tid);
14856 		mutex_enter(&ptgt->tgt_mutex);
14857 	}
14858 
14859 	plun = ptgt->tgt_lun;
14860 	while (plun != NULL) {
14861 		struct fcp_lun *next_lun = plun->lun_next;
14862 
14863 		fcp_dealloc_lun(plun);
14864 		plun = next_lun;
14865 	}
14866 
14867 	mutex_exit(&ptgt->tgt_mutex);
14868 	fcp_dealloc_tgt(ptgt);
14869 }
14870 
14871 /*
14872  *     Function: fcp_is_retryable
14873  *
14874  *  Description: Indicates if the internal packet is retryable.
14875  *
14876  *     Argument: *icmd		FCP internal packet.
14877  *
14878  * Return Value: 0	Not retryable
14879  *		 1	Retryable
14880  *
14881  *	Context: User, Kernel and Interrupt context
14882  */
14883 static int
14884 fcp_is_retryable(struct fcp_ipkt *icmd)
14885 {
14886 	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14887 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14888 		return (0);
14889 	}
14890 
14891 	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14892 	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14893 }
14894 
14895 /*
14896  *     Function: fcp_create_on_demand
14897  *
14898  *     Argument: *pptr		FCP port.
14899  *		 *pwwn		Port WWN.
14900  *
14901  * Return Value: 0	Success
14902  *		 EIO
14903  *		 ENOMEM
14904  *		 EBUSY
14905  *		 EINVAL
14906  *
14907  *	Context: User and Kernel context
14908  */
14909 static int
14910 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14911 {
14912 	int			wait_ms;
14913 	int			tcount;
14914 	int			lcount;
14915 	int			ret;
14916 	int			error;
14917 	int			rval = EIO;
14918 	int			ntries;
14919 	fc_portmap_t		*devlist;
14920 	opaque_t		pd;
14921 	struct fcp_lun		*plun;
14922 	struct fcp_tgt		*ptgt;
14923 	int			old_manual = 0;
14924 
14925 	/* Allocates the fc_portmap_t structure. */
14926 	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14927 
14928 	/*
14929 	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14930 	 * in the commented statement below:
14931 	 *
14932 	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14933 	 *
14934 	 * Below, the deadline for the discovery process is set.
14935 	 */
14936 	mutex_enter(&pptr->port_mutex);
14937 	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14938 	mutex_exit(&pptr->port_mutex);
14939 
14940 	/*
14941 	 * We try to find the remote port based on the WWN provided by the
14942 	 * caller.  We actually ask fp/fctl if it has it.
14943 	 */
14944 	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14945 	    (la_wwn_t *)pwwn, &error, 1);
14946 
14947 	if (pd == NULL) {
14948 		kmem_free(devlist, sizeof (*devlist));
14949 		return (rval);
14950 	}
14951 
14952 	/*
14953 	 * The remote port was found.  We ask fp/fctl to update our
14954 	 * fc_portmap_t structure.
14955 	 */
14956 	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14957 	    (la_wwn_t *)pwwn, devlist);
14958 	if (ret != FC_SUCCESS) {
14959 		kmem_free(devlist, sizeof (*devlist));
14960 		return (rval);
14961 	}
14962 
14963 	/*
14964 	 * The map flag field is set to indicates that the creation is being
14965 	 * done at the user request (Ioclt probably luxadm or cfgadm).
14966 	 */
14967 	devlist->map_type = PORT_DEVICE_USER_CREATE;
14968 
14969 	mutex_enter(&pptr->port_mutex);
14970 
14971 	/*
14972 	 * We check to see if fcp already has a target that describes the
14973 	 * device being created.  If not it is created.
14974 	 */
14975 	ptgt = fcp_lookup_target(pptr, pwwn);
14976 	if (ptgt == NULL) {
14977 		lcount = pptr->port_link_cnt;
14978 		mutex_exit(&pptr->port_mutex);
14979 
14980 		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14981 		if (ptgt == NULL) {
14982 			fcp_log(CE_WARN, pptr->port_dip,
14983 			    "!FC target allocation failed");
14984 			return (ENOMEM);
14985 		}
14986 
14987 		mutex_enter(&pptr->port_mutex);
14988 	}
14989 
14990 	mutex_enter(&ptgt->tgt_mutex);
14991 	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
14992 	ptgt->tgt_tmp_cnt = 1;
14993 	ptgt->tgt_device_created = 0;
14994 	/*
14995 	 * If fabric and auto config is set but the target was
14996 	 * manually unconfigured then reset to the manual_config_only to
14997 	 * 0 so the device will get configured.
14998 	 */
14999 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15000 	    fcp_enable_auto_configuration &&
15001 	    ptgt->tgt_manual_config_only == 1) {
15002 		old_manual = 1;
15003 		ptgt->tgt_manual_config_only = 0;
15004 	}
15005 	mutex_exit(&ptgt->tgt_mutex);
15006 
15007 	fcp_update_targets(pptr, devlist, 1,
15008 	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15009 
15010 	lcount = pptr->port_link_cnt;
15011 	tcount = ptgt->tgt_change_cnt;
15012 
15013 	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15014 	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15015 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15016 		    fcp_enable_auto_configuration && old_manual) {
15017 			mutex_enter(&ptgt->tgt_mutex);
15018 			ptgt->tgt_manual_config_only = 1;
15019 			mutex_exit(&ptgt->tgt_mutex);
15020 		}
15021 
15022 		if (pptr->port_link_cnt != lcount ||
15023 		    ptgt->tgt_change_cnt != tcount) {
15024 			rval = EBUSY;
15025 		}
15026 		mutex_exit(&pptr->port_mutex);
15027 
15028 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15029 		    FCP_BUF_LEVEL_3, 0,
15030 		    "fcp_create_on_demand: mapflags ptgt=%x, "
15031 		    "lcount=%x::port_link_cnt=%x, "
15032 		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
15033 		    ptgt, lcount, pptr->port_link_cnt,
15034 		    tcount, ptgt->tgt_change_cnt, rval);
15035 		return (rval);
15036 	}
15037 
15038 	/*
15039 	 * Due to lack of synchronization mechanisms, we perform
15040 	 * periodic monitoring of our request; Because requests
15041 	 * get dropped when another one supercedes (either because
15042 	 * of a link change or a target change), it is difficult to
15043 	 * provide a clean synchronization mechanism (such as a
15044 	 * semaphore or a conditional variable) without exhaustively
15045 	 * rewriting the mainline discovery code of this driver.
15046 	 */
15047 	wait_ms = 500;
15048 
15049 	ntries = fcp_max_target_retries;
15050 
15051 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15052 	    FCP_BUF_LEVEL_3, 0,
15053 	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15054 	    "lcount=%x::port_link_cnt=%x, "
15055 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15056 	    "tgt_tmp_cnt =%x",
15057 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15058 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15059 	    ptgt->tgt_tmp_cnt);
15060 
15061 	mutex_enter(&ptgt->tgt_mutex);
15062 	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15063 	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15064 		mutex_exit(&ptgt->tgt_mutex);
15065 		mutex_exit(&pptr->port_mutex);
15066 
15067 		delay(drv_usectohz(wait_ms * 1000));
15068 
15069 		mutex_enter(&pptr->port_mutex);
15070 		mutex_enter(&ptgt->tgt_mutex);
15071 	}
15072 
15073 
15074 	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15075 		rval = EBUSY;
15076 	} else {
15077 		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15078 		    FCP_TGT_NODE_PRESENT) {
15079 			rval = 0;
15080 		}
15081 	}
15082 
15083 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15084 	    FCP_BUF_LEVEL_3, 0,
15085 	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15086 	    "lcount=%x::port_link_cnt=%x, "
15087 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15088 	    "tgt_tmp_cnt =%x",
15089 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15090 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15091 	    ptgt->tgt_tmp_cnt);
15092 
15093 	if (rval) {
15094 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15095 		    fcp_enable_auto_configuration && old_manual) {
15096 			ptgt->tgt_manual_config_only = 1;
15097 		}
15098 		mutex_exit(&ptgt->tgt_mutex);
15099 		mutex_exit(&pptr->port_mutex);
15100 		kmem_free(devlist, sizeof (*devlist));
15101 
15102 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15103 		    FCP_BUF_LEVEL_3, 0,
15104 		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15105 		    "lcount=%x::port_link_cnt=%x, "
15106 		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15107 		    "tgt_device_created=%x, tgt D_ID=%x",
15108 		    ntries, ptgt, lcount, pptr->port_link_cnt,
15109 		    tcount, ptgt->tgt_change_cnt, rval,
15110 		    ptgt->tgt_device_created, ptgt->tgt_d_id);
15111 		return (rval);
15112 	}
15113 
15114 	if ((plun = ptgt->tgt_lun) != NULL) {
15115 		tcount = plun->lun_tgt->tgt_change_cnt;
15116 	} else {
15117 		rval = EINVAL;
15118 	}
15119 	lcount = pptr->port_link_cnt;
15120 
15121 	/*
15122 	 * Configuring the target with no LUNs will fail. We
15123 	 * should reset the node state so that it is not
15124 	 * automatically configured when the LUNs are added
15125 	 * to this target.
15126 	 */
15127 	if (ptgt->tgt_lun_cnt == 0) {
15128 		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15129 	}
15130 	mutex_exit(&ptgt->tgt_mutex);
15131 	mutex_exit(&pptr->port_mutex);
15132 
15133 	while (plun) {
15134 		child_info_t	*cip;
15135 
15136 		mutex_enter(&plun->lun_mutex);
15137 		cip = plun->lun_cip;
15138 		mutex_exit(&plun->lun_mutex);
15139 
15140 		mutex_enter(&ptgt->tgt_mutex);
15141 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15142 			mutex_exit(&ptgt->tgt_mutex);
15143 
15144 			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15145 			    FCP_ONLINE, lcount, tcount,
15146 			    NDI_ONLINE_ATTACH);
15147 			if (rval != NDI_SUCCESS) {
15148 				FCP_TRACE(fcp_logq,
15149 				    pptr->port_instbuf, fcp_trace,
15150 				    FCP_BUF_LEVEL_3, 0,
15151 				    "fcp_create_on_demand: "
15152 				    "pass_to_hp_and_wait failed "
15153 				    "rval=%x", rval);
15154 				rval = EIO;
15155 			} else {
15156 				mutex_enter(&LUN_TGT->tgt_mutex);
15157 				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15158 				    FCP_LUN_BUSY);
15159 				mutex_exit(&LUN_TGT->tgt_mutex);
15160 			}
15161 			mutex_enter(&ptgt->tgt_mutex);
15162 		}
15163 
15164 		plun = plun->lun_next;
15165 		mutex_exit(&ptgt->tgt_mutex);
15166 	}
15167 
15168 	kmem_free(devlist, sizeof (*devlist));
15169 
15170 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15171 	    fcp_enable_auto_configuration && old_manual) {
15172 		mutex_enter(&ptgt->tgt_mutex);
15173 		/* if successful then set manual to 0 */
15174 		if (rval == 0) {
15175 			ptgt->tgt_manual_config_only = 0;
15176 		} else {
15177 			/* reset to 1 so the user has to do the config */
15178 			ptgt->tgt_manual_config_only = 1;
15179 		}
15180 		mutex_exit(&ptgt->tgt_mutex);
15181 	}
15182 
15183 	return (rval);
15184 }
15185 
15186 
15187 static void
15188 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15189 {
15190 	int		count;
15191 	uchar_t		byte;
15192 
15193 	count = 0;
15194 	while (*string) {
15195 		byte = FCP_ATOB(*string); string++;
15196 		byte = byte << 4 | FCP_ATOB(*string); string++;
15197 		bytes[count++] = byte;
15198 
15199 		if (count >= byte_len) {
15200 			break;
15201 		}
15202 	}
15203 }
15204 
15205 static void
15206 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15207 {
15208 	int		i;
15209 
15210 	for (i = 0; i < FC_WWN_SIZE; i++) {
15211 		(void) sprintf(string + (i * 2),
15212 		    "%02x", wwn[i]);
15213 	}
15214 
15215 }
15216 
15217 static void
15218 fcp_print_error(fc_packet_t *fpkt)
15219 {
15220 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15221 	    fpkt->pkt_ulp_private;
15222 	struct fcp_port	*pptr;
15223 	struct fcp_tgt	*ptgt;
15224 	struct fcp_lun	*plun;
15225 	caddr_t			buf;
15226 	int			scsi_cmd = 0;
15227 
15228 	ptgt = icmd->ipkt_tgt;
15229 	plun = icmd->ipkt_lun;
15230 	pptr = ptgt->tgt_port;
15231 
15232 	buf = kmem_zalloc(256, KM_NOSLEEP);
15233 	if (buf == NULL) {
15234 		return;
15235 	}
15236 
15237 	switch (icmd->ipkt_opcode) {
15238 	case SCMD_REPORT_LUN:
15239 		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15240 		    " lun=0x%%x failed");
15241 		scsi_cmd++;
15242 		break;
15243 
15244 	case SCMD_INQUIRY_PAGE83:
15245 		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15246 		    " lun=0x%%x failed");
15247 		scsi_cmd++;
15248 		break;
15249 
15250 	case SCMD_INQUIRY:
15251 		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15252 		    " lun=0x%%x failed");
15253 		scsi_cmd++;
15254 		break;
15255 
15256 	case LA_ELS_PLOGI:
15257 		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15258 		break;
15259 
15260 	case LA_ELS_PRLI:
15261 		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15262 		break;
15263 	}
15264 
15265 	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15266 		struct fcp_rsp		response, *rsp;
15267 		uchar_t			asc, ascq;
15268 		caddr_t			sense_key = NULL;
15269 		struct fcp_rsp_info	fcp_rsp_err, *bep;
15270 
15271 		if (icmd->ipkt_nodma) {
15272 			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15273 			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15274 			    sizeof (struct fcp_rsp));
15275 		} else {
15276 			rsp = &response;
15277 			bep = &fcp_rsp_err;
15278 
15279 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15280 			    sizeof (struct fcp_rsp));
15281 
15282 			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15283 			    bep, fpkt->pkt_resp_acc,
15284 			    sizeof (struct fcp_rsp_info));
15285 		}
15286 
15287 
15288 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15289 			(void) sprintf(buf + strlen(buf),
15290 			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15291 			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15292 			    " senselen=%%x. Giving up");
15293 
15294 			fcp_log(CE_WARN, pptr->port_dip, buf,
15295 			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15296 			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15297 			    rsp->fcp_u.fcp_status.reserved_1,
15298 			    rsp->fcp_response_len, rsp->fcp_sense_len);
15299 
15300 			kmem_free(buf, 256);
15301 			return;
15302 		}
15303 
15304 		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15305 		    bep->rsp_code != FCP_NO_FAILURE) {
15306 			(void) sprintf(buf + strlen(buf),
15307 			    " FCP Response code = 0x%x", bep->rsp_code);
15308 		}
15309 
15310 		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15311 			struct scsi_extended_sense sense_info, *sense_ptr;
15312 
15313 			if (icmd->ipkt_nodma) {
15314 				sense_ptr = (struct scsi_extended_sense *)
15315 				    ((caddr_t)fpkt->pkt_resp +
15316 				    sizeof (struct fcp_rsp) +
15317 				    rsp->fcp_response_len);
15318 			} else {
15319 				sense_ptr = &sense_info;
15320 
15321 				FCP_CP_IN(fpkt->pkt_resp +
15322 				    sizeof (struct fcp_rsp) +
15323 				    rsp->fcp_response_len, &sense_info,
15324 				    fpkt->pkt_resp_acc,
15325 				    sizeof (struct scsi_extended_sense));
15326 			}
15327 
15328 			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15329 			    NUM_IMPL_SENSE_KEYS) {
15330 				sense_key = sense_keys[sense_ptr->es_key];
15331 			} else {
15332 				sense_key = "Undefined";
15333 			}
15334 
15335 			asc = sense_ptr->es_add_code;
15336 			ascq = sense_ptr->es_qual_code;
15337 
15338 			(void) sprintf(buf + strlen(buf),
15339 			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15340 			    " Giving up");
15341 
15342 			fcp_log(CE_WARN, pptr->port_dip, buf,
15343 			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15344 			    asc, ascq);
15345 		} else {
15346 			(void) sprintf(buf + strlen(buf),
15347 			    " : SCSI status=%%x. Giving up");
15348 
15349 			fcp_log(CE_WARN, pptr->port_dip, buf,
15350 			    ptgt->tgt_d_id, plun->lun_num,
15351 			    rsp->fcp_u.fcp_status.scsi_status);
15352 		}
15353 	} else {
15354 		caddr_t state, reason, action, expln;
15355 
15356 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15357 		    &action, &expln);
15358 
15359 		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15360 		    " Reason:%%s. Giving up");
15361 
15362 		if (scsi_cmd) {
15363 			fcp_log(CE_WARN, pptr->port_dip, buf,
15364 			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15365 		} else {
15366 			fcp_log(CE_WARN, pptr->port_dip, buf,
15367 			    ptgt->tgt_d_id, state, reason);
15368 		}
15369 	}
15370 
15371 	kmem_free(buf, 256);
15372 }
15373 
15374 
15375 static int
15376 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15377     struct fcp_ipkt *icmd, int rval, caddr_t op)
15378 {
15379 	int	ret = DDI_FAILURE;
15380 	char	*error;
15381 
15382 	switch (rval) {
15383 	case FC_DEVICE_BUSY_NEW_RSCN:
15384 		/*
15385 		 * This means that there was a new RSCN that the transport
15386 		 * knows about (which the ULP *may* know about too) but the
15387 		 * pkt that was sent down was related to an older RSCN. So, we
15388 		 * are just going to reset the retry count and deadline and
15389 		 * continue to retry. The idea is that transport is currently
15390 		 * working on the new RSCN and will soon let the ULPs know
15391 		 * about it and when it does the existing logic will kick in
15392 		 * where it will change the tcount to indicate that something
15393 		 * changed on the target. So, rediscovery will start and there
15394 		 * will not be an infinite retry.
15395 		 *
15396 		 * For a full flow of how the RSCN info is transferred back and
15397 		 * forth, see fp.c
15398 		 */
15399 		icmd->ipkt_retries = 0;
15400 		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15401 		    FCP_ICMD_DEADLINE;
15402 
15403 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15404 		    FCP_BUF_LEVEL_3, 0,
15405 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15406 		    rval, ptgt->tgt_d_id);
15407 		/* FALLTHROUGH */
15408 
15409 	case FC_STATEC_BUSY:
15410 	case FC_DEVICE_BUSY:
15411 	case FC_PBUSY:
15412 	case FC_FBUSY:
15413 	case FC_TRAN_BUSY:
15414 	case FC_OFFLINE:
15415 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15416 		    FCP_BUF_LEVEL_3, 0,
15417 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15418 		    rval, ptgt->tgt_d_id);
15419 		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15420 		    fcp_is_retryable(icmd)) {
15421 			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15422 			ret = DDI_SUCCESS;
15423 		}
15424 		break;
15425 
15426 	case FC_LOGINREQ:
15427 		/*
15428 		 * FC_LOGINREQ used to be handled just like all the cases
15429 		 * above. It has been changed to handled a PRLI that fails
15430 		 * with FC_LOGINREQ different than other ipkts that fail
15431 		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15432 		 * a simple matter to turn it into a PLOGI instead, so that's
15433 		 * exactly what we do here.
15434 		 */
15435 		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15436 			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15437 			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15438 			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15439 		} else {
15440 			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15441 			    FCP_BUF_LEVEL_3, 0,
15442 			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15443 			    rval, ptgt->tgt_d_id);
15444 			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15445 			    fcp_is_retryable(icmd)) {
15446 				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15447 				ret = DDI_SUCCESS;
15448 			}
15449 		}
15450 		break;
15451 
15452 	default:
15453 		mutex_enter(&pptr->port_mutex);
15454 		mutex_enter(&ptgt->tgt_mutex);
15455 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15456 			mutex_exit(&ptgt->tgt_mutex);
15457 			mutex_exit(&pptr->port_mutex);
15458 
15459 			(void) fc_ulp_error(rval, &error);
15460 			fcp_log(CE_WARN, pptr->port_dip,
15461 			    "!Failed to send %s to D_ID=%x error=%s",
15462 			    op, ptgt->tgt_d_id, error);
15463 		} else {
15464 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15465 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15466 			    "fcp_handle_ipkt_errors,1: state change occured"
15467 			    " for D_ID=0x%x", ptgt->tgt_d_id);
15468 			mutex_exit(&ptgt->tgt_mutex);
15469 			mutex_exit(&pptr->port_mutex);
15470 		}
15471 		break;
15472 	}
15473 
15474 	return (ret);
15475 }
15476 
15477 
15478 /*
15479  * Check of outstanding commands on any LUN for this target
15480  */
15481 static int
15482 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15483 {
15484 	struct	fcp_lun	*plun;
15485 	struct	fcp_pkt	*cmd;
15486 
15487 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15488 		mutex_enter(&plun->lun_mutex);
15489 		for (cmd = plun->lun_pkt_head; cmd != NULL;
15490 		    cmd = cmd->cmd_forw) {
15491 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15492 				mutex_exit(&plun->lun_mutex);
15493 				return (FC_SUCCESS);
15494 			}
15495 		}
15496 		mutex_exit(&plun->lun_mutex);
15497 	}
15498 
15499 	return (FC_FAILURE);
15500 }
15501 
15502 static fc_portmap_t *
15503 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15504 {
15505 	int			i;
15506 	fc_portmap_t		*devlist;
15507 	fc_portmap_t		*devptr = NULL;
15508 	struct fcp_tgt	*ptgt;
15509 
15510 	mutex_enter(&pptr->port_mutex);
15511 	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15512 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15513 		    ptgt = ptgt->tgt_next) {
15514 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15515 				++*dev_cnt;
15516 			}
15517 		}
15518 	}
15519 
15520 	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15521 	    KM_NOSLEEP);
15522 	if (devlist == NULL) {
15523 		mutex_exit(&pptr->port_mutex);
15524 		fcp_log(CE_WARN, pptr->port_dip,
15525 		    "!fcp%d: failed to allocate for portmap for construct map",
15526 		    pptr->port_instance);
15527 		return (devptr);
15528 	}
15529 
15530 	for (i = 0; i < FCP_NUM_HASH; i++) {
15531 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15532 		    ptgt = ptgt->tgt_next) {
15533 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15534 				int ret;
15535 
15536 				ret = fc_ulp_pwwn_to_portmap(
15537 				    pptr->port_fp_handle,
15538 				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15539 				    devlist);
15540 
15541 				if (ret == FC_SUCCESS) {
15542 					devlist++;
15543 					continue;
15544 				}
15545 
15546 				devlist->map_pd = NULL;
15547 				devlist->map_did.port_id = ptgt->tgt_d_id;
15548 				devlist->map_hard_addr.hard_addr =
15549 				    ptgt->tgt_hard_addr;
15550 
15551 				devlist->map_state = PORT_DEVICE_INVALID;
15552 				devlist->map_type = PORT_DEVICE_OLD;
15553 
15554 				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15555 				    &devlist->map_nwwn, FC_WWN_SIZE);
15556 
15557 				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15558 				    &devlist->map_pwwn, FC_WWN_SIZE);
15559 
15560 				devlist++;
15561 			}
15562 		}
15563 	}
15564 
15565 	mutex_exit(&pptr->port_mutex);
15566 
15567 	return (devptr);
15568 }
15569 /*
15570  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15571  */
15572 static void
15573 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15574 {
15575 	int i;
15576 	struct fcp_tgt	*ptgt;
15577 	struct fcp_lun	*plun;
15578 
15579 	for (i = 0; i < FCP_NUM_HASH; i++) {
15580 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15581 		    ptgt = ptgt->tgt_next) {
15582 			mutex_enter(&ptgt->tgt_mutex);
15583 			for (plun = ptgt->tgt_lun; plun != NULL;
15584 			    plun = plun->lun_next) {
15585 				if (plun->lun_mpxio &&
15586 				    plun->lun_state & FCP_LUN_BUSY) {
15587 					if (!fcp_pass_to_hp(pptr, plun,
15588 					    plun->lun_cip,
15589 					    FCP_MPXIO_PATH_SET_BUSY,
15590 					    pptr->port_link_cnt,
15591 					    ptgt->tgt_change_cnt, 0, 0)) {
15592 						FCP_TRACE(fcp_logq,
15593 						    pptr->port_instbuf,
15594 						    fcp_trace,
15595 						    FCP_BUF_LEVEL_2, 0,
15596 						    "path_verifybusy: "
15597 						    "disable lun %p failed!",
15598 						    plun);
15599 					}
15600 				}
15601 			}
15602 			mutex_exit(&ptgt->tgt_mutex);
15603 		}
15604 	}
15605 }
15606 
15607 static int
15608 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15609 {
15610 	dev_info_t		*cdip = NULL;
15611 	dev_info_t		*pdip = NULL;
15612 
15613 	ASSERT(plun);
15614 
15615 	mutex_enter(&plun->lun_mutex);
15616 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15617 		mutex_exit(&plun->lun_mutex);
15618 		return (NDI_FAILURE);
15619 	}
15620 	mutex_exit(&plun->lun_mutex);
15621 	cdip = mdi_pi_get_client(PIP(cip));
15622 	pdip = mdi_pi_get_phci(PIP(cip));
15623 
15624 	ASSERT(cdip != NULL);
15625 	ASSERT(pdip != NULL);
15626 
15627 	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15628 		/* LUN ready for IO */
15629 		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15630 	} else {
15631 		/* LUN busy to accept IO */
15632 		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15633 	}
15634 	return (NDI_SUCCESS);
15635 }
15636 
15637 /*
15638  * Caller must free the returned string of MAXPATHLEN len
15639  * If the device is offline (-1 instance number) NULL
15640  * will be returned.
15641  */
15642 static char *
15643 fcp_get_lun_path(struct fcp_lun *plun)
15644 {
15645 	dev_info_t	*dip = NULL;
15646 	char		*path = NULL;
15647 	mdi_pathinfo_t	*pip = NULL;
15648 
15649 	if (plun == NULL) {
15650 		return (NULL);
15651 	}
15652 
15653 	mutex_enter(&plun->lun_mutex);
15654 	if (plun->lun_mpxio == 0) {
15655 		dip = DIP(plun->lun_cip);
15656 		mutex_exit(&plun->lun_mutex);
15657 	} else {
15658 		/*
15659 		 * lun_cip must be accessed with lun_mutex held. Here
15660 		 * plun->lun_cip either points to a valid node or it is NULL.
15661 		 * Make a copy so that we can release lun_mutex.
15662 		 */
15663 		pip = PIP(plun->lun_cip);
15664 
15665 		/*
15666 		 * Increase ref count on the path so that we can release
15667 		 * lun_mutex and still be sure that the pathinfo node (and thus
15668 		 * also the client) is not deallocated. If pip is NULL, this
15669 		 * has no effect.
15670 		 */
15671 		mdi_hold_path(pip);
15672 
15673 		mutex_exit(&plun->lun_mutex);
15674 
15675 		/* Get the client. If pip is NULL, we get NULL. */
15676 		dip = mdi_pi_get_client(pip);
15677 	}
15678 
15679 	if (dip == NULL)
15680 		goto out;
15681 	if (ddi_get_instance(dip) < 0)
15682 		goto out;
15683 
15684 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15685 	if (path == NULL)
15686 		goto out;
15687 
15688 	(void) ddi_pathname(dip, path);
15689 
15690 	/* Clean up. */
15691 out:
15692 	if (pip != NULL)
15693 		mdi_rele_path(pip);
15694 
15695 	/*
15696 	 * In reality, the user wants a fully valid path (one they can open)
15697 	 * but this string is lacking the mount point, and the minor node.
15698 	 * It would be nice if we could "figure these out" somehow
15699 	 * and fill them in.  Otherwise, the userland code has to understand
15700 	 * driver specific details of which minor node is the "best" or
15701 	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15702 	 * which tape doesn't rewind)
15703 	 */
15704 	return (path);
15705 }
15706 
15707 static int
15708 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15709     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15710 {
15711 	int64_t reset_delay;
15712 	int rval, retry = 0;
15713 	struct fcp_port *pptr = fcp_dip2port(parent);
15714 
15715 	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15716 	    (ddi_get_lbolt64() - pptr->port_attach_time);
15717 	if (reset_delay < 0) {
15718 		reset_delay = 0;
15719 	}
15720 
15721 	if (fcp_bus_config_debug) {
15722 		flag |= NDI_DEVI_DEBUG;
15723 	}
15724 
15725 	switch (op) {
15726 	case BUS_CONFIG_ONE:
15727 		/*
15728 		 * Retry the command since we need to ensure
15729 		 * the fabric devices are available for root
15730 		 */
15731 		while (retry++ < fcp_max_bus_config_retries) {
15732 			rval =	(ndi_busop_bus_config(parent,
15733 			    flag | NDI_MDI_FALLBACK, op,
15734 			    arg, childp, (clock_t)reset_delay));
15735 			if (rval == 0) {
15736 				return (rval);
15737 			}
15738 		}
15739 
15740 		/*
15741 		 * drain taskq to make sure nodes are created and then
15742 		 * try again.
15743 		 */
15744 		taskq_wait(DEVI(parent)->devi_taskq);
15745 		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15746 		    op, arg, childp, 0));
15747 
15748 	case BUS_CONFIG_DRIVER:
15749 	case BUS_CONFIG_ALL: {
15750 		/*
15751 		 * delay till all devices report in (port_tmp_cnt == 0)
15752 		 * or FCP_INIT_WAIT_TIMEOUT
15753 		 */
15754 		mutex_enter(&pptr->port_mutex);
15755 		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15756 			(void) cv_timedwait(&pptr->port_config_cv,
15757 			    &pptr->port_mutex,
15758 			    ddi_get_lbolt() + (clock_t)reset_delay);
15759 			reset_delay =
15760 			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15761 			    (ddi_get_lbolt64() - pptr->port_attach_time);
15762 		}
15763 		mutex_exit(&pptr->port_mutex);
15764 		/* drain taskq to make sure nodes are created */
15765 		taskq_wait(DEVI(parent)->devi_taskq);
15766 		return (ndi_busop_bus_config(parent, flag, op,
15767 		    arg, childp, 0));
15768 	}
15769 
15770 	default:
15771 		return (NDI_FAILURE);
15772 	}
15773 	/*NOTREACHED*/
15774 }
15775 
15776 static int
15777 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15778     ddi_bus_config_op_t op, void *arg)
15779 {
15780 	if (fcp_bus_config_debug) {
15781 		flag |= NDI_DEVI_DEBUG;
15782 	}
15783 
15784 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15785 }
15786 
15787 
15788 /*
15789  * Routine to copy GUID into the lun structure.
15790  * returns 0 if copy was successful and 1 if encountered a
15791  * failure and did not copy the guid.
15792  */
15793 static int
15794 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15795 {
15796 
15797 	int retval = 0;
15798 
15799 	/* add one for the null terminator */
15800 	const unsigned int len = strlen(guidp) + 1;
15801 
15802 	if ((guidp == NULL) || (plun == NULL)) {
15803 		return (1);
15804 	}
15805 
15806 	/*
15807 	 * if the plun->lun_guid already has been allocated,
15808 	 * then check the size. if the size is exact, reuse
15809 	 * it....if not free it an allocate the required size.
15810 	 * The reallocation should NOT typically happen
15811 	 * unless the GUIDs reported changes between passes.
15812 	 * We free up and alloc again even if the
15813 	 * size was more than required. This is due to the
15814 	 * fact that the field lun_guid_size - serves
15815 	 * dual role of indicating the size of the wwn
15816 	 * size and ALSO the allocation size.
15817 	 */
15818 	if (plun->lun_guid) {
15819 		if (plun->lun_guid_size != len) {
15820 			/*
15821 			 * free the allocated memory and
15822 			 * initialize the field
15823 			 * lun_guid_size to 0.
15824 			 */
15825 			kmem_free(plun->lun_guid, plun->lun_guid_size);
15826 			plun->lun_guid = NULL;
15827 			plun->lun_guid_size = 0;
15828 		}
15829 	}
15830 	/*
15831 	 * alloc only if not already done.
15832 	 */
15833 	if (plun->lun_guid == NULL) {
15834 		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15835 		if (plun->lun_guid == NULL) {
15836 			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15837 			    "Unable to allocate"
15838 			    "Memory for GUID!!! size %d", len);
15839 			retval = 1;
15840 		} else {
15841 			plun->lun_guid_size = len;
15842 		}
15843 	}
15844 	if (plun->lun_guid) {
15845 		/*
15846 		 * now copy the GUID
15847 		 */
15848 		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15849 	}
15850 	return (retval);
15851 }
15852 
15853 /*
15854  * fcp_reconfig_wait
15855  *
15856  * Wait for a rediscovery/reconfiguration to complete before continuing.
15857  */
15858 
15859 static void
15860 fcp_reconfig_wait(struct fcp_port *pptr)
15861 {
15862 	clock_t		reconfig_start, wait_timeout;
15863 
15864 	/*
15865 	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15866 	 * reconfiguration in progress.
15867 	 */
15868 
15869 	mutex_enter(&pptr->port_mutex);
15870 	if (pptr->port_tmp_cnt == 0) {
15871 		mutex_exit(&pptr->port_mutex);
15872 		return;
15873 	}
15874 	mutex_exit(&pptr->port_mutex);
15875 
15876 	/*
15877 	 * If we cause a reconfig by raising power, delay until all devices
15878 	 * report in (port_tmp_cnt returns to 0)
15879 	 */
15880 
15881 	reconfig_start = ddi_get_lbolt();
15882 	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15883 
15884 	mutex_enter(&pptr->port_mutex);
15885 
15886 	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15887 	    pptr->port_tmp_cnt) {
15888 
15889 		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15890 		    reconfig_start + wait_timeout);
15891 	}
15892 
15893 	mutex_exit(&pptr->port_mutex);
15894 
15895 	/*
15896 	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15897 	 * we want may still be ok.  If not, it will error out later
15898 	 */
15899 }
15900 
15901 /*
15902  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15903  * We rely on the fcp_global_mutex to provide protection against changes to
15904  * the fcp_lun_blacklist.
15905  *
15906  * You can describe a list of target port WWNs and LUN numbers which will
15907  * not be configured. LUN numbers will be interpreted as decimal. White
15908  * spaces and ',' can be used in the list of LUN numbers.
15909  *
15910  * To prevent LUNs 1 and 2 from being configured for target
15911  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15912  *
15913  * pwwn-lun-blacklist=
15914  * "510000f010fd92a1,1,2",
15915  * "510000e012079df1,1,2";
15916  */
15917 static void
15918 fcp_read_blacklist(dev_info_t *dip,
15919     struct fcp_black_list_entry **pplun_blacklist)
15920 {
15921 	char **prop_array	= NULL;
15922 	char *curr_pwwn		= NULL;
15923 	char *curr_lun		= NULL;
15924 	uint32_t prop_item	= 0;
15925 	int idx			= 0;
15926 	int len			= 0;
15927 
15928 	ASSERT(mutex_owned(&fcp_global_mutex));
15929 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15930 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15931 	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15932 		return;
15933 	}
15934 
15935 	for (idx = 0; idx < prop_item; idx++) {
15936 
15937 		curr_pwwn = prop_array[idx];
15938 		while (*curr_pwwn == ' ') {
15939 			curr_pwwn++;
15940 		}
15941 		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15942 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15943 			    ", please check.", curr_pwwn);
15944 			continue;
15945 		}
15946 		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15947 		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15948 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15949 			    ", please check.", curr_pwwn);
15950 			continue;
15951 		}
15952 		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15953 			if (isxdigit(curr_pwwn[len]) != TRUE) {
15954 				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15955 				    "blacklist, please check.", curr_pwwn);
15956 				break;
15957 			}
15958 		}
15959 		if (len != sizeof (la_wwn_t) * 2) {
15960 			continue;
15961 		}
15962 
15963 		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15964 		*(curr_lun - 1) = '\0';
15965 		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15966 	}
15967 
15968 	ddi_prop_free(prop_array);
15969 }
15970 
15971 /*
15972  * Get the masking info about one remote target port designated by wwn.
15973  * Lun ids could be separated by ',' or white spaces.
15974  */
15975 static void
15976 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15977     struct fcp_black_list_entry **pplun_blacklist)
15978 {
15979 	int		idx			= 0;
15980 	uint32_t	offset			= 0;
15981 	unsigned long	lun_id			= 0;
15982 	char		lunid_buf[16];
15983 	char		*pend			= NULL;
15984 	int		illegal_digit		= 0;
15985 
15986 	while (offset < strlen(curr_lun)) {
15987 		while ((curr_lun[offset + idx] != ',') &&
15988 		    (curr_lun[offset + idx] != '\0') &&
15989 		    (curr_lun[offset + idx] != ' ')) {
15990 			if (isdigit(curr_lun[offset + idx]) == 0) {
15991 				illegal_digit++;
15992 			}
15993 			idx++;
15994 		}
15995 		if (illegal_digit > 0) {
15996 			offset += (idx+1);	/* To the start of next lun */
15997 			idx = 0;
15998 			illegal_digit = 0;
15999 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16000 			    "the blacklist, please check digits.",
16001 			    curr_lun, curr_pwwn);
16002 			continue;
16003 		}
16004 		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16005 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16006 			    "the blacklist, please check the length of LUN#.",
16007 			    curr_lun, curr_pwwn);
16008 			break;
16009 		}
16010 		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
16011 			offset++;
16012 			continue;
16013 		}
16014 
16015 		bcopy(curr_lun + offset, lunid_buf, idx);
16016 		lunid_buf[idx] = '\0';
16017 		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16018 			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16019 		} else {
16020 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16021 			    "the blacklist, please check %s.",
16022 			    curr_lun, curr_pwwn, lunid_buf);
16023 		}
16024 		offset += (idx+1);	/* To the start of next lun */
16025 		idx = 0;
16026 	}
16027 }
16028 
16029 /*
16030  * Add one masking record
16031  */
16032 static void
16033 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16034     struct fcp_black_list_entry **pplun_blacklist)
16035 {
16036 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16037 	struct fcp_black_list_entry	*new_entry	= NULL;
16038 	la_wwn_t			wwn;
16039 
16040 	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16041 	while (tmp_entry) {
16042 		if ((bcmp(&tmp_entry->wwn, &wwn,
16043 		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16044 			return;
16045 		}
16046 
16047 		tmp_entry = tmp_entry->next;
16048 	}
16049 
16050 	/* add to black list */
16051 	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16052 	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16053 	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16054 	new_entry->lun = lun_id;
16055 	new_entry->masked = 0;
16056 	new_entry->next = *pplun_blacklist;
16057 	*pplun_blacklist = new_entry;
16058 }
16059 
16060 /*
16061  * Check if we should mask the specified lun of this fcp_tgt
16062  */
16063 static int
16064 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id)
16065 {
16066 	struct fcp_black_list_entry *remote_port;
16067 
16068 	remote_port = fcp_lun_blacklist;
16069 	while (remote_port != NULL) {
16070 		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16071 			if (remote_port->lun == lun_id) {
16072 				remote_port->masked++;
16073 				if (remote_port->masked == 1) {
16074 					fcp_log(CE_NOTE, NULL, "LUN %d of port "
16075 					    "%02x%02x%02x%02x%02x%02x%02x%02x "
16076 					    "is masked due to black listing.\n",
16077 					    lun_id, wwn->raw_wwn[0],
16078 					    wwn->raw_wwn[1], wwn->raw_wwn[2],
16079 					    wwn->raw_wwn[3], wwn->raw_wwn[4],
16080 					    wwn->raw_wwn[5], wwn->raw_wwn[6],
16081 					    wwn->raw_wwn[7]);
16082 				}
16083 				return (TRUE);
16084 			}
16085 		}
16086 		remote_port = remote_port->next;
16087 	}
16088 	return (FALSE);
16089 }
16090 
16091 /*
16092  * Release all allocated resources
16093  */
16094 static void
16095 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist)
16096 {
16097 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16098 	struct fcp_black_list_entry	*current_entry	= NULL;
16099 
16100 	ASSERT(mutex_owned(&fcp_global_mutex));
16101 	/*
16102 	 * Traverse all luns
16103 	 */
16104 	while (tmp_entry) {
16105 		current_entry = tmp_entry;
16106 		tmp_entry = tmp_entry->next;
16107 		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16108 	}
16109 	*pplun_blacklist = NULL;
16110 }
16111 
16112 /*
16113  * In fcp module,
16114  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16115  */
16116 static struct scsi_pkt *
16117 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16118     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16119     int flags, int (*callback)(), caddr_t arg)
16120 {
16121 	fcp_port_t	*pptr = ADDR2FCP(ap);
16122 	fcp_pkt_t	*cmd  = NULL;
16123 	fc_frame_hdr_t	*hp;
16124 
16125 	/*
16126 	 * First step: get the packet
16127 	 */
16128 	if (pkt == NULL) {
16129 		pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16130 		    tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16131 		    callback, arg);
16132 		if (pkt == NULL) {
16133 			return (NULL);
16134 		}
16135 
16136 		/*
16137 		 * All fields in scsi_pkt will be initialized properly or
16138 		 * set to zero. We need do nothing for scsi_pkt.
16139 		 */
16140 		/*
16141 		 * But it's our responsibility to link other related data
16142 		 * structures. Their initialization will be done, just
16143 		 * before the scsi_pkt will be sent to FCA.
16144 		 */
16145 		cmd		= PKT2CMD(pkt);
16146 		cmd->cmd_pkt	= pkt;
16147 		cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16148 		/*
16149 		 * fc_packet_t
16150 		 */
16151 		cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16152 		cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16153 		    sizeof (struct fcp_pkt));
16154 		cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16155 		cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16156 		cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16157 		cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16158 		/*
16159 		 * Fill in the Fabric Channel Header
16160 		 */
16161 		hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16162 		hp->r_ctl = R_CTL_COMMAND;
16163 		hp->rsvd = 0;
16164 		hp->type = FC_TYPE_SCSI_FCP;
16165 		hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16166 		hp->seq_id = 0;
16167 		hp->df_ctl  = 0;
16168 		hp->seq_cnt = 0;
16169 		hp->ox_id = 0xffff;
16170 		hp->rx_id = 0xffff;
16171 		hp->ro = 0;
16172 	} else {
16173 		/*
16174 		 * We need think if we should reset any elements in
16175 		 * related data structures.
16176 		 */
16177 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
16178 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
16179 		    "reusing pkt, flags %d", flags);
16180 		cmd = PKT2CMD(pkt);
16181 		if (cmd->cmd_fp_pkt->pkt_pd) {
16182 			cmd->cmd_fp_pkt->pkt_pd = NULL;
16183 		}
16184 	}
16185 
16186 	/*
16187 	 * Second step:	 dma allocation/move
16188 	 */
16189 	if (bp && bp->b_bcount != 0) {
16190 		/*
16191 		 * Mark if it's read or write
16192 		 */
16193 		if (bp->b_flags & B_READ) {
16194 			cmd->cmd_flags |= CFLAG_IS_READ;
16195 		} else {
16196 			cmd->cmd_flags &= ~CFLAG_IS_READ;
16197 		}
16198 
16199 		bp_mapin(bp);
16200 		cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16201 		cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16202 		cmd->cmd_fp_pkt->pkt_data_resid = 0;
16203 	} else {
16204 		/*
16205 		 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16206 		 * to send zero-length read/write.
16207 		 */
16208 		cmd->cmd_fp_pkt->pkt_data = NULL;
16209 		cmd->cmd_fp_pkt->pkt_datalen = 0;
16210 	}
16211 
16212 	return (pkt);
16213 }
16214 
16215 static void
16216 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16217 {
16218 	fcp_port_t	*pptr = ADDR2FCP(ap);
16219 
16220 	/*
16221 	 * First we let FCA to uninitilize private part.
16222 	 */
16223 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16224 	    PKT2CMD(pkt)->cmd_fp_pkt);
16225 
16226 	/*
16227 	 * Then we uninitialize fc_packet.
16228 	 */
16229 
16230 	/*
16231 	 * Thirdly, we uninitializae fcp_pkt.
16232 	 */
16233 
16234 	/*
16235 	 * In the end, we free scsi_pkt.
16236 	 */
16237 	scsi_hba_pkt_free(ap, pkt);
16238 }
16239 
16240 static int
16241 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16242 {
16243 	fcp_port_t	*pptr = ADDR2FCP(ap);
16244 	fcp_lun_t	*plun = ADDR2LUN(ap);
16245 	fcp_tgt_t	*ptgt = plun->lun_tgt;
16246 	fcp_pkt_t	*cmd  = PKT2CMD(pkt);
16247 	fcp_cmd_t	*fcmd = &cmd->cmd_fcp_cmd;
16248 	fc_packet_t	*fpkt = cmd->cmd_fp_pkt;
16249 	int		 rval;
16250 
16251 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
16252 	(void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16253 
16254 	/*
16255 	 * Firstly, we need initialize fcp_pkt_t
16256 	 * Secondly, we need initialize fcp_cmd_t.
16257 	 */
16258 	bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16259 	fcmd->fcp_data_len = fpkt->pkt_datalen;
16260 	fcmd->fcp_ent_addr = plun->lun_addr;
16261 	if (pkt->pkt_flags & FLAG_HTAG) {
16262 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16263 	} else if (pkt->pkt_flags & FLAG_OTAG) {
16264 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16265 	} else if (pkt->pkt_flags & FLAG_STAG) {
16266 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16267 	} else {
16268 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16269 	}
16270 
16271 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16272 		fcmd->fcp_cntl.cntl_read_data = 1;
16273 		fcmd->fcp_cntl.cntl_write_data = 0;
16274 	} else {
16275 		fcmd->fcp_cntl.cntl_read_data = 0;
16276 		fcmd->fcp_cntl.cntl_write_data = 1;
16277 	}
16278 
16279 	/*
16280 	 * Then we need initialize fc_packet_t too.
16281 	 */
16282 	fpkt->pkt_timeout = pkt->pkt_time + 2;
16283 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16284 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16285 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16286 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16287 	} else {
16288 		fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16289 	}
16290 
16291 	if (pkt->pkt_flags & FLAG_NOINTR) {
16292 		fpkt->pkt_comp = NULL;
16293 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16294 	} else {
16295 		fpkt->pkt_comp = fcp_cmd_callback;
16296 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16297 		if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16298 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16299 		}
16300 	}
16301 
16302 	/*
16303 	 * Lastly, we need initialize scsi_pkt
16304 	 */
16305 	pkt->pkt_reason = CMD_CMPLT;
16306 	pkt->pkt_state = 0;
16307 	pkt->pkt_statistics = 0;
16308 	pkt->pkt_resid = 0;
16309 
16310 	/*
16311 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
16312 	 * have to do polled I/O
16313 	 */
16314 	if (pkt->pkt_flags & FLAG_NOINTR) {
16315 		return (fcp_dopoll(pptr, cmd));
16316 	}
16317 
16318 	cmd->cmd_state = FCP_PKT_ISSUED;
16319 	rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16320 	if (rval == FC_SUCCESS) {
16321 		return (TRAN_ACCEPT);
16322 	}
16323 
16324 	/*
16325 	 * Need more consideration
16326 	 *
16327 	 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16328 	 */
16329 	cmd->cmd_state = FCP_PKT_IDLE;
16330 	if (rval == FC_TRAN_BUSY) {
16331 		return (TRAN_BUSY);
16332 	} else {
16333 		return (TRAN_FATAL_ERROR);
16334 	}
16335 }
16336 
16337 /*
16338  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16339  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16340  */
16341 static void
16342 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16343 {
16344 	FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16345 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16346 }
16347 
16348 /*
16349  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16350  */
16351 static void
16352 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16353 {
16354 	FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16355 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16356 }
16357