xref: /titanic_44/usr/src/uts/common/io/fibre-channel/ulp/fcp.c (revision 8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfb)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * Fibre Channel SCSI ULP Mapping driver
26  */
27 
28 #include <sys/scsi/scsi.h>
29 #include <sys/types.h>
30 #include <sys/varargs.h>
31 #include <sys/devctl.h>
32 #include <sys/thread.h>
33 #include <sys/thread.h>
34 #include <sys/open.h>
35 #include <sys/file.h>
36 #include <sys/sunndi.h>
37 #include <sys/console.h>
38 #include <sys/proc.h>
39 #include <sys/time.h>
40 #include <sys/utsname.h>
41 #include <sys/scsi/impl/scsi_reset_notify.h>
42 #include <sys/ndi_impldefs.h>
43 #include <sys/byteorder.h>
44 #include <sys/fs/dv_node.h>
45 #include <sys/ctype.h>
46 #include <sys/sunmdi.h>
47 
48 #include <sys/fibre-channel/fc.h>
49 #include <sys/fibre-channel/impl/fc_ulpif.h>
50 #include <sys/fibre-channel/ulp/fcpvar.h>
51 
52 /*
53  * Discovery Process
54  * =================
55  *
56  *    The discovery process is a major function of FCP.	 In order to help
57  * understand that function a flow diagram is given here.  This diagram
58  * doesn't claim to cover all the cases and the events that can occur during
59  * the discovery process nor the subtleties of the code.  The code paths shown
60  * are simplified.  Its purpose is to help the reader (and potentially bug
61  * fixer) have an overall view of the logic of the code.  For that reason the
62  * diagram covers the simple case of the line coming up cleanly or of a new
63  * port attaching to FCP the link being up.  The reader must keep in mind
64  * that:
65  *
66  *	- There are special cases where bringing devices online and offline
67  *	  is driven by Ioctl.
68  *
69  *	- The behavior of the discovery process can be modified through the
70  *	  .conf file.
71  *
72  *	- The line can go down and come back up at any time during the
73  *	  discovery process which explains some of the complexity of the code.
74  *
75  * ............................................................................
76  *
77  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
78  *
79  *
80  *			+-------------------------+
81  *   fp/fctl module --->|    fcp_port_attach	  |
82  *			+-------------------------+
83  *	   |			     |
84  *	   |			     |
85  *	   |			     v
86  *	   |		+-------------------------+
87  *	   |		| fcp_handle_port_attach  |
88  *	   |		+-------------------------+
89  *	   |				|
90  *	   |				|
91  *	   +--------------------+	|
92  *				|	|
93  *				v	v
94  *			+-------------------------+
95  *			|   fcp_statec_callback	  |
96  *			+-------------------------+
97  *				    |
98  *				    |
99  *				    v
100  *			+-------------------------+
101  *			|    fcp_handle_devices	  |
102  *			+-------------------------+
103  *				    |
104  *				    |
105  *				    v
106  *			+-------------------------+
107  *			|   fcp_handle_mapflags	  |
108  *			+-------------------------+
109  *				    |
110  *				    |
111  *				    v
112  *			+-------------------------+
113  *			|     fcp_send_els	  |
114  *			|			  |
115  *			| PLOGI or PRLI To all the|
116  *			| reachable devices.	  |
117  *			+-------------------------+
118  *
119  *
120  * ............................................................................
121  *
122  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
123  *	   STEP 1 are called (it is actually the same function).
124  *
125  *
126  *			+-------------------------+
127  *			|    fcp_icmd_callback	  |
128  *   fp/fctl module --->|			  |
129  *			| callback for PLOGI and  |
130  *			| PRLI.			  |
131  *			+-------------------------+
132  *				     |
133  *				     |
134  *	    Received PLOGI Accept   /-\	  Received PRLI Accept
135  *		       _ _ _ _ _ _ /   \_ _ _ _ _ _
136  *		      |		   \   /	   |
137  *		      |		    \-/		   |
138  *		      |				   |
139  *		      v				   v
140  *	+-------------------------+	+-------------------------+
141  *	|     fcp_send_els	  |	|     fcp_send_scsi	  |
142  *	|			  |	|			  |
143  *	|	  PRLI		  |	|	REPORT_LUN	  |
144  *	+-------------------------+	+-------------------------+
145  *
146  * ............................................................................
147  *
148  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
149  *	   (It is actually the same function).
150  *
151  *
152  *			    +-------------------------+
153  *   fp/fctl module ------->|	 fcp_scsi_callback    |
154  *			    +-------------------------+
155  *					|
156  *					|
157  *					|
158  *	Receive REPORT_LUN reply       /-\	Receive INQUIRY PAGE83 reply
159  *		  _ _ _ _ _ _ _ _ _ _ /	  \_ _ _ _ _ _ _ _ _ _ _ _
160  *		 |		      \	  /			  |
161  *		 |		       \-/			  |
162  *		 |			|			  |
163  *		 | Receive INQUIRY reply|			  |
164  *		 |			|			  |
165  *		 v			v			  v
166  * +------------------------+ +----------------------+ +----------------------+
167  * |  fcp_handle_reportlun  | |	 fcp_handle_inquiry  | |  fcp_handle_page83   |
168  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
169  * +------------------------+ +----------------------+ +----------------------+
170  *		 |			|			  |
171  *		 |			|			  |
172  *		 |			|			  |
173  *		 v			v			  |
174  *     +-----------------+	+-----------------+		  |
175  *     |  fcp_send_scsi	 |	|  fcp_send_scsi  |		  |
176  *     |		 |	|		  |		  |
177  *     |     INQUIRY	 |	| INQUIRY PAGE83  |		  |
178  *     |  (To each LUN)	 |	+-----------------+		  |
179  *     +-----------------+					  |
180  *								  |
181  *								  v
182  *						      +------------------------+
183  *						      |	 fcp_call_finish_init  |
184  *						      +------------------------+
185  *								  |
186  *								  v
187  *						 +-----------------------------+
188  *						 |  fcp_call_finish_init_held  |
189  *						 +-----------------------------+
190  *								  |
191  *								  |
192  *			   All LUNs scanned			 /-\
193  *			       _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
194  *			      |					\   /
195  *			      |					 \-/
196  *			      v					  |
197  *		     +------------------+			  |
198  *		     |	fcp_finish_tgt	|			  |
199  *		     +------------------+			  |
200  *			      |	  Target Not Offline and	  |
201  *  Target Not Offline and    |	  not marked and tgt_node_state	  |
202  *  marked		     /-\  not FCP_TGT_NODE_ON_DEMAND	  |
203  *		_ _ _ _ _ _ /	\_ _ _ _ _ _ _ _		  |
204  *	       |	    \	/		|		  |
205  *	       |	     \-/		|		  |
206  *	       v				v		  |
207  * +----------------------------+     +-------------------+	  |
208  * |	 fcp_offline_target	|     |	 fcp_create_luns  |	  |
209  * |				|     +-------------------+	  |
210  * | A structure fcp_tgt_elem	|		|		  |
211  * | is created and queued in	|		v		  |
212  * | the FCP port list		|     +-------------------+	  |
213  * | port_offline_tgts.	 It	|     |	 fcp_pass_to_hp	  |	  |
214  * | will be unqueued by the	|     |			  |	  |
215  * | watchdog timer.		|     | Called for each	  |	  |
216  * +----------------------------+     | LUN. Dispatches	  |	  |
217  *		  |		      | fcp_hp_task	  |	  |
218  *		  |		      +-------------------+	  |
219  *		  |				|		  |
220  *		  |				|		  |
221  *		  |				|		  |
222  *		  |				+---------------->|
223  *		  |						  |
224  *		  +---------------------------------------------->|
225  *								  |
226  *								  |
227  *		All the targets (devices) have been scanned	 /-\
228  *				_ _ _ _	_ _ _ _	_ _ _ _ _ _ _ _ /   \
229  *			       |				\   /
230  *			       |				 \-/
231  *	    +-------------------------------------+		  |
232  *	    |		fcp_finish_init		  |		  |
233  *	    |					  |		  |
234  *	    | Signal broadcasts the condition	  |		  |
235  *	    | variable port_config_cv of the FCP  |		  |
236  *	    | port.  One potential code sequence  |		  |
237  *	    | waiting on the condition variable	  |		  |
238  *	    | the code sequence handling	  |		  |
239  *	    | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|		  |
240  *	    | The other is in the function	  |		  |
241  *	    | fcp_reconfig_wait which is called	  |		  |
242  *	    | in the transmit path preventing IOs |		  |
243  *	    | from going through till the disco-  |		  |
244  *	    | very process is over.		  |		  |
245  *	    +-------------------------------------+		  |
246  *			       |				  |
247  *			       |				  |
248  *			       +--------------------------------->|
249  *								  |
250  *								  v
251  *								Return
252  *
253  * ............................................................................
254  *
255  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
256  *
257  *
258  *			+-------------------------+
259  *			|      fcp_hp_task	  |
260  *			+-------------------------+
261  *				     |
262  *				     |
263  *				     v
264  *			+-------------------------+
265  *			|     fcp_trigger_lun	  |
266  *			+-------------------------+
267  *				     |
268  *				     |
269  *				     v
270  *		   Bring offline    /-\	 Bring online
271  *		  _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
272  *		 |		   \   /		   |
273  *		 |		    \-/			   |
274  *		 v					   v
275  *    +---------------------+			+-----------------------+
276  *    |	 fcp_offline_child  |			|      fcp_get_cip	|
277  *    +---------------------+			|			|
278  *						| Creates a dev_info_t	|
279  *						| or a mdi_pathinfo_t	|
280  *						| depending on whether	|
281  *						| mpxio is on or off.	|
282  *						+-----------------------+
283  *							   |
284  *							   |
285  *							   v
286  *						+-----------------------+
287  *						|  fcp_online_child	|
288  *						|			|
289  *						| Set device online	|
290  *						| using NDI or MDI.	|
291  *						+-----------------------+
292  *
293  * ............................................................................
294  *
295  * STEP 5: The watchdog timer expires.	The watch dog timer does much more that
296  *	   what is described here.  We only show the target offline path.
297  *
298  *
299  *			 +--------------------------+
300  *			 |	  fcp_watch	    |
301  *			 +--------------------------+
302  *				       |
303  *				       |
304  *				       v
305  *			 +--------------------------+
306  *			 |  fcp_scan_offline_tgts   |
307  *			 +--------------------------+
308  *				       |
309  *				       |
310  *				       v
311  *			 +--------------------------+
312  *			 |  fcp_offline_target_now  |
313  *			 +--------------------------+
314  *				       |
315  *				       |
316  *				       v
317  *			 +--------------------------+
318  *			 |   fcp_offline_tgt_luns   |
319  *			 +--------------------------+
320  *				       |
321  *				       |
322  *				       v
323  *			 +--------------------------+
324  *			 |     fcp_offline_lun	    |
325  *			 +--------------------------+
326  *				       |
327  *				       |
328  *				       v
329  *		     +----------------------------------+
330  *		     |	     fcp_offline_lun_now	|
331  *		     |					|
332  *		     | A request (or two if mpxio) is	|
333  *		     | sent to the hot plug task using	|
334  *		     | a fcp_hp_elem structure.		|
335  *		     +----------------------------------+
336  */
337 
338 /*
339  * Functions registered with DDI framework
340  */
341 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
342 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
343 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
344 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
345 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
346     cred_t *credp, int *rval);
347 
348 /*
349  * Functions registered with FC Transport framework
350  */
351 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
352     fc_attach_cmd_t cmd,  uint32_t s_id);
353 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
354     fc_detach_cmd_t cmd);
355 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
356     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
357     uint32_t claimed);
358 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
359     fc_unsol_buf_t *buf, uint32_t claimed);
360 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
361     fc_unsol_buf_t *buf, uint32_t claimed);
362 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
363     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
364     uint32_t  dev_cnt, uint32_t port_sid);
365 
366 /*
367  * Functions registered with SCSA framework
368  */
369 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
370     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
371 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
372     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
373 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
374     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
375 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
376 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
377 static int fcp_scsi_reset(struct scsi_address *ap, int level);
378 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
379 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
380     int whom);
381 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
382 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
383     void (*callback)(caddr_t), caddr_t arg);
384 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
385     char *name, ddi_eventcookie_t *event_cookiep);
386 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
387     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
388     ddi_callback_id_t *cb_id);
389 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
390     ddi_callback_id_t cb_id);
391 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
392     ddi_eventcookie_t eventid, void *impldata);
393 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
394     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
395 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
396     ddi_bus_config_op_t op, void *arg);
397 
398 /*
399  * Internal functions
400  */
401 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
402     int mode, int *rval);
403 
404 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
405     int mode, int *rval);
406 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
407     struct fcp_scsi_cmd *fscsi, int mode);
408 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
409     caddr_t base_addr, int mode);
410 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
411 
412 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
413     la_wwn_t *pwwn, int	*ret_val, int *fc_status, int *fc_pkt_state,
414     int *fc_pkt_reason, int *fc_pkt_action);
415 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
416     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
417 static int fcp_tgt_send_prli(struct fcp_tgt	*ptgt, int *fc_status,
418     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
419 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
420 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
421 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
422 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
423 
424 static void fcp_handle_devices(struct fcp_port *pptr,
425     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
426     fcp_map_tag_t *map_tag, int cause);
427 static int fcp_handle_mapflags(struct fcp_port *pptr,
428     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
429     int tgt_cnt, int cause);
430 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
431 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
432     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
433 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
434     int cause);
435 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
436     uint32_t state);
437 static struct fcp_port *fcp_get_port(opaque_t port_handle);
438 static void fcp_unsol_callback(fc_packet_t *fpkt);
439 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
440     uchar_t r_ctl, uchar_t type);
441 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
442 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
443     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
444     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
445 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
446 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
447     int nodma, int flags);
448 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
449 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
450     uchar_t *wwn);
451 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
452     uint32_t d_id);
453 static void fcp_icmd_callback(fc_packet_t *fpkt);
454 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
455     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
456 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
457 static void fcp_scsi_callback(fc_packet_t *fpkt);
458 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
459 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
460 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
461 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
462     uint16_t lun_num);
463 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
464     int link_cnt, int tgt_cnt, int cause);
465 static void fcp_finish_init(struct fcp_port *pptr);
466 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
467     int tgt_cnt, int cause);
468 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
469     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
470 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
471     int link_cnt, int tgt_cnt, int nowait, int flags);
472 static void fcp_offline_target_now(struct fcp_port *pptr,
473     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
474 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
475     int tgt_cnt, int flags);
476 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
477     int nowait, int flags);
478 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
479     int tgt_cnt);
480 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
481     int tgt_cnt, int flags);
482 static void fcp_scan_offline_luns(struct fcp_port *pptr);
483 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
484 static void fcp_update_offline_flags(struct fcp_lun *plun);
485 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
486 static void fcp_abort_commands(struct fcp_pkt *head, struct
487     fcp_port *pptr);
488 static void fcp_cmd_callback(fc_packet_t *fpkt);
489 static void fcp_complete_pkt(fc_packet_t *fpkt);
490 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
491     struct fcp_port *pptr);
492 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
493     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
494 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
495 static void fcp_dealloc_lun(struct fcp_lun *plun);
496 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
497     fc_portmap_t *map_entry, int link_cnt);
498 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
499 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
500 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
501     int internal);
502 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
503 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
504     uint32_t s_id, int instance);
505 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
506     int instance);
507 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
508 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
509     int);
510 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
511 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
512 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
513     int flags);
514 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
515 static int fcp_reset_target(struct scsi_address *ap, int level);
516 static int fcp_commoncap(struct scsi_address *ap, char *cap,
517     int val, int tgtonly, int doset);
518 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
519 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
520 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
521     int sleep);
522 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
523     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
524 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
525 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
526 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
527     int lcount, int tcount);
528 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
529 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
530 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
531     int tgt_cnt);
532 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
533     dev_info_t *pdip, caddr_t name);
534 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
535     int lcount, int tcount, int flags, int *circ);
536 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
537     int lcount, int tcount, int flags, int *circ);
538 static void fcp_remove_child(struct fcp_lun *plun);
539 static void fcp_watch(void *arg);
540 static void fcp_check_reset_delay(struct fcp_port *pptr);
541 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
542     struct fcp_lun *rlun, int tgt_cnt);
543 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
544 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
545     uchar_t *wwn, uint16_t lun);
546 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
547     struct fcp_lun *plun);
548 static void fcp_post_callback(struct fcp_pkt *cmd);
549 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
550 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
551 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
552     child_info_t *cip);
553 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
554     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
555     int tgt_cnt, int flags);
556 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
557     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
558     int tgt_cnt, int flags, int wait);
559 static void fcp_retransport_cmd(struct fcp_port *pptr,
560     struct fcp_pkt *cmd);
561 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
562     uint_t statistics);
563 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
564 static void fcp_update_targets(struct fcp_port *pptr,
565     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
566 static int fcp_call_finish_init(struct fcp_port *pptr,
567     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
568 static int fcp_call_finish_init_held(struct fcp_port *pptr,
569     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
570 static void fcp_reconfigure_luns(void * tgt_handle);
571 static void fcp_free_targets(struct fcp_port *pptr);
572 static void fcp_free_target(struct fcp_tgt *ptgt);
573 static int fcp_is_retryable(struct fcp_ipkt *icmd);
574 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
575 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
576 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
577 static void fcp_print_error(fc_packet_t *fpkt);
578 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
579     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
580 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
581 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
582     uint32_t *dev_cnt);
583 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
584 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
585 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
586     struct fcp_ioctl *, struct fcp_port **);
587 static char *fcp_get_lun_path(struct fcp_lun *plun);
588 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
589     int *rval);
590 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
591 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
592 static char *fcp_get_lun_path(struct fcp_lun *plun);
593 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
594     int *rval);
595 static void fcp_reconfig_wait(struct fcp_port *pptr);
596 
597 /*
598  * New functions added for mpxio support
599  */
600 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
601     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
602 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
603     int tcount);
604 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
605     dev_info_t *pdip);
606 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
607 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
608 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
609 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
610 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
611     int what);
612 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
613     fc_packet_t *fpkt);
614 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
615 
616 /*
617  * New functions added for lun masking support
618  */
619 static void fcp_read_blacklist(dev_info_t *dip,
620     struct fcp_black_list_entry **pplun_blacklist);
621 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
622     struct fcp_black_list_entry **pplun_blacklist);
623 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
624     struct fcp_black_list_entry **pplun_blacklist);
625 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
626 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
627 
628 /*
629  * New functions to support software FCA (like fcoei)
630  */
631 static struct scsi_pkt *fcp_pseudo_init_pkt(
632 	struct scsi_address *ap, struct scsi_pkt *pkt,
633 	struct buf *bp, int cmdlen, int statuslen,
634 	int tgtlen, int flags, int (*callback)(), caddr_t arg);
635 static void fcp_pseudo_destroy_pkt(
636 	struct scsi_address *ap, struct scsi_pkt *pkt);
637 static void fcp_pseudo_sync_pkt(
638 	struct scsi_address *ap, struct scsi_pkt *pkt);
639 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
640 static void fcp_pseudo_dmafree(
641 	struct scsi_address *ap, struct scsi_pkt *pkt);
642 
643 extern struct mod_ops	mod_driverops;
644 /*
645  * This variable is defined in modctl.c and set to '1' after the root driver
646  * and fs are loaded.  It serves as an indication that the root filesystem can
647  * be used.
648  */
649 extern int		modrootloaded;
650 /*
651  * This table contains strings associated with the SCSI sense key codes.  It
652  * is used by FCP to print a clear explanation of the code returned in the
653  * sense information by a device.
654  */
655 extern char		*sense_keys[];
656 /*
657  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
658  * under this device that the paths to a physical device are created when
659  * MPxIO is used.
660  */
661 extern dev_info_t	*scsi_vhci_dip;
662 
663 /*
664  * Report lun processing
665  */
666 #define	FCP_LUN_ADDRESSING		0x80
667 #define	FCP_PD_ADDRESSING		0x00
668 #define	FCP_VOLUME_ADDRESSING		0x40
669 
670 #define	FCP_SVE_THROTTLE		0x28 /* Vicom */
671 #define	MAX_INT_DMA			0x7fffffff
672 #define	FCP_MAX_SENSE_LEN		252
673 #define	FCP_MAX_RESPONSE_LEN		0xffffff
674 /*
675  * Property definitions
676  */
677 #define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
678 #define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
679 #define	TARGET_PROP	(char *)fcp_target_prop
680 #define	LUN_PROP	(char *)fcp_lun_prop
681 #define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
682 #define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
683 #define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
684 #define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
685 #define	INIT_PORT_PROP	(char *)fcp_init_port_prop
686 #define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
687 #define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
688 /*
689  * Short hand macros.
690  */
691 #define	LUN_PORT	(plun->lun_tgt->tgt_port)
692 #define	LUN_TGT		(plun->lun_tgt)
693 
694 /*
695  * Driver private macros
696  */
697 #define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
698 			((x) >= 'a' && (x) <= 'f') ?			\
699 			((x) - 'a' + 10) : ((x) - 'A' + 10))
700 
701 #define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
702 
703 #define	FCP_N_NDI_EVENTS						\
704 	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
705 
706 #define	FCP_LINK_STATE_CHANGED(p, c)			\
707 	((p)->port_link_cnt != (c)->ipkt_link_cnt)
708 
709 #define	FCP_TGT_STATE_CHANGED(t, c)			\
710 	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
711 
712 #define	FCP_STATE_CHANGED(p, t, c)		\
713 	(FCP_TGT_STATE_CHANGED(t, c))
714 
715 #define	FCP_MUST_RETRY(fpkt)				\
716 	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
717 	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
718 	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
719 	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
720 	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
721 	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
722 	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
723 	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
724 
725 #define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
726 	((es)->es_key == KEY_UNIT_ATTENTION &&	\
727 	(es)->es_add_code == 0x3f &&		\
728 	(es)->es_qual_code == 0x0e)
729 
730 #define	FCP_SENSE_NO_LUN(es)			\
731 	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
732 	(es)->es_add_code == 0x25 &&		\
733 	(es)->es_qual_code == 0x0)
734 
735 #define	FCP_VERSION		"20090729-1.190"
736 #define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
737 
738 #define	FCP_NUM_ELEMENTS(array)			\
739 	(sizeof (array) / sizeof ((array)[0]))
740 
741 /*
742  * Debugging, Error reporting, and tracing
743  */
744 #define	FCP_LOG_SIZE		1024 * 1024
745 
746 #define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
747 #define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
748 #define	FCP_LEVEL_3		0x00004		/* state change, discovery */
749 #define	FCP_LEVEL_4		0x00008		/* ULP messages */
750 #define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
751 #define	FCP_LEVEL_6		0x00020		/* Transport failures */
752 #define	FCP_LEVEL_7		0x00040
753 #define	FCP_LEVEL_8		0x00080		/* I/O tracing */
754 #define	FCP_LEVEL_9		0x00100		/* I/O tracing */
755 
756 
757 
758 /*
759  * Log contents to system messages file
760  */
761 #define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
762 #define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
763 #define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
764 #define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
765 #define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
766 #define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
767 #define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
768 #define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
769 #define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
770 
771 
772 /*
773  * Log contents to trace buffer
774  */
775 #define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
776 #define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
777 #define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
778 #define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
779 #define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
780 #define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
781 #define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
782 #define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
783 #define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
784 
785 
786 /*
787  * Log contents to both system messages file and trace buffer
788  */
789 #define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
790 				FC_TRACE_LOG_MSG)
791 #define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
792 				FC_TRACE_LOG_MSG)
793 #define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
794 				FC_TRACE_LOG_MSG)
795 #define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
796 				FC_TRACE_LOG_MSG)
797 #define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
798 				FC_TRACE_LOG_MSG)
799 #define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
800 				FC_TRACE_LOG_MSG)
801 #define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
802 				FC_TRACE_LOG_MSG)
803 #define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
804 				FC_TRACE_LOG_MSG)
805 #define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
806 				FC_TRACE_LOG_MSG)
807 #ifdef DEBUG
808 #define	FCP_DTRACE	fc_trace_debug
809 #else
810 #define	FCP_DTRACE
811 #endif
812 
813 #define	FCP_TRACE	fc_trace_debug
814 
815 static struct cb_ops fcp_cb_ops = {
816 	fcp_open,			/* open */
817 	fcp_close,			/* close */
818 	nodev,				/* strategy */
819 	nodev,				/* print */
820 	nodev,				/* dump */
821 	nodev,				/* read */
822 	nodev,				/* write */
823 	fcp_ioctl,			/* ioctl */
824 	nodev,				/* devmap */
825 	nodev,				/* mmap */
826 	nodev,				/* segmap */
827 	nochpoll,			/* chpoll */
828 	ddi_prop_op,			/* cb_prop_op */
829 	0,				/* streamtab */
830 	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
831 	CB_REV,				/* rev */
832 	nodev,				/* aread */
833 	nodev				/* awrite */
834 };
835 
836 
837 static struct dev_ops fcp_ops = {
838 	DEVO_REV,
839 	0,
840 	ddi_getinfo_1to1,
841 	nulldev,		/* identify */
842 	nulldev,		/* probe */
843 	fcp_attach,		/* attach and detach are mandatory */
844 	fcp_detach,
845 	nodev,			/* reset */
846 	&fcp_cb_ops,		/* cb_ops */
847 	NULL,			/* bus_ops */
848 	NULL,			/* power */
849 };
850 
851 
852 char *fcp_version = FCP_NAME_VERSION;
853 
854 static struct modldrv modldrv = {
855 	&mod_driverops,
856 	FCP_NAME_VERSION,
857 	&fcp_ops
858 };
859 
860 
861 static struct modlinkage modlinkage = {
862 	MODREV_1,
863 	&modldrv,
864 	NULL
865 };
866 
867 
868 static fc_ulp_modinfo_t fcp_modinfo = {
869 	&fcp_modinfo,			/* ulp_handle */
870 	FCTL_ULP_MODREV_4,		/* ulp_rev */
871 	FC4_SCSI_FCP,			/* ulp_type */
872 	"fcp",				/* ulp_name */
873 	FCP_STATEC_MASK,		/* ulp_statec_mask */
874 	fcp_port_attach,		/* ulp_port_attach */
875 	fcp_port_detach,		/* ulp_port_detach */
876 	fcp_port_ioctl,			/* ulp_port_ioctl */
877 	fcp_els_callback,		/* ulp_els_callback */
878 	fcp_data_callback,		/* ulp_data_callback */
879 	fcp_statec_callback		/* ulp_statec_callback */
880 };
881 
882 #ifdef	DEBUG
883 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
884 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
885 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
886 				FCP_LEVEL_6 | FCP_LEVEL_7)
887 #else
888 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
889 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
890 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
891 				FCP_LEVEL_6 | FCP_LEVEL_7)
892 #endif
893 
894 /* FCP global variables */
895 int			fcp_bus_config_debug = 0;
896 static int		fcp_log_size = FCP_LOG_SIZE;
897 static int		fcp_trace = FCP_TRACE_DEFAULT;
898 static fc_trace_logq_t	*fcp_logq = NULL;
899 static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
900 /*
901  * The auto-configuration is set by default.  The only way of disabling it is
902  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
903  */
904 static int		fcp_enable_auto_configuration = 1;
905 static int		fcp_max_bus_config_retries	= 4;
906 static int		fcp_lun_ready_retry = 300;
907 /*
908  * The value assigned to the following variable has changed several times due
909  * to a problem with the data underruns reporting of some firmware(s).	The
910  * current value of 50 gives a timeout value of 25 seconds for a max number
911  * of 256 LUNs.
912  */
913 static int		fcp_max_target_retries = 50;
914 /*
915  * Watchdog variables
916  * ------------------
917  *
918  * fcp_watchdog_init
919  *
920  *	Indicates if the watchdog timer is running or not.  This is actually
921  *	a counter of the number of Fibre Channel ports that attached.  When
922  *	the first port attaches the watchdog is started.  When the last port
923  *	detaches the watchdog timer is stopped.
924  *
925  * fcp_watchdog_time
926  *
927  *	This is the watchdog clock counter.  It is incremented by
928  *	fcp_watchdog_time each time the watchdog timer expires.
929  *
930  * fcp_watchdog_timeout
931  *
932  *	Increment value of the variable fcp_watchdog_time as well as the
933  *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
934  *	is strange that this is not a #define	but a variable since the code
935  *	never changes this value.  The reason why it can be said that the
936  *	unit is 1 second is because the number of ticks for the watchdog
937  *	timer is determined like this:
938  *
939  *	    fcp_watchdog_tick = fcp_watchdog_timeout *
940  *				  drv_usectohz(1000000);
941  *
942  *	The value 1000000 is hard coded in the code.
943  *
944  * fcp_watchdog_tick
945  *
946  *	Watchdog timer value in ticks.
947  */
948 static int		fcp_watchdog_init = 0;
949 static int		fcp_watchdog_time = 0;
950 static int		fcp_watchdog_timeout = 1;
951 static int		fcp_watchdog_tick;
952 
953 /*
954  * fcp_offline_delay is a global variable to enable customisation of
955  * the timeout on link offlines or RSCNs. The default value is set
956  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
957  * specified in FCP4 Chapter 11 (see www.t10.org).
958  *
959  * The variable fcp_offline_delay is specified in SECONDS.
960  *
961  * If we made this a static var then the user would not be able to
962  * change it. This variable is set in fcp_attach().
963  */
964 unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
965 
966 static void		*fcp_softstate = NULL; /* for soft state */
967 static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
968 static kmutex_t		fcp_global_mutex;
969 static kmutex_t		fcp_ioctl_mutex;
970 static dev_info_t	*fcp_global_dip = NULL;
971 static timeout_id_t	fcp_watchdog_id;
972 const char		*fcp_lun_prop = "lun";
973 const char		*fcp_sam_lun_prop = "sam-lun";
974 const char		*fcp_target_prop = "target";
975 /*
976  * NOTE: consumers of "node-wwn" property include stmsboot in ON
977  * consolidation.
978  */
979 const char		*fcp_node_wwn_prop = "node-wwn";
980 const char		*fcp_port_wwn_prop = "port-wwn";
981 const char		*fcp_conf_wwn_prop = "fc-port-wwn";
982 const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
983 const char		*fcp_manual_config_only = "manual_configuration_only";
984 const char		*fcp_init_port_prop = "initiator-port";
985 const char		*fcp_tgt_port_prop = "target-port";
986 const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
987 
988 static struct fcp_port	*fcp_port_head = NULL;
989 static ddi_eventcookie_t	fcp_insert_eid;
990 static ddi_eventcookie_t	fcp_remove_eid;
991 
992 static ndi_event_definition_t	fcp_ndi_event_defs[] = {
993 	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
994 	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
995 };
996 
997 /*
998  * List of valid commands for the scsi_ioctl call
999  */
1000 static uint8_t scsi_ioctl_list[] = {
1001 	SCMD_INQUIRY,
1002 	SCMD_REPORT_LUN,
1003 	SCMD_READ_CAPACITY
1004 };
1005 
1006 /*
1007  * this is used to dummy up a report lun response for cases
1008  * where the target doesn't support it
1009  */
1010 static uchar_t fcp_dummy_lun[] = {
1011 	0x00,		/* MSB length (length = no of luns * 8) */
1012 	0x00,
1013 	0x00,
1014 	0x08,		/* LSB length */
1015 	0x00,		/* MSB reserved */
1016 	0x00,
1017 	0x00,
1018 	0x00,		/* LSB reserved */
1019 	FCP_PD_ADDRESSING,
1020 	0x00,		/* LUN is ZERO at the first level */
1021 	0x00,
1022 	0x00,		/* second level is zero */
1023 	0x00,
1024 	0x00,		/* third level is zero */
1025 	0x00,
1026 	0x00		/* fourth level is zero */
1027 };
1028 
1029 static uchar_t fcp_alpa_to_switch[] = {
1030 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1031 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1032 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1033 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1034 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1035 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1036 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1037 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1038 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1039 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1040 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1041 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1042 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1043 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1044 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1045 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1046 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1047 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1048 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1049 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1050 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1051 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1052 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1053 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1054 };
1055 
1056 static caddr_t pid = "SESS01	      ";
1057 
1058 #if	!defined(lint)
1059 
1060 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1061     fcp_port::fcp_next fcp_watchdog_id))
1062 
1063 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1064 
1065 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1066     fcp_insert_eid
1067     fcp_remove_eid
1068     fcp_watchdog_time))
1069 
1070 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1071     fcp_cb_ops
1072     fcp_ops
1073     callb_cpr))
1074 
1075 #endif /* lint */
1076 
1077 /*
1078  * This table is used to determine whether or not it's safe to copy in
1079  * the target node name for a lun.  Since all luns behind the same target
1080  * have the same wwnn, only tagets that do not support multiple luns are
1081  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1082  */
1083 
1084 char *fcp_symmetric_disk_table[] = {
1085 	"SEAGATE ST",
1086 	"IBM	 DDYFT",
1087 	"SUNW	 SUNWGS",	/* Daktari enclosure */
1088 	"SUN	 SENA",		/* SES device */
1089 	"SUN	 SESS01"	/* VICOM SVE box */
1090 };
1091 
1092 int fcp_symmetric_disk_table_size =
1093 	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1094 
1095 /*
1096  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1097  * will panic if you don't pass this in to the routine, this information.
1098  * Need to determine what the actual impact to the system is by providing
1099  * this information if any. Since dma allocation is done in pkt_init it may
1100  * not have any impact. These values are straight from the Writing Device
1101  * Driver manual.
1102  */
1103 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1104 	DMA_ATTR_V0,	/* ddi_dma_attr version */
1105 	0,		/* low address */
1106 	0xffffffff,	/* high address */
1107 	0x00ffffff,	/* counter upper bound */
1108 	1,		/* alignment requirements */
1109 	0x3f,		/* burst sizes */
1110 	1,		/* minimum DMA access */
1111 	0xffffffff,	/* maximum DMA access */
1112 	(1 << 24) - 1,	/* segment boundary restrictions */
1113 	1,		/* scater/gather list length */
1114 	512,		/* device granularity */
1115 	0		/* DMA flags */
1116 };
1117 
1118 /*
1119  * The _init(9e) return value should be that of mod_install(9f). Under
1120  * some circumstances, a failure may not be related mod_install(9f) and
1121  * one would then require a return value to indicate the failure. Looking
1122  * at mod_install(9f), it is expected to return 0 for success and non-zero
1123  * for failure. mod_install(9f) for device drivers, further goes down the
1124  * calling chain and ends up in ddi_installdrv(), whose return values are
1125  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1126  * calling chain of mod_install(9f) which return values like EINVAL and
1127  * in some even return -1.
1128  *
1129  * To work around the vagaries of the mod_install() calling chain, return
1130  * either 0 or ENODEV depending on the success or failure of mod_install()
1131  */
1132 int
1133 _init(void)
1134 {
1135 	int rval;
1136 
1137 	/*
1138 	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1139 	 * before registering with the transport first.
1140 	 */
1141 	if (ddi_soft_state_init(&fcp_softstate,
1142 	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1143 		return (EINVAL);
1144 	}
1145 
1146 	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1147 	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1148 
1149 	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1150 		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1151 		mutex_destroy(&fcp_global_mutex);
1152 		mutex_destroy(&fcp_ioctl_mutex);
1153 		ddi_soft_state_fini(&fcp_softstate);
1154 		return (ENODEV);
1155 	}
1156 
1157 	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1158 
1159 	if ((rval = mod_install(&modlinkage)) != 0) {
1160 		fc_trace_free_logq(fcp_logq);
1161 		(void) fc_ulp_remove(&fcp_modinfo);
1162 		mutex_destroy(&fcp_global_mutex);
1163 		mutex_destroy(&fcp_ioctl_mutex);
1164 		ddi_soft_state_fini(&fcp_softstate);
1165 		rval = ENODEV;
1166 	}
1167 
1168 	return (rval);
1169 }
1170 
1171 
1172 /*
1173  * the system is done with us as a driver, so clean up
1174  */
1175 int
1176 _fini(void)
1177 {
1178 	int rval;
1179 
1180 	/*
1181 	 * don't start cleaning up until we know that the module remove
1182 	 * has worked  -- if this works, then we know that each instance
1183 	 * has successfully been DDI_DETACHed
1184 	 */
1185 	if ((rval = mod_remove(&modlinkage)) != 0) {
1186 		return (rval);
1187 	}
1188 
1189 	(void) fc_ulp_remove(&fcp_modinfo);
1190 
1191 	ddi_soft_state_fini(&fcp_softstate);
1192 	mutex_destroy(&fcp_global_mutex);
1193 	mutex_destroy(&fcp_ioctl_mutex);
1194 	fc_trace_free_logq(fcp_logq);
1195 
1196 	return (rval);
1197 }
1198 
1199 
1200 int
1201 _info(struct modinfo *modinfop)
1202 {
1203 	return (mod_info(&modlinkage, modinfop));
1204 }
1205 
1206 
1207 /*
1208  * attach the module
1209  */
1210 static int
1211 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1212 {
1213 	int rval = DDI_SUCCESS;
1214 
1215 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1216 	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1217 
1218 	if (cmd == DDI_ATTACH) {
1219 		/* The FCP pseudo device is created here. */
1220 		mutex_enter(&fcp_global_mutex);
1221 		fcp_global_dip = devi;
1222 		mutex_exit(&fcp_global_mutex);
1223 
1224 		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1225 		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1226 			ddi_report_dev(fcp_global_dip);
1227 		} else {
1228 			cmn_err(CE_WARN, "FCP: Cannot create minor node");
1229 			mutex_enter(&fcp_global_mutex);
1230 			fcp_global_dip = NULL;
1231 			mutex_exit(&fcp_global_mutex);
1232 
1233 			rval = DDI_FAILURE;
1234 		}
1235 		/*
1236 		 * We check the fcp_offline_delay property at this
1237 		 * point. This variable is global for the driver,
1238 		 * not specific to an instance.
1239 		 *
1240 		 * We do not recommend setting the value to less
1241 		 * than 10 seconds (RA_TOV_els), or greater than
1242 		 * 60 seconds.
1243 		 */
1244 		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1245 		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1246 		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
1247 		if ((fcp_offline_delay < 10) ||
1248 		    (fcp_offline_delay > 60)) {
1249 			cmn_err(CE_WARN, "Setting fcp_offline_delay "
1250 			    "to %d second(s). This is outside the "
1251 			    "recommended range of 10..60 seconds.",
1252 			    fcp_offline_delay);
1253 		}
1254 	}
1255 
1256 	return (rval);
1257 }
1258 
1259 
1260 /*ARGSUSED*/
1261 static int
1262 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1263 {
1264 	int	res = DDI_SUCCESS;
1265 
1266 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1267 	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
1268 
1269 	if (cmd == DDI_DETACH) {
1270 		/*
1271 		 * Check if there are active ports/threads. If there
1272 		 * are any, we will fail, else we will succeed (there
1273 		 * should not be much to clean up)
1274 		 */
1275 		mutex_enter(&fcp_global_mutex);
1276 		FCP_DTRACE(fcp_logq, "fcp",
1277 		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1278 		    (void *) fcp_port_head);
1279 
1280 		if (fcp_port_head == NULL) {
1281 			ddi_remove_minor_node(fcp_global_dip, NULL);
1282 			fcp_global_dip = NULL;
1283 			mutex_exit(&fcp_global_mutex);
1284 		} else {
1285 			mutex_exit(&fcp_global_mutex);
1286 			res = DDI_FAILURE;
1287 		}
1288 	}
1289 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1290 	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
1291 
1292 	return (res);
1293 }
1294 
1295 
1296 /* ARGSUSED */
1297 static int
1298 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1299 {
1300 	if (otype != OTYP_CHR) {
1301 		return (EINVAL);
1302 	}
1303 
1304 	/*
1305 	 * Allow only root to talk;
1306 	 */
1307 	if (drv_priv(credp)) {
1308 		return (EPERM);
1309 	}
1310 
1311 	mutex_enter(&fcp_global_mutex);
1312 	if (fcp_oflag & FCP_EXCL) {
1313 		mutex_exit(&fcp_global_mutex);
1314 		return (EBUSY);
1315 	}
1316 
1317 	if (flag & FEXCL) {
1318 		if (fcp_oflag & FCP_OPEN) {
1319 			mutex_exit(&fcp_global_mutex);
1320 			return (EBUSY);
1321 		}
1322 		fcp_oflag |= FCP_EXCL;
1323 	}
1324 	fcp_oflag |= FCP_OPEN;
1325 	mutex_exit(&fcp_global_mutex);
1326 
1327 	return (0);
1328 }
1329 
1330 
1331 /* ARGSUSED */
1332 static int
1333 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1334 {
1335 	if (otype != OTYP_CHR) {
1336 		return (EINVAL);
1337 	}
1338 
1339 	mutex_enter(&fcp_global_mutex);
1340 	if (!(fcp_oflag & FCP_OPEN)) {
1341 		mutex_exit(&fcp_global_mutex);
1342 		return (ENODEV);
1343 	}
1344 	fcp_oflag = FCP_IDLE;
1345 	mutex_exit(&fcp_global_mutex);
1346 
1347 	return (0);
1348 }
1349 
1350 
1351 /*
1352  * fcp_ioctl
1353  *	Entry point for the FCP ioctls
1354  *
1355  * Input:
1356  *	See ioctl(9E)
1357  *
1358  * Output:
1359  *	See ioctl(9E)
1360  *
1361  * Returns:
1362  *	See ioctl(9E)
1363  *
1364  * Context:
1365  *	Kernel context.
1366  */
1367 /* ARGSUSED */
1368 static int
1369 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1370     int *rval)
1371 {
1372 	int			ret = 0;
1373 
1374 	mutex_enter(&fcp_global_mutex);
1375 	if (!(fcp_oflag & FCP_OPEN)) {
1376 		mutex_exit(&fcp_global_mutex);
1377 		return (ENXIO);
1378 	}
1379 	mutex_exit(&fcp_global_mutex);
1380 
1381 	switch (cmd) {
1382 	case FCP_TGT_INQUIRY:
1383 	case FCP_TGT_CREATE:
1384 	case FCP_TGT_DELETE:
1385 		ret = fcp_setup_device_data_ioctl(cmd,
1386 		    (struct fcp_ioctl *)data, mode, rval);
1387 		break;
1388 
1389 	case FCP_TGT_SEND_SCSI:
1390 		mutex_enter(&fcp_ioctl_mutex);
1391 		ret = fcp_setup_scsi_ioctl(
1392 		    (struct fcp_scsi_cmd *)data, mode, rval);
1393 		mutex_exit(&fcp_ioctl_mutex);
1394 		break;
1395 
1396 	case FCP_STATE_COUNT:
1397 		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1398 		    mode, rval);
1399 		break;
1400 	case FCP_GET_TARGET_MAPPINGS:
1401 		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1402 		    mode, rval);
1403 		break;
1404 	default:
1405 		fcp_log(CE_WARN, NULL,
1406 		    "!Invalid ioctl opcode = 0x%x", cmd);
1407 		ret	= EINVAL;
1408 	}
1409 
1410 	return (ret);
1411 }
1412 
1413 
1414 /*
1415  * fcp_setup_device_data_ioctl
1416  *	Setup handler for the "device data" style of
1417  *	ioctl for FCP.	See "fcp_util.h" for data structure
1418  *	definition.
1419  *
1420  * Input:
1421  *	cmd	= FCP ioctl command
1422  *	data	= ioctl data
1423  *	mode	= See ioctl(9E)
1424  *
1425  * Output:
1426  *	data	= ioctl data
1427  *	rval	= return value - see ioctl(9E)
1428  *
1429  * Returns:
1430  *	See ioctl(9E)
1431  *
1432  * Context:
1433  *	Kernel context.
1434  */
1435 /* ARGSUSED */
1436 static int
1437 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1438     int *rval)
1439 {
1440 	struct fcp_port	*pptr;
1441 	struct	device_data	*dev_data;
1442 	uint32_t		link_cnt;
1443 	la_wwn_t		*wwn_ptr = NULL;
1444 	struct fcp_tgt		*ptgt = NULL;
1445 	struct fcp_lun		*plun = NULL;
1446 	int			i, error;
1447 	struct fcp_ioctl	fioctl;
1448 
1449 #ifdef	_MULTI_DATAMODEL
1450 	switch (ddi_model_convert_from(mode & FMODELS)) {
1451 	case DDI_MODEL_ILP32: {
1452 		struct fcp32_ioctl f32_ioctl;
1453 
1454 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1455 		    sizeof (struct fcp32_ioctl), mode)) {
1456 			return (EFAULT);
1457 		}
1458 		fioctl.fp_minor = f32_ioctl.fp_minor;
1459 		fioctl.listlen = f32_ioctl.listlen;
1460 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1461 		break;
1462 	}
1463 	case DDI_MODEL_NONE:
1464 		if (ddi_copyin((void *)data, (void *)&fioctl,
1465 		    sizeof (struct fcp_ioctl), mode)) {
1466 			return (EFAULT);
1467 		}
1468 		break;
1469 	}
1470 
1471 #else	/* _MULTI_DATAMODEL */
1472 	if (ddi_copyin((void *)data, (void *)&fioctl,
1473 	    sizeof (struct fcp_ioctl), mode)) {
1474 		return (EFAULT);
1475 	}
1476 #endif	/* _MULTI_DATAMODEL */
1477 
1478 	/*
1479 	 * Right now we can assume that the minor number matches with
1480 	 * this instance of fp. If this changes we will need to
1481 	 * revisit this logic.
1482 	 */
1483 	mutex_enter(&fcp_global_mutex);
1484 	pptr = fcp_port_head;
1485 	while (pptr) {
1486 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1487 			break;
1488 		} else {
1489 			pptr = pptr->port_next;
1490 		}
1491 	}
1492 	mutex_exit(&fcp_global_mutex);
1493 	if (pptr == NULL) {
1494 		return (ENXIO);
1495 	}
1496 	mutex_enter(&pptr->port_mutex);
1497 
1498 
1499 	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1500 	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
1501 		mutex_exit(&pptr->port_mutex);
1502 		return (ENOMEM);
1503 	}
1504 
1505 	if (ddi_copyin(fioctl.list, dev_data,
1506 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1507 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1508 		mutex_exit(&pptr->port_mutex);
1509 		return (EFAULT);
1510 	}
1511 	link_cnt = pptr->port_link_cnt;
1512 
1513 	if (cmd == FCP_TGT_INQUIRY) {
1514 		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1515 		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1516 		    sizeof (wwn_ptr->raw_wwn)) == 0) {
1517 			/* This ioctl is requesting INQ info of local HBA */
1518 			mutex_exit(&pptr->port_mutex);
1519 			dev_data[0].dev0_type = DTYPE_UNKNOWN;
1520 			dev_data[0].dev_status = 0;
1521 			if (ddi_copyout(dev_data, fioctl.list,
1522 			    (sizeof (struct device_data)) * fioctl.listlen,
1523 			    mode)) {
1524 				kmem_free(dev_data,
1525 				    sizeof (*dev_data) * fioctl.listlen);
1526 				return (EFAULT);
1527 			}
1528 			kmem_free(dev_data,
1529 			    sizeof (*dev_data) * fioctl.listlen);
1530 #ifdef	_MULTI_DATAMODEL
1531 			switch (ddi_model_convert_from(mode & FMODELS)) {
1532 			case DDI_MODEL_ILP32: {
1533 				struct fcp32_ioctl f32_ioctl;
1534 				f32_ioctl.fp_minor = fioctl.fp_minor;
1535 				f32_ioctl.listlen = fioctl.listlen;
1536 				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1537 				if (ddi_copyout((void *)&f32_ioctl,
1538 				    (void *)data,
1539 				    sizeof (struct fcp32_ioctl), mode)) {
1540 					return (EFAULT);
1541 				}
1542 				break;
1543 			}
1544 			case DDI_MODEL_NONE:
1545 				if (ddi_copyout((void *)&fioctl, (void *)data,
1546 				    sizeof (struct fcp_ioctl), mode)) {
1547 					return (EFAULT);
1548 				}
1549 				break;
1550 			}
1551 #else	/* _MULTI_DATAMODEL */
1552 			if (ddi_copyout((void *)&fioctl, (void *)data,
1553 			    sizeof (struct fcp_ioctl), mode)) {
1554 				return (EFAULT);
1555 			}
1556 #endif	/* _MULTI_DATAMODEL */
1557 			return (0);
1558 		}
1559 	}
1560 
1561 	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1562 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1563 		mutex_exit(&pptr->port_mutex);
1564 		return (ENXIO);
1565 	}
1566 
1567 	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1568 	    i++) {
1569 		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1570 
1571 		dev_data[i].dev0_type = DTYPE_UNKNOWN;
1572 
1573 
1574 		dev_data[i].dev_status = ENXIO;
1575 
1576 		if ((ptgt = fcp_lookup_target(pptr,
1577 		    (uchar_t *)wwn_ptr)) == NULL) {
1578 			mutex_exit(&pptr->port_mutex);
1579 			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1580 			    wwn_ptr, &error, 0) == NULL) {
1581 				dev_data[i].dev_status = ENODEV;
1582 				mutex_enter(&pptr->port_mutex);
1583 				continue;
1584 			} else {
1585 
1586 				dev_data[i].dev_status = EAGAIN;
1587 
1588 				mutex_enter(&pptr->port_mutex);
1589 				continue;
1590 			}
1591 		} else {
1592 			mutex_enter(&ptgt->tgt_mutex);
1593 			if (ptgt->tgt_state & (FCP_TGT_MARK |
1594 			    FCP_TGT_BUSY)) {
1595 				dev_data[i].dev_status = EAGAIN;
1596 				mutex_exit(&ptgt->tgt_mutex);
1597 				continue;
1598 			}
1599 
1600 			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1601 				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1602 					dev_data[i].dev_status = ENOTSUP;
1603 				} else {
1604 					dev_data[i].dev_status = ENXIO;
1605 				}
1606 				mutex_exit(&ptgt->tgt_mutex);
1607 				continue;
1608 			}
1609 
1610 			switch (cmd) {
1611 			case FCP_TGT_INQUIRY:
1612 				/*
1613 				 * The reason we give device type of
1614 				 * lun 0 only even though in some
1615 				 * cases(like maxstrat) lun 0 device
1616 				 * type may be 0x3f(invalid) is that
1617 				 * for bridge boxes target will appear
1618 				 * as luns and the first lun could be
1619 				 * a device that utility may not care
1620 				 * about (like a tape device).
1621 				 */
1622 				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1623 				dev_data[i].dev_status = 0;
1624 				mutex_exit(&ptgt->tgt_mutex);
1625 
1626 				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1627 					dev_data[i].dev0_type = DTYPE_UNKNOWN;
1628 				} else {
1629 					dev_data[i].dev0_type = plun->lun_type;
1630 				}
1631 				mutex_enter(&ptgt->tgt_mutex);
1632 				break;
1633 
1634 			case FCP_TGT_CREATE:
1635 				mutex_exit(&ptgt->tgt_mutex);
1636 				mutex_exit(&pptr->port_mutex);
1637 
1638 				/*
1639 				 * serialize state change call backs.
1640 				 * only one call back will be handled
1641 				 * at a time.
1642 				 */
1643 				mutex_enter(&fcp_global_mutex);
1644 				if (fcp_oflag & FCP_BUSY) {
1645 					mutex_exit(&fcp_global_mutex);
1646 					if (dev_data) {
1647 						kmem_free(dev_data,
1648 						    sizeof (*dev_data) *
1649 						    fioctl.listlen);
1650 					}
1651 					return (EBUSY);
1652 				}
1653 				fcp_oflag |= FCP_BUSY;
1654 				mutex_exit(&fcp_global_mutex);
1655 
1656 				dev_data[i].dev_status =
1657 				    fcp_create_on_demand(pptr,
1658 				    wwn_ptr->raw_wwn);
1659 
1660 				if (dev_data[i].dev_status != 0) {
1661 					char	buf[25];
1662 
1663 					for (i = 0; i < FC_WWN_SIZE; i++) {
1664 						(void) sprintf(&buf[i << 1],
1665 						    "%02x",
1666 						    wwn_ptr->raw_wwn[i]);
1667 					}
1668 
1669 					fcp_log(CE_WARN, pptr->port_dip,
1670 					    "!Failed to create nodes for"
1671 					    " pwwn=%s; error=%x", buf,
1672 					    dev_data[i].dev_status);
1673 				}
1674 
1675 				/* allow state change call backs again */
1676 				mutex_enter(&fcp_global_mutex);
1677 				fcp_oflag &= ~FCP_BUSY;
1678 				mutex_exit(&fcp_global_mutex);
1679 
1680 				mutex_enter(&pptr->port_mutex);
1681 				mutex_enter(&ptgt->tgt_mutex);
1682 
1683 				break;
1684 
1685 			case FCP_TGT_DELETE:
1686 				break;
1687 
1688 			default:
1689 				fcp_log(CE_WARN, pptr->port_dip,
1690 				    "!Invalid device data ioctl "
1691 				    "opcode = 0x%x", cmd);
1692 			}
1693 			mutex_exit(&ptgt->tgt_mutex);
1694 		}
1695 	}
1696 	mutex_exit(&pptr->port_mutex);
1697 
1698 	if (ddi_copyout(dev_data, fioctl.list,
1699 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1700 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1701 		return (EFAULT);
1702 	}
1703 	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1704 
1705 #ifdef	_MULTI_DATAMODEL
1706 	switch (ddi_model_convert_from(mode & FMODELS)) {
1707 	case DDI_MODEL_ILP32: {
1708 		struct fcp32_ioctl f32_ioctl;
1709 
1710 		f32_ioctl.fp_minor = fioctl.fp_minor;
1711 		f32_ioctl.listlen = fioctl.listlen;
1712 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1713 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1714 		    sizeof (struct fcp32_ioctl), mode)) {
1715 			return (EFAULT);
1716 		}
1717 		break;
1718 	}
1719 	case DDI_MODEL_NONE:
1720 		if (ddi_copyout((void *)&fioctl, (void *)data,
1721 		    sizeof (struct fcp_ioctl), mode)) {
1722 			return (EFAULT);
1723 		}
1724 		break;
1725 	}
1726 #else	/* _MULTI_DATAMODEL */
1727 
1728 	if (ddi_copyout((void *)&fioctl, (void *)data,
1729 	    sizeof (struct fcp_ioctl), mode)) {
1730 		return (EFAULT);
1731 	}
1732 #endif	/* _MULTI_DATAMODEL */
1733 
1734 	return (0);
1735 }
1736 
1737 /*
1738  * Fetch the target mappings (path, etc.) for all LUNs
1739  * on this port.
1740  */
1741 /* ARGSUSED */
1742 static int
1743 fcp_get_target_mappings(struct fcp_ioctl *data,
1744     int mode, int *rval)
1745 {
1746 	struct fcp_port	    *pptr;
1747 	fc_hba_target_mappings_t    *mappings;
1748 	fc_hba_mapping_entry_t	    *map;
1749 	struct fcp_tgt	    *ptgt = NULL;
1750 	struct fcp_lun	    *plun = NULL;
1751 	int			    i, mapIndex, mappingSize;
1752 	int			    listlen;
1753 	struct fcp_ioctl	    fioctl;
1754 	char			    *path;
1755 	fcp_ent_addr_t		    sam_lun_addr;
1756 
1757 #ifdef	_MULTI_DATAMODEL
1758 	switch (ddi_model_convert_from(mode & FMODELS)) {
1759 	case DDI_MODEL_ILP32: {
1760 		struct fcp32_ioctl f32_ioctl;
1761 
1762 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1763 		    sizeof (struct fcp32_ioctl), mode)) {
1764 			return (EFAULT);
1765 		}
1766 		fioctl.fp_minor = f32_ioctl.fp_minor;
1767 		fioctl.listlen = f32_ioctl.listlen;
1768 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1769 		break;
1770 	}
1771 	case DDI_MODEL_NONE:
1772 		if (ddi_copyin((void *)data, (void *)&fioctl,
1773 		    sizeof (struct fcp_ioctl), mode)) {
1774 			return (EFAULT);
1775 		}
1776 		break;
1777 	}
1778 
1779 #else	/* _MULTI_DATAMODEL */
1780 	if (ddi_copyin((void *)data, (void *)&fioctl,
1781 	    sizeof (struct fcp_ioctl), mode)) {
1782 		return (EFAULT);
1783 	}
1784 #endif	/* _MULTI_DATAMODEL */
1785 
1786 	/*
1787 	 * Right now we can assume that the minor number matches with
1788 	 * this instance of fp. If this changes we will need to
1789 	 * revisit this logic.
1790 	 */
1791 	mutex_enter(&fcp_global_mutex);
1792 	pptr = fcp_port_head;
1793 	while (pptr) {
1794 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1795 			break;
1796 		} else {
1797 			pptr = pptr->port_next;
1798 		}
1799 	}
1800 	mutex_exit(&fcp_global_mutex);
1801 	if (pptr == NULL) {
1802 		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1803 		    fioctl.fp_minor);
1804 		return (ENXIO);
1805 	}
1806 
1807 
1808 	/* We use listlen to show the total buffer size */
1809 	mappingSize = fioctl.listlen;
1810 
1811 	/* Now calculate how many mapping entries will fit */
1812 	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1813 	    - sizeof (fc_hba_target_mappings_t);
1814 	if (listlen <= 0) {
1815 		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1816 		return (ENXIO);
1817 	}
1818 	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1819 
1820 	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1821 		return (ENOMEM);
1822 	}
1823 	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1824 
1825 	/* Now get to work */
1826 	mapIndex = 0;
1827 
1828 	mutex_enter(&pptr->port_mutex);
1829 	/* Loop through all targets on this port */
1830 	for (i = 0; i < FCP_NUM_HASH; i++) {
1831 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1832 		    ptgt = ptgt->tgt_next) {
1833 
1834 
1835 			/* Loop through all LUNs on this target */
1836 			for (plun = ptgt->tgt_lun; plun != NULL;
1837 			    plun = plun->lun_next) {
1838 				if (plun->lun_state & FCP_LUN_OFFLINE) {
1839 					continue;
1840 				}
1841 
1842 				path = fcp_get_lun_path(plun);
1843 				if (path == NULL) {
1844 					continue;
1845 				}
1846 
1847 				if (mapIndex >= listlen) {
1848 					mapIndex ++;
1849 					kmem_free(path, MAXPATHLEN);
1850 					continue;
1851 				}
1852 				map = &mappings->entries[mapIndex++];
1853 				bcopy(path, map->targetDriver,
1854 				    sizeof (map->targetDriver));
1855 				map->d_id = ptgt->tgt_d_id;
1856 				map->busNumber = 0;
1857 				map->targetNumber = ptgt->tgt_d_id;
1858 				map->osLUN = plun->lun_num;
1859 
1860 				/*
1861 				 * We had swapped lun when we stored it in
1862 				 * lun_addr. We need to swap it back before
1863 				 * returning it to user land
1864 				 */
1865 
1866 				sam_lun_addr.ent_addr_0 =
1867 				    BE_16(plun->lun_addr.ent_addr_0);
1868 				sam_lun_addr.ent_addr_1 =
1869 				    BE_16(plun->lun_addr.ent_addr_1);
1870 				sam_lun_addr.ent_addr_2 =
1871 				    BE_16(plun->lun_addr.ent_addr_2);
1872 				sam_lun_addr.ent_addr_3 =
1873 				    BE_16(plun->lun_addr.ent_addr_3);
1874 
1875 				bcopy(&sam_lun_addr, &map->samLUN,
1876 				    FCP_LUN_SIZE);
1877 				bcopy(ptgt->tgt_node_wwn.raw_wwn,
1878 				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1879 				bcopy(ptgt->tgt_port_wwn.raw_wwn,
1880 				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1881 
1882 				if (plun->lun_guid) {
1883 
1884 					/* convert ascii wwn to bytes */
1885 					fcp_ascii_to_wwn(plun->lun_guid,
1886 					    map->guid, sizeof (map->guid));
1887 
1888 					if ((sizeof (map->guid)) <
1889 					    plun->lun_guid_size / 2) {
1890 						cmn_err(CE_WARN,
1891 						    "fcp_get_target_mappings:"
1892 						    "guid copy space "
1893 						    "insufficient."
1894 						    "Copy Truncation - "
1895 						    "available %d; need %d",
1896 						    (int)sizeof (map->guid),
1897 						    (int)
1898 						    plun->lun_guid_size / 2);
1899 					}
1900 				}
1901 				kmem_free(path, MAXPATHLEN);
1902 			}
1903 		}
1904 	}
1905 	mutex_exit(&pptr->port_mutex);
1906 	mappings->numLuns = mapIndex;
1907 
1908 	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1909 		kmem_free(mappings, mappingSize);
1910 		return (EFAULT);
1911 	}
1912 	kmem_free(mappings, mappingSize);
1913 
1914 #ifdef	_MULTI_DATAMODEL
1915 	switch (ddi_model_convert_from(mode & FMODELS)) {
1916 	case DDI_MODEL_ILP32: {
1917 		struct fcp32_ioctl f32_ioctl;
1918 
1919 		f32_ioctl.fp_minor = fioctl.fp_minor;
1920 		f32_ioctl.listlen = fioctl.listlen;
1921 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1922 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1923 		    sizeof (struct fcp32_ioctl), mode)) {
1924 			return (EFAULT);
1925 		}
1926 		break;
1927 	}
1928 	case DDI_MODEL_NONE:
1929 		if (ddi_copyout((void *)&fioctl, (void *)data,
1930 		    sizeof (struct fcp_ioctl), mode)) {
1931 			return (EFAULT);
1932 		}
1933 		break;
1934 	}
1935 #else	/* _MULTI_DATAMODEL */
1936 
1937 	if (ddi_copyout((void *)&fioctl, (void *)data,
1938 	    sizeof (struct fcp_ioctl), mode)) {
1939 		return (EFAULT);
1940 	}
1941 #endif	/* _MULTI_DATAMODEL */
1942 
1943 	return (0);
1944 }
1945 
1946 /*
1947  * fcp_setup_scsi_ioctl
1948  *	Setup handler for the "scsi passthru" style of
1949  *	ioctl for FCP.	See "fcp_util.h" for data structure
1950  *	definition.
1951  *
1952  * Input:
1953  *	u_fscsi	= ioctl data (user address space)
1954  *	mode	= See ioctl(9E)
1955  *
1956  * Output:
1957  *	u_fscsi	= ioctl data (user address space)
1958  *	rval	= return value - see ioctl(9E)
1959  *
1960  * Returns:
1961  *	0	= OK
1962  *	EAGAIN	= See errno.h
1963  *	EBUSY	= See errno.h
1964  *	EFAULT	= See errno.h
1965  *	EINTR	= See errno.h
1966  *	EINVAL	= See errno.h
1967  *	EIO	= See errno.h
1968  *	ENOMEM	= See errno.h
1969  *	ENXIO	= See errno.h
1970  *
1971  * Context:
1972  *	Kernel context.
1973  */
1974 /* ARGSUSED */
1975 static int
1976 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1977     int mode, int *rval)
1978 {
1979 	int			ret		= 0;
1980 	int			temp_ret;
1981 	caddr_t			k_cdbbufaddr	= NULL;
1982 	caddr_t			k_bufaddr	= NULL;
1983 	caddr_t			k_rqbufaddr	= NULL;
1984 	caddr_t			u_cdbbufaddr;
1985 	caddr_t			u_bufaddr;
1986 	caddr_t			u_rqbufaddr;
1987 	struct fcp_scsi_cmd	k_fscsi;
1988 
1989 	/*
1990 	 * Get fcp_scsi_cmd array element from user address space
1991 	 */
1992 	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1993 	    != 0) {
1994 		return (ret);
1995 	}
1996 
1997 
1998 	/*
1999 	 * Even though kmem_alloc() checks the validity of the
2000 	 * buffer length, this check is needed when the
2001 	 * kmem_flags set and the zero buffer length is passed.
2002 	 */
2003 	if ((k_fscsi.scsi_cdblen <= 0) ||
2004 	    (k_fscsi.scsi_buflen <= 0) ||
2005 	    (k_fscsi.scsi_buflen > FCP_MAX_RESPONSE_LEN) ||
2006 	    (k_fscsi.scsi_rqlen <= 0) ||
2007 	    (k_fscsi.scsi_rqlen > FCP_MAX_SENSE_LEN)) {
2008 		return (EINVAL);
2009 	}
2010 
2011 	/*
2012 	 * Allocate data for fcp_scsi_cmd pointer fields
2013 	 */
2014 	if (ret == 0) {
2015 		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2016 		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2017 		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2018 
2019 		if (k_cdbbufaddr == NULL ||
2020 		    k_bufaddr	 == NULL ||
2021 		    k_rqbufaddr	 == NULL) {
2022 			ret = ENOMEM;
2023 		}
2024 	}
2025 
2026 	/*
2027 	 * Get fcp_scsi_cmd pointer fields from user
2028 	 * address space
2029 	 */
2030 	if (ret == 0) {
2031 		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2032 		u_bufaddr    = k_fscsi.scsi_bufaddr;
2033 		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2034 
2035 		if (ddi_copyin(u_cdbbufaddr,
2036 		    k_cdbbufaddr,
2037 		    k_fscsi.scsi_cdblen,
2038 		    mode)) {
2039 			ret = EFAULT;
2040 		} else if (ddi_copyin(u_bufaddr,
2041 		    k_bufaddr,
2042 		    k_fscsi.scsi_buflen,
2043 		    mode)) {
2044 			ret = EFAULT;
2045 		} else if (ddi_copyin(u_rqbufaddr,
2046 		    k_rqbufaddr,
2047 		    k_fscsi.scsi_rqlen,
2048 		    mode)) {
2049 			ret = EFAULT;
2050 		}
2051 	}
2052 
2053 	/*
2054 	 * Send scsi command (blocking)
2055 	 */
2056 	if (ret == 0) {
2057 		/*
2058 		 * Prior to sending the scsi command, the
2059 		 * fcp_scsi_cmd data structure must contain kernel,
2060 		 * not user, addresses.
2061 		 */
2062 		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
2063 		k_fscsi.scsi_bufaddr	= k_bufaddr;
2064 		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
2065 
2066 		ret = fcp_send_scsi_ioctl(&k_fscsi);
2067 
2068 		/*
2069 		 * After sending the scsi command, the
2070 		 * fcp_scsi_cmd data structure must contain user,
2071 		 * not kernel, addresses.
2072 		 */
2073 		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
2074 		k_fscsi.scsi_bufaddr	= u_bufaddr;
2075 		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
2076 	}
2077 
2078 	/*
2079 	 * Put fcp_scsi_cmd pointer fields to user address space
2080 	 */
2081 	if (ret == 0) {
2082 		if (ddi_copyout(k_cdbbufaddr,
2083 		    u_cdbbufaddr,
2084 		    k_fscsi.scsi_cdblen,
2085 		    mode)) {
2086 			ret = EFAULT;
2087 		} else if (ddi_copyout(k_bufaddr,
2088 		    u_bufaddr,
2089 		    k_fscsi.scsi_buflen,
2090 		    mode)) {
2091 			ret = EFAULT;
2092 		} else if (ddi_copyout(k_rqbufaddr,
2093 		    u_rqbufaddr,
2094 		    k_fscsi.scsi_rqlen,
2095 		    mode)) {
2096 			ret = EFAULT;
2097 		}
2098 	}
2099 
2100 	/*
2101 	 * Free data for fcp_scsi_cmd pointer fields
2102 	 */
2103 	if (k_cdbbufaddr != NULL) {
2104 		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2105 	}
2106 	if (k_bufaddr != NULL) {
2107 		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2108 	}
2109 	if (k_rqbufaddr != NULL) {
2110 		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2111 	}
2112 
2113 	/*
2114 	 * Put fcp_scsi_cmd array element to user address space
2115 	 */
2116 	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2117 	if (temp_ret != 0) {
2118 		ret = temp_ret;
2119 	}
2120 
2121 	/*
2122 	 * Return status
2123 	 */
2124 	return (ret);
2125 }
2126 
2127 
2128 /*
2129  * fcp_copyin_scsi_cmd
2130  *	Copy in fcp_scsi_cmd data structure from user address space.
2131  *	The data may be in 32 bit or 64 bit modes.
2132  *
2133  * Input:
2134  *	base_addr	= from address (user address space)
2135  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2136  *
2137  * Output:
2138  *	fscsi		= to address (kernel address space)
2139  *
2140  * Returns:
2141  *	0	= OK
2142  *	EFAULT	= Error
2143  *
2144  * Context:
2145  *	Kernel context.
2146  */
2147 static int
2148 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2149 {
2150 #ifdef	_MULTI_DATAMODEL
2151 	struct fcp32_scsi_cmd	f32scsi;
2152 
2153 	switch (ddi_model_convert_from(mode & FMODELS)) {
2154 	case DDI_MODEL_ILP32:
2155 		/*
2156 		 * Copy data from user address space
2157 		 */
2158 		if (ddi_copyin((void *)base_addr,
2159 		    &f32scsi,
2160 		    sizeof (struct fcp32_scsi_cmd),
2161 		    mode)) {
2162 			return (EFAULT);
2163 		}
2164 		/*
2165 		 * Convert from 32 bit to 64 bit
2166 		 */
2167 		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2168 		break;
2169 	case DDI_MODEL_NONE:
2170 		/*
2171 		 * Copy data from user address space
2172 		 */
2173 		if (ddi_copyin((void *)base_addr,
2174 		    fscsi,
2175 		    sizeof (struct fcp_scsi_cmd),
2176 		    mode)) {
2177 			return (EFAULT);
2178 		}
2179 		break;
2180 	}
2181 #else	/* _MULTI_DATAMODEL */
2182 	/*
2183 	 * Copy data from user address space
2184 	 */
2185 	if (ddi_copyin((void *)base_addr,
2186 	    fscsi,
2187 	    sizeof (struct fcp_scsi_cmd),
2188 	    mode)) {
2189 		return (EFAULT);
2190 	}
2191 #endif	/* _MULTI_DATAMODEL */
2192 
2193 	return (0);
2194 }
2195 
2196 
2197 /*
2198  * fcp_copyout_scsi_cmd
2199  *	Copy out fcp_scsi_cmd data structure to user address space.
2200  *	The data may be in 32 bit or 64 bit modes.
2201  *
2202  * Input:
2203  *	fscsi		= to address (kernel address space)
2204  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2205  *
2206  * Output:
2207  *	base_addr	= from address (user address space)
2208  *
2209  * Returns:
2210  *	0	= OK
2211  *	EFAULT	= Error
2212  *
2213  * Context:
2214  *	Kernel context.
2215  */
2216 static int
2217 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2218 {
2219 #ifdef	_MULTI_DATAMODEL
2220 	struct fcp32_scsi_cmd	f32scsi;
2221 
2222 	switch (ddi_model_convert_from(mode & FMODELS)) {
2223 	case DDI_MODEL_ILP32:
2224 		/*
2225 		 * Convert from 64 bit to 32 bit
2226 		 */
2227 		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2228 		/*
2229 		 * Copy data to user address space
2230 		 */
2231 		if (ddi_copyout(&f32scsi,
2232 		    (void *)base_addr,
2233 		    sizeof (struct fcp32_scsi_cmd),
2234 		    mode)) {
2235 			return (EFAULT);
2236 		}
2237 		break;
2238 	case DDI_MODEL_NONE:
2239 		/*
2240 		 * Copy data to user address space
2241 		 */
2242 		if (ddi_copyout(fscsi,
2243 		    (void *)base_addr,
2244 		    sizeof (struct fcp_scsi_cmd),
2245 		    mode)) {
2246 			return (EFAULT);
2247 		}
2248 		break;
2249 	}
2250 #else	/* _MULTI_DATAMODEL */
2251 	/*
2252 	 * Copy data to user address space
2253 	 */
2254 	if (ddi_copyout(fscsi,
2255 	    (void *)base_addr,
2256 	    sizeof (struct fcp_scsi_cmd),
2257 	    mode)) {
2258 		return (EFAULT);
2259 	}
2260 #endif	/* _MULTI_DATAMODEL */
2261 
2262 	return (0);
2263 }
2264 
2265 
2266 /*
2267  * fcp_send_scsi_ioctl
2268  *	Sends the SCSI command in blocking mode.
2269  *
2270  * Input:
2271  *	fscsi		= SCSI command data structure
2272  *
2273  * Output:
2274  *	fscsi		= SCSI command data structure
2275  *
2276  * Returns:
2277  *	0	= OK
2278  *	EAGAIN	= See errno.h
2279  *	EBUSY	= See errno.h
2280  *	EINTR	= See errno.h
2281  *	EINVAL	= See errno.h
2282  *	EIO	= See errno.h
2283  *	ENOMEM	= See errno.h
2284  *	ENXIO	= See errno.h
2285  *
2286  * Context:
2287  *	Kernel context.
2288  */
2289 static int
2290 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2291 {
2292 	struct fcp_lun	*plun		= NULL;
2293 	struct fcp_port	*pptr		= NULL;
2294 	struct fcp_tgt	*ptgt		= NULL;
2295 	fc_packet_t		*fpkt		= NULL;
2296 	struct fcp_ipkt	*icmd		= NULL;
2297 	int			target_created	= FALSE;
2298 	fc_frame_hdr_t		*hp;
2299 	struct fcp_cmd		fcp_cmd;
2300 	struct fcp_cmd		*fcmd;
2301 	union scsi_cdb		*scsi_cdb;
2302 	la_wwn_t		*wwn_ptr;
2303 	int			nodma;
2304 	struct fcp_rsp		*rsp;
2305 	struct fcp_rsp_info	*rsp_info;
2306 	caddr_t			rsp_sense;
2307 	int			buf_len;
2308 	int			info_len;
2309 	int			sense_len;
2310 	struct scsi_extended_sense	*sense_to = NULL;
2311 	timeout_id_t		tid;
2312 	uint8_t			reconfig_lun = FALSE;
2313 	uint8_t			reconfig_pending = FALSE;
2314 	uint8_t			scsi_cmd;
2315 	int			rsp_len;
2316 	int			cmd_index;
2317 	int			fc_status;
2318 	int			pkt_state;
2319 	int			pkt_action;
2320 	int			pkt_reason;
2321 	int			ret, xport_retval = ~FC_SUCCESS;
2322 	int			lcount;
2323 	int			tcount;
2324 	int			reconfig_status;
2325 	int			port_busy = FALSE;
2326 	uchar_t			*lun_string;
2327 
2328 	/*
2329 	 * Check valid SCSI command
2330 	 */
2331 	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2332 	ret = EINVAL;
2333 	for (cmd_index = 0;
2334 	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2335 	    ret != 0;
2336 	    cmd_index++) {
2337 		/*
2338 		 * First byte of CDB is the SCSI command
2339 		 */
2340 		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2341 			ret = 0;
2342 		}
2343 	}
2344 
2345 	/*
2346 	 * Check inputs
2347 	 */
2348 	if (fscsi->scsi_flags != FCP_SCSI_READ) {
2349 		ret = EINVAL;
2350 	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2351 		/* no larger than */
2352 		ret = EINVAL;
2353 	}
2354 
2355 
2356 	/*
2357 	 * Find FC port
2358 	 */
2359 	if (ret == 0) {
2360 		/*
2361 		 * Acquire global mutex
2362 		 */
2363 		mutex_enter(&fcp_global_mutex);
2364 
2365 		pptr = fcp_port_head;
2366 		while (pptr) {
2367 			if (pptr->port_instance ==
2368 			    (uint32_t)fscsi->scsi_fc_port_num) {
2369 				break;
2370 			} else {
2371 				pptr = pptr->port_next;
2372 			}
2373 		}
2374 
2375 		if (pptr == NULL) {
2376 			ret = ENXIO;
2377 		} else {
2378 			/*
2379 			 * fc_ulp_busy_port can raise power
2380 			 *  so, we must not hold any mutexes involved in PM
2381 			 */
2382 			mutex_exit(&fcp_global_mutex);
2383 			ret = fc_ulp_busy_port(pptr->port_fp_handle);
2384 		}
2385 
2386 		if (ret == 0) {
2387 
2388 			/* remember port is busy, so we will release later */
2389 			port_busy = TRUE;
2390 
2391 			/*
2392 			 * If there is a reconfiguration in progress, wait
2393 			 * for it to complete.
2394 			 */
2395 
2396 			fcp_reconfig_wait(pptr);
2397 
2398 			/* reacquire mutexes in order */
2399 			mutex_enter(&fcp_global_mutex);
2400 			mutex_enter(&pptr->port_mutex);
2401 
2402 			/*
2403 			 * Will port accept DMA?
2404 			 */
2405 			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2406 			    ? 1 : 0;
2407 
2408 			/*
2409 			 * If init or offline, device not known
2410 			 *
2411 			 * If we are discovering (onlining), we can
2412 			 * NOT obviously provide reliable data about
2413 			 * devices until it is complete
2414 			 */
2415 			if (pptr->port_state &	  (FCP_STATE_INIT |
2416 			    FCP_STATE_OFFLINE)) {
2417 				ret = ENXIO;
2418 			} else if (pptr->port_state & FCP_STATE_ONLINING) {
2419 				ret = EBUSY;
2420 			} else {
2421 				/*
2422 				 * Find target from pwwn
2423 				 *
2424 				 * The wwn must be put into a local
2425 				 * variable to ensure alignment.
2426 				 */
2427 				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2428 				ptgt = fcp_lookup_target(pptr,
2429 				    (uchar_t *)wwn_ptr);
2430 
2431 				/*
2432 				 * If target not found,
2433 				 */
2434 				if (ptgt == NULL) {
2435 					/*
2436 					 * Note: Still have global &
2437 					 * port mutexes
2438 					 */
2439 					mutex_exit(&pptr->port_mutex);
2440 					ptgt = fcp_port_create_tgt(pptr,
2441 					    wwn_ptr, &ret, &fc_status,
2442 					    &pkt_state, &pkt_action,
2443 					    &pkt_reason);
2444 					mutex_enter(&pptr->port_mutex);
2445 
2446 					fscsi->scsi_fc_status  = fc_status;
2447 					fscsi->scsi_pkt_state  =
2448 					    (uchar_t)pkt_state;
2449 					fscsi->scsi_pkt_reason = pkt_reason;
2450 					fscsi->scsi_pkt_action =
2451 					    (uchar_t)pkt_action;
2452 
2453 					if (ptgt != NULL) {
2454 						target_created = TRUE;
2455 					} else if (ret == 0) {
2456 						ret = ENOMEM;
2457 					}
2458 				}
2459 
2460 				if (ret == 0) {
2461 					/*
2462 					 * Acquire target
2463 					 */
2464 					mutex_enter(&ptgt->tgt_mutex);
2465 
2466 					/*
2467 					 * If target is mark or busy,
2468 					 * then target can not be used
2469 					 */
2470 					if (ptgt->tgt_state &
2471 					    (FCP_TGT_MARK |
2472 					    FCP_TGT_BUSY)) {
2473 						ret = EBUSY;
2474 					} else {
2475 						/*
2476 						 * Mark target as busy
2477 						 */
2478 						ptgt->tgt_state |=
2479 						    FCP_TGT_BUSY;
2480 					}
2481 
2482 					/*
2483 					 * Release target
2484 					 */
2485 					lcount = pptr->port_link_cnt;
2486 					tcount = ptgt->tgt_change_cnt;
2487 					mutex_exit(&ptgt->tgt_mutex);
2488 				}
2489 			}
2490 
2491 			/*
2492 			 * Release port
2493 			 */
2494 			mutex_exit(&pptr->port_mutex);
2495 		}
2496 
2497 		/*
2498 		 * Release global mutex
2499 		 */
2500 		mutex_exit(&fcp_global_mutex);
2501 	}
2502 
2503 	if (ret == 0) {
2504 		uint64_t belun = BE_64(fscsi->scsi_lun);
2505 
2506 		/*
2507 		 * If it's a target device, find lun from pwwn
2508 		 * The wwn must be put into a local
2509 		 * variable to ensure alignment.
2510 		 */
2511 		mutex_enter(&pptr->port_mutex);
2512 		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2513 		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2514 			/* this is not a target */
2515 			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2516 			ret = ENXIO;
2517 		} else if ((belun << 16) != 0) {
2518 			/*
2519 			 * Since fcp only support PD and LU addressing method
2520 			 * so far, the last 6 bytes of a valid LUN are expected
2521 			 * to be filled with 00h.
2522 			 */
2523 			fscsi->scsi_fc_status = FC_INVALID_LUN;
2524 			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2525 			    " method 0x%02x with LUN number 0x%016" PRIx64,
2526 			    (uint8_t)(belun >> 62), belun);
2527 			ret = ENXIO;
2528 		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2529 		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2530 			/*
2531 			 * This is a SCSI target, but no LUN at this
2532 			 * address.
2533 			 *
2534 			 * In the future, we may want to send this to
2535 			 * the target, and let it respond
2536 			 * appropriately
2537 			 */
2538 			ret = ENXIO;
2539 		}
2540 		mutex_exit(&pptr->port_mutex);
2541 	}
2542 
2543 	/*
2544 	 * Finished grabbing external resources
2545 	 * Allocate internal packet (icmd)
2546 	 */
2547 	if (ret == 0) {
2548 		/*
2549 		 * Calc rsp len assuming rsp info included
2550 		 */
2551 		rsp_len = sizeof (struct fcp_rsp) +
2552 		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2553 
2554 		icmd = fcp_icmd_alloc(pptr, ptgt,
2555 		    sizeof (struct fcp_cmd),
2556 		    rsp_len,
2557 		    fscsi->scsi_buflen,
2558 		    nodma,
2559 		    lcount,			/* ipkt_link_cnt */
2560 		    tcount,			/* ipkt_change_cnt */
2561 		    0,				/* cause */
2562 		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
2563 
2564 		if (icmd == NULL) {
2565 			ret = ENOMEM;
2566 		} else {
2567 			/*
2568 			 * Setup internal packet as sema sync
2569 			 */
2570 			fcp_ipkt_sema_init(icmd);
2571 		}
2572 	}
2573 
2574 	if (ret == 0) {
2575 		/*
2576 		 * Init fpkt pointer for use.
2577 		 */
2578 
2579 		fpkt = icmd->ipkt_fpkt;
2580 
2581 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
2582 		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
2583 		fpkt->pkt_timeout	= fscsi->scsi_timeout;
2584 
2585 		/*
2586 		 * Init fcmd pointer for use by SCSI command
2587 		 */
2588 
2589 		if (nodma) {
2590 			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2591 		} else {
2592 			fcmd = &fcp_cmd;
2593 		}
2594 		bzero(fcmd, sizeof (struct fcp_cmd));
2595 		ptgt = plun->lun_tgt;
2596 
2597 		lun_string = (uchar_t *)&fscsi->scsi_lun;
2598 
2599 		fcmd->fcp_ent_addr.ent_addr_0 =
2600 		    BE_16(*(uint16_t *)&(lun_string[0]));
2601 		fcmd->fcp_ent_addr.ent_addr_1 =
2602 		    BE_16(*(uint16_t *)&(lun_string[2]));
2603 		fcmd->fcp_ent_addr.ent_addr_2 =
2604 		    BE_16(*(uint16_t *)&(lun_string[4]));
2605 		fcmd->fcp_ent_addr.ent_addr_3 =
2606 		    BE_16(*(uint16_t *)&(lun_string[6]));
2607 
2608 		/*
2609 		 * Setup internal packet(icmd)
2610 		 */
2611 		icmd->ipkt_lun		= plun;
2612 		icmd->ipkt_restart	= 0;
2613 		icmd->ipkt_retries	= 0;
2614 		icmd->ipkt_opcode	= 0;
2615 
2616 		/*
2617 		 * Init the frame HEADER Pointer for use
2618 		 */
2619 		hp = &fpkt->pkt_cmd_fhdr;
2620 
2621 		hp->s_id	= pptr->port_id;
2622 		hp->d_id	= ptgt->tgt_d_id;
2623 		hp->r_ctl	= R_CTL_COMMAND;
2624 		hp->type	= FC_TYPE_SCSI_FCP;
2625 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2626 		hp->rsvd	= 0;
2627 		hp->seq_id	= 0;
2628 		hp->seq_cnt	= 0;
2629 		hp->ox_id	= 0xffff;
2630 		hp->rx_id	= 0xffff;
2631 		hp->ro		= 0;
2632 
2633 		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
2634 		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
2635 		fcmd->fcp_cntl.cntl_write_data	= 0;
2636 		fcmd->fcp_data_len	= fscsi->scsi_buflen;
2637 
2638 		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2639 		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2640 		    fscsi->scsi_cdblen);
2641 
2642 		if (!nodma) {
2643 			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2644 			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2645 		}
2646 
2647 		/*
2648 		 * Send SCSI command to FC transport
2649 		 */
2650 
2651 		if (ret == 0) {
2652 			mutex_enter(&ptgt->tgt_mutex);
2653 
2654 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2655 				mutex_exit(&ptgt->tgt_mutex);
2656 				fscsi->scsi_fc_status = xport_retval =
2657 				    fc_ulp_transport(pptr->port_fp_handle,
2658 				    fpkt);
2659 				if (fscsi->scsi_fc_status != FC_SUCCESS) {
2660 					ret = EIO;
2661 				}
2662 			} else {
2663 				mutex_exit(&ptgt->tgt_mutex);
2664 				ret = EBUSY;
2665 			}
2666 		}
2667 	}
2668 
2669 	/*
2670 	 * Wait for completion only if fc_ulp_transport was called and it
2671 	 * returned a success. This is the only time callback will happen.
2672 	 * Otherwise, there is no point in waiting
2673 	 */
2674 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2675 		ret = fcp_ipkt_sema_wait(icmd);
2676 	}
2677 
2678 	/*
2679 	 * Copy data to IOCTL data structures
2680 	 */
2681 	rsp = NULL;
2682 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2683 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2684 
2685 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2686 			fcp_log(CE_WARN, pptr->port_dip,
2687 			    "!SCSI command to d_id=0x%x lun=0x%x"
2688 			    " failed, Bad FCP response values:"
2689 			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2690 			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2691 			    ptgt->tgt_d_id, plun->lun_num,
2692 			    rsp->reserved_0, rsp->reserved_1,
2693 			    rsp->fcp_u.fcp_status.reserved_0,
2694 			    rsp->fcp_u.fcp_status.reserved_1,
2695 			    rsp->fcp_response_len, rsp->fcp_sense_len);
2696 
2697 			ret = EIO;
2698 		}
2699 	}
2700 
2701 	if ((ret == 0) && (rsp != NULL)) {
2702 		/*
2703 		 * Calc response lengths
2704 		 */
2705 		sense_len = 0;
2706 		info_len = 0;
2707 
2708 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
2709 			info_len = rsp->fcp_response_len;
2710 		}
2711 
2712 		rsp_info   = (struct fcp_rsp_info *)
2713 		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2714 
2715 		/*
2716 		 * Get SCSI status
2717 		 */
2718 		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2719 		/*
2720 		 * If a lun was just added or removed and the next command
2721 		 * comes through this interface, we need to capture the check
2722 		 * condition so we can discover the new topology.
2723 		 */
2724 		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2725 		    rsp->fcp_u.fcp_status.sense_len_set) {
2726 			sense_len = rsp->fcp_sense_len;
2727 			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2728 			sense_to = (struct scsi_extended_sense *)rsp_sense;
2729 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2730 			    (FCP_SENSE_NO_LUN(sense_to))) {
2731 				reconfig_lun = TRUE;
2732 			}
2733 		}
2734 
2735 		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2736 		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2737 			if (reconfig_lun == FALSE) {
2738 				reconfig_status =
2739 				    fcp_is_reconfig_needed(ptgt, fpkt);
2740 			}
2741 
2742 			if ((reconfig_lun == TRUE) ||
2743 			    (reconfig_status == TRUE)) {
2744 				mutex_enter(&ptgt->tgt_mutex);
2745 				if (ptgt->tgt_tid == NULL) {
2746 					/*
2747 					 * Either we've been notified the
2748 					 * REPORT_LUN data has changed, or
2749 					 * we've determined on our own that
2750 					 * we're out of date.  Kick off
2751 					 * rediscovery.
2752 					 */
2753 					tid = timeout(fcp_reconfigure_luns,
2754 					    (caddr_t)ptgt, drv_usectohz(1));
2755 
2756 					ptgt->tgt_tid = tid;
2757 					ptgt->tgt_state |= FCP_TGT_BUSY;
2758 					ret = EBUSY;
2759 					reconfig_pending = TRUE;
2760 				}
2761 				mutex_exit(&ptgt->tgt_mutex);
2762 			}
2763 		}
2764 
2765 		/*
2766 		 * Calc residuals and buffer lengths
2767 		 */
2768 
2769 		if (ret == 0) {
2770 			buf_len = fscsi->scsi_buflen;
2771 			fscsi->scsi_bufresid	= 0;
2772 			if (rsp->fcp_u.fcp_status.resid_under) {
2773 				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2774 					fscsi->scsi_bufresid = rsp->fcp_resid;
2775 				} else {
2776 					cmn_err(CE_WARN, "fcp: bad residue %x "
2777 					    "for txfer len %x", rsp->fcp_resid,
2778 					    fscsi->scsi_buflen);
2779 					fscsi->scsi_bufresid =
2780 					    fscsi->scsi_buflen;
2781 				}
2782 				buf_len -= fscsi->scsi_bufresid;
2783 			}
2784 			if (rsp->fcp_u.fcp_status.resid_over) {
2785 				fscsi->scsi_bufresid = -rsp->fcp_resid;
2786 			}
2787 
2788 			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
2789 			if (fscsi->scsi_rqlen < sense_len) {
2790 				sense_len = fscsi->scsi_rqlen;
2791 			}
2792 
2793 			fscsi->scsi_fc_rspcode	= 0;
2794 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
2795 				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
2796 			}
2797 			fscsi->scsi_pkt_state	= fpkt->pkt_state;
2798 			fscsi->scsi_pkt_action	= fpkt->pkt_action;
2799 			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
2800 
2801 			/*
2802 			 * Copy data and request sense
2803 			 *
2804 			 * Data must be copied by using the FCP_CP_IN macro.
2805 			 * This will ensure the proper byte order since the data
2806 			 * is being copied directly from the memory mapped
2807 			 * device register.
2808 			 *
2809 			 * The response (and request sense) will be in the
2810 			 * correct byte order.	No special copy is necessary.
2811 			 */
2812 
2813 			if (buf_len) {
2814 				FCP_CP_IN(fpkt->pkt_data,
2815 				    fscsi->scsi_bufaddr,
2816 				    fpkt->pkt_data_acc,
2817 				    buf_len);
2818 			}
2819 			bcopy((void *)rsp_sense,
2820 			    (void *)fscsi->scsi_rqbufaddr,
2821 			    sense_len);
2822 		}
2823 	}
2824 
2825 	/*
2826 	 * Cleanup transport data structures if icmd was alloc-ed
2827 	 * So, cleanup happens in the same thread that icmd was alloc-ed
2828 	 */
2829 	if (icmd != NULL) {
2830 		fcp_ipkt_sema_cleanup(icmd);
2831 	}
2832 
2833 	/* restore pm busy/idle status */
2834 	if (port_busy) {
2835 		fc_ulp_idle_port(pptr->port_fp_handle);
2836 	}
2837 
2838 	/*
2839 	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2840 	 * flag, it'll be cleared when the reconfig is complete.
2841 	 */
2842 	if ((ptgt != NULL) && !reconfig_pending) {
2843 		/*
2844 		 * If target was created,
2845 		 */
2846 		if (target_created) {
2847 			mutex_enter(&ptgt->tgt_mutex);
2848 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2849 			mutex_exit(&ptgt->tgt_mutex);
2850 		} else {
2851 			/*
2852 			 * De-mark target as busy
2853 			 */
2854 			mutex_enter(&ptgt->tgt_mutex);
2855 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2856 			mutex_exit(&ptgt->tgt_mutex);
2857 		}
2858 	}
2859 	return (ret);
2860 }
2861 
2862 
2863 static int
2864 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2865     fc_packet_t	*fpkt)
2866 {
2867 	uchar_t			*lun_string;
2868 	uint16_t		lun_num, i;
2869 	int			num_luns;
2870 	int			actual_luns;
2871 	int			num_masked_luns;
2872 	int			lun_buflen;
2873 	struct fcp_lun	*plun	= NULL;
2874 	struct fcp_reportlun_resp	*report_lun;
2875 	uint8_t			reconfig_needed = FALSE;
2876 	uint8_t			lun_exists = FALSE;
2877 	fcp_port_t			*pptr		 = ptgt->tgt_port;
2878 
2879 	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2880 
2881 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2882 	    fpkt->pkt_datalen);
2883 
2884 	/* get number of luns (which is supplied as LUNS * 8) */
2885 	num_luns = BE_32(report_lun->num_lun) >> 3;
2886 
2887 	/*
2888 	 * Figure out exactly how many lun strings our response buffer
2889 	 * can hold.
2890 	 */
2891 	lun_buflen = (fpkt->pkt_datalen -
2892 	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
2893 
2894 	/*
2895 	 * Is our response buffer full or not? We don't want to
2896 	 * potentially walk beyond the number of luns we have.
2897 	 */
2898 	if (num_luns <= lun_buflen) {
2899 		actual_luns = num_luns;
2900 	} else {
2901 		actual_luns = lun_buflen;
2902 	}
2903 
2904 	mutex_enter(&ptgt->tgt_mutex);
2905 
2906 	/* Scan each lun to see if we have masked it. */
2907 	num_masked_luns = 0;
2908 	if (fcp_lun_blacklist != NULL) {
2909 		for (i = 0; i < actual_luns; i++) {
2910 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2911 			switch (lun_string[0] & 0xC0) {
2912 			case FCP_LUN_ADDRESSING:
2913 			case FCP_PD_ADDRESSING:
2914 			case FCP_VOLUME_ADDRESSING:
2915 				lun_num = ((lun_string[0] & 0x3F) << 8)
2916 				    | lun_string[1];
2917 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
2918 				    lun_num) == TRUE) {
2919 					num_masked_luns++;
2920 				}
2921 				break;
2922 			default:
2923 				break;
2924 			}
2925 		}
2926 	}
2927 
2928 	/*
2929 	 * The quick and easy check.  If the number of LUNs reported
2930 	 * doesn't match the number we currently know about, we need
2931 	 * to reconfigure.
2932 	 */
2933 	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2934 		mutex_exit(&ptgt->tgt_mutex);
2935 		kmem_free(report_lun, fpkt->pkt_datalen);
2936 		return (TRUE);
2937 	}
2938 
2939 	/*
2940 	 * If the quick and easy check doesn't turn up anything, we walk
2941 	 * the list of luns from the REPORT_LUN response and look for
2942 	 * any luns we don't know about.  If we find one, we know we need
2943 	 * to reconfigure. We will skip LUNs that are masked because of the
2944 	 * blacklist.
2945 	 */
2946 	for (i = 0; i < actual_luns; i++) {
2947 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2948 		lun_exists = FALSE;
2949 		switch (lun_string[0] & 0xC0) {
2950 		case FCP_LUN_ADDRESSING:
2951 		case FCP_PD_ADDRESSING:
2952 		case FCP_VOLUME_ADDRESSING:
2953 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2954 
2955 			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2956 			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2957 				lun_exists = TRUE;
2958 				break;
2959 			}
2960 
2961 			for (plun = ptgt->tgt_lun; plun;
2962 			    plun = plun->lun_next) {
2963 				if (plun->lun_num == lun_num) {
2964 					lun_exists = TRUE;
2965 					break;
2966 				}
2967 			}
2968 			break;
2969 		default:
2970 			break;
2971 		}
2972 
2973 		if (lun_exists == FALSE) {
2974 			reconfig_needed = TRUE;
2975 			break;
2976 		}
2977 	}
2978 
2979 	mutex_exit(&ptgt->tgt_mutex);
2980 	kmem_free(report_lun, fpkt->pkt_datalen);
2981 
2982 	return (reconfig_needed);
2983 }
2984 
2985 /*
2986  * This function is called by fcp_handle_page83 and uses inquiry response data
2987  * stored in plun->lun_inq to determine whether or not a device is a member of
2988  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2989  * otherwise 1.
2990  */
2991 static int
2992 fcp_symmetric_device_probe(struct fcp_lun *plun)
2993 {
2994 	struct scsi_inquiry	*stdinq = &plun->lun_inq;
2995 	char			*devidptr;
2996 	int			i, len;
2997 
2998 	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2999 		devidptr = fcp_symmetric_disk_table[i];
3000 		len = (int)strlen(devidptr);
3001 
3002 		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3003 			return (0);
3004 		}
3005 	}
3006 	return (1);
3007 }
3008 
3009 
3010 /*
3011  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3012  * It basically returns the current count of # of state change callbacks
3013  * i.e the value of tgt_change_cnt.
3014  *
3015  * INPUT:
3016  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3017  *   fcp_ioctl.listlen	-> 1
3018  *   fcp_ioctl.list	-> Pointer to a 32 bit integer
3019  */
3020 /*ARGSUSED2*/
3021 static int
3022 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3023 {
3024 	int			ret;
3025 	uint32_t		link_cnt;
3026 	struct fcp_ioctl	fioctl;
3027 	struct fcp_port	*pptr = NULL;
3028 
3029 	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3030 	    &pptr)) != 0) {
3031 		return (ret);
3032 	}
3033 
3034 	ASSERT(pptr != NULL);
3035 
3036 	if (fioctl.listlen != 1) {
3037 		return (EINVAL);
3038 	}
3039 
3040 	mutex_enter(&pptr->port_mutex);
3041 	if (pptr->port_state & FCP_STATE_OFFLINE) {
3042 		mutex_exit(&pptr->port_mutex);
3043 		return (ENXIO);
3044 	}
3045 
3046 	/*
3047 	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3048 	 * When the fcp initially attaches to the port and there are nothing
3049 	 * hanging out of the port or if there was a repeat offline state change
3050 	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3051 	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3052 	 * will differentiate the 2 cases.
3053 	 */
3054 	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3055 		mutex_exit(&pptr->port_mutex);
3056 		return (ENXIO);
3057 	}
3058 
3059 	link_cnt = pptr->port_link_cnt;
3060 	mutex_exit(&pptr->port_mutex);
3061 
3062 	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3063 		return (EFAULT);
3064 	}
3065 
3066 #ifdef	_MULTI_DATAMODEL
3067 	switch (ddi_model_convert_from(mode & FMODELS)) {
3068 	case DDI_MODEL_ILP32: {
3069 		struct fcp32_ioctl f32_ioctl;
3070 
3071 		f32_ioctl.fp_minor = fioctl.fp_minor;
3072 		f32_ioctl.listlen = fioctl.listlen;
3073 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3074 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3075 		    sizeof (struct fcp32_ioctl), mode)) {
3076 			return (EFAULT);
3077 		}
3078 		break;
3079 	}
3080 	case DDI_MODEL_NONE:
3081 		if (ddi_copyout((void *)&fioctl, (void *)data,
3082 		    sizeof (struct fcp_ioctl), mode)) {
3083 			return (EFAULT);
3084 		}
3085 		break;
3086 	}
3087 #else	/* _MULTI_DATAMODEL */
3088 
3089 	if (ddi_copyout((void *)&fioctl, (void *)data,
3090 	    sizeof (struct fcp_ioctl), mode)) {
3091 		return (EFAULT);
3092 	}
3093 #endif	/* _MULTI_DATAMODEL */
3094 
3095 	return (0);
3096 }
3097 
3098 /*
3099  * This function copies the fcp_ioctl structure passed in from user land
3100  * into kernel land. Handles 32 bit applications.
3101  */
3102 /*ARGSUSED*/
3103 static int
3104 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3105     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3106 {
3107 	struct fcp_port	*t_pptr;
3108 
3109 #ifdef	_MULTI_DATAMODEL
3110 	switch (ddi_model_convert_from(mode & FMODELS)) {
3111 	case DDI_MODEL_ILP32: {
3112 		struct fcp32_ioctl f32_ioctl;
3113 
3114 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3115 		    sizeof (struct fcp32_ioctl), mode)) {
3116 			return (EFAULT);
3117 		}
3118 		fioctl->fp_minor = f32_ioctl.fp_minor;
3119 		fioctl->listlen = f32_ioctl.listlen;
3120 		fioctl->list = (caddr_t)(long)f32_ioctl.list;
3121 		break;
3122 	}
3123 	case DDI_MODEL_NONE:
3124 		if (ddi_copyin((void *)data, (void *)fioctl,
3125 		    sizeof (struct fcp_ioctl), mode)) {
3126 			return (EFAULT);
3127 		}
3128 		break;
3129 	}
3130 
3131 #else	/* _MULTI_DATAMODEL */
3132 	if (ddi_copyin((void *)data, (void *)fioctl,
3133 	    sizeof (struct fcp_ioctl), mode)) {
3134 		return (EFAULT);
3135 	}
3136 #endif	/* _MULTI_DATAMODEL */
3137 
3138 	/*
3139 	 * Right now we can assume that the minor number matches with
3140 	 * this instance of fp. If this changes we will need to
3141 	 * revisit this logic.
3142 	 */
3143 	mutex_enter(&fcp_global_mutex);
3144 	t_pptr = fcp_port_head;
3145 	while (t_pptr) {
3146 		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3147 			break;
3148 		} else {
3149 			t_pptr = t_pptr->port_next;
3150 		}
3151 	}
3152 	*pptr = t_pptr;
3153 	mutex_exit(&fcp_global_mutex);
3154 	if (t_pptr == NULL) {
3155 		return (ENXIO);
3156 	}
3157 
3158 	return (0);
3159 }
3160 
3161 /*
3162  *     Function: fcp_port_create_tgt
3163  *
3164  *  Description: As the name suggest this function creates the target context
3165  *		 specified by the the WWN provided by the caller.  If the
3166  *		 creation goes well and the target is known by fp/fctl a PLOGI
3167  *		 followed by a PRLI are issued.
3168  *
3169  *     Argument: pptr		fcp port structure
3170  *		 pwwn		WWN of the target
3171  *		 ret_val	Address of the return code.  It could be:
3172  *				EIO, ENOMEM or 0.
3173  *		 fc_status	PLOGI or PRLI status completion
3174  *		 fc_pkt_state	PLOGI or PRLI state completion
3175  *		 fc_pkt_reason	PLOGI or PRLI reason completion
3176  *		 fc_pkt_action	PLOGI or PRLI action completion
3177  *
3178  * Return Value: NULL if it failed
3179  *		 Target structure address if it succeeds
3180  */
3181 static struct fcp_tgt *
3182 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3183     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3184 {
3185 	struct fcp_tgt	*ptgt = NULL;
3186 	fc_portmap_t		devlist;
3187 	int			lcount;
3188 	int			error;
3189 
3190 	*ret_val = 0;
3191 
3192 	/*
3193 	 * Check FC port device & get port map
3194 	 */
3195 	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3196 	    &error, 1) == NULL) {
3197 		*ret_val = EIO;
3198 	} else {
3199 		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3200 		    &devlist) != FC_SUCCESS) {
3201 			*ret_val = EIO;
3202 		}
3203 	}
3204 
3205 	/* Set port map flags */
3206 	devlist.map_type = PORT_DEVICE_USER_CREATE;
3207 
3208 	/* Allocate target */
3209 	if (*ret_val == 0) {
3210 		lcount = pptr->port_link_cnt;
3211 		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3212 		if (ptgt == NULL) {
3213 			fcp_log(CE_WARN, pptr->port_dip,
3214 			    "!FC target allocation failed");
3215 			*ret_val = ENOMEM;
3216 		} else {
3217 			/* Setup target */
3218 			mutex_enter(&ptgt->tgt_mutex);
3219 
3220 			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
3221 			ptgt->tgt_tmp_cnt	= 1;
3222 			ptgt->tgt_d_id		= devlist.map_did.port_id;
3223 			ptgt->tgt_hard_addr	=
3224 			    devlist.map_hard_addr.hard_addr;
3225 			ptgt->tgt_pd_handle	= devlist.map_pd;
3226 			ptgt->tgt_fca_dev	= NULL;
3227 
3228 			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3229 			    FC_WWN_SIZE);
3230 			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3231 			    FC_WWN_SIZE);
3232 
3233 			mutex_exit(&ptgt->tgt_mutex);
3234 		}
3235 	}
3236 
3237 	/* Release global mutex for PLOGI and PRLI */
3238 	mutex_exit(&fcp_global_mutex);
3239 
3240 	/* Send PLOGI (If necessary) */
3241 	if (*ret_val == 0) {
3242 		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3243 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3244 	}
3245 
3246 	/* Send PRLI (If necessary) */
3247 	if (*ret_val == 0) {
3248 		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3249 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3250 	}
3251 
3252 	mutex_enter(&fcp_global_mutex);
3253 
3254 	return (ptgt);
3255 }
3256 
3257 /*
3258  *     Function: fcp_tgt_send_plogi
3259  *
3260  *  Description: This function sends a PLOGI to the target specified by the
3261  *		 caller and waits till it completes.
3262  *
3263  *     Argument: ptgt		Target to send the plogi to.
3264  *		 fc_status	Status returned by fp/fctl in the PLOGI request.
3265  *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
3266  *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
3267  *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
3268  *
3269  * Return Value: 0
3270  *		 ENOMEM
3271  *		 EIO
3272  *
3273  *	Context: User context.
3274  */
3275 static int
3276 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3277     int *fc_pkt_reason, int *fc_pkt_action)
3278 {
3279 	struct fcp_port	*pptr;
3280 	struct fcp_ipkt	*icmd;
3281 	struct fc_packet	*fpkt;
3282 	fc_frame_hdr_t		*hp;
3283 	struct la_els_logi	logi;
3284 	int			tcount;
3285 	int			lcount;
3286 	int			ret, login_retval = ~FC_SUCCESS;
3287 
3288 	ret = 0;
3289 
3290 	pptr = ptgt->tgt_port;
3291 
3292 	lcount = pptr->port_link_cnt;
3293 	tcount = ptgt->tgt_change_cnt;
3294 
3295 	/* Alloc internal packet */
3296 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3297 	    sizeof (la_els_logi_t), 0,
3298 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3299 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3300 
3301 	if (icmd == NULL) {
3302 		ret = ENOMEM;
3303 	} else {
3304 		/*
3305 		 * Setup internal packet as sema sync
3306 		 */
3307 		fcp_ipkt_sema_init(icmd);
3308 
3309 		/*
3310 		 * Setup internal packet (icmd)
3311 		 */
3312 		icmd->ipkt_lun		= NULL;
3313 		icmd->ipkt_restart	= 0;
3314 		icmd->ipkt_retries	= 0;
3315 		icmd->ipkt_opcode	= LA_ELS_PLOGI;
3316 
3317 		/*
3318 		 * Setup fc_packet
3319 		 */
3320 		fpkt = icmd->ipkt_fpkt;
3321 
3322 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
3323 		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
3324 		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
3325 
3326 		/*
3327 		 * Setup FC frame header
3328 		 */
3329 		hp = &fpkt->pkt_cmd_fhdr;
3330 
3331 		hp->s_id	= pptr->port_id;	/* source ID */
3332 		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
3333 		hp->r_ctl	= R_CTL_ELS_REQ;
3334 		hp->type	= FC_TYPE_EXTENDED_LS;
3335 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3336 		hp->seq_id	= 0;
3337 		hp->rsvd	= 0;
3338 		hp->df_ctl	= 0;
3339 		hp->seq_cnt	= 0;
3340 		hp->ox_id	= 0xffff;		/* i.e. none */
3341 		hp->rx_id	= 0xffff;		/* i.e. none */
3342 		hp->ro		= 0;
3343 
3344 		/*
3345 		 * Setup PLOGI
3346 		 */
3347 		bzero(&logi, sizeof (struct la_els_logi));
3348 		logi.ls_code.ls_code = LA_ELS_PLOGI;
3349 
3350 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3351 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3352 
3353 		/*
3354 		 * Send PLOGI
3355 		 */
3356 		*fc_status = login_retval =
3357 		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3358 		if (*fc_status != FC_SUCCESS) {
3359 			ret = EIO;
3360 		}
3361 	}
3362 
3363 	/*
3364 	 * Wait for completion
3365 	 */
3366 	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3367 		ret = fcp_ipkt_sema_wait(icmd);
3368 
3369 		*fc_pkt_state	= fpkt->pkt_state;
3370 		*fc_pkt_reason	= fpkt->pkt_reason;
3371 		*fc_pkt_action	= fpkt->pkt_action;
3372 	}
3373 
3374 	/*
3375 	 * Cleanup transport data structures if icmd was alloc-ed AND if there
3376 	 * is going to be no callback (i.e if fc_ulp_login() failed).
3377 	 * Otherwise, cleanup happens in callback routine.
3378 	 */
3379 	if (icmd != NULL) {
3380 		fcp_ipkt_sema_cleanup(icmd);
3381 	}
3382 
3383 	return (ret);
3384 }
3385 
3386 /*
3387  *     Function: fcp_tgt_send_prli
3388  *
3389  *  Description: Does nothing as of today.
3390  *
3391  *     Argument: ptgt		Target to send the prli to.
3392  *		 fc_status	Status returned by fp/fctl in the PRLI request.
3393  *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
3394  *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
3395  *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
3396  *
3397  * Return Value: 0
3398  */
3399 /*ARGSUSED*/
3400 static int
3401 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3402     int *fc_pkt_reason, int *fc_pkt_action)
3403 {
3404 	return (0);
3405 }
3406 
3407 /*
3408  *     Function: fcp_ipkt_sema_init
3409  *
3410  *  Description: Initializes the semaphore contained in the internal packet.
3411  *
3412  *     Argument: icmd	Internal packet the semaphore of which must be
3413  *			initialized.
3414  *
3415  * Return Value: None
3416  *
3417  *	Context: User context only.
3418  */
3419 static void
3420 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3421 {
3422 	struct fc_packet	*fpkt;
3423 
3424 	fpkt = icmd->ipkt_fpkt;
3425 
3426 	/* Create semaphore for sync */
3427 	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3428 
3429 	/* Setup the completion callback */
3430 	fpkt->pkt_comp = fcp_ipkt_sema_callback;
3431 }
3432 
3433 /*
3434  *     Function: fcp_ipkt_sema_wait
3435  *
3436  *  Description: Wait on the semaphore embedded in the internal packet.	 The
3437  *		 semaphore is released in the callback.
3438  *
3439  *     Argument: icmd	Internal packet to wait on for completion.
3440  *
3441  * Return Value: 0
3442  *		 EIO
3443  *		 EBUSY
3444  *		 EAGAIN
3445  *
3446  *	Context: User context only.
3447  *
3448  * This function does a conversion between the field pkt_state of the fc_packet
3449  * embedded in the internal packet (icmd) and the code it returns.
3450  */
3451 static int
3452 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3453 {
3454 	struct fc_packet	*fpkt;
3455 	int	ret;
3456 
3457 	ret = EIO;
3458 	fpkt = icmd->ipkt_fpkt;
3459 
3460 	/*
3461 	 * Wait on semaphore
3462 	 */
3463 	sema_p(&(icmd->ipkt_sema));
3464 
3465 	/*
3466 	 * Check the status of the FC packet
3467 	 */
3468 	switch (fpkt->pkt_state) {
3469 	case FC_PKT_SUCCESS:
3470 		ret = 0;
3471 		break;
3472 	case FC_PKT_LOCAL_RJT:
3473 		switch (fpkt->pkt_reason) {
3474 		case FC_REASON_SEQ_TIMEOUT:
3475 		case FC_REASON_RX_BUF_TIMEOUT:
3476 			ret = EAGAIN;
3477 			break;
3478 		case FC_REASON_PKT_BUSY:
3479 			ret = EBUSY;
3480 			break;
3481 		}
3482 		break;
3483 	case FC_PKT_TIMEOUT:
3484 		ret = EAGAIN;
3485 		break;
3486 	case FC_PKT_LOCAL_BSY:
3487 	case FC_PKT_TRAN_BSY:
3488 	case FC_PKT_NPORT_BSY:
3489 	case FC_PKT_FABRIC_BSY:
3490 		ret = EBUSY;
3491 		break;
3492 	case FC_PKT_LS_RJT:
3493 	case FC_PKT_BA_RJT:
3494 		switch (fpkt->pkt_reason) {
3495 		case FC_REASON_LOGICAL_BSY:
3496 			ret = EBUSY;
3497 			break;
3498 		}
3499 		break;
3500 	case FC_PKT_FS_RJT:
3501 		switch (fpkt->pkt_reason) {
3502 		case FC_REASON_FS_LOGICAL_BUSY:
3503 			ret = EBUSY;
3504 			break;
3505 		}
3506 		break;
3507 	}
3508 
3509 	return (ret);
3510 }
3511 
3512 /*
3513  *     Function: fcp_ipkt_sema_callback
3514  *
3515  *  Description: Registered as the completion callback function for the FC
3516  *		 transport when the ipkt semaphore is used for sync. This will
3517  *		 cleanup the used data structures, if necessary and wake up
3518  *		 the user thread to complete the transaction.
3519  *
3520  *     Argument: fpkt	FC packet (points to the icmd)
3521  *
3522  * Return Value: None
3523  *
3524  *	Context: User context only
3525  */
3526 static void
3527 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3528 {
3529 	struct fcp_ipkt	*icmd;
3530 
3531 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3532 
3533 	/*
3534 	 * Wake up user thread
3535 	 */
3536 	sema_v(&(icmd->ipkt_sema));
3537 }
3538 
3539 /*
3540  *     Function: fcp_ipkt_sema_cleanup
3541  *
3542  *  Description: Called to cleanup (if necessary) the data structures used
3543  *		 when ipkt sema is used for sync.  This function will detect
3544  *		 whether the caller is the last thread (via counter) and
3545  *		 cleanup only if necessary.
3546  *
3547  *     Argument: icmd	Internal command packet
3548  *
3549  * Return Value: None
3550  *
3551  *	Context: User context only
3552  */
3553 static void
3554 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3555 {
3556 	struct fcp_tgt	*ptgt;
3557 	struct fcp_port	*pptr;
3558 
3559 	ptgt = icmd->ipkt_tgt;
3560 	pptr = icmd->ipkt_port;
3561 
3562 	/*
3563 	 * Acquire data structure
3564 	 */
3565 	mutex_enter(&ptgt->tgt_mutex);
3566 
3567 	/*
3568 	 * Destroy semaphore
3569 	 */
3570 	sema_destroy(&(icmd->ipkt_sema));
3571 
3572 	/*
3573 	 * Cleanup internal packet
3574 	 */
3575 	mutex_exit(&ptgt->tgt_mutex);
3576 	fcp_icmd_free(pptr, icmd);
3577 }
3578 
3579 /*
3580  *     Function: fcp_port_attach
3581  *
3582  *  Description: Called by the transport framework to resume, suspend or
3583  *		 attach a new port.
3584  *
3585  *     Argument: ulph		Port handle
3586  *		 *pinfo		Port information
3587  *		 cmd		Command
3588  *		 s_id		Port ID
3589  *
3590  * Return Value: FC_FAILURE or FC_SUCCESS
3591  */
3592 /*ARGSUSED*/
3593 static int
3594 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3595     fc_attach_cmd_t cmd, uint32_t s_id)
3596 {
3597 	int	instance;
3598 	int	res = FC_FAILURE; /* default result */
3599 
3600 	ASSERT(pinfo != NULL);
3601 
3602 	instance = ddi_get_instance(pinfo->port_dip);
3603 
3604 	switch (cmd) {
3605 	case FC_CMD_ATTACH:
3606 		/*
3607 		 * this port instance attaching for the first time (or after
3608 		 * being detached before)
3609 		 */
3610 		if (fcp_handle_port_attach(ulph, pinfo, s_id,
3611 		    instance) == DDI_SUCCESS) {
3612 			res = FC_SUCCESS;
3613 		} else {
3614 			ASSERT(ddi_get_soft_state(fcp_softstate,
3615 			    instance) == NULL);
3616 		}
3617 		break;
3618 
3619 	case FC_CMD_RESUME:
3620 	case FC_CMD_POWER_UP:
3621 		/*
3622 		 * this port instance was attached and the suspended and
3623 		 * will now be resumed
3624 		 */
3625 		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3626 		    instance) == DDI_SUCCESS) {
3627 			res = FC_SUCCESS;
3628 		}
3629 		break;
3630 
3631 	default:
3632 		/* shouldn't happen */
3633 		FCP_TRACE(fcp_logq, "fcp",
3634 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
3635 		    "port_attach: unknown cmdcommand: %d", cmd);
3636 		break;
3637 	}
3638 
3639 	/* return result */
3640 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3641 	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3642 
3643 	return (res);
3644 }
3645 
3646 
3647 /*
3648  * detach or suspend this port instance
3649  *
3650  * acquires and releases the global mutex
3651  *
3652  * acquires and releases the mutex for this port
3653  *
3654  * acquires and releases the hotplug mutex for this port
3655  */
3656 /*ARGSUSED*/
3657 static int
3658 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3659     fc_detach_cmd_t cmd)
3660 {
3661 	int			flag;
3662 	int			instance;
3663 	struct fcp_port		*pptr;
3664 
3665 	instance = ddi_get_instance(info->port_dip);
3666 	pptr = ddi_get_soft_state(fcp_softstate, instance);
3667 
3668 	switch (cmd) {
3669 	case FC_CMD_SUSPEND:
3670 		FCP_DTRACE(fcp_logq, "fcp",
3671 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3672 		    "port suspend called for port %d", instance);
3673 		flag = FCP_STATE_SUSPENDED;
3674 		break;
3675 
3676 	case FC_CMD_POWER_DOWN:
3677 		FCP_DTRACE(fcp_logq, "fcp",
3678 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3679 		    "port power down called for port %d", instance);
3680 		flag = FCP_STATE_POWER_DOWN;
3681 		break;
3682 
3683 	case FC_CMD_DETACH:
3684 		FCP_DTRACE(fcp_logq, "fcp",
3685 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3686 		    "port detach called for port %d", instance);
3687 		flag = FCP_STATE_DETACHING;
3688 		break;
3689 
3690 	default:
3691 		/* shouldn't happen */
3692 		return (FC_FAILURE);
3693 	}
3694 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3695 	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3696 
3697 	return (fcp_handle_port_detach(pptr, flag, instance));
3698 }
3699 
3700 
3701 /*
3702  * called for ioctls on the transport's devctl interface, and the transport
3703  * has passed it to us
3704  *
3705  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3706  *
3707  * return FC_SUCCESS if we decide to claim the ioctl,
3708  * else return FC_UNCLAIMED
3709  *
3710  * *rval is set iff we decide to claim the ioctl
3711  */
3712 /*ARGSUSED*/
3713 static int
3714 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3715     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3716 {
3717 	int			retval = FC_UNCLAIMED;	/* return value */
3718 	struct fcp_port		*pptr = NULL;		/* our soft state */
3719 	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
3720 	dev_info_t		*cdip;
3721 	mdi_pathinfo_t		*pip = NULL;
3722 	char			*ndi_nm;		/* NDI name */
3723 	char			*ndi_addr;		/* NDI addr */
3724 	int			is_mpxio, circ;
3725 	int			devi_entered = 0;
3726 	time_t			end_time;
3727 
3728 	ASSERT(rval != NULL);
3729 
3730 	FCP_DTRACE(fcp_logq, "fcp",
3731 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3732 	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3733 
3734 	/* if already claimed then forget it */
3735 	if (claimed) {
3736 		/*
3737 		 * for now, if this ioctl has already been claimed, then
3738 		 * we just ignore it
3739 		 */
3740 		return (retval);
3741 	}
3742 
3743 	/* get our port info */
3744 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
3745 		fcp_log(CE_WARN, NULL,
3746 		    "!fcp:Invalid port handle handle in ioctl");
3747 		*rval = ENXIO;
3748 		return (retval);
3749 	}
3750 	is_mpxio = pptr->port_mpxio;
3751 
3752 	switch (cmd) {
3753 	case DEVCTL_BUS_GETSTATE:
3754 	case DEVCTL_BUS_QUIESCE:
3755 	case DEVCTL_BUS_UNQUIESCE:
3756 	case DEVCTL_BUS_RESET:
3757 	case DEVCTL_BUS_RESETALL:
3758 
3759 	case DEVCTL_BUS_DEV_CREATE:
3760 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3761 			return (retval);
3762 		}
3763 		break;
3764 
3765 	case DEVCTL_DEVICE_GETSTATE:
3766 	case DEVCTL_DEVICE_OFFLINE:
3767 	case DEVCTL_DEVICE_ONLINE:
3768 	case DEVCTL_DEVICE_REMOVE:
3769 	case DEVCTL_DEVICE_RESET:
3770 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3771 			return (retval);
3772 		}
3773 
3774 		ASSERT(dcp != NULL);
3775 
3776 		/* ensure we have a name and address */
3777 		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3778 		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3779 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
3780 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
3781 			    "ioctl: can't get name (%s) or addr (%s)",
3782 			    ndi_nm ? ndi_nm : "<null ptr>",
3783 			    ndi_addr ? ndi_addr : "<null ptr>");
3784 			ndi_dc_freehdl(dcp);
3785 			return (retval);
3786 		}
3787 
3788 
3789 		/* get our child's DIP */
3790 		ASSERT(pptr != NULL);
3791 		if (is_mpxio) {
3792 			mdi_devi_enter(pptr->port_dip, &circ);
3793 		} else {
3794 			ndi_devi_enter(pptr->port_dip, &circ);
3795 		}
3796 		devi_entered = 1;
3797 
3798 		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3799 		    ndi_addr)) == NULL) {
3800 			/* Look for virtually enumerated devices. */
3801 			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3802 			if (pip == NULL ||
3803 			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3804 				*rval = ENXIO;
3805 				goto out;
3806 			}
3807 		}
3808 		break;
3809 
3810 	default:
3811 		*rval = ENOTTY;
3812 		return (retval);
3813 	}
3814 
3815 	/* this ioctl is ours -- process it */
3816 
3817 	retval = FC_SUCCESS;		/* just means we claim the ioctl */
3818 
3819 	/* we assume it will be a success; else we'll set error value */
3820 	*rval = 0;
3821 
3822 
3823 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3824 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3825 	    "ioctl: claiming this one");
3826 
3827 	/* handle ioctls now */
3828 	switch (cmd) {
3829 	case DEVCTL_DEVICE_GETSTATE:
3830 		ASSERT(cdip != NULL);
3831 		ASSERT(dcp != NULL);
3832 		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3833 			*rval = EFAULT;
3834 		}
3835 		break;
3836 
3837 	case DEVCTL_DEVICE_REMOVE:
3838 	case DEVCTL_DEVICE_OFFLINE: {
3839 		int			flag = 0;
3840 		int			lcount;
3841 		int			tcount;
3842 		struct fcp_pkt	*head = NULL;
3843 		struct fcp_lun	*plun;
3844 		child_info_t		*cip = CIP(cdip);
3845 		int			all = 1;
3846 		struct fcp_lun	*tplun;
3847 		struct fcp_tgt	*ptgt;
3848 
3849 		ASSERT(pptr != NULL);
3850 		ASSERT(cdip != NULL);
3851 
3852 		mutex_enter(&pptr->port_mutex);
3853 		if (pip != NULL) {
3854 			cip = CIP(pip);
3855 		}
3856 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3857 			mutex_exit(&pptr->port_mutex);
3858 			*rval = ENXIO;
3859 			break;
3860 		}
3861 
3862 		head = fcp_scan_commands(plun);
3863 		if (head != NULL) {
3864 			fcp_abort_commands(head, LUN_PORT);
3865 		}
3866 		lcount = pptr->port_link_cnt;
3867 		tcount = plun->lun_tgt->tgt_change_cnt;
3868 		mutex_exit(&pptr->port_mutex);
3869 
3870 		if (cmd == DEVCTL_DEVICE_REMOVE) {
3871 			flag = NDI_DEVI_REMOVE;
3872 		}
3873 
3874 		if (is_mpxio) {
3875 			mdi_devi_exit(pptr->port_dip, circ);
3876 		} else {
3877 			ndi_devi_exit(pptr->port_dip, circ);
3878 		}
3879 		devi_entered = 0;
3880 
3881 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3882 		    FCP_OFFLINE, lcount, tcount, flag);
3883 
3884 		if (*rval != NDI_SUCCESS) {
3885 			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3886 			break;
3887 		}
3888 
3889 		fcp_update_offline_flags(plun);
3890 
3891 		ptgt = plun->lun_tgt;
3892 		mutex_enter(&ptgt->tgt_mutex);
3893 		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3894 		    tplun->lun_next) {
3895 			mutex_enter(&tplun->lun_mutex);
3896 			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3897 				all = 0;
3898 			}
3899 			mutex_exit(&tplun->lun_mutex);
3900 		}
3901 
3902 		if (all) {
3903 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3904 			/*
3905 			 * The user is unconfiguring/offlining the device.
3906 			 * If fabric and the auto configuration is set
3907 			 * then make sure the user is the only one who
3908 			 * can reconfigure the device.
3909 			 */
3910 			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3911 			    fcp_enable_auto_configuration) {
3912 				ptgt->tgt_manual_config_only = 1;
3913 			}
3914 		}
3915 		mutex_exit(&ptgt->tgt_mutex);
3916 		break;
3917 	}
3918 
3919 	case DEVCTL_DEVICE_ONLINE: {
3920 		int			lcount;
3921 		int			tcount;
3922 		struct fcp_lun	*plun;
3923 		child_info_t		*cip = CIP(cdip);
3924 
3925 		ASSERT(cdip != NULL);
3926 		ASSERT(pptr != NULL);
3927 
3928 		mutex_enter(&pptr->port_mutex);
3929 		if (pip != NULL) {
3930 			cip = CIP(pip);
3931 		}
3932 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3933 			mutex_exit(&pptr->port_mutex);
3934 			*rval = ENXIO;
3935 			break;
3936 		}
3937 		lcount = pptr->port_link_cnt;
3938 		tcount = plun->lun_tgt->tgt_change_cnt;
3939 		mutex_exit(&pptr->port_mutex);
3940 
3941 		/*
3942 		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3943 		 * to allow the device attach to occur when the device is
3944 		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3945 		 * from the scsi_probe()).
3946 		 */
3947 		mutex_enter(&LUN_TGT->tgt_mutex);
3948 		plun->lun_state |= FCP_LUN_ONLINING;
3949 		mutex_exit(&LUN_TGT->tgt_mutex);
3950 
3951 		if (is_mpxio) {
3952 			mdi_devi_exit(pptr->port_dip, circ);
3953 		} else {
3954 			ndi_devi_exit(pptr->port_dip, circ);
3955 		}
3956 		devi_entered = 0;
3957 
3958 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3959 		    FCP_ONLINE, lcount, tcount, 0);
3960 
3961 		if (*rval != NDI_SUCCESS) {
3962 			/* Reset the FCP_LUN_ONLINING bit */
3963 			mutex_enter(&LUN_TGT->tgt_mutex);
3964 			plun->lun_state &= ~FCP_LUN_ONLINING;
3965 			mutex_exit(&LUN_TGT->tgt_mutex);
3966 			*rval = EIO;
3967 			break;
3968 		}
3969 		mutex_enter(&LUN_TGT->tgt_mutex);
3970 		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3971 		    FCP_LUN_ONLINING);
3972 		mutex_exit(&LUN_TGT->tgt_mutex);
3973 		break;
3974 	}
3975 
3976 	case DEVCTL_BUS_DEV_CREATE: {
3977 		uchar_t			*bytes = NULL;
3978 		uint_t			nbytes;
3979 		struct fcp_tgt		*ptgt = NULL;
3980 		struct fcp_lun		*plun = NULL;
3981 		dev_info_t		*useless_dip = NULL;
3982 
3983 		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3984 		    DEVCTL_CONSTRUCT, &useless_dip);
3985 		if (*rval != 0 || useless_dip == NULL) {
3986 			break;
3987 		}
3988 
3989 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3990 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3991 		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3992 			*rval = EINVAL;
3993 			(void) ndi_devi_free(useless_dip);
3994 			if (bytes != NULL) {
3995 				ddi_prop_free(bytes);
3996 			}
3997 			break;
3998 		}
3999 
4000 		*rval = fcp_create_on_demand(pptr, bytes);
4001 		if (*rval == 0) {
4002 			mutex_enter(&pptr->port_mutex);
4003 			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4004 			if (ptgt) {
4005 				/*
4006 				 * We now have a pointer to the target that
4007 				 * was created. Lets point to the first LUN on
4008 				 * this new target.
4009 				 */
4010 				mutex_enter(&ptgt->tgt_mutex);
4011 
4012 				plun = ptgt->tgt_lun;
4013 				/*
4014 				 * There may be stale/offline LUN entries on
4015 				 * this list (this is by design) and so we have
4016 				 * to make sure we point to the first online
4017 				 * LUN
4018 				 */
4019 				while (plun &&
4020 				    plun->lun_state & FCP_LUN_OFFLINE) {
4021 					plun = plun->lun_next;
4022 				}
4023 
4024 				mutex_exit(&ptgt->tgt_mutex);
4025 			}
4026 			mutex_exit(&pptr->port_mutex);
4027 		}
4028 
4029 		if (*rval == 0 && ptgt && plun) {
4030 			mutex_enter(&plun->lun_mutex);
4031 			/*
4032 			 * Allow up to fcp_lun_ready_retry seconds to
4033 			 * configure all the luns behind the target.
4034 			 *
4035 			 * The intent here is to allow targets with long
4036 			 * reboot/reset-recovery times to become available
4037 			 * while limiting the maximum wait time for an
4038 			 * unresponsive target.
4039 			 */
4040 			end_time = ddi_get_lbolt() +
4041 			    SEC_TO_TICK(fcp_lun_ready_retry);
4042 
4043 			while (ddi_get_lbolt() < end_time) {
4044 				retval = FC_SUCCESS;
4045 
4046 				/*
4047 				 * The new ndi interfaces for on-demand creation
4048 				 * are inflexible, Do some more work to pass on
4049 				 * a path name of some LUN (design is broken !)
4050 				 */
4051 				if (plun->lun_cip) {
4052 					if (plun->lun_mpxio == 0) {
4053 						cdip = DIP(plun->lun_cip);
4054 					} else {
4055 						cdip = mdi_pi_get_client(
4056 						    PIP(plun->lun_cip));
4057 					}
4058 					if (cdip == NULL) {
4059 						*rval = ENXIO;
4060 						break;
4061 					}
4062 
4063 					if (!i_ddi_devi_attached(cdip)) {
4064 						mutex_exit(&plun->lun_mutex);
4065 						delay(drv_usectohz(1000000));
4066 						mutex_enter(&plun->lun_mutex);
4067 					} else {
4068 						/*
4069 						 * This Lun is ready, lets
4070 						 * check the next one.
4071 						 */
4072 						mutex_exit(&plun->lun_mutex);
4073 						plun = plun->lun_next;
4074 						while (plun && (plun->lun_state
4075 						    & FCP_LUN_OFFLINE)) {
4076 							plun = plun->lun_next;
4077 						}
4078 						if (!plun) {
4079 							break;
4080 						}
4081 						mutex_enter(&plun->lun_mutex);
4082 					}
4083 				} else {
4084 					/*
4085 					 * lun_cip field for a valid lun
4086 					 * should never be NULL. Fail the
4087 					 * command.
4088 					 */
4089 					*rval = ENXIO;
4090 					break;
4091 				}
4092 			}
4093 			if (plun) {
4094 				mutex_exit(&plun->lun_mutex);
4095 			} else {
4096 				char devnm[MAXNAMELEN];
4097 				int nmlen;
4098 
4099 				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4100 				    ddi_node_name(cdip),
4101 				    ddi_get_name_addr(cdip));
4102 
4103 				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4104 				    0) {
4105 					*rval = EFAULT;
4106 				}
4107 			}
4108 		} else {
4109 			int	i;
4110 			char	buf[25];
4111 
4112 			for (i = 0; i < FC_WWN_SIZE; i++) {
4113 				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4114 			}
4115 
4116 			fcp_log(CE_WARN, pptr->port_dip,
4117 			    "!Failed to create nodes for pwwn=%s; error=%x",
4118 			    buf, *rval);
4119 		}
4120 
4121 		(void) ndi_devi_free(useless_dip);
4122 		ddi_prop_free(bytes);
4123 		break;
4124 	}
4125 
4126 	case DEVCTL_DEVICE_RESET: {
4127 		struct fcp_lun		*plun;
4128 		child_info_t		*cip = CIP(cdip);
4129 
4130 		ASSERT(cdip != NULL);
4131 		ASSERT(pptr != NULL);
4132 		mutex_enter(&pptr->port_mutex);
4133 		if (pip != NULL) {
4134 			cip = CIP(pip);
4135 		}
4136 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4137 			mutex_exit(&pptr->port_mutex);
4138 			*rval = ENXIO;
4139 			break;
4140 		}
4141 		mutex_exit(&pptr->port_mutex);
4142 
4143 		mutex_enter(&plun->lun_tgt->tgt_mutex);
4144 		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4145 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4146 
4147 			*rval = ENXIO;
4148 			break;
4149 		}
4150 
4151 		if (plun->lun_sd == NULL) {
4152 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4153 
4154 			*rval = ENXIO;
4155 			break;
4156 		}
4157 		mutex_exit(&plun->lun_tgt->tgt_mutex);
4158 
4159 		/*
4160 		 * set up ap so that fcp_reset can figure out
4161 		 * which target to reset
4162 		 */
4163 		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4164 		    RESET_TARGET) == FALSE) {
4165 			*rval = EIO;
4166 		}
4167 		break;
4168 	}
4169 
4170 	case DEVCTL_BUS_GETSTATE:
4171 		ASSERT(dcp != NULL);
4172 		ASSERT(pptr != NULL);
4173 		ASSERT(pptr->port_dip != NULL);
4174 		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4175 		    NDI_SUCCESS) {
4176 			*rval = EFAULT;
4177 		}
4178 		break;
4179 
4180 	case DEVCTL_BUS_QUIESCE:
4181 	case DEVCTL_BUS_UNQUIESCE:
4182 		*rval = ENOTSUP;
4183 		break;
4184 
4185 	case DEVCTL_BUS_RESET:
4186 	case DEVCTL_BUS_RESETALL:
4187 		ASSERT(pptr != NULL);
4188 		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4189 		break;
4190 
4191 	default:
4192 		ASSERT(dcp != NULL);
4193 		*rval = ENOTTY;
4194 		break;
4195 	}
4196 
4197 	/* all done -- clean up and return */
4198 out:	if (devi_entered) {
4199 		if (is_mpxio) {
4200 			mdi_devi_exit(pptr->port_dip, circ);
4201 		} else {
4202 			ndi_devi_exit(pptr->port_dip, circ);
4203 		}
4204 	}
4205 
4206 	if (dcp != NULL) {
4207 		ndi_dc_freehdl(dcp);
4208 	}
4209 
4210 	return (retval);
4211 }
4212 
4213 
4214 /*ARGSUSED*/
4215 static int
4216 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4217     uint32_t claimed)
4218 {
4219 	uchar_t			r_ctl;
4220 	uchar_t			ls_code;
4221 	struct fcp_port	*pptr;
4222 
4223 	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4224 		return (FC_UNCLAIMED);
4225 	}
4226 
4227 	mutex_enter(&pptr->port_mutex);
4228 	if (pptr->port_state & (FCP_STATE_DETACHING |
4229 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4230 		mutex_exit(&pptr->port_mutex);
4231 		return (FC_UNCLAIMED);
4232 	}
4233 	mutex_exit(&pptr->port_mutex);
4234 
4235 	r_ctl = buf->ub_frame.r_ctl;
4236 
4237 	switch (r_ctl & R_CTL_ROUTING) {
4238 	case R_CTL_EXTENDED_SVC:
4239 		if (r_ctl == R_CTL_ELS_REQ) {
4240 			ls_code = buf->ub_buffer[0];
4241 
4242 			switch (ls_code) {
4243 			case LA_ELS_PRLI:
4244 				/*
4245 				 * We really don't care if something fails.
4246 				 * If the PRLI was not sent out, then the
4247 				 * other end will time it out.
4248 				 */
4249 				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4250 					return (FC_SUCCESS);
4251 				}
4252 				return (FC_UNCLAIMED);
4253 				/* NOTREACHED */
4254 
4255 			default:
4256 				break;
4257 			}
4258 		}
4259 		/* FALLTHROUGH */
4260 
4261 	default:
4262 		return (FC_UNCLAIMED);
4263 	}
4264 }
4265 
4266 
4267 /*ARGSUSED*/
4268 static int
4269 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4270     uint32_t claimed)
4271 {
4272 	return (FC_UNCLAIMED);
4273 }
4274 
4275 /*
4276  *     Function: fcp_statec_callback
4277  *
4278  *  Description: The purpose of this function is to handle a port state change.
4279  *		 It is called from fp/fctl and, in a few instances, internally.
4280  *
4281  *     Argument: ulph		fp/fctl port handle
4282  *		 port_handle	fcp_port structure
4283  *		 port_state	Physical state of the port
4284  *		 port_top	Topology
4285  *		 *devlist	Pointer to the first entry of a table
4286  *				containing the remote ports that can be
4287  *				reached.
4288  *		 dev_cnt	Number of entries pointed by devlist.
4289  *		 port_sid	Port ID of the local port.
4290  *
4291  * Return Value: None
4292  */
4293 /*ARGSUSED*/
4294 static void
4295 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4296     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4297     uint32_t dev_cnt, uint32_t port_sid)
4298 {
4299 	uint32_t		link_count;
4300 	int			map_len = 0;
4301 	struct fcp_port	*pptr;
4302 	fcp_map_tag_t		*map_tag = NULL;
4303 
4304 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
4305 		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4306 		return;			/* nothing to work with! */
4307 	}
4308 
4309 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4310 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
4311 	    "fcp_statec_callback: port state/dev_cnt/top ="
4312 	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4313 	    dev_cnt, port_top);
4314 
4315 	mutex_enter(&pptr->port_mutex);
4316 
4317 	/*
4318 	 * If a thread is in detach, don't do anything.
4319 	 */
4320 	if (pptr->port_state & (FCP_STATE_DETACHING |
4321 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4322 		mutex_exit(&pptr->port_mutex);
4323 		return;
4324 	}
4325 
4326 	/*
4327 	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4328 	 * init_pkt is called, it knows whether or not the target's status
4329 	 * (or pd) might be changing.
4330 	 */
4331 
4332 	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4333 		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4334 	}
4335 
4336 	/*
4337 	 * the transport doesn't allocate or probe unless being
4338 	 * asked to by either the applications or ULPs
4339 	 *
4340 	 * in cases where the port is OFFLINE at the time of port
4341 	 * attach callback and the link comes ONLINE later, for
4342 	 * easier automatic node creation (i.e. without you having to
4343 	 * go out and run the utility to perform LOGINs) the
4344 	 * following conditional is helpful
4345 	 */
4346 	pptr->port_phys_state = port_state;
4347 
4348 	if (dev_cnt) {
4349 		mutex_exit(&pptr->port_mutex);
4350 
4351 		map_len = sizeof (*map_tag) * dev_cnt;
4352 		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4353 		if (map_tag == NULL) {
4354 			fcp_log(CE_WARN, pptr->port_dip,
4355 			    "!fcp%d: failed to allocate for map tags; "
4356 			    " state change will not be processed",
4357 			    pptr->port_instance);
4358 
4359 			mutex_enter(&pptr->port_mutex);
4360 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4361 			mutex_exit(&pptr->port_mutex);
4362 
4363 			return;
4364 		}
4365 
4366 		mutex_enter(&pptr->port_mutex);
4367 	}
4368 
4369 	if (pptr->port_id != port_sid) {
4370 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4371 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4372 		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4373 		    port_sid);
4374 		/*
4375 		 * The local port changed ID. It is the first time a port ID
4376 		 * is assigned or something drastic happened.  We might have
4377 		 * been unplugged and replugged on another loop or fabric port
4378 		 * or somebody grabbed the AL_PA we had or somebody rezoned
4379 		 * the fabric we were plugged into.
4380 		 */
4381 		pptr->port_id = port_sid;
4382 	}
4383 
4384 	switch (FC_PORT_STATE_MASK(port_state)) {
4385 	case FC_STATE_OFFLINE:
4386 	case FC_STATE_RESET_REQUESTED:
4387 		/*
4388 		 * link has gone from online to offline -- just update the
4389 		 * state of this port to BUSY and MARKed to go offline
4390 		 */
4391 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4392 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4393 		    "link went offline");
4394 		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4395 			/*
4396 			 * We were offline a while ago and this one
4397 			 * seems to indicate that the loop has gone
4398 			 * dead forever.
4399 			 */
4400 			pptr->port_tmp_cnt += dev_cnt;
4401 			pptr->port_state &= ~FCP_STATE_OFFLINE;
4402 			pptr->port_state |= FCP_STATE_INIT;
4403 			link_count = pptr->port_link_cnt;
4404 			fcp_handle_devices(pptr, devlist, dev_cnt,
4405 			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4406 		} else {
4407 			pptr->port_link_cnt++;
4408 			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4409 			fcp_update_state(pptr, (FCP_LUN_BUSY |
4410 			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4411 			if (pptr->port_mpxio) {
4412 				fcp_update_mpxio_path_verifybusy(pptr);
4413 			}
4414 			pptr->port_state |= FCP_STATE_OFFLINE;
4415 			pptr->port_state &=
4416 			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4417 			pptr->port_tmp_cnt = 0;
4418 		}
4419 		mutex_exit(&pptr->port_mutex);
4420 		break;
4421 
4422 	case FC_STATE_ONLINE:
4423 	case FC_STATE_LIP:
4424 	case FC_STATE_LIP_LBIT_SET:
4425 		/*
4426 		 * link has gone from offline to online
4427 		 */
4428 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4429 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4430 		    "link went online");
4431 
4432 		pptr->port_link_cnt++;
4433 
4434 		while (pptr->port_ipkt_cnt) {
4435 			mutex_exit(&pptr->port_mutex);
4436 			delay(drv_usectohz(1000000));
4437 			mutex_enter(&pptr->port_mutex);
4438 		}
4439 
4440 		pptr->port_topology = port_top;
4441 
4442 		/*
4443 		 * The state of the targets and luns accessible through this
4444 		 * port is updated.
4445 		 */
4446 		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4447 		    FCP_CAUSE_LINK_CHANGE);
4448 
4449 		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4450 		pptr->port_state |= FCP_STATE_ONLINING;
4451 		pptr->port_tmp_cnt = dev_cnt;
4452 		link_count = pptr->port_link_cnt;
4453 
4454 		pptr->port_deadline = fcp_watchdog_time +
4455 		    FCP_ICMD_DEADLINE;
4456 
4457 		if (!dev_cnt) {
4458 			/*
4459 			 * We go directly to the online state if no remote
4460 			 * ports were discovered.
4461 			 */
4462 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4463 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4464 			    "No remote ports discovered");
4465 
4466 			pptr->port_state &= ~FCP_STATE_ONLINING;
4467 			pptr->port_state |= FCP_STATE_ONLINE;
4468 		}
4469 
4470 		switch (port_top) {
4471 		case FC_TOP_FABRIC:
4472 		case FC_TOP_PUBLIC_LOOP:
4473 		case FC_TOP_PRIVATE_LOOP:
4474 		case FC_TOP_PT_PT:
4475 
4476 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4477 				fcp_retry_ns_registry(pptr, port_sid);
4478 			}
4479 
4480 			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4481 			    map_tag, FCP_CAUSE_LINK_CHANGE);
4482 			break;
4483 
4484 		default:
4485 			/*
4486 			 * We got here because we were provided with an unknown
4487 			 * topology.
4488 			 */
4489 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4490 				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4491 			}
4492 
4493 			pptr->port_tmp_cnt -= dev_cnt;
4494 			fcp_log(CE_WARN, pptr->port_dip,
4495 			    "!unknown/unsupported topology (0x%x)", port_top);
4496 			break;
4497 		}
4498 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4499 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4500 		    "Notify ssd of the reset to reinstate the reservations");
4501 
4502 		scsi_hba_reset_notify_callback(&pptr->port_mutex,
4503 		    &pptr->port_reset_notify_listf);
4504 
4505 		mutex_exit(&pptr->port_mutex);
4506 
4507 		break;
4508 
4509 	case FC_STATE_RESET:
4510 		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4511 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4512 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4513 		    "RESET state, waiting for Offline/Online state_cb");
4514 		mutex_exit(&pptr->port_mutex);
4515 		break;
4516 
4517 	case FC_STATE_DEVICE_CHANGE:
4518 		/*
4519 		 * We come here when an application has requested
4520 		 * Dynamic node creation/deletion in Fabric connectivity.
4521 		 */
4522 		if (pptr->port_state & (FCP_STATE_OFFLINE |
4523 		    FCP_STATE_INIT)) {
4524 			/*
4525 			 * This case can happen when the FCTL is in the
4526 			 * process of giving us on online and the host on
4527 			 * the other side issues a PLOGI/PLOGO. Ideally
4528 			 * the state changes should be serialized unless
4529 			 * they are opposite (online-offline).
4530 			 * The transport will give us a final state change
4531 			 * so we can ignore this for the time being.
4532 			 */
4533 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4534 			mutex_exit(&pptr->port_mutex);
4535 			break;
4536 		}
4537 
4538 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4539 			fcp_retry_ns_registry(pptr, port_sid);
4540 		}
4541 
4542 		/*
4543 		 * Extend the deadline under steady state conditions
4544 		 * to provide more time for the device-change-commands
4545 		 */
4546 		if (!pptr->port_ipkt_cnt) {
4547 			pptr->port_deadline = fcp_watchdog_time +
4548 			    FCP_ICMD_DEADLINE;
4549 		}
4550 
4551 		/*
4552 		 * There is another race condition here, where if we were
4553 		 * in ONLINEING state and a devices in the map logs out,
4554 		 * fp will give another state change as DEVICE_CHANGE
4555 		 * and OLD. This will result in that target being offlined.
4556 		 * The pd_handle is freed. If from the first statec callback
4557 		 * we were going to fire a PLOGI/PRLI, the system will
4558 		 * panic in fc_ulp_transport with invalid pd_handle.
4559 		 * The fix is to check for the link_cnt before issuing
4560 		 * any command down.
4561 		 */
4562 		fcp_update_targets(pptr, devlist, dev_cnt,
4563 		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4564 
4565 		link_count = pptr->port_link_cnt;
4566 
4567 		fcp_handle_devices(pptr, devlist, dev_cnt,
4568 		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4569 
4570 		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4571 
4572 		mutex_exit(&pptr->port_mutex);
4573 		break;
4574 
4575 	case FC_STATE_TARGET_PORT_RESET:
4576 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4577 			fcp_retry_ns_registry(pptr, port_sid);
4578 		}
4579 
4580 		/* Do nothing else */
4581 		mutex_exit(&pptr->port_mutex);
4582 		break;
4583 
4584 	default:
4585 		fcp_log(CE_WARN, pptr->port_dip,
4586 		    "!Invalid state change=0x%x", port_state);
4587 		mutex_exit(&pptr->port_mutex);
4588 		break;
4589 	}
4590 
4591 	if (map_tag) {
4592 		kmem_free(map_tag, map_len);
4593 	}
4594 }
4595 
4596 /*
4597  *     Function: fcp_handle_devices
4598  *
4599  *  Description: This function updates the devices currently known by
4600  *		 walking the list provided by the caller.  The list passed
4601  *		 by the caller is supposed to be the list of reachable
4602  *		 devices.
4603  *
4604  *     Argument: *pptr		Fcp port structure.
4605  *		 *devlist	Pointer to the first entry of a table
4606  *				containing the remote ports that can be
4607  *				reached.
4608  *		 dev_cnt	Number of entries pointed by devlist.
4609  *		 link_cnt	Link state count.
4610  *		 *map_tag	Array of fcp_map_tag_t structures.
4611  *		 cause		What caused this function to be called.
4612  *
4613  * Return Value: None
4614  *
4615  *	  Notes: The pptr->port_mutex must be held.
4616  */
4617 static void
4618 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4619     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4620 {
4621 	int			i;
4622 	int			check_finish_init = 0;
4623 	fc_portmap_t		*map_entry;
4624 	struct fcp_tgt	*ptgt = NULL;
4625 
4626 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4627 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
4628 	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4629 
4630 	if (dev_cnt) {
4631 		ASSERT(map_tag != NULL);
4632 	}
4633 
4634 	/*
4635 	 * The following code goes through the list of remote ports that are
4636 	 * accessible through this (pptr) local port (The list walked is the
4637 	 * one provided by the caller which is the list of the remote ports
4638 	 * currently reachable).  It checks if any of them was already
4639 	 * known by looking for the corresponding target structure based on
4640 	 * the world wide name.	 If a target is part of the list it is tagged
4641 	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4642 	 *
4643 	 * Old comment
4644 	 * -----------
4645 	 * Before we drop port mutex; we MUST get the tags updated; This
4646 	 * two step process is somewhat slow, but more reliable.
4647 	 */
4648 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4649 		map_entry = &(devlist[i]);
4650 
4651 		/*
4652 		 * get ptr to this map entry in our port's
4653 		 * list (if any)
4654 		 */
4655 		ptgt = fcp_lookup_target(pptr,
4656 		    (uchar_t *)&(map_entry->map_pwwn));
4657 
4658 		if (ptgt) {
4659 			map_tag[i] = ptgt->tgt_change_cnt;
4660 			if (cause == FCP_CAUSE_LINK_CHANGE) {
4661 				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4662 			}
4663 		}
4664 	}
4665 
4666 	/*
4667 	 * At this point we know which devices of the new list were already
4668 	 * known (The field tgt_aux_state of the target structure has been
4669 	 * set to FCP_TGT_TAGGED).
4670 	 *
4671 	 * The following code goes through the list of targets currently known
4672 	 * by the local port (the list is actually a hashing table).  If a
4673 	 * target is found and is not tagged, it means the target cannot
4674 	 * be reached anymore through the local port (pptr).  It is offlined.
4675 	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4676 	 */
4677 	for (i = 0; i < FCP_NUM_HASH; i++) {
4678 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4679 		    ptgt = ptgt->tgt_next) {
4680 			mutex_enter(&ptgt->tgt_mutex);
4681 			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4682 			    (cause == FCP_CAUSE_LINK_CHANGE) &&
4683 			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4684 				fcp_offline_target_now(pptr, ptgt,
4685 				    link_cnt, ptgt->tgt_change_cnt, 0);
4686 			}
4687 			mutex_exit(&ptgt->tgt_mutex);
4688 		}
4689 	}
4690 
4691 	/*
4692 	 * At this point, the devices that were known but cannot be reached
4693 	 * anymore, have most likely been offlined.
4694 	 *
4695 	 * The following section of code seems to go through the list of
4696 	 * remote ports that can now be reached.  For every single one it
4697 	 * checks if it is already known or if it is a new port.
4698 	 */
4699 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4700 
4701 		if (check_finish_init) {
4702 			ASSERT(i > 0);
4703 			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4704 			    map_tag[i - 1], cause);
4705 			check_finish_init = 0;
4706 		}
4707 
4708 		/* get a pointer to this map entry */
4709 		map_entry = &(devlist[i]);
4710 
4711 		/*
4712 		 * Check for the duplicate map entry flag. If we have marked
4713 		 * this entry as a duplicate we skip it since the correct
4714 		 * (perhaps even same) state change will be encountered
4715 		 * later in the list.
4716 		 */
4717 		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4718 			continue;
4719 		}
4720 
4721 		/* get ptr to this map entry in our port's list (if any) */
4722 		ptgt = fcp_lookup_target(pptr,
4723 		    (uchar_t *)&(map_entry->map_pwwn));
4724 
4725 		if (ptgt) {
4726 			/*
4727 			 * This device was already known.  The field
4728 			 * tgt_aux_state is reset (was probably set to
4729 			 * FCP_TGT_TAGGED previously in this routine).
4730 			 */
4731 			ptgt->tgt_aux_state = 0;
4732 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4733 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4734 			    "handle_devices: map did/state/type/flags = "
4735 			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4736 			    "tgt_state=%d",
4737 			    map_entry->map_did.port_id, map_entry->map_state,
4738 			    map_entry->map_type, map_entry->map_flags,
4739 			    ptgt->tgt_d_id, ptgt->tgt_state);
4740 		}
4741 
4742 		if (map_entry->map_type == PORT_DEVICE_OLD ||
4743 		    map_entry->map_type == PORT_DEVICE_NEW ||
4744 		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4745 		    map_entry->map_type == PORT_DEVICE_CHANGED) {
4746 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4747 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
4748 			    "map_type=%x, did = %x",
4749 			    map_entry->map_type,
4750 			    map_entry->map_did.port_id);
4751 		}
4752 
4753 		switch (map_entry->map_type) {
4754 		case PORT_DEVICE_NOCHANGE:
4755 		case PORT_DEVICE_USER_CREATE:
4756 		case PORT_DEVICE_USER_LOGIN:
4757 		case PORT_DEVICE_NEW:
4758 		case PORT_DEVICE_REPORTLUN_CHANGED:
4759 			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4760 
4761 			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4762 			    link_cnt, (ptgt) ? map_tag[i] : 0,
4763 			    cause) == TRUE) {
4764 
4765 				FCP_TGT_TRACE(ptgt, map_tag[i],
4766 				    FCP_TGT_TRACE_2);
4767 				check_finish_init++;
4768 			}
4769 			break;
4770 
4771 		case PORT_DEVICE_OLD:
4772 			if (ptgt != NULL) {
4773 				FCP_TGT_TRACE(ptgt, map_tag[i],
4774 				    FCP_TGT_TRACE_3);
4775 
4776 				mutex_enter(&ptgt->tgt_mutex);
4777 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4778 					/*
4779 					 * Must do an in-line wait for I/Os
4780 					 * to get drained
4781 					 */
4782 					mutex_exit(&ptgt->tgt_mutex);
4783 					mutex_exit(&pptr->port_mutex);
4784 
4785 					mutex_enter(&ptgt->tgt_mutex);
4786 					while (ptgt->tgt_ipkt_cnt ||
4787 					    fcp_outstanding_lun_cmds(ptgt)
4788 					    == FC_SUCCESS) {
4789 						mutex_exit(&ptgt->tgt_mutex);
4790 						delay(drv_usectohz(1000000));
4791 						mutex_enter(&ptgt->tgt_mutex);
4792 					}
4793 					mutex_exit(&ptgt->tgt_mutex);
4794 
4795 					mutex_enter(&pptr->port_mutex);
4796 					mutex_enter(&ptgt->tgt_mutex);
4797 
4798 					(void) fcp_offline_target(pptr, ptgt,
4799 					    link_cnt, map_tag[i], 0, 0);
4800 				}
4801 				mutex_exit(&ptgt->tgt_mutex);
4802 			}
4803 			check_finish_init++;
4804 			break;
4805 
4806 		case PORT_DEVICE_USER_DELETE:
4807 		case PORT_DEVICE_USER_LOGOUT:
4808 			if (ptgt != NULL) {
4809 				FCP_TGT_TRACE(ptgt, map_tag[i],
4810 				    FCP_TGT_TRACE_4);
4811 
4812 				mutex_enter(&ptgt->tgt_mutex);
4813 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4814 					(void) fcp_offline_target(pptr, ptgt,
4815 					    link_cnt, map_tag[i], 1, 0);
4816 				}
4817 				mutex_exit(&ptgt->tgt_mutex);
4818 			}
4819 			check_finish_init++;
4820 			break;
4821 
4822 		case PORT_DEVICE_CHANGED:
4823 			if (ptgt != NULL) {
4824 				FCP_TGT_TRACE(ptgt, map_tag[i],
4825 				    FCP_TGT_TRACE_5);
4826 
4827 				if (fcp_device_changed(pptr, ptgt,
4828 				    map_entry, link_cnt, map_tag[i],
4829 				    cause) == TRUE) {
4830 					check_finish_init++;
4831 				}
4832 			} else {
4833 				if (fcp_handle_mapflags(pptr, ptgt,
4834 				    map_entry, link_cnt, 0, cause) == TRUE) {
4835 					check_finish_init++;
4836 				}
4837 			}
4838 			break;
4839 
4840 		default:
4841 			fcp_log(CE_WARN, pptr->port_dip,
4842 			    "!Invalid map_type=0x%x", map_entry->map_type);
4843 			check_finish_init++;
4844 			break;
4845 		}
4846 	}
4847 
4848 	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4849 		ASSERT(i > 0);
4850 		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4851 		    map_tag[i-1], cause);
4852 	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4853 		fcp_offline_all(pptr, link_cnt, cause);
4854 	}
4855 }
4856 
4857 static int
4858 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4859 {
4860 	struct fcp_lun	*plun;
4861 	struct fcp_port *pptr;
4862 	int		 rscn_count;
4863 	int		 lun0_newalloc;
4864 	int		 ret  = TRUE;
4865 
4866 	ASSERT(ptgt);
4867 	pptr = ptgt->tgt_port;
4868 	lun0_newalloc = 0;
4869 	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4870 		/*
4871 		 * no LUN struct for LUN 0 yet exists,
4872 		 * so create one
4873 		 */
4874 		plun = fcp_alloc_lun(ptgt);
4875 		if (plun == NULL) {
4876 			fcp_log(CE_WARN, pptr->port_dip,
4877 			    "!Failed to allocate lun 0 for"
4878 			    " D_ID=%x", ptgt->tgt_d_id);
4879 			return (ret);
4880 		}
4881 		lun0_newalloc = 1;
4882 	}
4883 
4884 	mutex_enter(&ptgt->tgt_mutex);
4885 	/*
4886 	 * consider lun 0 as device not connected if it is
4887 	 * offlined or newly allocated
4888 	 */
4889 	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4890 		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4891 	}
4892 	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4893 	plun->lun_state &= ~FCP_LUN_OFFLINE;
4894 	ptgt->tgt_lun_cnt = 1;
4895 	ptgt->tgt_report_lun_cnt = 0;
4896 	mutex_exit(&ptgt->tgt_mutex);
4897 
4898 	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4899 	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4900 	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4901 	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4902 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4903 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4904 		    "to D_ID=%x", ptgt->tgt_d_id);
4905 	} else {
4906 		ret = FALSE;
4907 	}
4908 
4909 	return (ret);
4910 }
4911 
4912 /*
4913  *     Function: fcp_handle_mapflags
4914  *
4915  *  Description: This function creates a target structure if the ptgt passed
4916  *		 is NULL.  It also kicks off the PLOGI if we are not logged
4917  *		 into the target yet or the PRLI if we are logged into the
4918  *		 target already.  The rest of the treatment is done in the
4919  *		 callbacks of the PLOGI or PRLI.
4920  *
4921  *     Argument: *pptr		FCP Port structure.
4922  *		 *ptgt		Target structure.
4923  *		 *map_entry	Array of fc_portmap_t structures.
4924  *		 link_cnt	Link state count.
4925  *		 tgt_cnt	Target state count.
4926  *		 cause		What caused this function to be called.
4927  *
4928  * Return Value: TRUE	Failed
4929  *		 FALSE	Succeeded
4930  *
4931  *	  Notes: pptr->port_mutex must be owned.
4932  */
4933 static int
4934 fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
4935     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4936 {
4937 	int			lcount;
4938 	int			tcount;
4939 	int			ret = TRUE;
4940 	int			alloc;
4941 	struct fcp_ipkt	*icmd;
4942 	struct fcp_lun	*pseq_lun = NULL;
4943 	uchar_t			opcode;
4944 	int			valid_ptgt_was_passed = FALSE;
4945 
4946 	ASSERT(mutex_owned(&pptr->port_mutex));
4947 
4948 	/*
4949 	 * This case is possible where the FCTL has come up and done discovery
4950 	 * before FCP was loaded and attached. FCTL would have discovered the
4951 	 * devices and later the ULP came online. In this case ULP's would get
4952 	 * PORT_DEVICE_NOCHANGE but target would be NULL.
4953 	 */
4954 	if (ptgt == NULL) {
4955 		/* don't already have a target */
4956 		mutex_exit(&pptr->port_mutex);
4957 		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4958 		mutex_enter(&pptr->port_mutex);
4959 
4960 		if (ptgt == NULL) {
4961 			fcp_log(CE_WARN, pptr->port_dip,
4962 			    "!FC target allocation failed");
4963 			return (ret);
4964 		}
4965 		mutex_enter(&ptgt->tgt_mutex);
4966 		ptgt->tgt_statec_cause = cause;
4967 		ptgt->tgt_tmp_cnt = 1;
4968 		mutex_exit(&ptgt->tgt_mutex);
4969 	} else {
4970 		valid_ptgt_was_passed = TRUE;
4971 	}
4972 
4973 	/*
4974 	 * Copy in the target parameters
4975 	 */
4976 	mutex_enter(&ptgt->tgt_mutex);
4977 	ptgt->tgt_d_id = map_entry->map_did.port_id;
4978 	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4979 	ptgt->tgt_pd_handle = map_entry->map_pd;
4980 	ptgt->tgt_fca_dev = NULL;
4981 
4982 	/* Copy port and node WWNs */
4983 	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4984 	    FC_WWN_SIZE);
4985 	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4986 	    FC_WWN_SIZE);
4987 
4988 	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4989 	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4990 	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4991 	    valid_ptgt_was_passed) {
4992 		/*
4993 		 * determine if there are any tape LUNs on this target
4994 		 */
4995 		for (pseq_lun = ptgt->tgt_lun;
4996 		    pseq_lun != NULL;
4997 		    pseq_lun = pseq_lun->lun_next) {
4998 			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4999 			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
5000 				fcp_update_tgt_state(ptgt, FCP_RESET,
5001 				    FCP_LUN_MARK);
5002 				mutex_exit(&ptgt->tgt_mutex);
5003 				return (ret);
5004 			}
5005 		}
5006 	}
5007 
5008 	/*
5009 	 * if UA'REPORT_LUN_CHANGED received,
5010 	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
5011 	 */
5012 	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5013 		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5014 		mutex_exit(&ptgt->tgt_mutex);
5015 		mutex_exit(&pptr->port_mutex);
5016 
5017 		ret = fcp_handle_reportlun_changed(ptgt, cause);
5018 
5019 		mutex_enter(&pptr->port_mutex);
5020 		return (ret);
5021 	}
5022 
5023 	/*
5024 	 * If ptgt was NULL when this function was entered, then tgt_node_state
5025 	 * was never specifically initialized but zeroed out which means
5026 	 * FCP_TGT_NODE_NONE.
5027 	 */
5028 	switch (ptgt->tgt_node_state) {
5029 	case FCP_TGT_NODE_NONE:
5030 	case FCP_TGT_NODE_ON_DEMAND:
5031 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5032 		    !fcp_enable_auto_configuration &&
5033 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5034 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5035 		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5036 		    fcp_enable_auto_configuration &&
5037 		    (ptgt->tgt_manual_config_only == 1) &&
5038 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5039 			/*
5040 			 * If auto configuration is set and
5041 			 * the tgt_manual_config_only flag is set then
5042 			 * we only want the user to be able to change
5043 			 * the state through create_on_demand.
5044 			 */
5045 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5046 		} else {
5047 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5048 		}
5049 		break;
5050 
5051 	case FCP_TGT_NODE_PRESENT:
5052 		break;
5053 	}
5054 	/*
5055 	 * If we are booting from a fabric device, make sure we
5056 	 * mark the node state appropriately for this target to be
5057 	 * enumerated
5058 	 */
5059 	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5060 		if (bcmp((caddr_t)pptr->port_boot_wwn,
5061 		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5062 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
5063 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5064 		}
5065 	}
5066 	mutex_exit(&ptgt->tgt_mutex);
5067 
5068 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5069 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
5070 	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5071 	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5072 	    map_entry->map_rscn_info.ulp_rscn_count);
5073 
5074 	mutex_enter(&ptgt->tgt_mutex);
5075 
5076 	/*
5077 	 * Reset target OFFLINE state and mark the target BUSY
5078 	 */
5079 	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5080 	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5081 
5082 	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5083 	lcount = link_cnt;
5084 
5085 	mutex_exit(&ptgt->tgt_mutex);
5086 	mutex_exit(&pptr->port_mutex);
5087 
5088 	/*
5089 	 * if we are already logged in, then we do a PRLI, else
5090 	 * we do a PLOGI first (to get logged in)
5091 	 *
5092 	 * We will not check if we are the PLOGI initiator
5093 	 */
5094 	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5095 	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5096 
5097 	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5098 
5099 	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5100 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5101 	    cause, map_entry->map_rscn_info.ulp_rscn_count);
5102 
5103 	if (icmd == NULL) {
5104 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5105 		/*
5106 		 * We've exited port_mutex before calling fcp_icmd_alloc,
5107 		 * we need to make sure we reacquire it before returning.
5108 		 */
5109 		mutex_enter(&pptr->port_mutex);
5110 		return (FALSE);
5111 	}
5112 
5113 	/* TRUE is only returned while target is intended skipped */
5114 	ret = FALSE;
5115 	/* discover info about this target */
5116 	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5117 	    lcount, tcount, cause)) == DDI_SUCCESS) {
5118 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5119 	} else {
5120 		fcp_icmd_free(pptr, icmd);
5121 		ret = TRUE;
5122 	}
5123 	mutex_enter(&pptr->port_mutex);
5124 
5125 	return (ret);
5126 }
5127 
5128 /*
5129  *     Function: fcp_send_els
5130  *
5131  *  Description: Sends an ELS to the target specified by the caller.  Supports
5132  *		 PLOGI and PRLI.
5133  *
5134  *     Argument: *pptr		Fcp port.
5135  *		 *ptgt		Target to send the ELS to.
5136  *		 *icmd		Internal packet
5137  *		 opcode		ELS opcode
5138  *		 lcount		Link state change counter
5139  *		 tcount		Target state change counter
5140  *		 cause		What caused the call
5141  *
5142  * Return Value: DDI_SUCCESS
5143  *		 Others
5144  */
5145 static int
5146 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5147     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5148 {
5149 	fc_packet_t		*fpkt;
5150 	fc_frame_hdr_t		*hp;
5151 	int			internal = 0;
5152 	int			alloc;
5153 	int			cmd_len;
5154 	int			resp_len;
5155 	int			res = DDI_FAILURE; /* default result */
5156 	int			rval = DDI_FAILURE;
5157 
5158 	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5159 	ASSERT(ptgt->tgt_port == pptr);
5160 
5161 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5162 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5163 	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5164 	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5165 
5166 	if (opcode == LA_ELS_PLOGI) {
5167 		cmd_len = sizeof (la_els_logi_t);
5168 		resp_len = sizeof (la_els_logi_t);
5169 	} else {
5170 		ASSERT(opcode == LA_ELS_PRLI);
5171 		cmd_len = sizeof (la_els_prli_t);
5172 		resp_len = sizeof (la_els_prli_t);
5173 	}
5174 
5175 	if (icmd == NULL) {
5176 		alloc = FCP_MAX(sizeof (la_els_logi_t),
5177 		    sizeof (la_els_prli_t));
5178 		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5179 		    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5180 		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5181 		if (icmd == NULL) {
5182 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5183 			return (res);
5184 		}
5185 		internal++;
5186 	}
5187 	fpkt = icmd->ipkt_fpkt;
5188 
5189 	fpkt->pkt_cmdlen = cmd_len;
5190 	fpkt->pkt_rsplen = resp_len;
5191 	fpkt->pkt_datalen = 0;
5192 	icmd->ipkt_retries = 0;
5193 
5194 	/* fill in fpkt info */
5195 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5196 	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5197 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5198 
5199 	/* get ptr to frame hdr in fpkt */
5200 	hp = &fpkt->pkt_cmd_fhdr;
5201 
5202 	/*
5203 	 * fill in frame hdr
5204 	 */
5205 	hp->r_ctl = R_CTL_ELS_REQ;
5206 	hp->s_id = pptr->port_id;	/* source ID */
5207 	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
5208 	hp->type = FC_TYPE_EXTENDED_LS;
5209 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5210 	hp->seq_id = 0;
5211 	hp->rsvd = 0;
5212 	hp->df_ctl  = 0;
5213 	hp->seq_cnt = 0;
5214 	hp->ox_id = 0xffff;		/* i.e. none */
5215 	hp->rx_id = 0xffff;		/* i.e. none */
5216 	hp->ro = 0;
5217 
5218 	/*
5219 	 * at this point we have a filled in cmd pkt
5220 	 *
5221 	 * fill in the respective info, then use the transport to send
5222 	 * the packet
5223 	 *
5224 	 * for a PLOGI call fc_ulp_login(), and
5225 	 * for a PRLI call fc_ulp_issue_els()
5226 	 */
5227 	switch (opcode) {
5228 	case LA_ELS_PLOGI: {
5229 		struct la_els_logi logi;
5230 
5231 		bzero(&logi, sizeof (struct la_els_logi));
5232 
5233 		hp = &fpkt->pkt_cmd_fhdr;
5234 		hp->r_ctl = R_CTL_ELS_REQ;
5235 		logi.ls_code.ls_code = LA_ELS_PLOGI;
5236 		logi.ls_code.mbz = 0;
5237 
5238 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5239 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5240 
5241 		icmd->ipkt_opcode = LA_ELS_PLOGI;
5242 
5243 		mutex_enter(&pptr->port_mutex);
5244 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5245 
5246 			mutex_exit(&pptr->port_mutex);
5247 
5248 			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5249 			if (rval == FC_SUCCESS) {
5250 				res = DDI_SUCCESS;
5251 				break;
5252 			}
5253 
5254 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5255 
5256 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5257 			    rval, "PLOGI");
5258 		} else {
5259 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5260 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
5261 			    "fcp_send_els1: state change occured"
5262 			    " for D_ID=0x%x", ptgt->tgt_d_id);
5263 			mutex_exit(&pptr->port_mutex);
5264 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5265 		}
5266 		break;
5267 	}
5268 
5269 	case LA_ELS_PRLI: {
5270 		struct la_els_prli	prli;
5271 		struct fcp_prli		*fprli;
5272 
5273 		bzero(&prli, sizeof (struct la_els_prli));
5274 
5275 		hp = &fpkt->pkt_cmd_fhdr;
5276 		hp->r_ctl = R_CTL_ELS_REQ;
5277 
5278 		/* fill in PRLI cmd ELS fields */
5279 		prli.ls_code = LA_ELS_PRLI;
5280 		prli.page_length = 0x10;	/* huh? */
5281 		prli.payload_length = sizeof (struct la_els_prli);
5282 
5283 		icmd->ipkt_opcode = LA_ELS_PRLI;
5284 
5285 		/* get ptr to PRLI service params */
5286 		fprli = (struct fcp_prli *)prli.service_params;
5287 
5288 		/* fill in service params */
5289 		fprli->type = 0x08;
5290 		fprli->resvd1 = 0;
5291 		fprli->orig_process_assoc_valid = 0;
5292 		fprli->resp_process_assoc_valid = 0;
5293 		fprli->establish_image_pair = 1;
5294 		fprli->resvd2 = 0;
5295 		fprli->resvd3 = 0;
5296 		fprli->obsolete_1 = 0;
5297 		fprli->obsolete_2 = 0;
5298 		fprli->data_overlay_allowed = 0;
5299 		fprli->initiator_fn = 1;
5300 		fprli->confirmed_compl_allowed = 1;
5301 
5302 		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5303 			fprli->target_fn = 1;
5304 		} else {
5305 			fprli->target_fn = 0;
5306 		}
5307 
5308 		fprli->retry = 1;
5309 		fprli->read_xfer_rdy_disabled = 1;
5310 		fprli->write_xfer_rdy_disabled = 0;
5311 
5312 		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5313 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5314 
5315 		/* issue the PRLI request */
5316 
5317 		mutex_enter(&pptr->port_mutex);
5318 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5319 
5320 			mutex_exit(&pptr->port_mutex);
5321 
5322 			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5323 			if (rval == FC_SUCCESS) {
5324 				res = DDI_SUCCESS;
5325 				break;
5326 			}
5327 
5328 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5329 
5330 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5331 			    rval, "PRLI");
5332 		} else {
5333 			mutex_exit(&pptr->port_mutex);
5334 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5335 		}
5336 		break;
5337 	}
5338 
5339 	default:
5340 		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5341 		break;
5342 	}
5343 
5344 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5345 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5346 	    "fcp_send_els: returning %d", res);
5347 
5348 	if (res != DDI_SUCCESS) {
5349 		if (internal) {
5350 			fcp_icmd_free(pptr, icmd);
5351 		}
5352 	}
5353 
5354 	return (res);
5355 }
5356 
5357 
5358 /*
5359  * called internally update the state of all of the tgts and each LUN
5360  * for this port (i.e. each target  known to be attached to this port)
5361  * if they are not already offline
5362  *
5363  * must be called with the port mutex owned
5364  *
5365  * acquires and releases the target mutexes for each target attached
5366  * to this port
5367  */
5368 void
5369 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5370 {
5371 	int i;
5372 	struct fcp_tgt *ptgt;
5373 
5374 	ASSERT(mutex_owned(&pptr->port_mutex));
5375 
5376 	for (i = 0; i < FCP_NUM_HASH; i++) {
5377 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5378 		    ptgt = ptgt->tgt_next) {
5379 			mutex_enter(&ptgt->tgt_mutex);
5380 			fcp_update_tgt_state(ptgt, FCP_SET, state);
5381 			ptgt->tgt_change_cnt++;
5382 			ptgt->tgt_statec_cause = cause;
5383 			ptgt->tgt_tmp_cnt = 1;
5384 			ptgt->tgt_done = 0;
5385 			mutex_exit(&ptgt->tgt_mutex);
5386 		}
5387 	}
5388 }
5389 
5390 
5391 static void
5392 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5393 {
5394 	int i;
5395 	int ndevs;
5396 	struct fcp_tgt *ptgt;
5397 
5398 	ASSERT(mutex_owned(&pptr->port_mutex));
5399 
5400 	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5401 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5402 		    ptgt = ptgt->tgt_next) {
5403 			ndevs++;
5404 		}
5405 	}
5406 
5407 	if (ndevs == 0) {
5408 		return;
5409 	}
5410 	pptr->port_tmp_cnt = ndevs;
5411 
5412 	for (i = 0; i < FCP_NUM_HASH; i++) {
5413 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5414 		    ptgt = ptgt->tgt_next) {
5415 			(void) fcp_call_finish_init_held(pptr, ptgt,
5416 			    lcount, ptgt->tgt_change_cnt, cause);
5417 		}
5418 	}
5419 }
5420 
5421 /*
5422  *     Function: fcp_update_tgt_state
5423  *
5424  *  Description: This function updates the field tgt_state of a target.	 That
5425  *		 field is a bitmap and which bit can be set or reset
5426  *		 individually.	The action applied to the target state is also
5427  *		 applied to all the LUNs belonging to the target (provided the
5428  *		 LUN is not offline).  A side effect of applying the state
5429  *		 modification to the target and the LUNs is the field tgt_trace
5430  *		 of the target and lun_trace of the LUNs is set to zero.
5431  *
5432  *
5433  *     Argument: *ptgt	Target structure.
5434  *		 flag	Flag indication what action to apply (set/reset).
5435  *		 state	State bits to update.
5436  *
5437  * Return Value: None
5438  *
5439  *	Context: Interrupt, Kernel or User context.
5440  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5441  *		 calling this function.
5442  */
5443 void
5444 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5445 {
5446 	struct fcp_lun *plun;
5447 
5448 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5449 
5450 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5451 		/* The target is not offline. */
5452 		if (flag == FCP_SET) {
5453 			ptgt->tgt_state |= state;
5454 			ptgt->tgt_trace = 0;
5455 		} else {
5456 			ptgt->tgt_state &= ~state;
5457 		}
5458 
5459 		for (plun = ptgt->tgt_lun; plun != NULL;
5460 		    plun = plun->lun_next) {
5461 			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5462 				/* The LUN is not offline. */
5463 				if (flag == FCP_SET) {
5464 					plun->lun_state |= state;
5465 					plun->lun_trace = 0;
5466 				} else {
5467 					plun->lun_state &= ~state;
5468 				}
5469 			}
5470 		}
5471 	}
5472 }
5473 
5474 /*
5475  *     Function: fcp_update_tgt_state
5476  *
5477  *  Description: This function updates the field lun_state of a LUN.  That
5478  *		 field is a bitmap and which bit can be set or reset
5479  *		 individually.
5480  *
5481  *     Argument: *plun	LUN structure.
5482  *		 flag	Flag indication what action to apply (set/reset).
5483  *		 state	State bits to update.
5484  *
5485  * Return Value: None
5486  *
5487  *	Context: Interrupt, Kernel or User context.
5488  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5489  *		 calling this function.
5490  */
5491 void
5492 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5493 {
5494 	struct fcp_tgt	*ptgt = plun->lun_tgt;
5495 
5496 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5497 
5498 	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5499 		if (flag == FCP_SET) {
5500 			plun->lun_state |= state;
5501 		} else {
5502 			plun->lun_state &= ~state;
5503 		}
5504 	}
5505 }
5506 
5507 /*
5508  *     Function: fcp_get_port
5509  *
5510  *  Description: This function returns the fcp_port structure from the opaque
5511  *		 handle passed by the caller.  That opaque handle is the handle
5512  *		 used by fp/fctl to identify a particular local port.  That
5513  *		 handle has been stored in the corresponding fcp_port
5514  *		 structure.  This function is going to walk the global list of
5515  *		 fcp_port structures till one has a port_fp_handle that matches
5516  *		 the handle passed by the caller.  This function enters the
5517  *		 mutex fcp_global_mutex while walking the global list and then
5518  *		 releases it.
5519  *
5520  *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
5521  *				particular port.
5522  *
5523  * Return Value: NULL		Not found.
5524  *		 Not NULL	Pointer to the fcp_port structure.
5525  *
5526  *	Context: Interrupt, Kernel or User context.
5527  */
5528 static struct fcp_port *
5529 fcp_get_port(opaque_t port_handle)
5530 {
5531 	struct fcp_port *pptr;
5532 
5533 	ASSERT(port_handle != NULL);
5534 
5535 	mutex_enter(&fcp_global_mutex);
5536 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5537 		if (pptr->port_fp_handle == port_handle) {
5538 			break;
5539 		}
5540 	}
5541 	mutex_exit(&fcp_global_mutex);
5542 
5543 	return (pptr);
5544 }
5545 
5546 
5547 static void
5548 fcp_unsol_callback(fc_packet_t *fpkt)
5549 {
5550 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5551 	struct fcp_port *pptr = icmd->ipkt_port;
5552 
5553 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5554 		caddr_t state, reason, action, expln;
5555 
5556 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
5557 		    &action, &expln);
5558 
5559 		fcp_log(CE_WARN, pptr->port_dip,
5560 		    "!couldn't post response to unsolicited request: "
5561 		    " state=%s reason=%s rx_id=%x ox_id=%x",
5562 		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5563 		    fpkt->pkt_cmd_fhdr.rx_id);
5564 	}
5565 	fcp_icmd_free(pptr, icmd);
5566 }
5567 
5568 
5569 /*
5570  * Perform general purpose preparation of a response to an unsolicited request
5571  */
5572 static void
5573 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5574     uchar_t r_ctl, uchar_t type)
5575 {
5576 	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5577 	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5578 	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5579 	pkt->pkt_cmd_fhdr.type = type;
5580 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5581 	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5582 	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5583 	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5584 	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5585 	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5586 	pkt->pkt_cmd_fhdr.ro = 0;
5587 	pkt->pkt_cmd_fhdr.rsvd = 0;
5588 	pkt->pkt_comp = fcp_unsol_callback;
5589 	pkt->pkt_pd = NULL;
5590 	pkt->pkt_ub_resp_token = (opaque_t)buf;
5591 }
5592 
5593 
5594 /*ARGSUSED*/
5595 static int
5596 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5597 {
5598 	fc_packet_t		*fpkt;
5599 	struct la_els_prli	prli;
5600 	struct fcp_prli		*fprli;
5601 	struct fcp_ipkt	*icmd;
5602 	struct la_els_prli	*from;
5603 	struct fcp_prli		*orig;
5604 	struct fcp_tgt	*ptgt;
5605 	int			tcount = 0;
5606 	int			lcount;
5607 
5608 	from = (struct la_els_prli *)buf->ub_buffer;
5609 	orig = (struct fcp_prli *)from->service_params;
5610 	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5611 	    NULL) {
5612 		mutex_enter(&ptgt->tgt_mutex);
5613 		tcount = ptgt->tgt_change_cnt;
5614 		mutex_exit(&ptgt->tgt_mutex);
5615 	}
5616 
5617 	mutex_enter(&pptr->port_mutex);
5618 	lcount = pptr->port_link_cnt;
5619 	mutex_exit(&pptr->port_mutex);
5620 
5621 	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5622 	    sizeof (la_els_prli_t), 0,
5623 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5624 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5625 		return (FC_FAILURE);
5626 	}
5627 
5628 	fpkt = icmd->ipkt_fpkt;
5629 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5630 	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5631 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5632 	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5633 	fpkt->pkt_rsplen = 0;
5634 	fpkt->pkt_datalen = 0;
5635 
5636 	icmd->ipkt_opcode = LA_ELS_PRLI;
5637 
5638 	bzero(&prli, sizeof (struct la_els_prli));
5639 	fprli = (struct fcp_prli *)prli.service_params;
5640 	prli.ls_code = LA_ELS_ACC;
5641 	prli.page_length = 0x10;
5642 	prli.payload_length = sizeof (struct la_els_prli);
5643 
5644 	/* fill in service params */
5645 	fprli->type = 0x08;
5646 	fprli->resvd1 = 0;
5647 	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5648 	fprli->orig_process_associator = orig->orig_process_associator;
5649 	fprli->resp_process_assoc_valid = 0;
5650 	fprli->establish_image_pair = 1;
5651 	fprli->resvd2 = 0;
5652 	fprli->resvd3 = 0;
5653 	fprli->obsolete_1 = 0;
5654 	fprli->obsolete_2 = 0;
5655 	fprli->data_overlay_allowed = 0;
5656 	fprli->initiator_fn = 1;
5657 	fprli->confirmed_compl_allowed = 1;
5658 
5659 	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5660 		fprli->target_fn = 1;
5661 	} else {
5662 		fprli->target_fn = 0;
5663 	}
5664 
5665 	fprli->retry = 1;
5666 	fprli->read_xfer_rdy_disabled = 1;
5667 	fprli->write_xfer_rdy_disabled = 0;
5668 
5669 	/* save the unsol prli payload first */
5670 	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5671 	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5672 
5673 	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5674 	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5675 
5676 	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5677 
5678 	mutex_enter(&pptr->port_mutex);
5679 	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5680 		int rval;
5681 		mutex_exit(&pptr->port_mutex);
5682 
5683 		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5684 		    FC_SUCCESS) {
5685 			if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5686 			    ptgt != NULL) {
5687 				fcp_queue_ipkt(pptr, fpkt);
5688 				return (FC_SUCCESS);
5689 			}
5690 			/* Let it timeout */
5691 			fcp_icmd_free(pptr, icmd);
5692 			return (FC_FAILURE);
5693 		}
5694 	} else {
5695 		mutex_exit(&pptr->port_mutex);
5696 		fcp_icmd_free(pptr, icmd);
5697 		return (FC_FAILURE);
5698 	}
5699 
5700 	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5701 
5702 	return (FC_SUCCESS);
5703 }
5704 
5705 /*
5706  *     Function: fcp_icmd_alloc
5707  *
5708  *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
5709  *		 field is initialized to fcp_icmd_callback.  Sometimes it is
5710  *		 modified by the caller (such as fcp_send_scsi).  The
5711  *		 structure is also tied to the state of the line and of the
5712  *		 target at a particular time.  That link is established by
5713  *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5714  *		 and tcount which came respectively from pptr->link_cnt and
5715  *		 ptgt->tgt_change_cnt.
5716  *
5717  *     Argument: *pptr		Fcp port.
5718  *		 *ptgt		Target (destination of the command).
5719  *		 cmd_len	Length of the command.
5720  *		 resp_len	Length of the expected response.
5721  *		 data_len	Length of the data.
5722  *		 nodma		Indicates weither the command and response.
5723  *				will be transfer through DMA or not.
5724  *		 lcount		Link state change counter.
5725  *		 tcount		Target state change counter.
5726  *		 cause		Reason that lead to this call.
5727  *
5728  * Return Value: NULL		Failed.
5729  *		 Not NULL	Internal packet address.
5730  */
5731 static struct fcp_ipkt *
5732 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5733     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5734     uint32_t rscn_count)
5735 {
5736 	int			dma_setup = 0;
5737 	fc_packet_t		*fpkt;
5738 	struct fcp_ipkt	*icmd = NULL;
5739 
5740 	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5741 	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5742 	    KM_NOSLEEP);
5743 	if (icmd == NULL) {
5744 		fcp_log(CE_WARN, pptr->port_dip,
5745 		    "!internal packet allocation failed");
5746 		return (NULL);
5747 	}
5748 
5749 	/*
5750 	 * initialize the allocated packet
5751 	 */
5752 	icmd->ipkt_nodma = nodma;
5753 	icmd->ipkt_next = icmd->ipkt_prev = NULL;
5754 	icmd->ipkt_lun = NULL;
5755 
5756 	icmd->ipkt_link_cnt = lcount;
5757 	icmd->ipkt_change_cnt = tcount;
5758 	icmd->ipkt_cause = cause;
5759 
5760 	mutex_enter(&pptr->port_mutex);
5761 	icmd->ipkt_port = pptr;
5762 	mutex_exit(&pptr->port_mutex);
5763 
5764 	/* keep track of amt of data to be sent in pkt */
5765 	icmd->ipkt_cmdlen = cmd_len;
5766 	icmd->ipkt_resplen = resp_len;
5767 	icmd->ipkt_datalen = data_len;
5768 
5769 	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5770 	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5771 
5772 	/* set pkt's private ptr to point to cmd pkt */
5773 	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5774 
5775 	/* set FCA private ptr to memory just beyond */
5776 	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5777 	    ((char *)icmd + sizeof (struct fcp_ipkt) +
5778 	    pptr->port_dmacookie_sz);
5779 
5780 	/* get ptr to fpkt substruct and fill it in */
5781 	fpkt = icmd->ipkt_fpkt;
5782 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5783 	    sizeof (struct fcp_ipkt));
5784 
5785 	if (ptgt != NULL) {
5786 		icmd->ipkt_tgt = ptgt;
5787 		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5788 	}
5789 
5790 	fpkt->pkt_comp = fcp_icmd_callback;
5791 	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5792 	fpkt->pkt_cmdlen = cmd_len;
5793 	fpkt->pkt_rsplen = resp_len;
5794 	fpkt->pkt_datalen = data_len;
5795 
5796 	/*
5797 	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5798 	 * rscn_count as fcp knows down to the transport. If a valid count was
5799 	 * passed into this function, we allocate memory to actually pass down
5800 	 * this info.
5801 	 *
5802 	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5803 	 * basically mean that fcp will not be able to help transport
5804 	 * distinguish if a new RSCN has come after fcp was last informed about
5805 	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5806 	 * 5068068 where the device might end up going offline in case of RSCN
5807 	 * storms.
5808 	 */
5809 	fpkt->pkt_ulp_rscn_infop = NULL;
5810 	if (rscn_count != FC_INVALID_RSCN_COUNT) {
5811 		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5812 		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5813 		if (fpkt->pkt_ulp_rscn_infop == NULL) {
5814 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5815 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5816 			    "Failed to alloc memory to pass rscn info");
5817 		}
5818 	}
5819 
5820 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5821 		fc_ulp_rscn_info_t	*rscnp;
5822 
5823 		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5824 		rscnp->ulp_rscn_count = rscn_count;
5825 	}
5826 
5827 	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5828 		goto fail;
5829 	}
5830 	dma_setup++;
5831 
5832 	/*
5833 	 * Must hold target mutex across setting of pkt_pd and call to
5834 	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5835 	 * away while we're not looking.
5836 	 */
5837 	if (ptgt != NULL) {
5838 		mutex_enter(&ptgt->tgt_mutex);
5839 		fpkt->pkt_pd = ptgt->tgt_pd_handle;
5840 
5841 		/* ask transport to do its initialization on this pkt */
5842 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5843 		    != FC_SUCCESS) {
5844 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5845 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5846 			    "fc_ulp_init_packet failed");
5847 			mutex_exit(&ptgt->tgt_mutex);
5848 			goto fail;
5849 		}
5850 		mutex_exit(&ptgt->tgt_mutex);
5851 	} else {
5852 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5853 		    != FC_SUCCESS) {
5854 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5855 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5856 			    "fc_ulp_init_packet failed");
5857 			goto fail;
5858 		}
5859 	}
5860 
5861 	mutex_enter(&pptr->port_mutex);
5862 	if (pptr->port_state & (FCP_STATE_DETACHING |
5863 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5864 		int rval;
5865 
5866 		mutex_exit(&pptr->port_mutex);
5867 
5868 		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5869 		ASSERT(rval == FC_SUCCESS);
5870 
5871 		goto fail;
5872 	}
5873 
5874 	if (ptgt != NULL) {
5875 		mutex_enter(&ptgt->tgt_mutex);
5876 		ptgt->tgt_ipkt_cnt++;
5877 		mutex_exit(&ptgt->tgt_mutex);
5878 	}
5879 
5880 	pptr->port_ipkt_cnt++;
5881 
5882 	mutex_exit(&pptr->port_mutex);
5883 
5884 	return (icmd);
5885 
5886 fail:
5887 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5888 		kmem_free(fpkt->pkt_ulp_rscn_infop,
5889 		    sizeof (fc_ulp_rscn_info_t));
5890 		fpkt->pkt_ulp_rscn_infop = NULL;
5891 	}
5892 
5893 	if (dma_setup) {
5894 		fcp_free_dma(pptr, icmd);
5895 	}
5896 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5897 	    (size_t)pptr->port_dmacookie_sz);
5898 
5899 	return (NULL);
5900 }
5901 
5902 /*
5903  *     Function: fcp_icmd_free
5904  *
5905  *  Description: Frees the internal command passed by the caller.
5906  *
5907  *     Argument: *pptr		Fcp port.
5908  *		 *icmd		Internal packet to free.
5909  *
5910  * Return Value: None
5911  */
5912 static void
5913 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5914 {
5915 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
5916 
5917 	/* Let the underlying layers do their cleanup. */
5918 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5919 	    icmd->ipkt_fpkt);
5920 
5921 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5922 		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5923 		    sizeof (fc_ulp_rscn_info_t));
5924 	}
5925 
5926 	fcp_free_dma(pptr, icmd);
5927 
5928 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5929 	    (size_t)pptr->port_dmacookie_sz);
5930 
5931 	mutex_enter(&pptr->port_mutex);
5932 
5933 	if (ptgt) {
5934 		mutex_enter(&ptgt->tgt_mutex);
5935 		ptgt->tgt_ipkt_cnt--;
5936 		mutex_exit(&ptgt->tgt_mutex);
5937 	}
5938 
5939 	pptr->port_ipkt_cnt--;
5940 	mutex_exit(&pptr->port_mutex);
5941 }
5942 
5943 /*
5944  *     Function: fcp_alloc_dma
5945  *
5946  *  Description: Allocated the DMA resources required for the internal
5947  *		 packet.
5948  *
5949  *     Argument: *pptr	FCP port.
5950  *		 *icmd	Internal FCP packet.
5951  *		 nodma	Indicates if the Cmd and Resp will be DMAed.
5952  *		 flags	Allocation flags (Sleep or NoSleep).
5953  *
5954  * Return Value: FC_SUCCESS
5955  *		 FC_NOMEM
5956  */
5957 static int
5958 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5959     int nodma, int flags)
5960 {
5961 	int		rval;
5962 	size_t		real_size;
5963 	uint_t		ccount;
5964 	int		bound = 0;
5965 	int		cmd_resp = 0;
5966 	fc_packet_t	*fpkt;
5967 	ddi_dma_cookie_t	pkt_data_cookie;
5968 	ddi_dma_cookie_t	*cp;
5969 	uint32_t		cnt;
5970 
5971 	fpkt = &icmd->ipkt_fc_packet;
5972 
5973 	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5974 	    fpkt->pkt_resp_dma == NULL);
5975 
5976 	icmd->ipkt_nodma = nodma;
5977 
5978 	if (nodma) {
5979 		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5980 		if (fpkt->pkt_cmd == NULL) {
5981 			goto fail;
5982 		}
5983 
5984 		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5985 		if (fpkt->pkt_resp == NULL) {
5986 			goto fail;
5987 		}
5988 	} else {
5989 		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5990 
5991 		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5992 		if (rval == FC_FAILURE) {
5993 			ASSERT(fpkt->pkt_cmd_dma == NULL &&
5994 			    fpkt->pkt_resp_dma == NULL);
5995 			goto fail;
5996 		}
5997 		cmd_resp++;
5998 	}
5999 
6000 	if ((fpkt->pkt_datalen != 0) &&
6001 	    !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
6002 		/*
6003 		 * set up DMA handle and memory for the data in this packet
6004 		 */
6005 		if (ddi_dma_alloc_handle(pptr->port_dip,
6006 		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6007 		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6008 			goto fail;
6009 		}
6010 
6011 		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6012 		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6013 		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6014 		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6015 			goto fail;
6016 		}
6017 
6018 		/* was DMA mem size gotten < size asked for/needed ?? */
6019 		if (real_size < fpkt->pkt_datalen) {
6020 			goto fail;
6021 		}
6022 
6023 		/* bind DMA address and handle together */
6024 		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6025 		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6026 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6027 		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6028 			goto fail;
6029 		}
6030 		bound++;
6031 
6032 		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6033 			goto fail;
6034 		}
6035 
6036 		fpkt->pkt_data_cookie_cnt = ccount;
6037 
6038 		cp = fpkt->pkt_data_cookie;
6039 		*cp = pkt_data_cookie;
6040 		cp++;
6041 
6042 		for (cnt = 1; cnt < ccount; cnt++, cp++) {
6043 			ddi_dma_nextcookie(fpkt->pkt_data_dma,
6044 			    &pkt_data_cookie);
6045 			*cp = pkt_data_cookie;
6046 		}
6047 
6048 	} else if (fpkt->pkt_datalen != 0) {
6049 		/*
6050 		 * If it's a pseudo FCA, then it can't support DMA even in
6051 		 * SCSI data phase.
6052 		 */
6053 		fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6054 		if (fpkt->pkt_data == NULL) {
6055 			goto fail;
6056 		}
6057 
6058 	}
6059 
6060 	return (FC_SUCCESS);
6061 
6062 fail:
6063 	if (bound) {
6064 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6065 	}
6066 
6067 	if (fpkt->pkt_data_dma) {
6068 		if (fpkt->pkt_data) {
6069 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6070 		}
6071 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6072 	} else {
6073 		if (fpkt->pkt_data) {
6074 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6075 		}
6076 	}
6077 
6078 	if (nodma) {
6079 		if (fpkt->pkt_cmd) {
6080 			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6081 		}
6082 		if (fpkt->pkt_resp) {
6083 			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6084 		}
6085 	} else {
6086 		if (cmd_resp) {
6087 			fcp_free_cmd_resp(pptr, fpkt);
6088 		}
6089 	}
6090 
6091 	return (FC_NOMEM);
6092 }
6093 
6094 
6095 static void
6096 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6097 {
6098 	fc_packet_t *fpkt = icmd->ipkt_fpkt;
6099 
6100 	if (fpkt->pkt_data_dma) {
6101 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6102 		if (fpkt->pkt_data) {
6103 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6104 		}
6105 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6106 	} else {
6107 		if (fpkt->pkt_data) {
6108 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6109 		}
6110 		/*
6111 		 * Need we reset pkt_* to zero???
6112 		 */
6113 	}
6114 
6115 	if (icmd->ipkt_nodma) {
6116 		if (fpkt->pkt_cmd) {
6117 			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6118 		}
6119 		if (fpkt->pkt_resp) {
6120 			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6121 		}
6122 	} else {
6123 		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6124 
6125 		fcp_free_cmd_resp(pptr, fpkt);
6126 	}
6127 }
6128 
6129 /*
6130  *     Function: fcp_lookup_target
6131  *
6132  *  Description: Finds a target given a WWN.
6133  *
6134  *     Argument: *pptr	FCP port.
6135  *		 *wwn	World Wide Name of the device to look for.
6136  *
6137  * Return Value: NULL		No target found
6138  *		 Not NULL	Target structure
6139  *
6140  *	Context: Interrupt context.
6141  *		 The mutex pptr->port_mutex must be owned.
6142  */
6143 /* ARGSUSED */
6144 static struct fcp_tgt *
6145 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6146 {
6147 	int			hash;
6148 	struct fcp_tgt	*ptgt;
6149 
6150 	ASSERT(mutex_owned(&pptr->port_mutex));
6151 
6152 	hash = FCP_HASH(wwn);
6153 
6154 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6155 	    ptgt = ptgt->tgt_next) {
6156 		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6157 		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6158 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
6159 			break;
6160 		}
6161 	}
6162 
6163 	return (ptgt);
6164 }
6165 
6166 
6167 /*
6168  * Find target structure given a port identifier
6169  */
6170 static struct fcp_tgt *
6171 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6172 {
6173 	fc_portid_t		port_id;
6174 	la_wwn_t		pwwn;
6175 	struct fcp_tgt	*ptgt = NULL;
6176 
6177 	port_id.priv_lilp_posit = 0;
6178 	port_id.port_id = d_id;
6179 	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6180 	    &pwwn) == FC_SUCCESS) {
6181 		mutex_enter(&pptr->port_mutex);
6182 		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6183 		mutex_exit(&pptr->port_mutex);
6184 	}
6185 
6186 	return (ptgt);
6187 }
6188 
6189 
6190 /*
6191  * the packet completion callback routine for info cmd pkts
6192  *
6193  * this means fpkt pts to a response to either a PLOGI or a PRLI
6194  *
6195  * if there is an error an attempt is made to call a routine to resend
6196  * the command that failed
6197  */
6198 static void
6199 fcp_icmd_callback(fc_packet_t *fpkt)
6200 {
6201 	struct fcp_ipkt	*icmd;
6202 	struct fcp_port	*pptr;
6203 	struct fcp_tgt	*ptgt;
6204 	struct la_els_prli	*prli;
6205 	struct la_els_prli	prli_s;
6206 	struct fcp_prli		*fprli;
6207 	struct fcp_lun	*plun;
6208 	int		free_pkt = 1;
6209 	int		rval;
6210 	ls_code_t	resp;
6211 	uchar_t		prli_acc = 0;
6212 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
6213 	int		lun0_newalloc;
6214 
6215 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6216 
6217 	/* get ptrs to the port and target structs for the cmd */
6218 	pptr = icmd->ipkt_port;
6219 	ptgt = icmd->ipkt_tgt;
6220 
6221 	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6222 
6223 	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6224 		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6225 		    sizeof (prli_s));
6226 		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6227 	}
6228 
6229 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6230 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6231 	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
6232 	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6233 	    ptgt->tgt_d_id);
6234 
6235 	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6236 	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6237 
6238 		mutex_enter(&ptgt->tgt_mutex);
6239 		if (ptgt->tgt_pd_handle == NULL) {
6240 			/*
6241 			 * in a fabric environment the port device handles
6242 			 * get created only after successful LOGIN into the
6243 			 * transport, so the transport makes this port
6244 			 * device (pd) handle available in this packet, so
6245 			 * save it now
6246 			 */
6247 			ASSERT(fpkt->pkt_pd != NULL);
6248 			ptgt->tgt_pd_handle = fpkt->pkt_pd;
6249 		}
6250 		mutex_exit(&ptgt->tgt_mutex);
6251 
6252 		/* which ELS cmd is this response for ?? */
6253 		switch (icmd->ipkt_opcode) {
6254 		case LA_ELS_PLOGI:
6255 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6256 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6257 			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6258 			    ptgt->tgt_d_id,
6259 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6260 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6261 
6262 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6263 			    FCP_TGT_TRACE_15);
6264 
6265 			/* Note that we are not allocating a new icmd */
6266 			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6267 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6268 			    icmd->ipkt_cause) != DDI_SUCCESS) {
6269 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6270 				    FCP_TGT_TRACE_16);
6271 				goto fail;
6272 			}
6273 			break;
6274 
6275 		case LA_ELS_PRLI:
6276 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6277 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6278 			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6279 
6280 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6281 			    FCP_TGT_TRACE_17);
6282 
6283 			prli = &prli_s;
6284 
6285 			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6286 			    sizeof (prli_s));
6287 
6288 			fprli = (struct fcp_prli *)prli->service_params;
6289 
6290 			mutex_enter(&ptgt->tgt_mutex);
6291 			ptgt->tgt_icap = fprli->initiator_fn;
6292 			ptgt->tgt_tcap = fprli->target_fn;
6293 			mutex_exit(&ptgt->tgt_mutex);
6294 
6295 			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6296 				/*
6297 				 * this FCP device does not support target mode
6298 				 */
6299 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6300 				    FCP_TGT_TRACE_18);
6301 				goto fail;
6302 			}
6303 			if (fprli->retry == 1) {
6304 				fc_ulp_disable_relogin(pptr->port_fp_handle,
6305 				    &ptgt->tgt_port_wwn);
6306 			}
6307 
6308 			/* target is no longer offline */
6309 			mutex_enter(&pptr->port_mutex);
6310 			mutex_enter(&ptgt->tgt_mutex);
6311 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6312 				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6313 				    FCP_TGT_MARK);
6314 			} else {
6315 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6316 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6317 				    "fcp_icmd_callback,1: state change "
6318 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6319 				mutex_exit(&ptgt->tgt_mutex);
6320 				mutex_exit(&pptr->port_mutex);
6321 				goto fail;
6322 			}
6323 			mutex_exit(&ptgt->tgt_mutex);
6324 			mutex_exit(&pptr->port_mutex);
6325 
6326 			/*
6327 			 * lun 0 should always respond to inquiry, so
6328 			 * get the LUN struct for LUN 0
6329 			 *
6330 			 * Currently we deal with first level of addressing.
6331 			 * If / when we start supporting 0x device types
6332 			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6333 			 * this logic will need revisiting.
6334 			 */
6335 			lun0_newalloc = 0;
6336 			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6337 				/*
6338 				 * no LUN struct for LUN 0 yet exists,
6339 				 * so create one
6340 				 */
6341 				plun = fcp_alloc_lun(ptgt);
6342 				if (plun == NULL) {
6343 					fcp_log(CE_WARN, pptr->port_dip,
6344 					    "!Failed to allocate lun 0 for"
6345 					    " D_ID=%x", ptgt->tgt_d_id);
6346 					goto fail;
6347 				}
6348 				lun0_newalloc = 1;
6349 			}
6350 
6351 			/* fill in LUN info */
6352 			mutex_enter(&ptgt->tgt_mutex);
6353 			/*
6354 			 * consider lun 0 as device not connected if it is
6355 			 * offlined or newly allocated
6356 			 */
6357 			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6358 			    lun0_newalloc) {
6359 				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6360 			}
6361 			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6362 			plun->lun_state &= ~FCP_LUN_OFFLINE;
6363 			ptgt->tgt_lun_cnt = 1;
6364 			ptgt->tgt_report_lun_cnt = 0;
6365 			mutex_exit(&ptgt->tgt_mutex);
6366 
6367 			/* Retrieve the rscn count (if a valid one exists) */
6368 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6369 				rscn_count = ((fc_ulp_rscn_info_t *)
6370 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6371 				    ->ulp_rscn_count;
6372 			} else {
6373 				rscn_count = FC_INVALID_RSCN_COUNT;
6374 			}
6375 
6376 			/* send Report Lun request to target */
6377 			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6378 			    sizeof (struct fcp_reportlun_resp),
6379 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6380 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6381 				mutex_enter(&pptr->port_mutex);
6382 				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6383 					fcp_log(CE_WARN, pptr->port_dip,
6384 					    "!Failed to send REPORT LUN to"
6385 					    "  D_ID=%x", ptgt->tgt_d_id);
6386 				} else {
6387 					FCP_TRACE(fcp_logq,
6388 					    pptr->port_instbuf, fcp_trace,
6389 					    FCP_BUF_LEVEL_5, 0,
6390 					    "fcp_icmd_callback,2:state change"
6391 					    " occured for D_ID=0x%x",
6392 					    ptgt->tgt_d_id);
6393 				}
6394 				mutex_exit(&pptr->port_mutex);
6395 
6396 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6397 				    FCP_TGT_TRACE_19);
6398 
6399 				goto fail;
6400 			} else {
6401 				free_pkt = 0;
6402 				fcp_icmd_free(pptr, icmd);
6403 			}
6404 			break;
6405 
6406 		default:
6407 			fcp_log(CE_WARN, pptr->port_dip,
6408 			    "!fcp_icmd_callback Invalid opcode");
6409 			goto fail;
6410 		}
6411 
6412 		return;
6413 	}
6414 
6415 
6416 	/*
6417 	 * Other PLOGI failures are not retried as the
6418 	 * transport does it already
6419 	 */
6420 	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6421 		if (fcp_is_retryable(icmd) &&
6422 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6423 
6424 			if (FCP_MUST_RETRY(fpkt)) {
6425 				fcp_queue_ipkt(pptr, fpkt);
6426 				return;
6427 			}
6428 
6429 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6430 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6431 			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
6432 			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6433 			    fpkt->pkt_reason);
6434 
6435 			/*
6436 			 * Retry by recalling the routine that
6437 			 * originally queued this packet
6438 			 */
6439 			mutex_enter(&pptr->port_mutex);
6440 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6441 				caddr_t msg;
6442 
6443 				mutex_exit(&pptr->port_mutex);
6444 
6445 				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6446 
6447 				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6448 					fpkt->pkt_timeout +=
6449 					    FCP_TIMEOUT_DELTA;
6450 				}
6451 
6452 				rval = fc_ulp_issue_els(pptr->port_fp_handle,
6453 				    fpkt);
6454 				if (rval == FC_SUCCESS) {
6455 					return;
6456 				}
6457 
6458 				if (rval == FC_STATEC_BUSY ||
6459 				    rval == FC_OFFLINE) {
6460 					fcp_queue_ipkt(pptr, fpkt);
6461 					return;
6462 				}
6463 				(void) fc_ulp_error(rval, &msg);
6464 
6465 				fcp_log(CE_NOTE, pptr->port_dip,
6466 				    "!ELS 0x%x failed to d_id=0x%x;"
6467 				    " %s", icmd->ipkt_opcode,
6468 				    ptgt->tgt_d_id, msg);
6469 			} else {
6470 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6471 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6472 				    "fcp_icmd_callback,3: state change "
6473 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6474 				mutex_exit(&pptr->port_mutex);
6475 			}
6476 		}
6477 	} else {
6478 		if (fcp_is_retryable(icmd) &&
6479 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6480 			if (FCP_MUST_RETRY(fpkt)) {
6481 				fcp_queue_ipkt(pptr, fpkt);
6482 				return;
6483 			}
6484 		}
6485 		mutex_enter(&pptr->port_mutex);
6486 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6487 		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6488 			mutex_exit(&pptr->port_mutex);
6489 			fcp_print_error(fpkt);
6490 		} else {
6491 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6492 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6493 			    "fcp_icmd_callback,4: state change occured"
6494 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6495 			mutex_exit(&pptr->port_mutex);
6496 		}
6497 	}
6498 
6499 fail:
6500 	if (free_pkt) {
6501 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6502 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6503 		fcp_icmd_free(pptr, icmd);
6504 	}
6505 }
6506 
6507 
6508 /*
6509  * called internally to send an info cmd using the transport
6510  *
6511  * sends either an INQ or a REPORT_LUN
6512  *
6513  * when the packet is completed fcp_scsi_callback is called
6514  */
6515 static int
6516 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6517     int lcount, int tcount, int cause, uint32_t rscn_count)
6518 {
6519 	int			nodma;
6520 	struct fcp_ipkt		*icmd;
6521 	struct fcp_tgt		*ptgt;
6522 	struct fcp_port		*pptr;
6523 	fc_frame_hdr_t		*hp;
6524 	fc_packet_t		*fpkt;
6525 	struct fcp_cmd		fcp_cmd;
6526 	struct fcp_cmd		*fcmd;
6527 	union scsi_cdb		*scsi_cdb;
6528 
6529 	ASSERT(plun != NULL);
6530 
6531 	ptgt = plun->lun_tgt;
6532 	ASSERT(ptgt != NULL);
6533 
6534 	pptr = ptgt->tgt_port;
6535 	ASSERT(pptr != NULL);
6536 
6537 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6538 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6539 	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6540 
6541 	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6542 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6543 	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6544 	    rscn_count);
6545 
6546 	if (icmd == NULL) {
6547 		return (DDI_FAILURE);
6548 	}
6549 
6550 	fpkt = icmd->ipkt_fpkt;
6551 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6552 	icmd->ipkt_retries = 0;
6553 	icmd->ipkt_opcode = opcode;
6554 	icmd->ipkt_lun = plun;
6555 
6556 	if (nodma) {
6557 		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6558 	} else {
6559 		fcmd = &fcp_cmd;
6560 	}
6561 	bzero(fcmd, sizeof (struct fcp_cmd));
6562 
6563 	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6564 
6565 	hp = &fpkt->pkt_cmd_fhdr;
6566 
6567 	hp->s_id = pptr->port_id;
6568 	hp->d_id = ptgt->tgt_d_id;
6569 	hp->r_ctl = R_CTL_COMMAND;
6570 	hp->type = FC_TYPE_SCSI_FCP;
6571 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6572 	hp->rsvd = 0;
6573 	hp->seq_id = 0;
6574 	hp->seq_cnt = 0;
6575 	hp->ox_id = 0xffff;
6576 	hp->rx_id = 0xffff;
6577 	hp->ro = 0;
6578 
6579 	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6580 
6581 	/*
6582 	 * Request SCSI target for expedited processing
6583 	 */
6584 
6585 	/*
6586 	 * Set up for untagged queuing because we do not
6587 	 * know if the fibre device supports queuing.
6588 	 */
6589 	fcmd->fcp_cntl.cntl_reserved_0 = 0;
6590 	fcmd->fcp_cntl.cntl_reserved_1 = 0;
6591 	fcmd->fcp_cntl.cntl_reserved_2 = 0;
6592 	fcmd->fcp_cntl.cntl_reserved_3 = 0;
6593 	fcmd->fcp_cntl.cntl_reserved_4 = 0;
6594 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6595 	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6596 
6597 	switch (opcode) {
6598 	case SCMD_INQUIRY_PAGE83:
6599 		/*
6600 		 * Prepare to get the Inquiry VPD page 83 information
6601 		 */
6602 		fcmd->fcp_cntl.cntl_read_data = 1;
6603 		fcmd->fcp_cntl.cntl_write_data = 0;
6604 		fcmd->fcp_data_len = alloc_len;
6605 
6606 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6607 		fpkt->pkt_comp = fcp_scsi_callback;
6608 
6609 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6610 		scsi_cdb->g0_addr2 = 0x01;
6611 		scsi_cdb->g0_addr1 = 0x83;
6612 		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6613 		break;
6614 
6615 	case SCMD_INQUIRY:
6616 		fcmd->fcp_cntl.cntl_read_data = 1;
6617 		fcmd->fcp_cntl.cntl_write_data = 0;
6618 		fcmd->fcp_data_len = alloc_len;
6619 
6620 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6621 		fpkt->pkt_comp = fcp_scsi_callback;
6622 
6623 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6624 		scsi_cdb->g0_count0 = SUN_INQSIZE;
6625 		break;
6626 
6627 	case SCMD_REPORT_LUN: {
6628 		fc_portid_t	d_id;
6629 		opaque_t	fca_dev;
6630 
6631 		ASSERT(alloc_len >= 16);
6632 
6633 		d_id.priv_lilp_posit = 0;
6634 		d_id.port_id = ptgt->tgt_d_id;
6635 
6636 		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6637 
6638 		mutex_enter(&ptgt->tgt_mutex);
6639 		ptgt->tgt_fca_dev = fca_dev;
6640 		mutex_exit(&ptgt->tgt_mutex);
6641 
6642 		fcmd->fcp_cntl.cntl_read_data = 1;
6643 		fcmd->fcp_cntl.cntl_write_data = 0;
6644 		fcmd->fcp_data_len = alloc_len;
6645 
6646 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6647 		fpkt->pkt_comp = fcp_scsi_callback;
6648 
6649 		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6650 		scsi_cdb->scc5_count0 = alloc_len & 0xff;
6651 		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6652 		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6653 		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6654 		break;
6655 	}
6656 
6657 	default:
6658 		fcp_log(CE_WARN, pptr->port_dip,
6659 		    "!fcp_send_scsi Invalid opcode");
6660 		break;
6661 	}
6662 
6663 	if (!nodma) {
6664 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6665 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6666 	}
6667 
6668 	mutex_enter(&pptr->port_mutex);
6669 	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6670 
6671 		mutex_exit(&pptr->port_mutex);
6672 		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6673 		    FC_SUCCESS) {
6674 			fcp_icmd_free(pptr, icmd);
6675 			return (DDI_FAILURE);
6676 		}
6677 		return (DDI_SUCCESS);
6678 	} else {
6679 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6680 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6681 		    "fcp_send_scsi,1: state change occured"
6682 		    " for D_ID=0x%x", ptgt->tgt_d_id);
6683 		mutex_exit(&pptr->port_mutex);
6684 		fcp_icmd_free(pptr, icmd);
6685 		return (DDI_FAILURE);
6686 	}
6687 }
6688 
6689 
6690 /*
6691  * called by fcp_scsi_callback to check to handle the case where
6692  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6693  */
6694 static int
6695 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6696 {
6697 	uchar_t				rqlen;
6698 	int				rval = DDI_FAILURE;
6699 	struct scsi_extended_sense	sense_info, *sense;
6700 	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
6701 	    fpkt->pkt_ulp_private;
6702 	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
6703 	struct fcp_port		*pptr = ptgt->tgt_port;
6704 
6705 	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6706 
6707 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6708 		/*
6709 		 * SCSI-II Reserve Release support. Some older FC drives return
6710 		 * Reservation conflict for Report Luns command.
6711 		 */
6712 		if (icmd->ipkt_nodma) {
6713 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6714 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6715 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6716 		} else {
6717 			fcp_rsp_t	new_resp;
6718 
6719 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6720 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6721 
6722 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6723 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6724 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6725 
6726 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6727 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6728 		}
6729 
6730 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6731 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6732 
6733 		return (DDI_SUCCESS);
6734 	}
6735 
6736 	sense = &sense_info;
6737 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
6738 		/* no need to continue if sense length is not set */
6739 		return (rval);
6740 	}
6741 
6742 	/* casting 64-bit integer to 8-bit */
6743 	rqlen = (uchar_t)min(rsp->fcp_sense_len,
6744 	    sizeof (struct scsi_extended_sense));
6745 
6746 	if (rqlen < 14) {
6747 		/* no need to continue if request length isn't long enough */
6748 		return (rval);
6749 	}
6750 
6751 	if (icmd->ipkt_nodma) {
6752 		/*
6753 		 * We can safely use fcp_response_len here since the
6754 		 * only path that calls fcp_check_reportlun,
6755 		 * fcp_scsi_callback, has already called
6756 		 * fcp_validate_fcp_response.
6757 		 */
6758 		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6759 		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6760 	} else {
6761 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6762 		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6763 		    sizeof (struct scsi_extended_sense));
6764 	}
6765 
6766 	if (!FCP_SENSE_NO_LUN(sense)) {
6767 		mutex_enter(&ptgt->tgt_mutex);
6768 		/* clear the flag if any */
6769 		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6770 		mutex_exit(&ptgt->tgt_mutex);
6771 	}
6772 
6773 	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6774 	    (sense->es_add_code == 0x20)) {
6775 		if (icmd->ipkt_nodma) {
6776 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6777 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6778 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6779 		} else {
6780 			fcp_rsp_t	new_resp;
6781 
6782 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6783 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6784 
6785 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6786 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6787 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6788 
6789 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6790 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6791 		}
6792 
6793 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6794 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6795 
6796 		return (DDI_SUCCESS);
6797 	}
6798 
6799 	/*
6800 	 * This is for the STK library which returns a check condition,
6801 	 * to indicate device is not ready, manual assistance needed.
6802 	 * This is to a report lun command when the door is open.
6803 	 */
6804 	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6805 		if (icmd->ipkt_nodma) {
6806 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6807 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6808 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6809 		} else {
6810 			fcp_rsp_t	new_resp;
6811 
6812 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6813 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6814 
6815 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6816 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6817 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6818 
6819 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6820 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6821 		}
6822 
6823 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6824 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6825 
6826 		return (DDI_SUCCESS);
6827 	}
6828 
6829 	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6830 	    (FCP_SENSE_NO_LUN(sense))) {
6831 		mutex_enter(&ptgt->tgt_mutex);
6832 		if ((FCP_SENSE_NO_LUN(sense)) &&
6833 		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6834 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6835 			mutex_exit(&ptgt->tgt_mutex);
6836 			/*
6837 			 * reconfig was triggred by ILLEGAL REQUEST but
6838 			 * got ILLEGAL REQUEST again
6839 			 */
6840 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6841 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
6842 			    "!FCP: Unable to obtain Report Lun data"
6843 			    " target=%x", ptgt->tgt_d_id);
6844 		} else {
6845 			if (ptgt->tgt_tid == NULL) {
6846 				timeout_id_t	tid;
6847 				/*
6848 				 * REPORT LUN data has changed.	 Kick off
6849 				 * rediscovery
6850 				 */
6851 				tid = timeout(fcp_reconfigure_luns,
6852 				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6853 
6854 				ptgt->tgt_tid = tid;
6855 				ptgt->tgt_state |= FCP_TGT_BUSY;
6856 			}
6857 			if (FCP_SENSE_NO_LUN(sense)) {
6858 				ptgt->tgt_state |= FCP_TGT_ILLREQ;
6859 			}
6860 			mutex_exit(&ptgt->tgt_mutex);
6861 			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6862 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6863 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6864 				    "!FCP:Report Lun Has Changed"
6865 				    " target=%x", ptgt->tgt_d_id);
6866 			} else if (FCP_SENSE_NO_LUN(sense)) {
6867 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6868 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6869 				    "!FCP:LU Not Supported"
6870 				    " target=%x", ptgt->tgt_d_id);
6871 			}
6872 		}
6873 		rval = DDI_SUCCESS;
6874 	}
6875 
6876 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6877 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6878 	    "D_ID=%x, sense=%x, status=%x",
6879 	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6880 	    rsp->fcp_u.fcp_status.scsi_status);
6881 
6882 	return (rval);
6883 }
6884 
6885 /*
6886  *     Function: fcp_scsi_callback
6887  *
6888  *  Description: This is the callback routine set by fcp_send_scsi() after
6889  *		 it calls fcp_icmd_alloc().  The SCSI command completed here
6890  *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
6891  *		 INQUIRY_PAGE83.
6892  *
6893  *     Argument: *fpkt	 FC packet used to convey the command
6894  *
6895  * Return Value: None
6896  */
6897 static void
6898 fcp_scsi_callback(fc_packet_t *fpkt)
6899 {
6900 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
6901 	    fpkt->pkt_ulp_private;
6902 	struct fcp_rsp_info	fcp_rsp_err, *bep;
6903 	struct fcp_port	*pptr;
6904 	struct fcp_tgt	*ptgt;
6905 	struct fcp_lun	*plun;
6906 	struct fcp_rsp		response, *rsp;
6907 
6908 	ptgt = icmd->ipkt_tgt;
6909 	pptr = ptgt->tgt_port;
6910 	plun = icmd->ipkt_lun;
6911 
6912 	if (icmd->ipkt_nodma) {
6913 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6914 	} else {
6915 		rsp = &response;
6916 		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6917 		    sizeof (struct fcp_rsp));
6918 	}
6919 
6920 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6921 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6922 	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
6923 	    "status=%x, lun num=%x",
6924 	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6925 	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6926 
6927 	/*
6928 	 * Pre-init LUN GUID with NWWN if it is not a device that
6929 	 * supports multiple luns and we know it's not page83
6930 	 * compliant.  Although using a NWWN is not lun unique,
6931 	 * we will be fine since there is only one lun behind the taget
6932 	 * in this case.
6933 	 */
6934 	if ((plun->lun_guid_size == 0) &&
6935 	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6936 	    (fcp_symmetric_device_probe(plun) == 0)) {
6937 
6938 		char ascii_wwn[FC_WWN_SIZE*2+1];
6939 		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6940 		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6941 	}
6942 
6943 	/*
6944 	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6945 	 * when thay have more data than what is asked in CDB. An overrun
6946 	 * is really when FCP_DL is smaller than the data length in CDB.
6947 	 * In the case here we know that REPORT LUN command we formed within
6948 	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6949 	 * behavior. In reality this is FC_SUCCESS.
6950 	 */
6951 	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6952 	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6953 	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6954 		fpkt->pkt_state = FC_PKT_SUCCESS;
6955 	}
6956 
6957 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6958 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6959 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6960 		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6961 		    ptgt->tgt_d_id);
6962 
6963 		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6964 			/*
6965 			 * Inquiry VPD page command on A5K SES devices would
6966 			 * result in data CRC errors.
6967 			 */
6968 			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6969 				(void) fcp_handle_page83(fpkt, icmd, 1);
6970 				return;
6971 			}
6972 		}
6973 		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6974 		    FCP_MUST_RETRY(fpkt)) {
6975 			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6976 			fcp_retry_scsi_cmd(fpkt);
6977 			return;
6978 		}
6979 
6980 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6981 		    FCP_TGT_TRACE_20);
6982 
6983 		mutex_enter(&pptr->port_mutex);
6984 		mutex_enter(&ptgt->tgt_mutex);
6985 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6986 			mutex_exit(&ptgt->tgt_mutex);
6987 			mutex_exit(&pptr->port_mutex);
6988 			fcp_print_error(fpkt);
6989 		} else {
6990 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6991 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6992 			    "fcp_scsi_callback,1: state change occured"
6993 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6994 			mutex_exit(&ptgt->tgt_mutex);
6995 			mutex_exit(&pptr->port_mutex);
6996 		}
6997 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6998 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6999 		fcp_icmd_free(pptr, icmd);
7000 		return;
7001 	}
7002 
7003 	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7004 
7005 	mutex_enter(&pptr->port_mutex);
7006 	mutex_enter(&ptgt->tgt_mutex);
7007 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7008 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7009 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7010 		    "fcp_scsi_callback,2: state change occured"
7011 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7012 		mutex_exit(&ptgt->tgt_mutex);
7013 		mutex_exit(&pptr->port_mutex);
7014 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7015 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7016 		fcp_icmd_free(pptr, icmd);
7017 		return;
7018 	}
7019 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7020 
7021 	mutex_exit(&ptgt->tgt_mutex);
7022 	mutex_exit(&pptr->port_mutex);
7023 
7024 	if (icmd->ipkt_nodma) {
7025 		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7026 		    sizeof (struct fcp_rsp));
7027 	} else {
7028 		bep = &fcp_rsp_err;
7029 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7030 		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7031 	}
7032 
7033 	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7034 		fcp_retry_scsi_cmd(fpkt);
7035 		return;
7036 	}
7037 
7038 	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7039 	    FCP_NO_FAILURE) {
7040 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7041 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7042 		    "rsp_code=0x%x, rsp_len_set=0x%x",
7043 		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7044 		fcp_retry_scsi_cmd(fpkt);
7045 		return;
7046 	}
7047 
7048 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7049 	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7050 		fcp_queue_ipkt(pptr, fpkt);
7051 		return;
7052 	}
7053 
7054 	/*
7055 	 * Devices that do not support INQUIRY_PAGE83, return check condition
7056 	 * with illegal request as per SCSI spec.
7057 	 * Crossbridge is one such device and Daktari's SES node is another.
7058 	 * We want to ideally enumerate these devices as a non-mpxio devices.
7059 	 * SES nodes (Daktari only currently) are an exception to this.
7060 	 */
7061 	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7062 	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7063 
7064 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7065 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
7066 		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7067 		    "check condition. May enumerate as non-mpxio device",
7068 		    ptgt->tgt_d_id, plun->lun_type);
7069 
7070 		/*
7071 		 * If we let Daktari's SES be enumerated as a non-mpxio
7072 		 * device, there will be a discrepency in that the other
7073 		 * internal FC disks will get enumerated as mpxio devices.
7074 		 * Applications like luxadm expect this to be consistent.
7075 		 *
7076 		 * So, we put in a hack here to check if this is an SES device
7077 		 * and handle it here.
7078 		 */
7079 		if (plun->lun_type == DTYPE_ESI) {
7080 			/*
7081 			 * Since, pkt_state is actually FC_PKT_SUCCESS
7082 			 * at this stage, we fake a failure here so that
7083 			 * fcp_handle_page83 will create a device path using
7084 			 * the WWN instead of the GUID which is not there anyway
7085 			 */
7086 			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7087 			(void) fcp_handle_page83(fpkt, icmd, 1);
7088 			return;
7089 		}
7090 
7091 		mutex_enter(&ptgt->tgt_mutex);
7092 		plun->lun_state &= ~(FCP_LUN_OFFLINE |
7093 		    FCP_LUN_MARK | FCP_LUN_BUSY);
7094 		mutex_exit(&ptgt->tgt_mutex);
7095 
7096 		(void) fcp_call_finish_init(pptr, ptgt,
7097 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7098 		    icmd->ipkt_cause);
7099 		fcp_icmd_free(pptr, icmd);
7100 		return;
7101 	}
7102 
7103 	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7104 		int rval = DDI_FAILURE;
7105 
7106 		/*
7107 		 * handle cases where report lun isn't supported
7108 		 * by faking up our own REPORT_LUN response or
7109 		 * UNIT ATTENTION
7110 		 */
7111 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7112 			rval = fcp_check_reportlun(rsp, fpkt);
7113 
7114 			/*
7115 			 * fcp_check_reportlun might have modified the
7116 			 * FCP response. Copy it in again to get an updated
7117 			 * FCP response
7118 			 */
7119 			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7120 				rsp = &response;
7121 
7122 				FCP_CP_IN(fpkt->pkt_resp, rsp,
7123 				    fpkt->pkt_resp_acc,
7124 				    sizeof (struct fcp_rsp));
7125 			}
7126 		}
7127 
7128 		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7129 			if (rval == DDI_SUCCESS) {
7130 				(void) fcp_call_finish_init(pptr, ptgt,
7131 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7132 				    icmd->ipkt_cause);
7133 				fcp_icmd_free(pptr, icmd);
7134 			} else {
7135 				fcp_retry_scsi_cmd(fpkt);
7136 			}
7137 
7138 			return;
7139 		}
7140 	} else {
7141 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7142 			mutex_enter(&ptgt->tgt_mutex);
7143 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7144 			mutex_exit(&ptgt->tgt_mutex);
7145 		}
7146 	}
7147 
7148 	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7149 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7150 		(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7151 		    DDI_DMA_SYNC_FORCPU);
7152 	}
7153 
7154 	switch (icmd->ipkt_opcode) {
7155 	case SCMD_INQUIRY:
7156 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7157 		fcp_handle_inquiry(fpkt, icmd);
7158 		break;
7159 
7160 	case SCMD_REPORT_LUN:
7161 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7162 		    FCP_TGT_TRACE_22);
7163 		fcp_handle_reportlun(fpkt, icmd);
7164 		break;
7165 
7166 	case SCMD_INQUIRY_PAGE83:
7167 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7168 		(void) fcp_handle_page83(fpkt, icmd, 0);
7169 		break;
7170 
7171 	default:
7172 		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7173 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7174 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7175 		fcp_icmd_free(pptr, icmd);
7176 		break;
7177 	}
7178 }
7179 
7180 
7181 static void
7182 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7183 {
7184 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
7185 	    fpkt->pkt_ulp_private;
7186 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
7187 	struct fcp_port	*pptr = ptgt->tgt_port;
7188 
7189 	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7190 	    fcp_is_retryable(icmd)) {
7191 		mutex_enter(&pptr->port_mutex);
7192 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7193 			mutex_exit(&pptr->port_mutex);
7194 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7195 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7196 			    "Retrying %s to %x; state=%x, reason=%x",
7197 			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7198 			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7199 			    fpkt->pkt_state, fpkt->pkt_reason);
7200 
7201 			fcp_queue_ipkt(pptr, fpkt);
7202 		} else {
7203 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7204 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7205 			    "fcp_retry_scsi_cmd,1: state change occured"
7206 			    " for D_ID=0x%x", ptgt->tgt_d_id);
7207 			mutex_exit(&pptr->port_mutex);
7208 			(void) fcp_call_finish_init(pptr, ptgt,
7209 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7210 			    icmd->ipkt_cause);
7211 			fcp_icmd_free(pptr, icmd);
7212 		}
7213 	} else {
7214 		fcp_print_error(fpkt);
7215 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7216 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7217 		fcp_icmd_free(pptr, icmd);
7218 	}
7219 }
7220 
7221 /*
7222  *     Function: fcp_handle_page83
7223  *
7224  *  Description: Treats the response to INQUIRY_PAGE83.
7225  *
7226  *     Argument: *fpkt	FC packet used to convey the command.
7227  *		 *icmd	Original fcp_ipkt structure.
7228  *		 ignore_page83_data
7229  *			if it's 1, that means it's a special devices's
7230  *			page83 response, it should be enumerated under mpxio
7231  *
7232  * Return Value: None
7233  */
7234 static void
7235 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7236     int ignore_page83_data)
7237 {
7238 	struct fcp_port	*pptr;
7239 	struct fcp_lun	*plun;
7240 	struct fcp_tgt	*ptgt;
7241 	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7242 	int			fail = 0;
7243 	ddi_devid_t		devid;
7244 	char			*guid = NULL;
7245 	int			ret;
7246 
7247 	ASSERT(icmd != NULL && fpkt != NULL);
7248 
7249 	pptr = icmd->ipkt_port;
7250 	ptgt = icmd->ipkt_tgt;
7251 	plun = icmd->ipkt_lun;
7252 
7253 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7254 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7255 
7256 		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7257 		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
7258 
7259 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7260 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7261 		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7262 		    "dtype=0x%x, lun num=%x",
7263 		    pptr->port_instance, ptgt->tgt_d_id,
7264 		    dev_id_page[0], plun->lun_num);
7265 
7266 		ret = ddi_devid_scsi_encode(
7267 		    DEVID_SCSI_ENCODE_VERSION_LATEST,
7268 		    NULL,		/* driver name */
7269 		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
7270 		    sizeof (plun->lun_inq), /* size of standard inquiry */
7271 		    NULL,		/* page 80 data */
7272 		    0,		/* page 80 len */
7273 		    dev_id_page,	/* page 83 data */
7274 		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7275 		    &devid);
7276 
7277 		if (ret == DDI_SUCCESS) {
7278 
7279 			guid = ddi_devid_to_guid(devid);
7280 
7281 			if (guid) {
7282 				/*
7283 				 * Check our current guid.  If it's non null
7284 				 * and it has changed, we need to copy it into
7285 				 * lun_old_guid since we might still need it.
7286 				 */
7287 				if (plun->lun_guid &&
7288 				    strcmp(guid, plun->lun_guid)) {
7289 					unsigned int len;
7290 
7291 					/*
7292 					 * If the guid of the LUN changes,
7293 					 * reconfiguration should be triggered
7294 					 * to reflect the changes.
7295 					 * i.e. we should offline the LUN with
7296 					 * the old guid, and online the LUN with
7297 					 * the new guid.
7298 					 */
7299 					plun->lun_state |= FCP_LUN_CHANGED;
7300 
7301 					if (plun->lun_old_guid) {
7302 						kmem_free(plun->lun_old_guid,
7303 						    plun->lun_old_guid_size);
7304 					}
7305 
7306 					len = plun->lun_guid_size;
7307 					plun->lun_old_guid_size = len;
7308 
7309 					plun->lun_old_guid = kmem_zalloc(len,
7310 					    KM_NOSLEEP);
7311 
7312 					if (plun->lun_old_guid) {
7313 						/*
7314 						 * The alloc was successful then
7315 						 * let's do the copy.
7316 						 */
7317 						bcopy(plun->lun_guid,
7318 						    plun->lun_old_guid, len);
7319 					} else {
7320 						fail = 1;
7321 						plun->lun_old_guid_size = 0;
7322 					}
7323 				}
7324 				if (!fail) {
7325 					if (fcp_copy_guid_2_lun_block(
7326 					    plun, guid)) {
7327 						fail = 1;
7328 					}
7329 				}
7330 				ddi_devid_free_guid(guid);
7331 
7332 			} else {
7333 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7334 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
7335 				    "fcp_handle_page83: unable to create "
7336 				    "GUID");
7337 
7338 				/* couldn't create good guid from devid */
7339 				fail = 1;
7340 			}
7341 			ddi_devid_free(devid);
7342 
7343 		} else if (ret == DDI_NOT_WELL_FORMED) {
7344 			/* NULL filled data for page 83 */
7345 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7346 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7347 			    "fcp_handle_page83: retry GUID");
7348 
7349 			icmd->ipkt_retries = 0;
7350 			fcp_retry_scsi_cmd(fpkt);
7351 			return;
7352 		} else {
7353 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7354 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7355 			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7356 			    ret);
7357 			/*
7358 			 * Since the page83 validation
7359 			 * introduced late, we are being
7360 			 * tolerant to the existing devices
7361 			 * that already found to be working
7362 			 * under mpxio, like A5200's SES device,
7363 			 * its page83 response will not be standard-compliant,
7364 			 * but we still want it to be enumerated under mpxio.
7365 			 */
7366 			if (fcp_symmetric_device_probe(plun) != 0) {
7367 				fail = 1;
7368 			}
7369 		}
7370 
7371 	} else {
7372 		/* bad packet state */
7373 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7374 
7375 		/*
7376 		 * For some special devices (A5K SES and Daktari's SES devices),
7377 		 * they should be enumerated under mpxio
7378 		 * or "luxadm dis" will fail
7379 		 */
7380 		if (ignore_page83_data) {
7381 			fail = 0;
7382 		} else {
7383 			fail = 1;
7384 		}
7385 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7386 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7387 		    "!Devid page cmd failed. "
7388 		    "fpkt_state: %x fpkt_reason: %x",
7389 		    "ignore_page83: %d",
7390 		    fpkt->pkt_state, fpkt->pkt_reason,
7391 		    ignore_page83_data);
7392 	}
7393 
7394 	mutex_enter(&pptr->port_mutex);
7395 	mutex_enter(&plun->lun_mutex);
7396 	/*
7397 	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7398 	 * mismatch between lun_cip and lun_mpxio.
7399 	 */
7400 	if (plun->lun_cip == NULL) {
7401 		/*
7402 		 * If we don't have a guid for this lun it's because we were
7403 		 * unable to glean one from the page 83 response.  Set the
7404 		 * control flag to 0 here to make sure that we don't attempt to
7405 		 * enumerate it under mpxio.
7406 		 */
7407 		if (fail || pptr->port_mpxio == 0) {
7408 			plun->lun_mpxio = 0;
7409 		} else {
7410 			plun->lun_mpxio = 1;
7411 		}
7412 	}
7413 	mutex_exit(&plun->lun_mutex);
7414 	mutex_exit(&pptr->port_mutex);
7415 
7416 	mutex_enter(&ptgt->tgt_mutex);
7417 	plun->lun_state &=
7418 	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7419 	mutex_exit(&ptgt->tgt_mutex);
7420 
7421 	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7422 	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7423 
7424 	fcp_icmd_free(pptr, icmd);
7425 }
7426 
7427 /*
7428  *     Function: fcp_handle_inquiry
7429  *
7430  *  Description: Called by fcp_scsi_callback to handle the response to an
7431  *		 INQUIRY request.
7432  *
7433  *     Argument: *fpkt	FC packet used to convey the command.
7434  *		 *icmd	Original fcp_ipkt structure.
7435  *
7436  * Return Value: None
7437  */
7438 static void
7439 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7440 {
7441 	struct fcp_port	*pptr;
7442 	struct fcp_lun	*plun;
7443 	struct fcp_tgt	*ptgt;
7444 	uchar_t		dtype;
7445 	uchar_t		pqual;
7446 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
7447 
7448 	ASSERT(icmd != NULL && fpkt != NULL);
7449 
7450 	pptr = icmd->ipkt_port;
7451 	ptgt = icmd->ipkt_tgt;
7452 	plun = icmd->ipkt_lun;
7453 
7454 	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7455 	    sizeof (struct scsi_inquiry));
7456 
7457 	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7458 	pqual = plun->lun_inq.inq_dtype >> 5;
7459 
7460 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7461 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7462 	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7463 	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7464 	    plun->lun_num, dtype, pqual);
7465 
7466 	if (pqual != 0) {
7467 		/*
7468 		 * Non-zero peripheral qualifier
7469 		 */
7470 		fcp_log(CE_CONT, pptr->port_dip,
7471 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7472 		    "Device type=0x%x Peripheral qual=0x%x\n",
7473 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7474 
7475 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7476 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7477 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7478 		    "Device type=0x%x Peripheral qual=0x%x\n",
7479 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7480 
7481 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7482 
7483 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7484 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7485 		fcp_icmd_free(pptr, icmd);
7486 		return;
7487 	}
7488 
7489 	/*
7490 	 * If the device is already initialized, check the dtype
7491 	 * for a change. If it has changed then update the flags
7492 	 * so the create_luns will offline the old device and
7493 	 * create the new device. Refer to bug: 4764752
7494 	 */
7495 	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7496 		plun->lun_state |= FCP_LUN_CHANGED;
7497 	}
7498 	plun->lun_type = plun->lun_inq.inq_dtype;
7499 
7500 	/*
7501 	 * This code is setting/initializing the throttling in the FCA
7502 	 * driver.
7503 	 */
7504 	mutex_enter(&pptr->port_mutex);
7505 	if (!pptr->port_notify) {
7506 		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7507 			uint32_t cmd = 0;
7508 			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7509 			    ((cmd & 0xFFFFFF00 >> 8) |
7510 			    FCP_SVE_THROTTLE << 8));
7511 			pptr->port_notify = 1;
7512 			mutex_exit(&pptr->port_mutex);
7513 			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7514 			mutex_enter(&pptr->port_mutex);
7515 		}
7516 	}
7517 
7518 	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7519 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7520 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7521 		    "fcp_handle_inquiry,1:state change occured"
7522 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7523 		mutex_exit(&pptr->port_mutex);
7524 
7525 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7526 		(void) fcp_call_finish_init(pptr, ptgt,
7527 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7528 		    icmd->ipkt_cause);
7529 		fcp_icmd_free(pptr, icmd);
7530 		return;
7531 	}
7532 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7533 	mutex_exit(&pptr->port_mutex);
7534 
7535 	/* Retrieve the rscn count (if a valid one exists) */
7536 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7537 		rscn_count = ((fc_ulp_rscn_info_t *)
7538 		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7539 	} else {
7540 		rscn_count = FC_INVALID_RSCN_COUNT;
7541 	}
7542 
7543 	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7544 	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
7545 	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7546 	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7547 		fcp_log(CE_WARN, NULL, "!failed to send page 83");
7548 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7549 		(void) fcp_call_finish_init(pptr, ptgt,
7550 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7551 		    icmd->ipkt_cause);
7552 	}
7553 
7554 	/*
7555 	 * Read Inquiry VPD Page 0x83 to uniquely
7556 	 * identify this logical unit.
7557 	 */
7558 	fcp_icmd_free(pptr, icmd);
7559 }
7560 
7561 /*
7562  *     Function: fcp_handle_reportlun
7563  *
7564  *  Description: Called by fcp_scsi_callback to handle the response to a
7565  *		 REPORT_LUN request.
7566  *
7567  *     Argument: *fpkt	FC packet used to convey the command.
7568  *		 *icmd	Original fcp_ipkt structure.
7569  *
7570  * Return Value: None
7571  */
7572 static void
7573 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7574 {
7575 	int				i;
7576 	int				nluns_claimed;
7577 	int				nluns_bufmax;
7578 	int				len;
7579 	uint16_t			lun_num;
7580 	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
7581 	struct fcp_port			*pptr;
7582 	struct fcp_tgt			*ptgt;
7583 	struct fcp_lun			*plun;
7584 	struct fcp_reportlun_resp	*report_lun;
7585 
7586 	pptr = icmd->ipkt_port;
7587 	ptgt = icmd->ipkt_tgt;
7588 	len = fpkt->pkt_datalen;
7589 
7590 	if ((len < FCP_LUN_HEADER) ||
7591 	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7592 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7593 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7594 		fcp_icmd_free(pptr, icmd);
7595 		return;
7596 	}
7597 
7598 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7599 	    fpkt->pkt_datalen);
7600 
7601 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7602 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7603 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7604 	    pptr->port_instance, ptgt->tgt_d_id);
7605 
7606 	/*
7607 	 * Get the number of luns (which is supplied as LUNS * 8) the
7608 	 * device claims it has.
7609 	 */
7610 	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7611 
7612 	/*
7613 	 * Get the maximum number of luns the buffer submitted can hold.
7614 	 */
7615 	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7616 
7617 	/*
7618 	 * Due to limitations of certain hardware, we support only 16 bit LUNs
7619 	 */
7620 	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7621 		kmem_free(report_lun, len);
7622 
7623 		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7624 		    " 0x%x number of LUNs for target=%x", nluns_claimed,
7625 		    ptgt->tgt_d_id);
7626 
7627 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7628 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7629 		fcp_icmd_free(pptr, icmd);
7630 		return;
7631 	}
7632 
7633 	/*
7634 	 * If there are more LUNs than we have allocated memory for,
7635 	 * allocate more space and send down yet another report lun if
7636 	 * the maximum number of attempts hasn't been reached.
7637 	 */
7638 	mutex_enter(&ptgt->tgt_mutex);
7639 
7640 	if ((nluns_claimed > nluns_bufmax) &&
7641 	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7642 
7643 		struct fcp_lun *plun;
7644 
7645 		ptgt->tgt_report_lun_cnt++;
7646 		plun = ptgt->tgt_lun;
7647 		ASSERT(plun != NULL);
7648 		mutex_exit(&ptgt->tgt_mutex);
7649 
7650 		kmem_free(report_lun, len);
7651 
7652 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7653 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7654 		    "!Dynamically discovered %d LUNs for D_ID=%x",
7655 		    nluns_claimed, ptgt->tgt_d_id);
7656 
7657 		/* Retrieve the rscn count (if a valid one exists) */
7658 		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7659 			rscn_count = ((fc_ulp_rscn_info_t *)
7660 			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7661 			    ulp_rscn_count;
7662 		} else {
7663 			rscn_count = FC_INVALID_RSCN_COUNT;
7664 		}
7665 
7666 		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7667 		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7668 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7669 		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7670 			(void) fcp_call_finish_init(pptr, ptgt,
7671 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7672 			    icmd->ipkt_cause);
7673 		}
7674 
7675 		fcp_icmd_free(pptr, icmd);
7676 		return;
7677 	}
7678 
7679 	if (nluns_claimed > nluns_bufmax) {
7680 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7681 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7682 		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7683 		    "	 Number of LUNs lost=%x",
7684 		    ptgt->tgt_port_wwn.raw_wwn[0],
7685 		    ptgt->tgt_port_wwn.raw_wwn[1],
7686 		    ptgt->tgt_port_wwn.raw_wwn[2],
7687 		    ptgt->tgt_port_wwn.raw_wwn[3],
7688 		    ptgt->tgt_port_wwn.raw_wwn[4],
7689 		    ptgt->tgt_port_wwn.raw_wwn[5],
7690 		    ptgt->tgt_port_wwn.raw_wwn[6],
7691 		    ptgt->tgt_port_wwn.raw_wwn[7],
7692 		    nluns_claimed - nluns_bufmax);
7693 
7694 		nluns_claimed = nluns_bufmax;
7695 	}
7696 	ptgt->tgt_lun_cnt = nluns_claimed;
7697 
7698 	/*
7699 	 * Identify missing LUNs and print warning messages
7700 	 */
7701 	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7702 		int offline;
7703 		int exists = 0;
7704 
7705 		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7706 
7707 		for (i = 0; i < nluns_claimed && exists == 0; i++) {
7708 			uchar_t		*lun_string;
7709 
7710 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7711 
7712 			switch (lun_string[0] & 0xC0) {
7713 			case FCP_LUN_ADDRESSING:
7714 			case FCP_PD_ADDRESSING:
7715 			case FCP_VOLUME_ADDRESSING:
7716 				lun_num = ((lun_string[0] & 0x3F) << 8) |
7717 				    lun_string[1];
7718 				if (plun->lun_num == lun_num) {
7719 					exists++;
7720 					break;
7721 				}
7722 				break;
7723 
7724 			default:
7725 				break;
7726 			}
7727 		}
7728 
7729 		if (!exists && !offline) {
7730 			mutex_exit(&ptgt->tgt_mutex);
7731 
7732 			mutex_enter(&pptr->port_mutex);
7733 			mutex_enter(&ptgt->tgt_mutex);
7734 			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7735 				/*
7736 				 * set disappear flag when device was connected
7737 				 */
7738 				if (!(plun->lun_state &
7739 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7740 					plun->lun_state |= FCP_LUN_DISAPPEARED;
7741 				}
7742 				mutex_exit(&ptgt->tgt_mutex);
7743 				mutex_exit(&pptr->port_mutex);
7744 				if (!(plun->lun_state &
7745 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7746 					fcp_log(CE_NOTE, pptr->port_dip,
7747 					    "!Lun=%x for target=%x disappeared",
7748 					    plun->lun_num, ptgt->tgt_d_id);
7749 				}
7750 				mutex_enter(&ptgt->tgt_mutex);
7751 			} else {
7752 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7753 				    fcp_trace, FCP_BUF_LEVEL_5, 0,
7754 				    "fcp_handle_reportlun,1: state change"
7755 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
7756 				mutex_exit(&ptgt->tgt_mutex);
7757 				mutex_exit(&pptr->port_mutex);
7758 				kmem_free(report_lun, len);
7759 				(void) fcp_call_finish_init(pptr, ptgt,
7760 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7761 				    icmd->ipkt_cause);
7762 				fcp_icmd_free(pptr, icmd);
7763 				return;
7764 			}
7765 		} else if (exists) {
7766 			/*
7767 			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7768 			 * actually exists in REPORT_LUN response
7769 			 */
7770 			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7771 				plun->lun_state &=
7772 				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
7773 			}
7774 			if (offline || plun->lun_num == 0) {
7775 				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7776 					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7777 					mutex_exit(&ptgt->tgt_mutex);
7778 					fcp_log(CE_NOTE, pptr->port_dip,
7779 					    "!Lun=%x for target=%x reappeared",
7780 					    plun->lun_num, ptgt->tgt_d_id);
7781 					mutex_enter(&ptgt->tgt_mutex);
7782 				}
7783 			}
7784 		}
7785 	}
7786 
7787 	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7788 	mutex_exit(&ptgt->tgt_mutex);
7789 
7790 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7791 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7792 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7793 	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7794 
7795 	/* scan each lun */
7796 	for (i = 0; i < nluns_claimed; i++) {
7797 		uchar_t	*lun_string;
7798 
7799 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7800 
7801 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7802 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7803 		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7804 		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7805 		    lun_string[0]);
7806 
7807 		switch (lun_string[0] & 0xC0) {
7808 		case FCP_LUN_ADDRESSING:
7809 		case FCP_PD_ADDRESSING:
7810 		case FCP_VOLUME_ADDRESSING:
7811 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7812 
7813 			/* We will skip masked LUNs because of the blacklist. */
7814 			if (fcp_lun_blacklist != NULL) {
7815 				mutex_enter(&ptgt->tgt_mutex);
7816 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
7817 				    lun_num) == TRUE) {
7818 					ptgt->tgt_lun_cnt--;
7819 					mutex_exit(&ptgt->tgt_mutex);
7820 					break;
7821 				}
7822 				mutex_exit(&ptgt->tgt_mutex);
7823 			}
7824 
7825 			/* see if this LUN is already allocated */
7826 			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7827 				plun = fcp_alloc_lun(ptgt);
7828 				if (plun == NULL) {
7829 					fcp_log(CE_NOTE, pptr->port_dip,
7830 					    "!Lun allocation failed"
7831 					    " target=%x lun=%x",
7832 					    ptgt->tgt_d_id, lun_num);
7833 					break;
7834 				}
7835 			}
7836 
7837 			mutex_enter(&plun->lun_tgt->tgt_mutex);
7838 			/* convert to LUN */
7839 			plun->lun_addr.ent_addr_0 =
7840 			    BE_16(*(uint16_t *)&(lun_string[0]));
7841 			plun->lun_addr.ent_addr_1 =
7842 			    BE_16(*(uint16_t *)&(lun_string[2]));
7843 			plun->lun_addr.ent_addr_2 =
7844 			    BE_16(*(uint16_t *)&(lun_string[4]));
7845 			plun->lun_addr.ent_addr_3 =
7846 			    BE_16(*(uint16_t *)&(lun_string[6]));
7847 
7848 			plun->lun_num = lun_num;
7849 			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7850 			plun->lun_state &= ~FCP_LUN_OFFLINE;
7851 			mutex_exit(&plun->lun_tgt->tgt_mutex);
7852 
7853 			/* Retrieve the rscn count (if a valid one exists) */
7854 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7855 				rscn_count = ((fc_ulp_rscn_info_t *)
7856 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7857 				    ulp_rscn_count;
7858 			} else {
7859 				rscn_count = FC_INVALID_RSCN_COUNT;
7860 			}
7861 
7862 			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7863 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7864 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7865 				mutex_enter(&pptr->port_mutex);
7866 				mutex_enter(&plun->lun_tgt->tgt_mutex);
7867 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7868 					fcp_log(CE_NOTE, pptr->port_dip,
7869 					    "!failed to send INQUIRY"
7870 					    " target=%x lun=%x",
7871 					    ptgt->tgt_d_id, plun->lun_num);
7872 				} else {
7873 					FCP_TRACE(fcp_logq,
7874 					    pptr->port_instbuf, fcp_trace,
7875 					    FCP_BUF_LEVEL_5, 0,
7876 					    "fcp_handle_reportlun,2: state"
7877 					    " change occured for D_ID=0x%x",
7878 					    ptgt->tgt_d_id);
7879 				}
7880 				mutex_exit(&plun->lun_tgt->tgt_mutex);
7881 				mutex_exit(&pptr->port_mutex);
7882 			} else {
7883 				continue;
7884 			}
7885 			break;
7886 
7887 		default:
7888 			fcp_log(CE_WARN, NULL,
7889 			    "!Unsupported LUN Addressing method %x "
7890 			    "in response to REPORT_LUN", lun_string[0]);
7891 			break;
7892 		}
7893 
7894 		/*
7895 		 * each time through this loop we should decrement
7896 		 * the tmp_cnt by one -- since we go through this loop
7897 		 * one time for each LUN, the tmp_cnt should never be <=0
7898 		 */
7899 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7900 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7901 	}
7902 
7903 	if (i == 0) {
7904 		fcp_log(CE_WARN, pptr->port_dip,
7905 		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7906 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7907 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7908 	}
7909 
7910 	kmem_free(report_lun, len);
7911 	fcp_icmd_free(pptr, icmd);
7912 }
7913 
7914 
7915 /*
7916  * called internally to return a LUN given a target and a LUN number
7917  */
7918 static struct fcp_lun *
7919 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7920 {
7921 	struct fcp_lun	*plun;
7922 
7923 	mutex_enter(&ptgt->tgt_mutex);
7924 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7925 		if (plun->lun_num == lun_num) {
7926 			mutex_exit(&ptgt->tgt_mutex);
7927 			return (plun);
7928 		}
7929 	}
7930 	mutex_exit(&ptgt->tgt_mutex);
7931 
7932 	return (NULL);
7933 }
7934 
7935 
7936 /*
7937  * handle finishing one target for fcp_finish_init
7938  *
7939  * return true (non-zero) if we want finish_init to continue with the
7940  * next target
7941  *
7942  * called with the port mutex held
7943  */
7944 /*ARGSUSED*/
7945 static int
7946 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7947     int link_cnt, int tgt_cnt, int cause)
7948 {
7949 	int	rval = 1;
7950 	ASSERT(pptr != NULL);
7951 	ASSERT(ptgt != NULL);
7952 
7953 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7954 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7955 	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7956 	    ptgt->tgt_state);
7957 
7958 	ASSERT(mutex_owned(&pptr->port_mutex));
7959 
7960 	if ((pptr->port_link_cnt != link_cnt) ||
7961 	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7962 		/*
7963 		 * oh oh -- another link reset or target change
7964 		 * must have occurred while we are in here
7965 		 */
7966 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7967 
7968 		return (0);
7969 	} else {
7970 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7971 	}
7972 
7973 	mutex_enter(&ptgt->tgt_mutex);
7974 
7975 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7976 		/*
7977 		 * tgt is not offline -- is it marked (i.e. needs
7978 		 * to be offlined) ??
7979 		 */
7980 		if (ptgt->tgt_state & FCP_TGT_MARK) {
7981 			/*
7982 			 * this target not offline *and*
7983 			 * marked
7984 			 */
7985 			ptgt->tgt_state &= ~FCP_TGT_MARK;
7986 			rval = fcp_offline_target(pptr, ptgt, link_cnt,
7987 			    tgt_cnt, 0, 0);
7988 		} else {
7989 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
7990 
7991 			/* create the LUNs */
7992 			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7993 				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7994 				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7995 				    cause);
7996 				ptgt->tgt_device_created = 1;
7997 			} else {
7998 				fcp_update_tgt_state(ptgt, FCP_RESET,
7999 				    FCP_LUN_BUSY);
8000 			}
8001 		}
8002 	}
8003 
8004 	mutex_exit(&ptgt->tgt_mutex);
8005 
8006 	return (rval);
8007 }
8008 
8009 
8010 /*
8011  * this routine is called to finish port initialization
8012  *
8013  * Each port has a "temp" counter -- when a state change happens (e.g.
8014  * port online), the temp count is set to the number of devices in the map.
8015  * Then, as each device gets "discovered", the temp counter is decremented
8016  * by one.  When this count reaches zero we know that all of the devices
8017  * in the map have been discovered (or an error has occurred), so we can
8018  * then finish initialization -- which is done by this routine (well, this
8019  * and fcp-finish_tgt())
8020  *
8021  * acquires and releases the global mutex
8022  *
8023  * called with the port mutex owned
8024  */
8025 static void
8026 fcp_finish_init(struct fcp_port *pptr)
8027 {
8028 #ifdef	DEBUG
8029 	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8030 	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8031 	    FCP_STACK_DEPTH);
8032 #endif /* DEBUG */
8033 
8034 	ASSERT(mutex_owned(&pptr->port_mutex));
8035 
8036 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8037 	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8038 	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8039 
8040 	if ((pptr->port_state & FCP_STATE_ONLINING) &&
8041 	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
8042 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8043 		pptr->port_state &= ~FCP_STATE_ONLINING;
8044 		pptr->port_state |= FCP_STATE_ONLINE;
8045 	}
8046 
8047 	/* Wake up threads waiting on config done */
8048 	cv_broadcast(&pptr->port_config_cv);
8049 }
8050 
8051 
8052 /*
8053  * called from fcp_finish_init to create the LUNs for a target
8054  *
8055  * called with the port mutex owned
8056  */
8057 static void
8058 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8059 {
8060 	struct fcp_lun	*plun;
8061 	struct fcp_port	*pptr;
8062 	child_info_t		*cip = NULL;
8063 
8064 	ASSERT(ptgt != NULL);
8065 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8066 
8067 	pptr = ptgt->tgt_port;
8068 
8069 	ASSERT(pptr != NULL);
8070 
8071 	/* scan all LUNs for this target */
8072 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8073 		if (plun->lun_state & FCP_LUN_OFFLINE) {
8074 			continue;
8075 		}
8076 
8077 		if (plun->lun_state & FCP_LUN_MARK) {
8078 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8079 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8080 			    "fcp_create_luns: offlining marked LUN!");
8081 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8082 			continue;
8083 		}
8084 
8085 		plun->lun_state &= ~FCP_LUN_BUSY;
8086 
8087 		/*
8088 		 * There are conditions in which FCP_LUN_INIT flag is cleared
8089 		 * but we have a valid plun->lun_cip. To cover this case also
8090 		 * CLEAR_BUSY whenever we have a valid lun_cip.
8091 		 */
8092 		if (plun->lun_mpxio && plun->lun_cip &&
8093 		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8094 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8095 		    0, 0))) {
8096 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8097 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8098 			    "fcp_create_luns: enable lun %p failed!",
8099 			    plun);
8100 		}
8101 
8102 		if (plun->lun_state & FCP_LUN_INIT &&
8103 		    !(plun->lun_state & FCP_LUN_CHANGED)) {
8104 			continue;
8105 		}
8106 
8107 		if (cause == FCP_CAUSE_USER_CREATE) {
8108 			continue;
8109 		}
8110 
8111 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
8112 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
8113 		    "create_luns: passing ONLINE elem to HP thread");
8114 
8115 		/*
8116 		 * If lun has changed, prepare for offlining the old path.
8117 		 * Do not offline the old path right now, since it may be
8118 		 * still opened.
8119 		 */
8120 		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8121 			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8122 		}
8123 
8124 		/* pass an ONLINE element to the hotplug thread */
8125 		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8126 		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8127 
8128 			/*
8129 			 * We can not synchronous attach (i.e pass
8130 			 * NDI_ONLINE_ATTACH) here as we might be
8131 			 * coming from an interrupt or callback
8132 			 * thread.
8133 			 */
8134 			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8135 			    link_cnt, tgt_cnt, 0, 0)) {
8136 				fcp_log(CE_CONT, pptr->port_dip,
8137 				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8138 				    plun->lun_tgt->tgt_d_id, plun->lun_num);
8139 			}
8140 		}
8141 	}
8142 }
8143 
8144 
8145 /*
8146  * function to online/offline devices
8147  */
8148 static int
8149 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8150     int online, int lcount, int tcount, int flags)
8151 {
8152 	int			rval = NDI_FAILURE;
8153 	int			circ;
8154 	child_info_t		*ccip;
8155 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
8156 	int			is_mpxio = pptr->port_mpxio;
8157 	dev_info_t		*cdip, *pdip;
8158 	char			*devname;
8159 
8160 	if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8161 		/*
8162 		 * When this event gets serviced, lun_cip and lun_mpxio
8163 		 * has changed, so it should be invalidated now.
8164 		 */
8165 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8166 		    FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8167 		    "plun: %p, cip: %p, what:%d", plun, cip, online);
8168 		return (rval);
8169 	}
8170 
8171 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8172 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
8173 	    "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8174 	    "flags=%x mpxio=%x\n",
8175 	    plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8176 	    plun->lun_mpxio);
8177 
8178 	/*
8179 	 * lun_mpxio needs checking here because we can end up in a race
8180 	 * condition where this task has been dispatched while lun_mpxio is
8181 	 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8182 	 * enable MPXIO for the LUN, but was unable to, and hence cleared
8183 	 * the flag. We rely on the serialization of the tasks here. We return
8184 	 * NDI_SUCCESS so any callers continue without reporting spurious
8185 	 * errors, and the still think we're an MPXIO LUN.
8186 	 */
8187 
8188 	if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8189 	    online == FCP_MPXIO_PATH_SET_BUSY) {
8190 		if (plun->lun_mpxio) {
8191 			rval = fcp_update_mpxio_path(plun, cip, online);
8192 		} else {
8193 			rval = NDI_SUCCESS;
8194 		}
8195 		return (rval);
8196 	}
8197 
8198 	/*
8199 	 * Explicit devfs_clean() due to ndi_devi_offline() not
8200 	 * executing devfs_clean() if parent lock is held.
8201 	 */
8202 	ASSERT(!servicing_interrupt());
8203 	if (online == FCP_OFFLINE) {
8204 		if (plun->lun_mpxio == 0) {
8205 			if (plun->lun_cip == cip) {
8206 				cdip = DIP(plun->lun_cip);
8207 			} else {
8208 				cdip = DIP(cip);
8209 			}
8210 		} else if ((plun->lun_cip == cip) && plun->lun_cip) {
8211 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8212 		} else if ((plun->lun_cip != cip) && cip) {
8213 			/*
8214 			 * This means a DTYPE/GUID change, we shall get the
8215 			 * dip of the old cip instead of the current lun_cip.
8216 			 */
8217 			cdip = mdi_pi_get_client(PIP(cip));
8218 		}
8219 		if (cdip) {
8220 			if (i_ddi_devi_attached(cdip)) {
8221 				pdip = ddi_get_parent(cdip);
8222 				devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8223 				ndi_devi_enter(pdip, &circ);
8224 				(void) ddi_deviname(cdip, devname);
8225 				ndi_devi_exit(pdip, circ);
8226 				/*
8227 				 * Release parent lock before calling
8228 				 * devfs_clean().
8229 				 */
8230 				rval = devfs_clean(pdip, devname + 1,
8231 				    DV_CLEAN_FORCE);
8232 				kmem_free(devname, MAXNAMELEN + 1);
8233 				/*
8234 				 * Return if devfs_clean() fails for
8235 				 * non-MPXIO case.
8236 				 * For MPXIO case, another path could be
8237 				 * offlined.
8238 				 */
8239 				if (rval && plun->lun_mpxio == 0) {
8240 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8241 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8242 					    "fcp_trigger_lun: devfs_clean "
8243 					    "failed rval=%x  dip=%p",
8244 					    rval, pdip);
8245 					return (NDI_FAILURE);
8246 				}
8247 			}
8248 		}
8249 	}
8250 
8251 	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8252 		return (NDI_FAILURE);
8253 	}
8254 
8255 	if (is_mpxio) {
8256 		mdi_devi_enter(pptr->port_dip, &circ);
8257 	} else {
8258 		ndi_devi_enter(pptr->port_dip, &circ);
8259 	}
8260 
8261 	mutex_enter(&pptr->port_mutex);
8262 	mutex_enter(&plun->lun_mutex);
8263 
8264 	if (online == FCP_ONLINE) {
8265 		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8266 		if (ccip == NULL) {
8267 			goto fail;
8268 		}
8269 	} else {
8270 		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8271 			goto fail;
8272 		}
8273 		ccip = cip;
8274 	}
8275 
8276 	if (online == FCP_ONLINE) {
8277 		rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8278 		    &circ);
8279 		fc_ulp_log_device_event(pptr->port_fp_handle,
8280 		    FC_ULP_DEVICE_ONLINE);
8281 	} else {
8282 		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8283 		    &circ);
8284 		fc_ulp_log_device_event(pptr->port_fp_handle,
8285 		    FC_ULP_DEVICE_OFFLINE);
8286 	}
8287 
8288 fail:	mutex_exit(&plun->lun_mutex);
8289 	mutex_exit(&pptr->port_mutex);
8290 
8291 	if (is_mpxio) {
8292 		mdi_devi_exit(pptr->port_dip, circ);
8293 	} else {
8294 		ndi_devi_exit(pptr->port_dip, circ);
8295 	}
8296 
8297 	fc_ulp_idle_port(pptr->port_fp_handle);
8298 
8299 	return (rval);
8300 }
8301 
8302 
8303 /*
8304  * take a target offline by taking all of its LUNs offline
8305  */
8306 /*ARGSUSED*/
8307 static int
8308 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8309     int link_cnt, int tgt_cnt, int nowait, int flags)
8310 {
8311 	struct fcp_tgt_elem	*elem;
8312 
8313 	ASSERT(mutex_owned(&pptr->port_mutex));
8314 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8315 
8316 	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8317 
8318 	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8319 	    ptgt->tgt_change_cnt)) {
8320 		mutex_exit(&ptgt->tgt_mutex);
8321 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8322 		mutex_enter(&ptgt->tgt_mutex);
8323 
8324 		return (0);
8325 	}
8326 
8327 	ptgt->tgt_pd_handle = NULL;
8328 	mutex_exit(&ptgt->tgt_mutex);
8329 	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8330 	mutex_enter(&ptgt->tgt_mutex);
8331 
8332 	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8333 
8334 	if (ptgt->tgt_tcap &&
8335 	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8336 		elem->flags = flags;
8337 		elem->time = fcp_watchdog_time;
8338 		if (nowait == 0) {
8339 			elem->time += fcp_offline_delay;
8340 		}
8341 		elem->ptgt = ptgt;
8342 		elem->link_cnt = link_cnt;
8343 		elem->tgt_cnt = tgt_cnt;
8344 		elem->next = pptr->port_offline_tgts;
8345 		pptr->port_offline_tgts = elem;
8346 	} else {
8347 		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8348 	}
8349 
8350 	return (1);
8351 }
8352 
8353 
8354 static void
8355 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8356     int link_cnt, int tgt_cnt, int flags)
8357 {
8358 	ASSERT(mutex_owned(&pptr->port_mutex));
8359 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8360 
8361 	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8362 	ptgt->tgt_state = FCP_TGT_OFFLINE;
8363 	ptgt->tgt_pd_handle = NULL;
8364 	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8365 }
8366 
8367 
8368 static void
8369 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8370     int flags)
8371 {
8372 	struct	fcp_lun	*plun;
8373 
8374 	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8375 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8376 
8377 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8378 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8379 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8380 		}
8381 	}
8382 }
8383 
8384 
8385 /*
8386  * take a LUN offline
8387  *
8388  * enters and leaves with the target mutex held, releasing it in the process
8389  *
8390  * allocates memory in non-sleep mode
8391  */
8392 static void
8393 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8394     int nowait, int flags)
8395 {
8396 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8397 	struct fcp_lun_elem	*elem;
8398 
8399 	ASSERT(plun != NULL);
8400 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8401 
8402 	if (nowait) {
8403 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8404 		return;
8405 	}
8406 
8407 	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8408 		elem->flags = flags;
8409 		elem->time = fcp_watchdog_time;
8410 		if (nowait == 0) {
8411 			elem->time += fcp_offline_delay;
8412 		}
8413 		elem->plun = plun;
8414 		elem->link_cnt = link_cnt;
8415 		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8416 		elem->next = pptr->port_offline_luns;
8417 		pptr->port_offline_luns = elem;
8418 	} else {
8419 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8420 	}
8421 }
8422 
8423 
8424 static void
8425 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8426 {
8427 	struct fcp_pkt	*head = NULL;
8428 
8429 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8430 
8431 	mutex_exit(&LUN_TGT->tgt_mutex);
8432 
8433 	head = fcp_scan_commands(plun);
8434 	if (head != NULL) {
8435 		fcp_abort_commands(head, LUN_PORT);
8436 	}
8437 
8438 	mutex_enter(&LUN_TGT->tgt_mutex);
8439 
8440 	if (plun->lun_cip && plun->lun_mpxio) {
8441 		/*
8442 		 * Intimate MPxIO lun busy is cleared
8443 		 */
8444 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8445 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8446 		    0, 0)) {
8447 			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8448 			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8449 			    LUN_TGT->tgt_d_id, plun->lun_num);
8450 		}
8451 		/*
8452 		 * Intimate MPxIO that the lun is now marked for offline
8453 		 */
8454 		mutex_exit(&LUN_TGT->tgt_mutex);
8455 		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8456 		mutex_enter(&LUN_TGT->tgt_mutex);
8457 	}
8458 }
8459 
8460 static void
8461 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8462     int flags)
8463 {
8464 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8465 
8466 	mutex_exit(&LUN_TGT->tgt_mutex);
8467 	fcp_update_offline_flags(plun);
8468 	mutex_enter(&LUN_TGT->tgt_mutex);
8469 
8470 	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8471 
8472 	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8473 	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8474 	    "offline_lun: passing OFFLINE elem to HP thread");
8475 
8476 	if (plun->lun_cip) {
8477 		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8478 		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8479 		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8480 		    LUN_TGT->tgt_trace);
8481 
8482 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8483 		    link_cnt, tgt_cnt, flags, 0)) {
8484 			fcp_log(CE_CONT, LUN_PORT->port_dip,
8485 			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8486 			    LUN_TGT->tgt_d_id, plun->lun_num);
8487 		}
8488 	}
8489 }
8490 
8491 static void
8492 fcp_scan_offline_luns(struct fcp_port *pptr)
8493 {
8494 	struct fcp_lun_elem	*elem;
8495 	struct fcp_lun_elem	*prev;
8496 	struct fcp_lun_elem	*next;
8497 
8498 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8499 
8500 	prev = NULL;
8501 	elem = pptr->port_offline_luns;
8502 	while (elem) {
8503 		next = elem->next;
8504 		if (elem->time <= fcp_watchdog_time) {
8505 			int			changed = 1;
8506 			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8507 
8508 			mutex_enter(&ptgt->tgt_mutex);
8509 			if (pptr->port_link_cnt == elem->link_cnt &&
8510 			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8511 				changed = 0;
8512 			}
8513 
8514 			if (!changed &&
8515 			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8516 				fcp_offline_lun_now(elem->plun,
8517 				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8518 			}
8519 			mutex_exit(&ptgt->tgt_mutex);
8520 
8521 			kmem_free(elem, sizeof (*elem));
8522 
8523 			if (prev) {
8524 				prev->next = next;
8525 			} else {
8526 				pptr->port_offline_luns = next;
8527 			}
8528 		} else {
8529 			prev = elem;
8530 		}
8531 		elem = next;
8532 	}
8533 }
8534 
8535 
8536 static void
8537 fcp_scan_offline_tgts(struct fcp_port *pptr)
8538 {
8539 	struct fcp_tgt_elem	*elem;
8540 	struct fcp_tgt_elem	*prev;
8541 	struct fcp_tgt_elem	*next;
8542 
8543 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8544 
8545 	prev = NULL;
8546 	elem = pptr->port_offline_tgts;
8547 	while (elem) {
8548 		next = elem->next;
8549 		if (elem->time <= fcp_watchdog_time) {
8550 			int		outdated = 1;
8551 			struct fcp_tgt	*ptgt = elem->ptgt;
8552 
8553 			mutex_enter(&ptgt->tgt_mutex);
8554 
8555 			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8556 				/* No change on tgt since elem was created. */
8557 				outdated = 0;
8558 			} else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8559 			    pptr->port_link_cnt == elem->link_cnt + 1 &&
8560 			    ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8561 				/*
8562 				 * Exactly one thing happened to the target
8563 				 * inbetween: the local port went offline.
8564 				 * For fp the remote port is already gone so
8565 				 * it will not tell us again to offline the
8566 				 * target. We must offline it now.
8567 				 */
8568 				outdated = 0;
8569 			}
8570 
8571 			if (!outdated && !(ptgt->tgt_state &
8572 			    FCP_TGT_OFFLINE)) {
8573 				fcp_offline_target_now(pptr,
8574 				    ptgt, elem->link_cnt, elem->tgt_cnt,
8575 				    elem->flags);
8576 			}
8577 
8578 			mutex_exit(&ptgt->tgt_mutex);
8579 
8580 			kmem_free(elem, sizeof (*elem));
8581 
8582 			if (prev) {
8583 				prev->next = next;
8584 			} else {
8585 				pptr->port_offline_tgts = next;
8586 			}
8587 		} else {
8588 			prev = elem;
8589 		}
8590 		elem = next;
8591 	}
8592 }
8593 
8594 
8595 static void
8596 fcp_update_offline_flags(struct fcp_lun *plun)
8597 {
8598 	struct fcp_port	*pptr = LUN_PORT;
8599 	ASSERT(plun != NULL);
8600 
8601 	mutex_enter(&LUN_TGT->tgt_mutex);
8602 	plun->lun_state |= FCP_LUN_OFFLINE;
8603 	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8604 
8605 	mutex_enter(&plun->lun_mutex);
8606 	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8607 		dev_info_t *cdip = NULL;
8608 
8609 		mutex_exit(&LUN_TGT->tgt_mutex);
8610 
8611 		if (plun->lun_mpxio == 0) {
8612 			cdip = DIP(plun->lun_cip);
8613 		} else if (plun->lun_cip) {
8614 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8615 		}
8616 
8617 		mutex_exit(&plun->lun_mutex);
8618 		if (cdip) {
8619 			(void) ndi_event_retrieve_cookie(
8620 			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8621 			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8622 			(void) ndi_event_run_callbacks(
8623 			    pptr->port_ndi_event_hdl, cdip,
8624 			    fcp_remove_eid, NULL);
8625 		}
8626 	} else {
8627 		mutex_exit(&plun->lun_mutex);
8628 		mutex_exit(&LUN_TGT->tgt_mutex);
8629 	}
8630 }
8631 
8632 
8633 /*
8634  * Scan all of the command pkts for this port, moving pkts that
8635  * match our LUN onto our own list (headed by "head")
8636  */
8637 static struct fcp_pkt *
8638 fcp_scan_commands(struct fcp_lun *plun)
8639 {
8640 	struct fcp_port	*pptr = LUN_PORT;
8641 
8642 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8643 	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8644 	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8645 
8646 	struct fcp_pkt	*head = NULL;	/* head of our list */
8647 	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8648 
8649 	int			cmds_found = 0;
8650 
8651 	mutex_enter(&pptr->port_pkt_mutex);
8652 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8653 		struct fcp_lun *tlun =
8654 		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8655 
8656 		ncmd = cmd->cmd_next;	/* set next command */
8657 
8658 		/*
8659 		 * if this pkt is for a different LUN  or the
8660 		 * command is sent down, skip it.
8661 		 */
8662 		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8663 		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8664 			pcmd = cmd;
8665 			continue;
8666 		}
8667 		cmds_found++;
8668 		if (pcmd != NULL) {
8669 			ASSERT(pptr->port_pkt_head != cmd);
8670 			pcmd->cmd_next = cmd->cmd_next;
8671 		} else {
8672 			ASSERT(cmd == pptr->port_pkt_head);
8673 			pptr->port_pkt_head = cmd->cmd_next;
8674 		}
8675 
8676 		if (cmd == pptr->port_pkt_tail) {
8677 			pptr->port_pkt_tail = pcmd;
8678 			if (pcmd) {
8679 				pcmd->cmd_next = NULL;
8680 			}
8681 		}
8682 
8683 		if (head == NULL) {
8684 			head = tail = cmd;
8685 		} else {
8686 			ASSERT(tail != NULL);
8687 
8688 			tail->cmd_next = cmd;
8689 			tail = cmd;
8690 		}
8691 		cmd->cmd_next = NULL;
8692 	}
8693 	mutex_exit(&pptr->port_pkt_mutex);
8694 
8695 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8696 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8697 	    "scan commands: %d cmd(s) found", cmds_found);
8698 
8699 	return (head);
8700 }
8701 
8702 
8703 /*
8704  * Abort all the commands in the command queue
8705  */
8706 static void
8707 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8708 {
8709 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8710 	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8711 
8712 	ASSERT(mutex_owned(&pptr->port_mutex));
8713 
8714 	/* scan through the pkts and invalid them */
8715 	for (cmd = head; cmd != NULL; cmd = ncmd) {
8716 		struct scsi_pkt *pkt = cmd->cmd_pkt;
8717 
8718 		ncmd = cmd->cmd_next;
8719 		ASSERT(pkt != NULL);
8720 
8721 		/*
8722 		 * The lun is going to be marked offline. Indicate
8723 		 * the target driver not to requeue or retry this command
8724 		 * as the device is going to be offlined pretty soon.
8725 		 */
8726 		pkt->pkt_reason = CMD_DEV_GONE;
8727 		pkt->pkt_statistics = 0;
8728 		pkt->pkt_state = 0;
8729 
8730 		/* reset cmd flags/state */
8731 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8732 		cmd->cmd_state = FCP_PKT_IDLE;
8733 
8734 		/*
8735 		 * ensure we have a packet completion routine,
8736 		 * then call it.
8737 		 */
8738 		ASSERT(pkt->pkt_comp != NULL);
8739 
8740 		mutex_exit(&pptr->port_mutex);
8741 		fcp_post_callback(cmd);
8742 		mutex_enter(&pptr->port_mutex);
8743 	}
8744 }
8745 
8746 
8747 /*
8748  * the pkt_comp callback for command packets
8749  */
8750 static void
8751 fcp_cmd_callback(fc_packet_t *fpkt)
8752 {
8753 	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8754 	struct scsi_pkt *pkt = cmd->cmd_pkt;
8755 	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8756 
8757 	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8758 
8759 	if (cmd->cmd_state == FCP_PKT_IDLE) {
8760 		cmn_err(CE_PANIC, "Packet already completed %p",
8761 		    (void *)cmd);
8762 	}
8763 
8764 	/*
8765 	 * Watch thread should be freeing the packet, ignore the pkt.
8766 	 */
8767 	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8768 		fcp_log(CE_CONT, pptr->port_dip,
8769 		    "!FCP: Pkt completed while aborting\n");
8770 		return;
8771 	}
8772 	cmd->cmd_state = FCP_PKT_IDLE;
8773 
8774 	fcp_complete_pkt(fpkt);
8775 
8776 #ifdef	DEBUG
8777 	mutex_enter(&pptr->port_pkt_mutex);
8778 	pptr->port_npkts--;
8779 	mutex_exit(&pptr->port_pkt_mutex);
8780 #endif /* DEBUG */
8781 
8782 	fcp_post_callback(cmd);
8783 }
8784 
8785 
8786 static void
8787 fcp_complete_pkt(fc_packet_t *fpkt)
8788 {
8789 	int			error = 0;
8790 	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8791 	    fpkt->pkt_ulp_private;
8792 	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8793 	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8794 	struct fcp_lun	*plun;
8795 	struct fcp_tgt	*ptgt;
8796 	struct fcp_rsp		*rsp;
8797 	struct scsi_address	save;
8798 
8799 #ifdef	DEBUG
8800 	save = pkt->pkt_address;
8801 #endif /* DEBUG */
8802 
8803 	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8804 
8805 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8806 		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8807 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8808 			    sizeof (struct fcp_rsp));
8809 		}
8810 
8811 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8812 		    STATE_SENT_CMD | STATE_GOT_STATUS;
8813 
8814 		pkt->pkt_resid = 0;
8815 
8816 		if (fpkt->pkt_datalen) {
8817 			pkt->pkt_state |= STATE_XFERRED_DATA;
8818 			if (fpkt->pkt_data_resid) {
8819 				error++;
8820 			}
8821 		}
8822 
8823 		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8824 		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8825 			/*
8826 			 * The next two checks make sure that if there
8827 			 * is no sense data or a valid response and
8828 			 * the command came back with check condition,
8829 			 * the command should be retried.
8830 			 */
8831 			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8832 			    !rsp->fcp_u.fcp_status.sense_len_set) {
8833 				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8834 				pkt->pkt_resid = cmd->cmd_dmacount;
8835 			}
8836 		}
8837 
8838 		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8839 			return;
8840 		}
8841 
8842 		plun = ADDR2LUN(&pkt->pkt_address);
8843 		ptgt = plun->lun_tgt;
8844 		ASSERT(ptgt != NULL);
8845 
8846 		/*
8847 		 * Update the transfer resid, if appropriate
8848 		 */
8849 		if (rsp->fcp_u.fcp_status.resid_over ||
8850 		    rsp->fcp_u.fcp_status.resid_under) {
8851 			pkt->pkt_resid = rsp->fcp_resid;
8852 		}
8853 
8854 		/*
8855 		 * First see if we got a FCP protocol error.
8856 		 */
8857 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8858 			struct fcp_rsp_info	*bep;
8859 			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8860 			    sizeof (struct fcp_rsp));
8861 
8862 			if (fcp_validate_fcp_response(rsp, pptr) !=
8863 			    FC_SUCCESS) {
8864 				pkt->pkt_reason = CMD_CMPLT;
8865 				*(pkt->pkt_scbp) = STATUS_CHECK;
8866 
8867 				fcp_log(CE_WARN, pptr->port_dip,
8868 				    "!SCSI command to d_id=0x%x lun=0x%x"
8869 				    " failed, Bad FCP response values:"
8870 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8871 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8872 				    ptgt->tgt_d_id, plun->lun_num,
8873 				    rsp->reserved_0, rsp->reserved_1,
8874 				    rsp->fcp_u.fcp_status.reserved_0,
8875 				    rsp->fcp_u.fcp_status.reserved_1,
8876 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8877 
8878 				return;
8879 			}
8880 
8881 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8882 				FCP_CP_IN(fpkt->pkt_resp +
8883 				    sizeof (struct fcp_rsp), bep,
8884 				    fpkt->pkt_resp_acc,
8885 				    sizeof (struct fcp_rsp_info));
8886 			}
8887 
8888 			if (bep->rsp_code != FCP_NO_FAILURE) {
8889 				child_info_t	*cip;
8890 
8891 				pkt->pkt_reason = CMD_TRAN_ERR;
8892 
8893 				mutex_enter(&plun->lun_mutex);
8894 				cip = plun->lun_cip;
8895 				mutex_exit(&plun->lun_mutex);
8896 
8897 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8898 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8899 				    "FCP response error on cmd=%p"
8900 				    " target=0x%x, cip=%p", cmd,
8901 				    ptgt->tgt_d_id, cip);
8902 			}
8903 		}
8904 
8905 		/*
8906 		 * See if we got a SCSI error with sense data
8907 		 */
8908 		if (rsp->fcp_u.fcp_status.sense_len_set) {
8909 			uchar_t				rqlen;
8910 			caddr_t				sense_from;
8911 			child_info_t			*cip;
8912 			timeout_id_t			tid;
8913 			struct scsi_arq_status		*arq;
8914 			struct scsi_extended_sense	*sense_to;
8915 
8916 			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8917 			sense_to = &arq->sts_sensedata;
8918 
8919 			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8920 			    sizeof (struct scsi_extended_sense));
8921 
8922 			sense_from = (caddr_t)fpkt->pkt_resp +
8923 			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8924 
8925 			if (fcp_validate_fcp_response(rsp, pptr) !=
8926 			    FC_SUCCESS) {
8927 				pkt->pkt_reason = CMD_CMPLT;
8928 				*(pkt->pkt_scbp) = STATUS_CHECK;
8929 
8930 				fcp_log(CE_WARN, pptr->port_dip,
8931 				    "!SCSI command to d_id=0x%x lun=0x%x"
8932 				    " failed, Bad FCP response values:"
8933 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8934 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8935 				    ptgt->tgt_d_id, plun->lun_num,
8936 				    rsp->reserved_0, rsp->reserved_1,
8937 				    rsp->fcp_u.fcp_status.reserved_0,
8938 				    rsp->fcp_u.fcp_status.reserved_1,
8939 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8940 
8941 				return;
8942 			}
8943 
8944 			/*
8945 			 * copy in sense information
8946 			 */
8947 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8948 				FCP_CP_IN(sense_from, sense_to,
8949 				    fpkt->pkt_resp_acc, rqlen);
8950 			} else {
8951 				bcopy(sense_from, sense_to, rqlen);
8952 			}
8953 
8954 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8955 			    (FCP_SENSE_NO_LUN(sense_to))) {
8956 				mutex_enter(&ptgt->tgt_mutex);
8957 				if (ptgt->tgt_tid == NULL) {
8958 					/*
8959 					 * Kick off rediscovery
8960 					 */
8961 					tid = timeout(fcp_reconfigure_luns,
8962 					    (caddr_t)ptgt, drv_usectohz(1));
8963 
8964 					ptgt->tgt_tid = tid;
8965 					ptgt->tgt_state |= FCP_TGT_BUSY;
8966 				}
8967 				mutex_exit(&ptgt->tgt_mutex);
8968 				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8969 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8970 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8971 					    "!FCP: Report Lun Has Changed"
8972 					    " target=%x", ptgt->tgt_d_id);
8973 				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8974 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8975 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8976 					    "!FCP: LU Not Supported"
8977 					    " target=%x", ptgt->tgt_d_id);
8978 				}
8979 			}
8980 			ASSERT(pkt->pkt_scbp != NULL);
8981 
8982 			pkt->pkt_state |= STATE_ARQ_DONE;
8983 
8984 			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8985 
8986 			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8987 			arq->sts_rqpkt_reason = 0;
8988 			arq->sts_rqpkt_statistics = 0;
8989 
8990 			arq->sts_rqpkt_state = STATE_GOT_BUS |
8991 			    STATE_GOT_TARGET | STATE_SENT_CMD |
8992 			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8993 			    STATE_XFERRED_DATA;
8994 
8995 			mutex_enter(&plun->lun_mutex);
8996 			cip = plun->lun_cip;
8997 			mutex_exit(&plun->lun_mutex);
8998 
8999 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9000 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9001 			    "SCSI Check condition on cmd=%p target=0x%x"
9002 			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
9003 			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9004 			    cmd->cmd_fcp_cmd.fcp_cdb[0],
9005 			    rsp->fcp_u.fcp_status.scsi_status,
9006 			    sense_to->es_key, sense_to->es_add_code,
9007 			    sense_to->es_qual_code);
9008 		}
9009 	} else {
9010 		plun = ADDR2LUN(&pkt->pkt_address);
9011 		ptgt = plun->lun_tgt;
9012 		ASSERT(ptgt != NULL);
9013 
9014 		/*
9015 		 * Work harder to translate errors into target driver
9016 		 * understandable ones. Note with despair that the target
9017 		 * drivers don't decode pkt_state and pkt_reason exhaustively
9018 		 * They resort to using the big hammer most often, which
9019 		 * may not get fixed in the life time of this driver.
9020 		 */
9021 		pkt->pkt_state = 0;
9022 		pkt->pkt_statistics = 0;
9023 
9024 		switch (fpkt->pkt_state) {
9025 		case FC_PKT_TRAN_ERROR:
9026 			switch (fpkt->pkt_reason) {
9027 			case FC_REASON_OVERRUN:
9028 				pkt->pkt_reason = CMD_CMD_OVR;
9029 				pkt->pkt_statistics |= STAT_ABORTED;
9030 				break;
9031 
9032 			case FC_REASON_XCHG_BSY: {
9033 				caddr_t ptr;
9034 
9035 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9036 
9037 				ptr = (caddr_t)pkt->pkt_scbp;
9038 				if (ptr) {
9039 					*ptr = STATUS_BUSY;
9040 				}
9041 				break;
9042 			}
9043 
9044 			case FC_REASON_ABORTED:
9045 				pkt->pkt_reason = CMD_TRAN_ERR;
9046 				pkt->pkt_statistics |= STAT_ABORTED;
9047 				break;
9048 
9049 			case FC_REASON_ABORT_FAILED:
9050 				pkt->pkt_reason = CMD_ABORT_FAIL;
9051 				break;
9052 
9053 			case FC_REASON_NO_SEQ_INIT:
9054 			case FC_REASON_CRC_ERROR:
9055 				pkt->pkt_reason = CMD_TRAN_ERR;
9056 				pkt->pkt_statistics |= STAT_ABORTED;
9057 				break;
9058 			default:
9059 				pkt->pkt_reason = CMD_TRAN_ERR;
9060 				break;
9061 			}
9062 			break;
9063 
9064 		case FC_PKT_PORT_OFFLINE: {
9065 			dev_info_t	*cdip = NULL;
9066 			caddr_t		ptr;
9067 
9068 			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9069 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9070 				    fcp_trace, FCP_BUF_LEVEL_8, 0,
9071 				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9072 				    ptgt->tgt_d_id);
9073 			}
9074 
9075 			mutex_enter(&plun->lun_mutex);
9076 			if (plun->lun_mpxio == 0) {
9077 				cdip = DIP(plun->lun_cip);
9078 			} else if (plun->lun_cip) {
9079 				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9080 			}
9081 
9082 			mutex_exit(&plun->lun_mutex);
9083 
9084 			if (cdip) {
9085 				(void) ndi_event_retrieve_cookie(
9086 				    pptr->port_ndi_event_hdl, cdip,
9087 				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9088 				    NDI_EVENT_NOPASS);
9089 				(void) ndi_event_run_callbacks(
9090 				    pptr->port_ndi_event_hdl, cdip,
9091 				    fcp_remove_eid, NULL);
9092 			}
9093 
9094 			/*
9095 			 * If the link goes off-line for a lip,
9096 			 * this will cause a error to the ST SG
9097 			 * SGEN drivers. By setting BUSY we will
9098 			 * give the drivers the chance to retry
9099 			 * before it blows of the job. ST will
9100 			 * remember how many times it has retried.
9101 			 */
9102 
9103 			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9104 			    (plun->lun_type == DTYPE_CHANGER)) {
9105 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9106 				ptr = (caddr_t)pkt->pkt_scbp;
9107 				if (ptr) {
9108 					*ptr = STATUS_BUSY;
9109 				}
9110 			} else {
9111 				pkt->pkt_reason = CMD_TRAN_ERR;
9112 				pkt->pkt_statistics |= STAT_BUS_RESET;
9113 			}
9114 			break;
9115 		}
9116 
9117 		case FC_PKT_TRAN_BSY:
9118 			/*
9119 			 * Use the ssd Qfull handling here.
9120 			 */
9121 			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9122 			pkt->pkt_state = STATE_GOT_BUS;
9123 			break;
9124 
9125 		case FC_PKT_TIMEOUT:
9126 			pkt->pkt_reason = CMD_TIMEOUT;
9127 			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9128 				pkt->pkt_statistics |= STAT_TIMEOUT;
9129 			} else {
9130 				pkt->pkt_statistics |= STAT_ABORTED;
9131 			}
9132 			break;
9133 
9134 		case FC_PKT_LOCAL_RJT:
9135 			switch (fpkt->pkt_reason) {
9136 			case FC_REASON_OFFLINE: {
9137 				dev_info_t	*cdip = NULL;
9138 
9139 				mutex_enter(&plun->lun_mutex);
9140 				if (plun->lun_mpxio == 0) {
9141 					cdip = DIP(plun->lun_cip);
9142 				} else if (plun->lun_cip) {
9143 					cdip = mdi_pi_get_client(
9144 					    PIP(plun->lun_cip));
9145 				}
9146 				mutex_exit(&plun->lun_mutex);
9147 
9148 				if (cdip) {
9149 					(void) ndi_event_retrieve_cookie(
9150 					    pptr->port_ndi_event_hdl, cdip,
9151 					    FCAL_REMOVE_EVENT,
9152 					    &fcp_remove_eid,
9153 					    NDI_EVENT_NOPASS);
9154 					(void) ndi_event_run_callbacks(
9155 					    pptr->port_ndi_event_hdl,
9156 					    cdip, fcp_remove_eid, NULL);
9157 				}
9158 
9159 				pkt->pkt_reason = CMD_TRAN_ERR;
9160 				pkt->pkt_statistics |= STAT_BUS_RESET;
9161 
9162 				break;
9163 			}
9164 
9165 			case FC_REASON_NOMEM:
9166 			case FC_REASON_QFULL: {
9167 				caddr_t ptr;
9168 
9169 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9170 				ptr = (caddr_t)pkt->pkt_scbp;
9171 				if (ptr) {
9172 					*ptr = STATUS_BUSY;
9173 				}
9174 				break;
9175 			}
9176 
9177 			case FC_REASON_DMA_ERROR:
9178 				pkt->pkt_reason = CMD_DMA_DERR;
9179 				pkt->pkt_statistics |= STAT_ABORTED;
9180 				break;
9181 
9182 			case FC_REASON_CRC_ERROR:
9183 			case FC_REASON_UNDERRUN: {
9184 				uchar_t		status;
9185 				/*
9186 				 * Work around for Bugid: 4240945.
9187 				 * IB on A5k doesn't set the Underrun bit
9188 				 * in the fcp status, when it is transferring
9189 				 * less than requested amount of data. Work
9190 				 * around the ses problem to keep luxadm
9191 				 * happy till ibfirmware is fixed.
9192 				 */
9193 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9194 					FCP_CP_IN(fpkt->pkt_resp, rsp,
9195 					    fpkt->pkt_resp_acc,
9196 					    sizeof (struct fcp_rsp));
9197 				}
9198 				status = rsp->fcp_u.fcp_status.scsi_status;
9199 				if (((plun->lun_type & DTYPE_MASK) ==
9200 				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9201 					pkt->pkt_reason = CMD_CMPLT;
9202 					*pkt->pkt_scbp = status;
9203 					pkt->pkt_resid = 0;
9204 				} else {
9205 					pkt->pkt_reason = CMD_TRAN_ERR;
9206 					pkt->pkt_statistics |= STAT_ABORTED;
9207 				}
9208 				break;
9209 			}
9210 
9211 			case FC_REASON_NO_CONNECTION:
9212 			case FC_REASON_UNSUPPORTED:
9213 			case FC_REASON_ILLEGAL_REQ:
9214 			case FC_REASON_BAD_SID:
9215 			case FC_REASON_DIAG_BUSY:
9216 			case FC_REASON_FCAL_OPN_FAIL:
9217 			case FC_REASON_BAD_XID:
9218 			default:
9219 				pkt->pkt_reason = CMD_TRAN_ERR;
9220 				pkt->pkt_statistics |= STAT_ABORTED;
9221 				break;
9222 
9223 			}
9224 			break;
9225 
9226 		case FC_PKT_NPORT_RJT:
9227 		case FC_PKT_FABRIC_RJT:
9228 		case FC_PKT_NPORT_BSY:
9229 		case FC_PKT_FABRIC_BSY:
9230 		default:
9231 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9232 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9233 			    "FC Status 0x%x, reason 0x%x",
9234 			    fpkt->pkt_state, fpkt->pkt_reason);
9235 			pkt->pkt_reason = CMD_TRAN_ERR;
9236 			pkt->pkt_statistics |= STAT_ABORTED;
9237 			break;
9238 		}
9239 
9240 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9241 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9242 		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9243 		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9244 		    fpkt->pkt_reason);
9245 	}
9246 
9247 	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9248 }
9249 
9250 
9251 static int
9252 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9253 {
9254 	if (rsp->reserved_0 || rsp->reserved_1 ||
9255 	    rsp->fcp_u.fcp_status.reserved_0 ||
9256 	    rsp->fcp_u.fcp_status.reserved_1) {
9257 		/*
9258 		 * These reserved fields should ideally be zero. FCP-2 does say
9259 		 * that the recipient need not check for reserved fields to be
9260 		 * zero. If they are not zero, we will not make a fuss about it
9261 		 * - just log it (in debug to both trace buffer and messages
9262 		 * file and to trace buffer only in non-debug) and move on.
9263 		 *
9264 		 * Non-zero reserved fields were seen with minnows.
9265 		 *
9266 		 * qlc takes care of some of this but we cannot assume that all
9267 		 * FCAs will do so.
9268 		 */
9269 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9270 		    FCP_BUF_LEVEL_5, 0,
9271 		    "Got fcp response packet with non-zero reserved fields "
9272 		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9273 		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9274 		    rsp->reserved_0, rsp->reserved_1,
9275 		    rsp->fcp_u.fcp_status.reserved_0,
9276 		    rsp->fcp_u.fcp_status.reserved_1);
9277 	}
9278 
9279 	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9280 	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9281 		return (FC_FAILURE);
9282 	}
9283 
9284 	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9285 	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9286 	    sizeof (struct fcp_rsp))) {
9287 		return (FC_FAILURE);
9288 	}
9289 
9290 	return (FC_SUCCESS);
9291 }
9292 
9293 
9294 /*
9295  * This is called when there is a change the in device state. The case we're
9296  * handling here is, if the d_id s does not match, offline this tgt and online
9297  * a new tgt with the new d_id.	 called from fcp_handle_devices with
9298  * port_mutex held.
9299  */
9300 static int
9301 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9302     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9303 {
9304 	ASSERT(mutex_owned(&pptr->port_mutex));
9305 
9306 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9307 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9308 	    "Starting fcp_device_changed...");
9309 
9310 	/*
9311 	 * The two cases where the port_device_changed is called is
9312 	 * either it changes it's d_id or it's hard address.
9313 	 */
9314 	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9315 	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9316 	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9317 
9318 		/* offline this target */
9319 		mutex_enter(&ptgt->tgt_mutex);
9320 		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9321 			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9322 			    0, 1, NDI_DEVI_REMOVE);
9323 		}
9324 		mutex_exit(&ptgt->tgt_mutex);
9325 
9326 		fcp_log(CE_NOTE, pptr->port_dip,
9327 		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9328 		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9329 		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9330 		    map_entry->map_hard_addr.hard_addr);
9331 	}
9332 
9333 	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9334 	    link_cnt, tgt_cnt, cause));
9335 }
9336 
9337 /*
9338  *     Function: fcp_alloc_lun
9339  *
9340  *  Description: Creates a new lun structure and adds it to the list
9341  *		 of luns of the target.
9342  *
9343  *     Argument: ptgt		Target the lun will belong to.
9344  *
9345  * Return Value: NULL		Failed
9346  *		 Not NULL	Succeeded
9347  *
9348  *	Context: Kernel context
9349  */
9350 static struct fcp_lun *
9351 fcp_alloc_lun(struct fcp_tgt *ptgt)
9352 {
9353 	struct fcp_lun *plun;
9354 
9355 	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9356 	if (plun != NULL) {
9357 		/*
9358 		 * Initialize the mutex before putting in the target list
9359 		 * especially before releasing the target mutex.
9360 		 */
9361 		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9362 		plun->lun_tgt = ptgt;
9363 
9364 		mutex_enter(&ptgt->tgt_mutex);
9365 		plun->lun_next = ptgt->tgt_lun;
9366 		ptgt->tgt_lun = plun;
9367 		plun->lun_old_guid = NULL;
9368 		plun->lun_old_guid_size = 0;
9369 		mutex_exit(&ptgt->tgt_mutex);
9370 	}
9371 
9372 	return (plun);
9373 }
9374 
9375 /*
9376  *     Function: fcp_dealloc_lun
9377  *
9378  *  Description: Frees the LUN structure passed by the caller.
9379  *
9380  *     Argument: plun		LUN structure to free.
9381  *
9382  * Return Value: None
9383  *
9384  *	Context: Kernel context.
9385  */
9386 static void
9387 fcp_dealloc_lun(struct fcp_lun *plun)
9388 {
9389 	mutex_enter(&plun->lun_mutex);
9390 	if (plun->lun_cip) {
9391 		fcp_remove_child(plun);
9392 	}
9393 	mutex_exit(&plun->lun_mutex);
9394 
9395 	mutex_destroy(&plun->lun_mutex);
9396 	if (plun->lun_guid) {
9397 		kmem_free(plun->lun_guid, plun->lun_guid_size);
9398 	}
9399 	if (plun->lun_old_guid) {
9400 		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9401 	}
9402 	kmem_free(plun, sizeof (*plun));
9403 }
9404 
9405 /*
9406  *     Function: fcp_alloc_tgt
9407  *
9408  *  Description: Creates a new target structure and adds it to the port
9409  *		 hash list.
9410  *
9411  *     Argument: pptr		fcp port structure
9412  *		 *map_entry	entry describing the target to create
9413  *		 link_cnt	Link state change counter
9414  *
9415  * Return Value: NULL		Failed
9416  *		 Not NULL	Succeeded
9417  *
9418  *	Context: Kernel context.
9419  */
9420 static struct fcp_tgt *
9421 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9422 {
9423 	int			hash;
9424 	uchar_t			*wwn;
9425 	struct fcp_tgt	*ptgt;
9426 
9427 	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9428 	if (ptgt != NULL) {
9429 		mutex_enter(&pptr->port_mutex);
9430 		if (link_cnt != pptr->port_link_cnt) {
9431 			/*
9432 			 * oh oh -- another link reset
9433 			 * in progress -- give up
9434 			 */
9435 			mutex_exit(&pptr->port_mutex);
9436 			kmem_free(ptgt, sizeof (*ptgt));
9437 			ptgt = NULL;
9438 		} else {
9439 			/*
9440 			 * initialize the mutex before putting in the port
9441 			 * wwn list, especially before releasing the port
9442 			 * mutex.
9443 			 */
9444 			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9445 
9446 			/* add new target entry to the port's hash list */
9447 			wwn = (uchar_t *)&map_entry->map_pwwn;
9448 			hash = FCP_HASH(wwn);
9449 
9450 			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9451 			pptr->port_tgt_hash_table[hash] = ptgt;
9452 
9453 			/* save cross-ptr */
9454 			ptgt->tgt_port = pptr;
9455 
9456 			ptgt->tgt_change_cnt = 1;
9457 
9458 			/* initialize the target manual_config_only flag */
9459 			if (fcp_enable_auto_configuration) {
9460 				ptgt->tgt_manual_config_only = 0;
9461 			} else {
9462 				ptgt->tgt_manual_config_only = 1;
9463 			}
9464 
9465 			mutex_exit(&pptr->port_mutex);
9466 		}
9467 	}
9468 
9469 	return (ptgt);
9470 }
9471 
9472 /*
9473  *     Function: fcp_dealloc_tgt
9474  *
9475  *  Description: Frees the target structure passed by the caller.
9476  *
9477  *     Argument: ptgt		Target structure to free.
9478  *
9479  * Return Value: None
9480  *
9481  *	Context: Kernel context.
9482  */
9483 static void
9484 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9485 {
9486 	mutex_destroy(&ptgt->tgt_mutex);
9487 	kmem_free(ptgt, sizeof (*ptgt));
9488 }
9489 
9490 
9491 /*
9492  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9493  *
9494  *	Device discovery commands will not be retried for-ever as
9495  *	this will have repercussions on other devices that need to
9496  *	be submitted to the hotplug thread. After a quick glance
9497  *	at the SCSI-3 spec, it was found that the spec doesn't
9498  *	mandate a forever retry, rather recommends a delayed retry.
9499  *
9500  *	Since Photon IB is single threaded, STATUS_BUSY is common
9501  *	in a 4+initiator environment. Make sure the total time
9502  *	spent on retries (including command timeout) does not
9503  *	60 seconds
9504  */
9505 static void
9506 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9507 {
9508 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9509 	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9510 
9511 	mutex_enter(&pptr->port_mutex);
9512 	mutex_enter(&ptgt->tgt_mutex);
9513 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9514 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9515 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9516 		    "fcp_queue_ipkt,1:state change occured"
9517 		    " for D_ID=0x%x", ptgt->tgt_d_id);
9518 		mutex_exit(&ptgt->tgt_mutex);
9519 		mutex_exit(&pptr->port_mutex);
9520 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9521 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9522 		fcp_icmd_free(pptr, icmd);
9523 		return;
9524 	}
9525 	mutex_exit(&ptgt->tgt_mutex);
9526 
9527 	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9528 
9529 	if (pptr->port_ipkt_list != NULL) {
9530 		/* add pkt to front of doubly-linked list */
9531 		pptr->port_ipkt_list->ipkt_prev = icmd;
9532 		icmd->ipkt_next = pptr->port_ipkt_list;
9533 		pptr->port_ipkt_list = icmd;
9534 		icmd->ipkt_prev = NULL;
9535 	} else {
9536 		/* this is the first/only pkt on the list */
9537 		pptr->port_ipkt_list = icmd;
9538 		icmd->ipkt_next = NULL;
9539 		icmd->ipkt_prev = NULL;
9540 	}
9541 	mutex_exit(&pptr->port_mutex);
9542 }
9543 
9544 /*
9545  *     Function: fcp_transport
9546  *
9547  *  Description: This function submits the Fibre Channel packet to the transort
9548  *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9549  *		 fails the submission, the treatment depends on the value of
9550  *		 the variable internal.
9551  *
9552  *     Argument: port_handle	fp/fctl port handle.
9553  *		 *fpkt		Packet to submit to the transport layer.
9554  *		 internal	Not zero when it's an internal packet.
9555  *
9556  * Return Value: FC_TRAN_BUSY
9557  *		 FC_STATEC_BUSY
9558  *		 FC_OFFLINE
9559  *		 FC_LOGINREQ
9560  *		 FC_DEVICE_BUSY
9561  *		 FC_SUCCESS
9562  */
9563 static int
9564 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9565 {
9566 	int	rval;
9567 
9568 	rval = fc_ulp_transport(port_handle, fpkt);
9569 	if (rval == FC_SUCCESS) {
9570 		return (rval);
9571 	}
9572 
9573 	/*
9574 	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9575 	 * a command, if the underlying modules see that there is a state
9576 	 * change, or if a port is OFFLINE, that means, that state change
9577 	 * hasn't reached FCP yet, so re-queue the command for deferred
9578 	 * submission.
9579 	 */
9580 	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9581 	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9582 	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9583 		/*
9584 		 * Defer packet re-submission. Life hang is possible on
9585 		 * internal commands if the port driver sends FC_STATEC_BUSY
9586 		 * for ever, but that shouldn't happen in a good environment.
9587 		 * Limiting re-transport for internal commands is probably a
9588 		 * good idea..
9589 		 * A race condition can happen when a port sees barrage of
9590 		 * link transitions offline to online. If the FCTL has
9591 		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9592 		 * internal commands should be queued to do the discovery.
9593 		 * The race condition is when an online comes and FCP starts
9594 		 * its internal discovery and the link goes offline. It is
9595 		 * possible that the statec_callback has not reached FCP
9596 		 * and FCP is carrying on with its internal discovery.
9597 		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9598 		 * that the link has gone offline. At this point FCP should
9599 		 * drop all the internal commands and wait for the
9600 		 * statec_callback. It will be facilitated by incrementing
9601 		 * port_link_cnt.
9602 		 *
9603 		 * For external commands, the (FC)pkt_timeout is decremented
9604 		 * by the QUEUE Delay added by our driver, Care is taken to
9605 		 * ensure that it doesn't become zero (zero means no timeout)
9606 		 * If the time expires right inside driver queue itself,
9607 		 * the watch thread will return it to the original caller
9608 		 * indicating that the command has timed-out.
9609 		 */
9610 		if (internal) {
9611 			char			*op;
9612 			struct fcp_ipkt	*icmd;
9613 
9614 			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9615 			switch (icmd->ipkt_opcode) {
9616 			case SCMD_REPORT_LUN:
9617 				op = "REPORT LUN";
9618 				break;
9619 
9620 			case SCMD_INQUIRY:
9621 				op = "INQUIRY";
9622 				break;
9623 
9624 			case SCMD_INQUIRY_PAGE83:
9625 				op = "INQUIRY-83";
9626 				break;
9627 
9628 			default:
9629 				op = "Internal SCSI COMMAND";
9630 				break;
9631 			}
9632 
9633 			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9634 			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9635 				rval = FC_SUCCESS;
9636 			}
9637 		} else {
9638 			struct fcp_pkt *cmd;
9639 			struct fcp_port *pptr;
9640 
9641 			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9642 			cmd->cmd_state = FCP_PKT_IDLE;
9643 			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9644 
9645 			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9646 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9647 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9648 				    "fcp_transport: xport busy for pkt %p",
9649 				    cmd->cmd_pkt);
9650 				rval = FC_TRAN_BUSY;
9651 			} else {
9652 				fcp_queue_pkt(pptr, cmd);
9653 				rval = FC_SUCCESS;
9654 			}
9655 		}
9656 	}
9657 
9658 	return (rval);
9659 }
9660 
9661 /*VARARGS3*/
9662 static void
9663 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9664 {
9665 	char		buf[256];
9666 	va_list		ap;
9667 
9668 	if (dip == NULL) {
9669 		dip = fcp_global_dip;
9670 	}
9671 
9672 	va_start(ap, fmt);
9673 	(void) vsprintf(buf, fmt, ap);
9674 	va_end(ap);
9675 
9676 	scsi_log(dip, "fcp", level, buf);
9677 }
9678 
9679 /*
9680  * This function retries NS registry of FC4 type.
9681  * It assumes that fcp_mutex is held.
9682  * The function does nothing if topology is not fabric
9683  * So, the topology has to be set before this function can be called
9684  */
9685 static void
9686 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9687 {
9688 	int	rval;
9689 
9690 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9691 
9692 	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9693 	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9694 	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9695 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9696 			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9697 		}
9698 		return;
9699 	}
9700 	mutex_exit(&pptr->port_mutex);
9701 	rval = fcp_do_ns_registry(pptr, s_id);
9702 	mutex_enter(&pptr->port_mutex);
9703 
9704 	if (rval == 0) {
9705 		/* Registry successful. Reset flag */
9706 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9707 	}
9708 }
9709 
9710 /*
9711  * This function registers the ULP with the switch by calling transport i/f
9712  */
9713 static int
9714 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9715 {
9716 	fc_ns_cmd_t		ns_cmd;
9717 	ns_rfc_type_t		rfc;
9718 	uint32_t		types[8];
9719 
9720 	/*
9721 	 * Prepare the Name server structure to
9722 	 * register with the transport in case of
9723 	 * Fabric configuration.
9724 	 */
9725 	bzero(&rfc, sizeof (rfc));
9726 	bzero(types, sizeof (types));
9727 
9728 	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9729 	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9730 
9731 	rfc.rfc_port_id.port_id = s_id;
9732 	bcopy(types, rfc.rfc_types, sizeof (types));
9733 
9734 	ns_cmd.ns_flags = 0;
9735 	ns_cmd.ns_cmd = NS_RFT_ID;
9736 	ns_cmd.ns_req_len = sizeof (rfc);
9737 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9738 	ns_cmd.ns_resp_len = 0;
9739 	ns_cmd.ns_resp_payload = NULL;
9740 
9741 	/*
9742 	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9743 	 */
9744 	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9745 		fcp_log(CE_WARN, pptr->port_dip,
9746 		    "!ns_registry: failed name server registration");
9747 		return (1);
9748 	}
9749 
9750 	return (0);
9751 }
9752 
9753 /*
9754  *     Function: fcp_handle_port_attach
9755  *
9756  *  Description: This function is called from fcp_port_attach() to attach a
9757  *		 new port. This routine does the following:
9758  *
9759  *		1) Allocates an fcp_port structure and initializes it.
9760  *		2) Tries to register the new FC-4 (FCP) capablity with the name
9761  *		   server.
9762  *		3) Kicks off the enumeration of the targets/luns visible
9763  *		   through this new port.  That is done by calling
9764  *		   fcp_statec_callback() if the port is online.
9765  *
9766  *     Argument: ulph		fp/fctl port handle.
9767  *		 *pinfo		Port information.
9768  *		 s_id		Port ID.
9769  *		 instance	Device instance number for the local port
9770  *				(returned by ddi_get_instance()).
9771  *
9772  * Return Value: DDI_SUCCESS
9773  *		 DDI_FAILURE
9774  *
9775  *	Context: User and Kernel context.
9776  */
9777 /*ARGSUSED*/
9778 int
9779 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9780     uint32_t s_id, int instance)
9781 {
9782 	int			res = DDI_FAILURE;
9783 	scsi_hba_tran_t		*tran;
9784 	int			mutex_initted = FALSE;
9785 	int			hba_attached = FALSE;
9786 	int			soft_state_linked = FALSE;
9787 	int			event_bind = FALSE;
9788 	struct fcp_port		*pptr;
9789 	fc_portmap_t		*tmp_list = NULL;
9790 	uint32_t		max_cnt, alloc_cnt;
9791 	uchar_t			*boot_wwn = NULL;
9792 	uint_t			nbytes;
9793 	int			manual_cfg;
9794 
9795 	/*
9796 	 * this port instance attaching for the first time (or after
9797 	 * being detached before)
9798 	 */
9799 	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9800 	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9801 
9802 	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9803 		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9804 		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9805 		    instance);
9806 		return (res);
9807 	}
9808 
9809 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9810 		/* this shouldn't happen */
9811 		ddi_soft_state_free(fcp_softstate, instance);
9812 		cmn_err(CE_WARN, "fcp: bad soft state");
9813 		return (res);
9814 	}
9815 
9816 	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9817 
9818 	/*
9819 	 * Make a copy of ulp_port_info as fctl allocates
9820 	 * a temp struct.
9821 	 */
9822 	(void) fcp_cp_pinfo(pptr, pinfo);
9823 
9824 	/*
9825 	 * Check for manual_configuration_only property.
9826 	 * Enable manual configurtion if the property is
9827 	 * set to 1, otherwise disable manual configuration.
9828 	 */
9829 	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9830 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9831 	    MANUAL_CFG_ONLY,
9832 	    -1)) != -1) {
9833 		if (manual_cfg == 1) {
9834 			char	*pathname;
9835 			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9836 			(void) ddi_pathname(pptr->port_dip, pathname);
9837 			cmn_err(CE_NOTE,
9838 			    "%s (%s%d) %s is enabled via %s.conf.",
9839 			    pathname,
9840 			    ddi_driver_name(pptr->port_dip),
9841 			    ddi_get_instance(pptr->port_dip),
9842 			    MANUAL_CFG_ONLY,
9843 			    ddi_driver_name(pptr->port_dip));
9844 			fcp_enable_auto_configuration = 0;
9845 			kmem_free(pathname, MAXPATHLEN);
9846 		}
9847 	}
9848 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9849 	pptr->port_link_cnt = 1;
9850 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9851 	pptr->port_id = s_id;
9852 	pptr->port_instance = instance;
9853 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9854 	pptr->port_state = FCP_STATE_INIT;
9855 	if (pinfo->port_acc_attr == NULL) {
9856 		/*
9857 		 * The corresponding FCA doesn't support DMA at all
9858 		 */
9859 		pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9860 	}
9861 
9862 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9863 
9864 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9865 		/*
9866 		 * If FCA supports DMA in SCSI data phase, we need preallocate
9867 		 * dma cookie, so stash the cookie size
9868 		 */
9869 		pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9870 		    pptr->port_data_dma_attr.dma_attr_sgllen;
9871 	}
9872 
9873 	/*
9874 	 * The two mutexes of fcp_port are initialized.	 The variable
9875 	 * mutex_initted is incremented to remember that fact.	That variable
9876 	 * is checked when the routine fails and the mutexes have to be
9877 	 * destroyed.
9878 	 */
9879 	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9880 	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9881 	mutex_initted++;
9882 
9883 	/*
9884 	 * The SCSI tran structure is allocate and initialized now.
9885 	 */
9886 	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9887 		fcp_log(CE_WARN, pptr->port_dip,
9888 		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9889 		goto fail;
9890 	}
9891 
9892 	/* link in the transport structure then fill it in */
9893 	pptr->port_tran = tran;
9894 	tran->tran_hba_private		= pptr;
9895 	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9896 	tran->tran_tgt_probe		= NULL;
9897 	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9898 	tran->tran_start		= fcp_scsi_start;
9899 	tran->tran_reset		= fcp_scsi_reset;
9900 	tran->tran_abort		= fcp_scsi_abort;
9901 	tran->tran_getcap		= fcp_scsi_getcap;
9902 	tran->tran_setcap		= fcp_scsi_setcap;
9903 	tran->tran_init_pkt		= NULL;
9904 	tran->tran_destroy_pkt		= NULL;
9905 	tran->tran_dmafree		= NULL;
9906 	tran->tran_sync_pkt		= NULL;
9907 	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9908 	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9909 	tran->tran_get_name		= fcp_scsi_get_name;
9910 	tran->tran_clear_aca		= NULL;
9911 	tran->tran_clear_task_set	= NULL;
9912 	tran->tran_terminate_task	= NULL;
9913 	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9914 	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9915 	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9916 	tran->tran_post_event		= fcp_scsi_bus_post_event;
9917 	tran->tran_quiesce		= NULL;
9918 	tran->tran_unquiesce		= NULL;
9919 	tran->tran_bus_reset		= NULL;
9920 	tran->tran_bus_config		= fcp_scsi_bus_config;
9921 	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9922 	tran->tran_bus_power		= NULL;
9923 	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9924 
9925 	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9926 	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9927 	tran->tran_setup_pkt		= fcp_pkt_setup;
9928 	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9929 	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9930 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9931 	if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9932 		/*
9933 		 * If FCA don't support DMA, then we use different vectors to
9934 		 * minimize the effects on DMA code flow path
9935 		 */
9936 		tran->tran_start	   = fcp_pseudo_start;
9937 		tran->tran_init_pkt	   = fcp_pseudo_init_pkt;
9938 		tran->tran_destroy_pkt	   = fcp_pseudo_destroy_pkt;
9939 		tran->tran_sync_pkt	   = fcp_pseudo_sync_pkt;
9940 		tran->tran_dmafree	   = fcp_pseudo_dmafree;
9941 		tran->tran_setup_pkt	   = NULL;
9942 		tran->tran_teardown_pkt	   = NULL;
9943 		tran->tran_pkt_constructor = NULL;
9944 		tran->tran_pkt_destructor  = NULL;
9945 		pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9946 	}
9947 
9948 	/*
9949 	 * Allocate an ndi event handle
9950 	 */
9951 	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9952 	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9953 
9954 	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9955 	    sizeof (fcp_ndi_event_defs));
9956 
9957 	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9958 	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9959 
9960 	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9961 	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9962 	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9963 
9964 	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9965 	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9966 	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9967 		goto fail;
9968 	}
9969 	event_bind++;	/* Checked in fail case */
9970 
9971 	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9972 	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9973 	    != DDI_SUCCESS) {
9974 		fcp_log(CE_WARN, pptr->port_dip,
9975 		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9976 		goto fail;
9977 	}
9978 	hba_attached++;	/* Checked in fail case */
9979 
9980 	pptr->port_mpxio = 0;
9981 	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9982 	    MDI_SUCCESS) {
9983 		pptr->port_mpxio++;
9984 	}
9985 
9986 	/*
9987 	 * The following code is putting the new port structure in the global
9988 	 * list of ports and, if it is the first port to attach, it start the
9989 	 * fcp_watchdog_tick.
9990 	 *
9991 	 * Why put this new port in the global before we are done attaching it?
9992 	 * We are actually making the structure globally known before we are
9993 	 * done attaching it.  The reason for that is: because of the code that
9994 	 * follows.  At this point the resources to handle the port are
9995 	 * allocated.  This function is now going to do the following:
9996 	 *
9997 	 *   1) It is going to try to register with the name server advertizing
9998 	 *	the new FCP capability of the port.
9999 	 *   2) It is going to play the role of the fp/fctl layer by building
10000 	 *	a list of worlwide names reachable through this port and call
10001 	 *	itself on fcp_statec_callback().  That requires the port to
10002 	 *	be part of the global list.
10003 	 */
10004 	mutex_enter(&fcp_global_mutex);
10005 	if (fcp_port_head == NULL) {
10006 		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10007 	}
10008 	pptr->port_next = fcp_port_head;
10009 	fcp_port_head = pptr;
10010 	soft_state_linked++;
10011 
10012 	if (fcp_watchdog_init++ == 0) {
10013 		fcp_watchdog_tick = fcp_watchdog_timeout *
10014 		    drv_usectohz(1000000);
10015 		fcp_watchdog_id = timeout(fcp_watch, NULL,
10016 		    fcp_watchdog_tick);
10017 	}
10018 	mutex_exit(&fcp_global_mutex);
10019 
10020 	/*
10021 	 * Here an attempt is made to register with the name server, the new
10022 	 * FCP capability.  That is done using an RTF_ID to the name server.
10023 	 * It is done synchronously.  The function fcp_do_ns_registry()
10024 	 * doesn't return till the name server responded.
10025 	 * On failures, just ignore it for now and it will get retried during
10026 	 * state change callbacks. We'll set a flag to show this failure
10027 	 */
10028 	if (fcp_do_ns_registry(pptr, s_id)) {
10029 		mutex_enter(&pptr->port_mutex);
10030 		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10031 		mutex_exit(&pptr->port_mutex);
10032 	} else {
10033 		mutex_enter(&pptr->port_mutex);
10034 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10035 		mutex_exit(&pptr->port_mutex);
10036 	}
10037 
10038 	/*
10039 	 * Lookup for boot WWN property
10040 	 */
10041 	if (modrootloaded != 1) {
10042 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10043 		    ddi_get_parent(pinfo->port_dip),
10044 		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10045 		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10046 		    (nbytes == FC_WWN_SIZE)) {
10047 			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10048 		}
10049 		if (boot_wwn) {
10050 			ddi_prop_free(boot_wwn);
10051 		}
10052 	}
10053 
10054 	/*
10055 	 * Handle various topologies and link states.
10056 	 */
10057 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10058 	case FC_STATE_OFFLINE:
10059 
10060 		/*
10061 		 * we're attaching a port where the link is offline
10062 		 *
10063 		 * Wait for ONLINE, at which time a state
10064 		 * change will cause a statec_callback
10065 		 *
10066 		 * in the mean time, do not do anything
10067 		 */
10068 		res = DDI_SUCCESS;
10069 		pptr->port_state |= FCP_STATE_OFFLINE;
10070 		break;
10071 
10072 	case FC_STATE_ONLINE: {
10073 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
10074 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10075 			res = DDI_SUCCESS;
10076 			break;
10077 		}
10078 		/*
10079 		 * discover devices and create nodes (a private
10080 		 * loop or point-to-point)
10081 		 */
10082 		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10083 
10084 		/*
10085 		 * At this point we are going to build a list of all the ports
10086 		 * that	can be reached through this local port.	 It looks like
10087 		 * we cannot handle more than FCP_MAX_DEVICES per local port
10088 		 * (128).
10089 		 */
10090 		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10091 		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10092 		    KM_NOSLEEP)) == NULL) {
10093 			fcp_log(CE_WARN, pptr->port_dip,
10094 			    "!fcp%d: failed to allocate portmap",
10095 			    instance);
10096 			goto fail;
10097 		}
10098 
10099 		/*
10100 		 * fc_ulp_getportmap() is going to provide us with the list of
10101 		 * remote ports in the buffer we just allocated.  The way the
10102 		 * list is going to be retrieved depends on the topology.
10103 		 * However, if we are connected to a Fabric, a name server
10104 		 * request may be sent to get the list of FCP capable ports.
10105 		 * It should be noted that is the case the request is
10106 		 * synchronous.	 This means we are stuck here till the name
10107 		 * server replies.  A lot of things can change during that time
10108 		 * and including, may be, being called on
10109 		 * fcp_statec_callback() for different reasons. I'm not sure
10110 		 * the code can handle that.
10111 		 */
10112 		max_cnt = FCP_MAX_DEVICES;
10113 		alloc_cnt = FCP_MAX_DEVICES;
10114 		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10115 		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10116 		    FC_SUCCESS) {
10117 			caddr_t msg;
10118 
10119 			(void) fc_ulp_error(res, &msg);
10120 
10121 			/*
10122 			 * this	 just means the transport is
10123 			 * busy perhaps building a portmap so,
10124 			 * for now, succeed this port attach
10125 			 * when the transport has a new map,
10126 			 * it'll send us a state change then
10127 			 */
10128 			fcp_log(CE_WARN, pptr->port_dip,
10129 			    "!failed to get port map : %s", msg);
10130 
10131 			res = DDI_SUCCESS;
10132 			break;	/* go return result */
10133 		}
10134 		if (max_cnt > alloc_cnt) {
10135 			alloc_cnt = max_cnt;
10136 		}
10137 
10138 		/*
10139 		 * We are now going to call fcp_statec_callback() ourselves.
10140 		 * By issuing this call we are trying to kick off the enumera-
10141 		 * tion process.
10142 		 */
10143 		/*
10144 		 * let the state change callback do the SCSI device
10145 		 * discovery and create the devinfos
10146 		 */
10147 		fcp_statec_callback(ulph, pptr->port_fp_handle,
10148 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10149 		    max_cnt, pptr->port_id);
10150 
10151 		res = DDI_SUCCESS;
10152 		break;
10153 	}
10154 
10155 	default:
10156 		/* unknown port state */
10157 		fcp_log(CE_WARN, pptr->port_dip,
10158 		    "!fcp%d: invalid port state at attach=0x%x",
10159 		    instance, pptr->port_phys_state);
10160 
10161 		mutex_enter(&pptr->port_mutex);
10162 		pptr->port_phys_state = FCP_STATE_OFFLINE;
10163 		mutex_exit(&pptr->port_mutex);
10164 
10165 		res = DDI_SUCCESS;
10166 		break;
10167 	}
10168 
10169 	/* free temp list if used */
10170 	if (tmp_list != NULL) {
10171 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10172 	}
10173 
10174 	/* note the attach time */
10175 	pptr->port_attach_time = lbolt64;
10176 
10177 	/* all done */
10178 	return (res);
10179 
10180 	/* a failure we have to clean up after */
10181 fail:
10182 	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10183 
10184 	if (soft_state_linked) {
10185 		/* remove this fcp_port from the linked list */
10186 		(void) fcp_soft_state_unlink(pptr);
10187 	}
10188 
10189 	/* unbind and free event set */
10190 	if (pptr->port_ndi_event_hdl) {
10191 		if (event_bind) {
10192 			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10193 			    &pptr->port_ndi_events, NDI_SLEEP);
10194 		}
10195 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10196 	}
10197 
10198 	if (pptr->port_ndi_event_defs) {
10199 		(void) kmem_free(pptr->port_ndi_event_defs,
10200 		    sizeof (fcp_ndi_event_defs));
10201 	}
10202 
10203 	/*
10204 	 * Clean up mpxio stuff
10205 	 */
10206 	if (pptr->port_mpxio) {
10207 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10208 		pptr->port_mpxio--;
10209 	}
10210 
10211 	/* undo SCSI HBA setup */
10212 	if (hba_attached) {
10213 		(void) scsi_hba_detach(pptr->port_dip);
10214 	}
10215 	if (pptr->port_tran != NULL) {
10216 		scsi_hba_tran_free(pptr->port_tran);
10217 	}
10218 
10219 	mutex_enter(&fcp_global_mutex);
10220 
10221 	/*
10222 	 * We check soft_state_linked, because it is incremented right before
10223 	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10224 	 * soft_state_linked is still FALSE, we do not want to decrement
10225 	 * fcp_watchdog_init or possibly call untimeout.
10226 	 */
10227 
10228 	if (soft_state_linked) {
10229 		if (--fcp_watchdog_init == 0) {
10230 			timeout_id_t	tid = fcp_watchdog_id;
10231 
10232 			mutex_exit(&fcp_global_mutex);
10233 			(void) untimeout(tid);
10234 		} else {
10235 			mutex_exit(&fcp_global_mutex);
10236 		}
10237 	} else {
10238 		mutex_exit(&fcp_global_mutex);
10239 	}
10240 
10241 	if (mutex_initted) {
10242 		mutex_destroy(&pptr->port_mutex);
10243 		mutex_destroy(&pptr->port_pkt_mutex);
10244 	}
10245 
10246 	if (tmp_list != NULL) {
10247 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10248 	}
10249 
10250 	/* this makes pptr invalid */
10251 	ddi_soft_state_free(fcp_softstate, instance);
10252 
10253 	return (DDI_FAILURE);
10254 }
10255 
10256 
10257 static int
10258 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10259 {
10260 	int count = 0;
10261 
10262 	mutex_enter(&pptr->port_mutex);
10263 
10264 	/*
10265 	 * if the port is powered down or suspended, nothing else
10266 	 * to do; just return.
10267 	 */
10268 	if (flag != FCP_STATE_DETACHING) {
10269 		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10270 		    FCP_STATE_SUSPENDED)) {
10271 			pptr->port_state |= flag;
10272 			mutex_exit(&pptr->port_mutex);
10273 			return (FC_SUCCESS);
10274 		}
10275 	}
10276 
10277 	if (pptr->port_state & FCP_STATE_IN_MDI) {
10278 		mutex_exit(&pptr->port_mutex);
10279 		return (FC_FAILURE);
10280 	}
10281 
10282 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10283 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10284 	    "fcp_handle_port_detach: port is detaching");
10285 
10286 	pptr->port_state |= flag;
10287 
10288 	/*
10289 	 * Wait for any ongoing reconfig/ipkt to complete, that
10290 	 * ensures the freeing to targets/luns is safe.
10291 	 * No more ref to this port should happen from statec/ioctl
10292 	 * after that as it was removed from the global port list.
10293 	 */
10294 	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10295 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10296 		/*
10297 		 * Let's give sufficient time for reconfig/ipkt
10298 		 * to complete.
10299 		 */
10300 		if (count++ >= FCP_ICMD_DEADLINE) {
10301 			break;
10302 		}
10303 		mutex_exit(&pptr->port_mutex);
10304 		delay(drv_usectohz(1000000));
10305 		mutex_enter(&pptr->port_mutex);
10306 	}
10307 
10308 	/*
10309 	 * if the driver is still busy then fail to
10310 	 * suspend/power down.
10311 	 */
10312 	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10313 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10314 		pptr->port_state &= ~flag;
10315 		mutex_exit(&pptr->port_mutex);
10316 		return (FC_FAILURE);
10317 	}
10318 
10319 	if (flag == FCP_STATE_DETACHING) {
10320 		pptr = fcp_soft_state_unlink(pptr);
10321 		ASSERT(pptr != NULL);
10322 	}
10323 
10324 	pptr->port_link_cnt++;
10325 	pptr->port_state |= FCP_STATE_OFFLINE;
10326 	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10327 
10328 	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10329 	    FCP_CAUSE_LINK_DOWN);
10330 	mutex_exit(&pptr->port_mutex);
10331 
10332 	/* kill watch dog timer if we're the last */
10333 	mutex_enter(&fcp_global_mutex);
10334 	if (--fcp_watchdog_init == 0) {
10335 		timeout_id_t	tid = fcp_watchdog_id;
10336 		mutex_exit(&fcp_global_mutex);
10337 		(void) untimeout(tid);
10338 	} else {
10339 		mutex_exit(&fcp_global_mutex);
10340 	}
10341 
10342 	/* clean up the port structures */
10343 	if (flag == FCP_STATE_DETACHING) {
10344 		fcp_cleanup_port(pptr, instance);
10345 	}
10346 
10347 	return (FC_SUCCESS);
10348 }
10349 
10350 
10351 static void
10352 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10353 {
10354 	ASSERT(pptr != NULL);
10355 
10356 	/* unbind and free event set */
10357 	if (pptr->port_ndi_event_hdl) {
10358 		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10359 		    &pptr->port_ndi_events, NDI_SLEEP);
10360 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10361 	}
10362 
10363 	if (pptr->port_ndi_event_defs) {
10364 		(void) kmem_free(pptr->port_ndi_event_defs,
10365 		    sizeof (fcp_ndi_event_defs));
10366 	}
10367 
10368 	/* free the lun/target structures and devinfos */
10369 	fcp_free_targets(pptr);
10370 
10371 	/*
10372 	 * Clean up mpxio stuff
10373 	 */
10374 	if (pptr->port_mpxio) {
10375 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10376 		pptr->port_mpxio--;
10377 	}
10378 
10379 	/* clean up SCSA stuff */
10380 	(void) scsi_hba_detach(pptr->port_dip);
10381 	if (pptr->port_tran != NULL) {
10382 		scsi_hba_tran_free(pptr->port_tran);
10383 	}
10384 
10385 #ifdef	KSTATS_CODE
10386 	/* clean up kstats */
10387 	if (pptr->fcp_ksp != NULL) {
10388 		kstat_delete(pptr->fcp_ksp);
10389 	}
10390 #endif
10391 
10392 	/* clean up soft state mutexes/condition variables */
10393 	mutex_destroy(&pptr->port_mutex);
10394 	mutex_destroy(&pptr->port_pkt_mutex);
10395 
10396 	/* all done with soft state */
10397 	ddi_soft_state_free(fcp_softstate, instance);
10398 }
10399 
10400 /*
10401  *     Function: fcp_kmem_cache_constructor
10402  *
10403  *  Description: This function allocates and initializes the resources required
10404  *		 to build a scsi_pkt structure the target driver.  The result
10405  *		 of the allocation and initialization will be cached in the
10406  *		 memory cache.	As DMA resources may be allocated here, that
10407  *		 means DMA resources will be tied up in the cache manager.
10408  *		 This is a tradeoff that has been made for performance reasons.
10409  *
10410  *     Argument: *buf		Memory to preinitialize.
10411  *		 *arg		FCP port structure (fcp_port).
10412  *		 kmflags	Value passed to kmem_cache_alloc() and
10413  *				propagated to the constructor.
10414  *
10415  * Return Value: 0	Allocation/Initialization was successful.
10416  *		 -1	Allocation or Initialization failed.
10417  *
10418  *
10419  * If the returned value is 0, the buffer is initialized like this:
10420  *
10421  *		    +================================+
10422  *	     +----> |	      struct scsi_pkt	     |
10423  *	     |	    |				     |
10424  *	     | +--- | pkt_ha_private		     |
10425  *	     | |    |				     |
10426  *	     | |    +================================+
10427  *	     | |
10428  *	     | |    +================================+
10429  *	     | +--> |	    struct fcp_pkt	     | <---------+
10430  *	     |	    |				     |		 |
10431  *	     +----- | cmd_pkt			     |		 |
10432  *		    |			  cmd_fp_pkt | ---+	 |
10433  *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10434  *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10435  *	  |    |    |--------------------------------|	  |	 |
10436  *	  |    |    |	      struct fc_packet	     | <--+	 |
10437  *	  |    |    |				     |		 |
10438  *	  |    |    |		     pkt_ulp_private | ----------+
10439  *	  |    |    |		     pkt_fca_private | -----+
10440  *	  |    |    |		     pkt_data_cookie | ---+ |
10441  *	  |    |    | pkt_cmdlen		     |	  | |
10442  *	  |    |(a) | pkt_rsplen		     |	  | |
10443  *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10444  *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10445  *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10446  *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10447  *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10448  *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10449  *		    +================================+	  | |  |   |   |    |
10450  *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10451  *		    |				     |	    |  |   |   |    |
10452  *		    +================================+	    |  |   |   |    |
10453  *		    |	      fca_private	     | <----+  |   |   |    |
10454  *		    |				     |	       |   |   |    |
10455  *		    +================================+	       |   |   |    |
10456  *							       |   |   |    |
10457  *							       |   |   |    |
10458  *		    +================================+	 (d)   |   |   |    |
10459  *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10460  *		    |				     |		   |   |    |
10461  *		    +================================+		   |   |    |
10462  *								   |   |    |
10463  *		    +================================+	 (d)	   |   |    |
10464  *		    |		fcp_resp	     | <-----------+   |    |
10465  *		    |	(DMA resources associated)   |		       |    |
10466  *		    +================================+		       |    |
10467  *								       |    |
10468  *								       |    |
10469  *								       |    |
10470  *		    +================================+	 (c)	       |    |
10471  *		    |	     fcp_cmd cookies	     | <---------------+    |
10472  *		    |				     |			    |
10473  *		    +================================+			    |
10474  *									    |
10475  *		    +================================+	 (c)		    |
10476  *		    |		 fcp_cmd	     | <--------------------+
10477  *		    |	(DMA resources associated)   |
10478  *		    +================================+
10479  *
10480  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10481  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10482  * (c) Only if DMA is used for the FCP_CMD buffer.
10483  * (d) Only if DMA is used for the FCP_RESP buffer
10484  */
10485 static int
10486 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10487     int kmflags)
10488 {
10489 	struct fcp_pkt	*cmd;
10490 	struct fcp_port	*pptr;
10491 	fc_packet_t	*fpkt;
10492 
10493 	pptr = (struct fcp_port *)tran->tran_hba_private;
10494 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10495 	bzero(cmd, tran->tran_hba_len);
10496 
10497 	cmd->cmd_pkt = pkt;
10498 	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10499 	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10500 	cmd->cmd_fp_pkt = fpkt;
10501 
10502 	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10503 	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10504 	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10505 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10506 
10507 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10508 	    sizeof (struct fcp_pkt));
10509 
10510 	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10511 	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10512 
10513 	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10514 		/*
10515 		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10516 		 * fcp_resp.  The transfer of information will be done by
10517 		 * bcopy.
10518 		 * The naming of the flags (that is actually a value) is
10519 		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10520 		 * DMA" but instead "NO DMA".
10521 		 */
10522 		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10523 		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10524 		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10525 	} else {
10526 		/*
10527 		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10528 		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10529 		 * interfaces.
10530 		 */
10531 		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10532 			return (-1);
10533 		}
10534 	}
10535 
10536 	return (0);
10537 }
10538 
10539 /*
10540  *     Function: fcp_kmem_cache_destructor
10541  *
10542  *  Description: Called by the destructor of the cache managed by SCSA.
10543  *		 All the resources pre-allocated in fcp_pkt_constructor
10544  *		 and the data also pre-initialized in fcp_pkt_constructor
10545  *		 are freed and uninitialized here.
10546  *
10547  *     Argument: *buf		Memory to uninitialize.
10548  *		 *arg		FCP port structure (fcp_port).
10549  *
10550  * Return Value: None
10551  *
10552  *	Context: kernel
10553  */
10554 static void
10555 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10556 {
10557 	struct fcp_pkt	*cmd;
10558 	struct fcp_port	*pptr;
10559 
10560 	pptr = (struct fcp_port *)(tran->tran_hba_private);
10561 	cmd = pkt->pkt_ha_private;
10562 
10563 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10564 		/*
10565 		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10566 		 * buffer and DMA resources allocated to do so are released.
10567 		 */
10568 		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10569 	}
10570 }
10571 
10572 /*
10573  *     Function: fcp_alloc_cmd_resp
10574  *
10575  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10576  *		 will be DMAed by the HBA.  The buffer is allocated applying
10577  *		 the DMA requirements for the HBA.  The buffers allocated will
10578  *		 also be bound.	 DMA resources are allocated in the process.
10579  *		 They will be released by fcp_free_cmd_resp().
10580  *
10581  *     Argument: *pptr	FCP port.
10582  *		 *fpkt	fc packet for which the cmd and resp packet should be
10583  *			allocated.
10584  *		 flags	Allocation flags.
10585  *
10586  * Return Value: FC_FAILURE
10587  *		 FC_SUCCESS
10588  *
10589  *	Context: User or Kernel context only if flags == KM_SLEEP.
10590  *		 Interrupt context if the KM_SLEEP is not specified.
10591  */
10592 static int
10593 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10594 {
10595 	int			rval;
10596 	int			cmd_len;
10597 	int			resp_len;
10598 	ulong_t			real_len;
10599 	int			(*cb) (caddr_t);
10600 	ddi_dma_cookie_t	pkt_cookie;
10601 	ddi_dma_cookie_t	*cp;
10602 	uint32_t		cnt;
10603 
10604 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10605 
10606 	cmd_len = fpkt->pkt_cmdlen;
10607 	resp_len = fpkt->pkt_rsplen;
10608 
10609 	ASSERT(fpkt->pkt_cmd_dma == NULL);
10610 
10611 	/* Allocation of a DMA handle used in subsequent calls. */
10612 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10613 	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10614 		return (FC_FAILURE);
10615 	}
10616 
10617 	/* A buffer is allocated that satisfies the DMA requirements. */
10618 	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10619 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10620 	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10621 
10622 	if (rval != DDI_SUCCESS) {
10623 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10624 		return (FC_FAILURE);
10625 	}
10626 
10627 	if (real_len < cmd_len) {
10628 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10629 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10630 		return (FC_FAILURE);
10631 	}
10632 
10633 	/* The buffer allocated is DMA bound. */
10634 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10635 	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10636 	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10637 
10638 	if (rval != DDI_DMA_MAPPED) {
10639 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10640 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10641 		return (FC_FAILURE);
10642 	}
10643 
10644 	if (fpkt->pkt_cmd_cookie_cnt >
10645 	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10646 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10647 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10648 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10649 		return (FC_FAILURE);
10650 	}
10651 
10652 	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10653 
10654 	/*
10655 	 * The buffer where the scatter/gather list is going to be built is
10656 	 * allocated.
10657 	 */
10658 	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10659 	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10660 	    KM_NOSLEEP);
10661 
10662 	if (cp == NULL) {
10663 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10664 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10665 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10666 		return (FC_FAILURE);
10667 	}
10668 
10669 	/*
10670 	 * The scatter/gather list for the buffer we just allocated is built
10671 	 * here.
10672 	 */
10673 	*cp = pkt_cookie;
10674 	cp++;
10675 
10676 	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10677 		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10678 		    &pkt_cookie);
10679 		*cp = pkt_cookie;
10680 	}
10681 
10682 	ASSERT(fpkt->pkt_resp_dma == NULL);
10683 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10684 	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10685 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10686 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10687 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10688 		return (FC_FAILURE);
10689 	}
10690 
10691 	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10692 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10693 	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10694 	    &fpkt->pkt_resp_acc);
10695 
10696 	if (rval != DDI_SUCCESS) {
10697 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10698 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10699 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10700 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10701 		kmem_free(fpkt->pkt_cmd_cookie,
10702 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10703 		return (FC_FAILURE);
10704 	}
10705 
10706 	if (real_len < resp_len) {
10707 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10708 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10709 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10710 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10711 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10712 		kmem_free(fpkt->pkt_cmd_cookie,
10713 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10714 		return (FC_FAILURE);
10715 	}
10716 
10717 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10718 	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10719 	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10720 
10721 	if (rval != DDI_DMA_MAPPED) {
10722 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10723 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10724 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10725 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10726 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10727 		kmem_free(fpkt->pkt_cmd_cookie,
10728 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10729 		return (FC_FAILURE);
10730 	}
10731 
10732 	if (fpkt->pkt_resp_cookie_cnt >
10733 	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10734 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10735 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10736 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10737 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10738 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10739 		kmem_free(fpkt->pkt_cmd_cookie,
10740 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10741 		return (FC_FAILURE);
10742 	}
10743 
10744 	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10745 
10746 	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10747 	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10748 	    KM_NOSLEEP);
10749 
10750 	if (cp == NULL) {
10751 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10752 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10753 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10754 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10755 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10756 		kmem_free(fpkt->pkt_cmd_cookie,
10757 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10758 		return (FC_FAILURE);
10759 	}
10760 
10761 	*cp = pkt_cookie;
10762 	cp++;
10763 
10764 	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10765 		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10766 		    &pkt_cookie);
10767 		*cp = pkt_cookie;
10768 	}
10769 
10770 	return (FC_SUCCESS);
10771 }
10772 
10773 /*
10774  *     Function: fcp_free_cmd_resp
10775  *
10776  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10777  *		 allocated by fcp_alloc_cmd_resp() and all the resources
10778  *		 associated with them.	That includes the DMA resources and the
10779  *		 buffer allocated for the cookies of each one of them.
10780  *
10781  *     Argument: *pptr		FCP port context.
10782  *		 *fpkt		fc packet containing the cmd and resp packet
10783  *				to be released.
10784  *
10785  * Return Value: None
10786  *
10787  *	Context: Interrupt, User and Kernel context.
10788  */
10789 /* ARGSUSED */
10790 static void
10791 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10792 {
10793 	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10794 
10795 	if (fpkt->pkt_resp_dma) {
10796 		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10797 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10798 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10799 	}
10800 
10801 	if (fpkt->pkt_resp_cookie) {
10802 		kmem_free(fpkt->pkt_resp_cookie,
10803 		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10804 		fpkt->pkt_resp_cookie = NULL;
10805 	}
10806 
10807 	if (fpkt->pkt_cmd_dma) {
10808 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10809 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10810 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10811 	}
10812 
10813 	if (fpkt->pkt_cmd_cookie) {
10814 		kmem_free(fpkt->pkt_cmd_cookie,
10815 		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10816 		fpkt->pkt_cmd_cookie = NULL;
10817 	}
10818 }
10819 
10820 
10821 /*
10822  * called by the transport to do our own target initialization
10823  *
10824  * can acquire and release the global mutex
10825  */
10826 /* ARGSUSED */
10827 static int
10828 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10829     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10830 {
10831 	uchar_t			*bytes;
10832 	uint_t			nbytes;
10833 	uint16_t		lun_num;
10834 	struct fcp_tgt	*ptgt;
10835 	struct fcp_lun	*plun;
10836 	struct fcp_port	*pptr = (struct fcp_port *)
10837 	    hba_tran->tran_hba_private;
10838 
10839 	ASSERT(pptr != NULL);
10840 
10841 	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10842 	    FCP_BUF_LEVEL_8, 0,
10843 	    "fcp_phys_tgt_init: called for %s (instance %d)",
10844 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10845 
10846 	/* get our port WWN property */
10847 	bytes = NULL;
10848 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10849 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10850 	    (nbytes != FC_WWN_SIZE)) {
10851 		/* no port WWN property */
10852 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10853 		    FCP_BUF_LEVEL_8, 0,
10854 		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10855 		    " for %s (instance %d): bytes=%p nbytes=%x",
10856 		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10857 		    nbytes);
10858 
10859 		if (bytes != NULL) {
10860 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10861 		}
10862 
10863 		return (DDI_NOT_WELL_FORMED);
10864 	}
10865 	ASSERT(bytes != NULL);
10866 
10867 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10868 	    LUN_PROP, 0xFFFF);
10869 	if (lun_num == 0xFFFF) {
10870 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10871 		    FCP_BUF_LEVEL_8, 0,
10872 		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10873 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10874 		    ddi_get_instance(tgt_dip));
10875 
10876 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10877 		return (DDI_NOT_WELL_FORMED);
10878 	}
10879 
10880 	mutex_enter(&pptr->port_mutex);
10881 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10882 		mutex_exit(&pptr->port_mutex);
10883 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10884 		    FCP_BUF_LEVEL_8, 0,
10885 		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10886 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10887 		    ddi_get_instance(tgt_dip));
10888 
10889 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10890 		return (DDI_FAILURE);
10891 	}
10892 
10893 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10894 	    FC_WWN_SIZE) == 0);
10895 	ASSERT(plun->lun_num == lun_num);
10896 
10897 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10898 
10899 	ptgt = plun->lun_tgt;
10900 
10901 	mutex_enter(&ptgt->tgt_mutex);
10902 	plun->lun_tgt_count++;
10903 	scsi_device_hba_private_set(sd, plun);
10904 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10905 	plun->lun_sd = sd;
10906 	mutex_exit(&ptgt->tgt_mutex);
10907 	mutex_exit(&pptr->port_mutex);
10908 
10909 	return (DDI_SUCCESS);
10910 }
10911 
10912 /*ARGSUSED*/
10913 static int
10914 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10915     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10916 {
10917 	uchar_t			*bytes;
10918 	uint_t			nbytes;
10919 	uint16_t		lun_num;
10920 	struct fcp_tgt	*ptgt;
10921 	struct fcp_lun	*plun;
10922 	struct fcp_port	*pptr = (struct fcp_port *)
10923 	    hba_tran->tran_hba_private;
10924 	child_info_t		*cip;
10925 
10926 	ASSERT(pptr != NULL);
10927 
10928 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10929 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10930 	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10931 	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10932 	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10933 
10934 	cip = (child_info_t *)sd->sd_pathinfo;
10935 	if (cip == NULL) {
10936 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10937 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10938 		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10939 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10940 		    ddi_get_instance(tgt_dip));
10941 
10942 		return (DDI_NOT_WELL_FORMED);
10943 	}
10944 
10945 	/* get our port WWN property */
10946 	bytes = NULL;
10947 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10948 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10949 	    (nbytes != FC_WWN_SIZE)) {
10950 		if (bytes) {
10951 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10952 		}
10953 		return (DDI_NOT_WELL_FORMED);
10954 	}
10955 
10956 	ASSERT(bytes != NULL);
10957 
10958 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10959 	    LUN_PROP, 0xFFFF);
10960 	if (lun_num == 0xFFFF) {
10961 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10962 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10963 		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10964 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10965 		    ddi_get_instance(tgt_dip));
10966 
10967 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10968 		return (DDI_NOT_WELL_FORMED);
10969 	}
10970 
10971 	mutex_enter(&pptr->port_mutex);
10972 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10973 		mutex_exit(&pptr->port_mutex);
10974 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10975 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10976 		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10977 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10978 		    ddi_get_instance(tgt_dip));
10979 
10980 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10981 		return (DDI_FAILURE);
10982 	}
10983 
10984 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10985 	    FC_WWN_SIZE) == 0);
10986 	ASSERT(plun->lun_num == lun_num);
10987 
10988 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10989 
10990 	ptgt = plun->lun_tgt;
10991 
10992 	mutex_enter(&ptgt->tgt_mutex);
10993 	plun->lun_tgt_count++;
10994 	scsi_device_hba_private_set(sd, plun);
10995 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10996 	plun->lun_sd = sd;
10997 	mutex_exit(&ptgt->tgt_mutex);
10998 	mutex_exit(&pptr->port_mutex);
10999 
11000 	return (DDI_SUCCESS);
11001 }
11002 
11003 
11004 /*
11005  * called by the transport to do our own target initialization
11006  *
11007  * can acquire and release the global mutex
11008  */
11009 /* ARGSUSED */
11010 static int
11011 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11012     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11013 {
11014 	struct fcp_port	*pptr = (struct fcp_port *)
11015 	    hba_tran->tran_hba_private;
11016 	int			rval;
11017 
11018 	ASSERT(pptr != NULL);
11019 
11020 	/*
11021 	 * Child node is getting initialized.  Look at the mpxio component
11022 	 * type on the child device to see if this device is mpxio managed
11023 	 * or not.
11024 	 */
11025 	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11026 		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11027 	} else {
11028 		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11029 	}
11030 
11031 	return (rval);
11032 }
11033 
11034 
11035 /* ARGSUSED */
11036 static void
11037 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11038     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11039 {
11040 	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
11041 	struct fcp_tgt	*ptgt;
11042 
11043 	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11044 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
11045 	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11046 	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11047 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11048 
11049 	if (plun == NULL) {
11050 		return;
11051 	}
11052 	ptgt = plun->lun_tgt;
11053 
11054 	ASSERT(ptgt != NULL);
11055 
11056 	mutex_enter(&ptgt->tgt_mutex);
11057 	ASSERT(plun->lun_tgt_count > 0);
11058 
11059 	if (--plun->lun_tgt_count == 0) {
11060 		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11061 	}
11062 	plun->lun_sd = NULL;
11063 	mutex_exit(&ptgt->tgt_mutex);
11064 }
11065 
11066 /*
11067  *     Function: fcp_scsi_start
11068  *
11069  *  Description: This function is called by the target driver to request a
11070  *		 command to be sent.
11071  *
11072  *     Argument: *ap		SCSI address of the device.
11073  *		 *pkt		SCSI packet containing the cmd to send.
11074  *
11075  * Return Value: TRAN_ACCEPT
11076  *		 TRAN_BUSY
11077  *		 TRAN_BADPKT
11078  *		 TRAN_FATAL_ERROR
11079  */
11080 static int
11081 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11082 {
11083 	struct fcp_port	*pptr = ADDR2FCP(ap);
11084 	struct fcp_lun	*plun = ADDR2LUN(ap);
11085 	struct fcp_pkt	*cmd = PKT2CMD(pkt);
11086 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11087 	int			rval;
11088 
11089 	/* ensure command isn't already issued */
11090 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11091 
11092 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11093 	    fcp_trace, FCP_BUF_LEVEL_9, 0,
11094 	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11095 
11096 	/*
11097 	 * It is strange that we enter the fcp_port mutex and the target
11098 	 * mutex to check the lun state (which has a mutex of its own).
11099 	 */
11100 	mutex_enter(&pptr->port_mutex);
11101 	mutex_enter(&ptgt->tgt_mutex);
11102 
11103 	/*
11104 	 * If the device is offline and is not in the process of coming
11105 	 * online, fail the request.
11106 	 */
11107 
11108 	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11109 	    !(plun->lun_state & FCP_LUN_ONLINING)) {
11110 		mutex_exit(&ptgt->tgt_mutex);
11111 		mutex_exit(&pptr->port_mutex);
11112 
11113 		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11114 			pkt->pkt_reason = CMD_DEV_GONE;
11115 		}
11116 
11117 		return (TRAN_FATAL_ERROR);
11118 	}
11119 	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11120 
11121 	/*
11122 	 * If we are suspended, kernel is trying to dump, so don't
11123 	 * block, fail or defer requests - send them down right away.
11124 	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11125 	 * assume we have been suspended.  There is hardware such as
11126 	 * the v880 that doesn't do PM.	 Thus, the check for
11127 	 * ddi_in_panic.
11128 	 *
11129 	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11130 	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11131 	 * either the device will have gone away or changed and we can fail
11132 	 * the request, or we can proceed if the device didn't change.
11133 	 *
11134 	 * If the pd in the target or the packet is NULL it's probably
11135 	 * because the device has gone away, we allow the request to be
11136 	 * put on the internal queue here in case the device comes back within
11137 	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11138 	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11139 	 * could be NULL because the device was disappearing during or since
11140 	 * packet initialization.
11141 	 */
11142 
11143 	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11144 	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11145 	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11146 	    (ptgt->tgt_pd_handle == NULL) ||
11147 	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11148 		/*
11149 		 * If ((LUN is busy AND
11150 		 *	LUN not suspended AND
11151 		 *	The system is not in panic state) OR
11152 		 *	(The port is coming up))
11153 		 *
11154 		 * We check to see if the any of the flags FLAG_NOINTR or
11155 		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11156 		 * returned will be TRAN_BUSY.	If not, the request is queued.
11157 		 */
11158 		mutex_exit(&ptgt->tgt_mutex);
11159 		mutex_exit(&pptr->port_mutex);
11160 
11161 		/* see if using interrupts is allowed (so queueing'll work) */
11162 		if (pkt->pkt_flags & FLAG_NOINTR) {
11163 			pkt->pkt_resid = 0;
11164 			return (TRAN_BUSY);
11165 		}
11166 		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11167 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11168 			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11169 			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11170 			return (TRAN_BUSY);
11171 		}
11172 #ifdef	DEBUG
11173 		mutex_enter(&pptr->port_pkt_mutex);
11174 		pptr->port_npkts++;
11175 		mutex_exit(&pptr->port_pkt_mutex);
11176 #endif /* DEBUG */
11177 
11178 		/* got queue up the pkt for later */
11179 		fcp_queue_pkt(pptr, cmd);
11180 		return (TRAN_ACCEPT);
11181 	}
11182 	cmd->cmd_state = FCP_PKT_ISSUED;
11183 
11184 	mutex_exit(&ptgt->tgt_mutex);
11185 	mutex_exit(&pptr->port_mutex);
11186 
11187 	/*
11188 	 * Now that we released the mutexes, what was protected by them can
11189 	 * change.
11190 	 */
11191 
11192 	/*
11193 	 * If there is a reconfiguration in progress, wait for it to complete.
11194 	 */
11195 	fcp_reconfig_wait(pptr);
11196 
11197 	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11198 	    pkt->pkt_time : 0;
11199 
11200 	/* prepare the packet */
11201 
11202 	fcp_prepare_pkt(pptr, cmd, plun);
11203 
11204 	if (cmd->cmd_pkt->pkt_time) {
11205 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11206 	} else {
11207 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11208 	}
11209 
11210 	/*
11211 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11212 	 * have to do polled I/O
11213 	 */
11214 	if (pkt->pkt_flags & FLAG_NOINTR) {
11215 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11216 		return (fcp_dopoll(pptr, cmd));
11217 	}
11218 
11219 #ifdef	DEBUG
11220 	mutex_enter(&pptr->port_pkt_mutex);
11221 	pptr->port_npkts++;
11222 	mutex_exit(&pptr->port_pkt_mutex);
11223 #endif /* DEBUG */
11224 
11225 	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11226 	if (rval == FC_SUCCESS) {
11227 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11228 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11229 		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11230 		return (TRAN_ACCEPT);
11231 	}
11232 
11233 	cmd->cmd_state = FCP_PKT_IDLE;
11234 
11235 #ifdef	DEBUG
11236 	mutex_enter(&pptr->port_pkt_mutex);
11237 	pptr->port_npkts--;
11238 	mutex_exit(&pptr->port_pkt_mutex);
11239 #endif /* DEBUG */
11240 
11241 	/*
11242 	 * For lack of clearer definitions, choose
11243 	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11244 	 */
11245 
11246 	if (rval == FC_TRAN_BUSY) {
11247 		pkt->pkt_resid = 0;
11248 		rval = TRAN_BUSY;
11249 	} else {
11250 		mutex_enter(&ptgt->tgt_mutex);
11251 		if (plun->lun_state & FCP_LUN_OFFLINE) {
11252 			child_info_t	*cip;
11253 
11254 			mutex_enter(&plun->lun_mutex);
11255 			cip = plun->lun_cip;
11256 			mutex_exit(&plun->lun_mutex);
11257 
11258 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11259 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11260 			    "fcp_transport failed 2 for %x: %x; dip=%p",
11261 			    plun->lun_tgt->tgt_d_id, rval, cip);
11262 
11263 			rval = TRAN_FATAL_ERROR;
11264 		} else {
11265 			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11266 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11267 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11268 				    "fcp_scsi_start: FC_BUSY for pkt %p",
11269 				    pkt);
11270 				rval = TRAN_BUSY;
11271 			} else {
11272 				rval = TRAN_ACCEPT;
11273 				fcp_queue_pkt(pptr, cmd);
11274 			}
11275 		}
11276 		mutex_exit(&ptgt->tgt_mutex);
11277 	}
11278 
11279 	return (rval);
11280 }
11281 
11282 /*
11283  * called by the transport to abort a packet
11284  */
11285 /*ARGSUSED*/
11286 static int
11287 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11288 {
11289 	int tgt_cnt;
11290 	struct fcp_port		*pptr = ADDR2FCP(ap);
11291 	struct fcp_lun	*plun = ADDR2LUN(ap);
11292 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11293 
11294 	if (pkt == NULL) {
11295 		if (ptgt) {
11296 			mutex_enter(&ptgt->tgt_mutex);
11297 			tgt_cnt = ptgt->tgt_change_cnt;
11298 			mutex_exit(&ptgt->tgt_mutex);
11299 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11300 			return (TRUE);
11301 		}
11302 	}
11303 	return (FALSE);
11304 }
11305 
11306 
11307 /*
11308  * Perform reset
11309  */
11310 int
11311 fcp_scsi_reset(struct scsi_address *ap, int level)
11312 {
11313 	int			rval = 0;
11314 	struct fcp_port		*pptr = ADDR2FCP(ap);
11315 	struct fcp_lun	*plun = ADDR2LUN(ap);
11316 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11317 
11318 	if (level == RESET_ALL) {
11319 		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11320 			rval = 1;
11321 		}
11322 	} else if (level == RESET_TARGET || level == RESET_LUN) {
11323 		/*
11324 		 * If we are in the middle of discovery, return
11325 		 * SUCCESS as this target will be rediscovered
11326 		 * anyway
11327 		 */
11328 		mutex_enter(&ptgt->tgt_mutex);
11329 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11330 			mutex_exit(&ptgt->tgt_mutex);
11331 			return (1);
11332 		}
11333 		mutex_exit(&ptgt->tgt_mutex);
11334 
11335 		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11336 			rval = 1;
11337 		}
11338 	}
11339 	return (rval);
11340 }
11341 
11342 
11343 /*
11344  * called by the framework to get a SCSI capability
11345  */
11346 static int
11347 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11348 {
11349 	return (fcp_commoncap(ap, cap, 0, whom, 0));
11350 }
11351 
11352 
11353 /*
11354  * called by the framework to set a SCSI capability
11355  */
11356 static int
11357 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11358 {
11359 	return (fcp_commoncap(ap, cap, value, whom, 1));
11360 }
11361 
11362 /*
11363  *     Function: fcp_pkt_setup
11364  *
11365  *  Description: This function sets up the scsi_pkt structure passed by the
11366  *		 caller. This function assumes fcp_pkt_constructor has been
11367  *		 called previously for the packet passed by the caller.	 If
11368  *		 successful this call will have the following results:
11369  *
11370  *		   - The resources needed that will be constant through out
11371  *		     the whole transaction are allocated.
11372  *		   - The fields that will be constant through out the whole
11373  *		     transaction are initialized.
11374  *		   - The scsi packet will be linked to the LUN structure
11375  *		     addressed by the transaction.
11376  *
11377  *     Argument:
11378  *		 *pkt		Pointer to a scsi_pkt structure.
11379  *		 callback
11380  *		 arg
11381  *
11382  * Return Value: 0	Success
11383  *		 !0	Failure
11384  *
11385  *	Context: Kernel context or interrupt context
11386  */
11387 /* ARGSUSED */
11388 static int
11389 fcp_pkt_setup(struct scsi_pkt *pkt,
11390     int (*callback)(caddr_t arg),
11391     caddr_t arg)
11392 {
11393 	struct fcp_pkt	*cmd;
11394 	struct fcp_port	*pptr;
11395 	struct fcp_lun	*plun;
11396 	struct fcp_tgt	*ptgt;
11397 	int		kf;
11398 	fc_packet_t	*fpkt;
11399 	fc_frame_hdr_t	*hp;
11400 
11401 	pptr = ADDR2FCP(&pkt->pkt_address);
11402 	plun = ADDR2LUN(&pkt->pkt_address);
11403 	ptgt = plun->lun_tgt;
11404 
11405 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11406 	fpkt = cmd->cmd_fp_pkt;
11407 
11408 	/*
11409 	 * this request is for dma allocation only
11410 	 */
11411 	/*
11412 	 * First step of fcp_scsi_init_pkt: pkt allocation
11413 	 * We determine if the caller is willing to wait for the
11414 	 * resources.
11415 	 */
11416 	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11417 
11418 	/*
11419 	 * Selective zeroing of the pkt.
11420 	 */
11421 	cmd->cmd_back = NULL;
11422 	cmd->cmd_next = NULL;
11423 
11424 	/*
11425 	 * Zero out fcp command
11426 	 */
11427 	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11428 
11429 	cmd->cmd_state = FCP_PKT_IDLE;
11430 
11431 	fpkt = cmd->cmd_fp_pkt;
11432 	fpkt->pkt_data_acc = NULL;
11433 
11434 	/*
11435 	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11436 	 * could be destroyed.	We need fail pkt_setup.
11437 	 */
11438 	if (pptr->port_state & FCP_STATE_OFFLINE) {
11439 		return (-1);
11440 	}
11441 
11442 	mutex_enter(&ptgt->tgt_mutex);
11443 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11444 
11445 	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11446 	    != FC_SUCCESS) {
11447 		mutex_exit(&ptgt->tgt_mutex);
11448 		return (-1);
11449 	}
11450 
11451 	mutex_exit(&ptgt->tgt_mutex);
11452 
11453 	/* Fill in the Fabric Channel Header */
11454 	hp = &fpkt->pkt_cmd_fhdr;
11455 	hp->r_ctl = R_CTL_COMMAND;
11456 	hp->rsvd = 0;
11457 	hp->type = FC_TYPE_SCSI_FCP;
11458 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11459 	hp->seq_id = 0;
11460 	hp->df_ctl  = 0;
11461 	hp->seq_cnt = 0;
11462 	hp->ox_id = 0xffff;
11463 	hp->rx_id = 0xffff;
11464 	hp->ro = 0;
11465 
11466 	/*
11467 	 * A doubly linked list (cmd_forw, cmd_back) is built
11468 	 * out of every allocated packet on a per-lun basis
11469 	 *
11470 	 * The packets are maintained in the list so as to satisfy
11471 	 * scsi_abort() requests. At present (which is unlikely to
11472 	 * change in the future) nobody performs a real scsi_abort
11473 	 * in the SCSI target drivers (as they don't keep the packets
11474 	 * after doing scsi_transport - so they don't know how to
11475 	 * abort a packet other than sending a NULL to abort all
11476 	 * outstanding packets)
11477 	 */
11478 	mutex_enter(&plun->lun_mutex);
11479 	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11480 		plun->lun_pkt_head->cmd_back = cmd;
11481 	} else {
11482 		plun->lun_pkt_tail = cmd;
11483 	}
11484 	plun->lun_pkt_head = cmd;
11485 	mutex_exit(&plun->lun_mutex);
11486 	return (0);
11487 }
11488 
11489 /*
11490  *     Function: fcp_pkt_teardown
11491  *
11492  *  Description: This function releases a scsi_pkt structure and all the
11493  *		 resources attached to it.
11494  *
11495  *     Argument: *pkt		Pointer to a scsi_pkt structure.
11496  *
11497  * Return Value: None
11498  *
11499  *	Context: User, Kernel or Interrupt context.
11500  */
11501 static void
11502 fcp_pkt_teardown(struct scsi_pkt *pkt)
11503 {
11504 	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11505 	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11506 	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11507 
11508 	/*
11509 	 * Remove the packet from the per-lun list
11510 	 */
11511 	mutex_enter(&plun->lun_mutex);
11512 	if (cmd->cmd_back) {
11513 		ASSERT(cmd != plun->lun_pkt_head);
11514 		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11515 	} else {
11516 		ASSERT(cmd == plun->lun_pkt_head);
11517 		plun->lun_pkt_head = cmd->cmd_forw;
11518 	}
11519 
11520 	if (cmd->cmd_forw) {
11521 		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11522 	} else {
11523 		ASSERT(cmd == plun->lun_pkt_tail);
11524 		plun->lun_pkt_tail = cmd->cmd_back;
11525 	}
11526 
11527 	mutex_exit(&plun->lun_mutex);
11528 
11529 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11530 }
11531 
11532 /*
11533  * Routine for reset notification setup, to register or cancel.
11534  * This function is called by SCSA
11535  */
11536 /*ARGSUSED*/
11537 static int
11538 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11539     void (*callback)(caddr_t), caddr_t arg)
11540 {
11541 	struct fcp_port *pptr = ADDR2FCP(ap);
11542 
11543 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11544 	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11545 }
11546 
11547 
11548 static int
11549 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11550     ddi_eventcookie_t *event_cookiep)
11551 {
11552 	struct fcp_port *pptr = fcp_dip2port(dip);
11553 
11554 	if (pptr == NULL) {
11555 		return (DDI_FAILURE);
11556 	}
11557 
11558 	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11559 	    event_cookiep, NDI_EVENT_NOPASS));
11560 }
11561 
11562 
11563 static int
11564 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11565     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11566     ddi_callback_id_t *cb_id)
11567 {
11568 	struct fcp_port *pptr = fcp_dip2port(dip);
11569 
11570 	if (pptr == NULL) {
11571 		return (DDI_FAILURE);
11572 	}
11573 
11574 	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11575 	    eventid, callback, arg, NDI_SLEEP, cb_id));
11576 }
11577 
11578 
11579 static int
11580 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11581 {
11582 
11583 	struct fcp_port *pptr = fcp_dip2port(dip);
11584 
11585 	if (pptr == NULL) {
11586 		return (DDI_FAILURE);
11587 	}
11588 	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11589 }
11590 
11591 
11592 /*
11593  * called by the transport to post an event
11594  */
11595 static int
11596 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11597     ddi_eventcookie_t eventid, void *impldata)
11598 {
11599 	struct fcp_port *pptr = fcp_dip2port(dip);
11600 
11601 	if (pptr == NULL) {
11602 		return (DDI_FAILURE);
11603 	}
11604 
11605 	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11606 	    eventid, impldata));
11607 }
11608 
11609 
11610 /*
11611  * A target in in many cases in Fibre Channel has a one to one relation
11612  * with a port identifier (which is also known as D_ID and also as AL_PA
11613  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11614  * will most likely result in resetting all LUNs (which means a reset will
11615  * occur on all the SCSI devices connected at the other end of the bridge)
11616  * That is the latest favorite topic for discussion, for, one can debate as
11617  * hot as one likes and come up with arguably a best solution to one's
11618  * satisfaction
11619  *
11620  * To stay on track and not digress much, here are the problems stated
11621  * briefly:
11622  *
11623  *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11624  *	target drivers use RESET_TARGET even if their instance is on a
11625  *	LUN. Doesn't that sound a bit broken ?
11626  *
11627  *	FCP SCSI (the current spec) only defines RESET TARGET in the
11628  *	control fields of an FCP_CMND structure. It should have been
11629  *	fixed right there, giving flexibility to the initiators to
11630  *	minimize havoc that could be caused by resetting a target.
11631  */
11632 static int
11633 fcp_reset_target(struct scsi_address *ap, int level)
11634 {
11635 	int			rval = FC_FAILURE;
11636 	char			lun_id[25];
11637 	struct fcp_port		*pptr = ADDR2FCP(ap);
11638 	struct fcp_lun	*plun = ADDR2LUN(ap);
11639 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11640 	struct scsi_pkt		*pkt;
11641 	struct fcp_pkt	*cmd;
11642 	struct fcp_rsp		*rsp;
11643 	uint32_t		tgt_cnt;
11644 	struct fcp_rsp_info	*rsp_info;
11645 	struct fcp_reset_elem	*p;
11646 	int			bval;
11647 
11648 	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11649 	    KM_NOSLEEP)) == NULL) {
11650 		return (rval);
11651 	}
11652 
11653 	mutex_enter(&ptgt->tgt_mutex);
11654 	if (level == RESET_TARGET) {
11655 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11656 			mutex_exit(&ptgt->tgt_mutex);
11657 			kmem_free(p, sizeof (struct fcp_reset_elem));
11658 			return (rval);
11659 		}
11660 		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11661 		(void) strcpy(lun_id, " ");
11662 	} else {
11663 		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11664 			mutex_exit(&ptgt->tgt_mutex);
11665 			kmem_free(p, sizeof (struct fcp_reset_elem));
11666 			return (rval);
11667 		}
11668 		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11669 
11670 		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11671 	}
11672 	tgt_cnt = ptgt->tgt_change_cnt;
11673 
11674 	mutex_exit(&ptgt->tgt_mutex);
11675 
11676 	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11677 	    0, 0, NULL, 0)) == NULL) {
11678 		kmem_free(p, sizeof (struct fcp_reset_elem));
11679 		mutex_enter(&ptgt->tgt_mutex);
11680 		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11681 		mutex_exit(&ptgt->tgt_mutex);
11682 		return (rval);
11683 	}
11684 	pkt->pkt_time = FCP_POLL_TIMEOUT;
11685 
11686 	/* fill in cmd part of packet */
11687 	cmd = PKT2CMD(pkt);
11688 	if (level == RESET_TARGET) {
11689 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11690 	} else {
11691 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11692 	}
11693 	cmd->cmd_fp_pkt->pkt_comp = NULL;
11694 	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11695 
11696 	/* prepare a packet for transport */
11697 	fcp_prepare_pkt(pptr, cmd, plun);
11698 
11699 	if (cmd->cmd_pkt->pkt_time) {
11700 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11701 	} else {
11702 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11703 	}
11704 
11705 	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11706 	bval = fcp_dopoll(pptr, cmd);
11707 	fc_ulp_idle_port(pptr->port_fp_handle);
11708 
11709 	/* submit the packet */
11710 	if (bval == TRAN_ACCEPT) {
11711 		int error = 3;
11712 
11713 		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11714 		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11715 		    sizeof (struct fcp_rsp));
11716 
11717 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11718 			if (fcp_validate_fcp_response(rsp, pptr) ==
11719 			    FC_SUCCESS) {
11720 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11721 					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11722 					    sizeof (struct fcp_rsp), rsp_info,
11723 					    cmd->cmd_fp_pkt->pkt_resp_acc,
11724 					    sizeof (struct fcp_rsp_info));
11725 				}
11726 				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11727 					rval = FC_SUCCESS;
11728 					error = 0;
11729 				} else {
11730 					error = 1;
11731 				}
11732 			} else {
11733 				error = 2;
11734 			}
11735 		}
11736 
11737 		switch (error) {
11738 		case 0:
11739 			fcp_log(CE_WARN, pptr->port_dip,
11740 			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11741 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11742 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11743 			break;
11744 
11745 		case 1:
11746 			fcp_log(CE_WARN, pptr->port_dip,
11747 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11748 			    " response code=%x",
11749 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11750 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11751 			    rsp_info->rsp_code);
11752 			break;
11753 
11754 		case 2:
11755 			fcp_log(CE_WARN, pptr->port_dip,
11756 			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11757 			    " Bad FCP response values: rsvd1=%x,"
11758 			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11759 			    " rsplen=%x, senselen=%x",
11760 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11761 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11762 			    rsp->reserved_0, rsp->reserved_1,
11763 			    rsp->fcp_u.fcp_status.reserved_0,
11764 			    rsp->fcp_u.fcp_status.reserved_1,
11765 			    rsp->fcp_response_len, rsp->fcp_sense_len);
11766 			break;
11767 
11768 		default:
11769 			fcp_log(CE_WARN, pptr->port_dip,
11770 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11771 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11772 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11773 			break;
11774 		}
11775 	}
11776 	scsi_destroy_pkt(pkt);
11777 
11778 	if (rval == FC_FAILURE) {
11779 		mutex_enter(&ptgt->tgt_mutex);
11780 		if (level == RESET_TARGET) {
11781 			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11782 		} else {
11783 			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11784 		}
11785 		mutex_exit(&ptgt->tgt_mutex);
11786 		kmem_free(p, sizeof (struct fcp_reset_elem));
11787 		return (rval);
11788 	}
11789 
11790 	mutex_enter(&pptr->port_mutex);
11791 	if (level == RESET_TARGET) {
11792 		p->tgt = ptgt;
11793 		p->lun = NULL;
11794 	} else {
11795 		p->tgt = NULL;
11796 		p->lun = plun;
11797 	}
11798 	p->tgt = ptgt;
11799 	p->tgt_cnt = tgt_cnt;
11800 	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11801 	p->next = pptr->port_reset_list;
11802 	pptr->port_reset_list = p;
11803 
11804 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11805 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11806 	    "Notify ssd of the reset to reinstate the reservations");
11807 
11808 	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11809 	    &pptr->port_reset_notify_listf);
11810 
11811 	mutex_exit(&pptr->port_mutex);
11812 
11813 	return (rval);
11814 }
11815 
11816 
11817 /*
11818  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11819  * SCSI capabilities
11820  */
11821 /* ARGSUSED */
11822 static int
11823 fcp_commoncap(struct scsi_address *ap, char *cap,
11824     int val, int tgtonly, int doset)
11825 {
11826 	struct fcp_port		*pptr = ADDR2FCP(ap);
11827 	struct fcp_lun	*plun = ADDR2LUN(ap);
11828 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11829 	int			cidx;
11830 	int			rval = FALSE;
11831 
11832 	if (cap == (char *)0) {
11833 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11834 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11835 		    "fcp_commoncap: invalid arg");
11836 		return (rval);
11837 	}
11838 
11839 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11840 		return (UNDEFINED);
11841 	}
11842 
11843 	/*
11844 	 * Process setcap request.
11845 	 */
11846 	if (doset) {
11847 		/*
11848 		 * At present, we can only set binary (0/1) values
11849 		 */
11850 		switch (cidx) {
11851 		case SCSI_CAP_ARQ:
11852 			if (val == 0) {
11853 				rval = FALSE;
11854 			} else {
11855 				rval = TRUE;
11856 			}
11857 			break;
11858 
11859 		case SCSI_CAP_LUN_RESET:
11860 			if (val) {
11861 				plun->lun_cap |= FCP_LUN_CAP_RESET;
11862 			} else {
11863 				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11864 			}
11865 			rval = TRUE;
11866 			break;
11867 
11868 		case SCSI_CAP_SECTOR_SIZE:
11869 			rval = TRUE;
11870 			break;
11871 		default:
11872 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11873 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11874 			    "fcp_setcap: unsupported %d", cidx);
11875 			rval = UNDEFINED;
11876 			break;
11877 		}
11878 
11879 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11880 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11881 		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11882 		    "0x%x/0x%x/0x%x/%d",
11883 		    cap, val, tgtonly, doset, rval);
11884 
11885 	} else {
11886 		/*
11887 		 * Process getcap request.
11888 		 */
11889 		switch (cidx) {
11890 		case SCSI_CAP_DMA_MAX:
11891 			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11892 
11893 			/*
11894 			 * Need to make an adjustment qlc is uint_t 64
11895 			 * st is int, so we will make the adjustment here
11896 			 * being as nobody wants to touch this.
11897 			 * It still leaves the max single block length
11898 			 * of 2 gig. This should last .
11899 			 */
11900 
11901 			if (rval == -1) {
11902 				rval = MAX_INT_DMA;
11903 			}
11904 
11905 			break;
11906 
11907 		case SCSI_CAP_INITIATOR_ID:
11908 			rval = pptr->port_id;
11909 			break;
11910 
11911 		case SCSI_CAP_ARQ:
11912 		case SCSI_CAP_RESET_NOTIFICATION:
11913 		case SCSI_CAP_TAGGED_QING:
11914 			rval = TRUE;
11915 			break;
11916 
11917 		case SCSI_CAP_SCSI_VERSION:
11918 			rval = 3;
11919 			break;
11920 
11921 		case SCSI_CAP_INTERCONNECT_TYPE:
11922 			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11923 			    (ptgt->tgt_hard_addr == 0)) {
11924 				rval = INTERCONNECT_FABRIC;
11925 			} else {
11926 				rval = INTERCONNECT_FIBRE;
11927 			}
11928 			break;
11929 
11930 		case SCSI_CAP_LUN_RESET:
11931 			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11932 			    TRUE : FALSE;
11933 			break;
11934 
11935 		default:
11936 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11937 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11938 			    "fcp_getcap: unsupported %d", cidx);
11939 			rval = UNDEFINED;
11940 			break;
11941 		}
11942 
11943 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11944 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11945 		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11946 		    "0x%x/0x%x/0x%x/%d",
11947 		    cap, val, tgtonly, doset, rval);
11948 	}
11949 
11950 	return (rval);
11951 }
11952 
11953 /*
11954  * called by the transport to get the port-wwn and lun
11955  * properties of this device, and to create a "name" based on them
11956  *
11957  * these properties don't exist on sun4m
11958  *
11959  * return 1 for success else return 0
11960  */
11961 /* ARGSUSED */
11962 static int
11963 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11964 {
11965 	int			i;
11966 	int			*lun;
11967 	int			numChars;
11968 	uint_t			nlun;
11969 	uint_t			count;
11970 	uint_t			nbytes;
11971 	uchar_t			*bytes;
11972 	uint16_t		lun_num;
11973 	uint32_t		tgt_id;
11974 	char			**conf_wwn;
11975 	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11976 	uchar_t			barray[FC_WWN_SIZE];
11977 	dev_info_t		*tgt_dip;
11978 	struct fcp_tgt	*ptgt;
11979 	struct fcp_port	*pptr;
11980 	struct fcp_lun	*plun;
11981 
11982 	ASSERT(sd != NULL);
11983 	ASSERT(name != NULL);
11984 
11985 	tgt_dip = sd->sd_dev;
11986 	pptr = ddi_get_soft_state(fcp_softstate,
11987 	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11988 	if (pptr == NULL) {
11989 		return (0);
11990 	}
11991 
11992 	ASSERT(tgt_dip != NULL);
11993 
11994 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11995 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11996 	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11997 		name[0] = '\0';
11998 		return (0);
11999 	}
12000 
12001 	if (nlun == 0) {
12002 		ddi_prop_free(lun);
12003 		return (0);
12004 	}
12005 
12006 	lun_num = lun[0];
12007 	ddi_prop_free(lun);
12008 
12009 	/*
12010 	 * Lookup for .conf WWN property
12011 	 */
12012 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12013 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12014 	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12015 		ASSERT(count >= 1);
12016 
12017 		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12018 		ddi_prop_free(conf_wwn);
12019 		mutex_enter(&pptr->port_mutex);
12020 		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12021 			mutex_exit(&pptr->port_mutex);
12022 			return (0);
12023 		}
12024 		ptgt = plun->lun_tgt;
12025 		mutex_exit(&pptr->port_mutex);
12026 
12027 		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12028 		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12029 
12030 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12031 		    ptgt->tgt_hard_addr != 0) {
12032 			tgt_id = (uint32_t)fcp_alpa_to_switch[
12033 			    ptgt->tgt_hard_addr];
12034 		} else {
12035 			tgt_id = ptgt->tgt_d_id;
12036 		}
12037 
12038 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12039 		    TARGET_PROP, tgt_id);
12040 	}
12041 
12042 	/* get the our port-wwn property */
12043 	bytes = NULL;
12044 	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12045 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12046 	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12047 		if (bytes != NULL) {
12048 			ddi_prop_free(bytes);
12049 		}
12050 		return (0);
12051 	}
12052 
12053 	for (i = 0; i < FC_WWN_SIZE; i++) {
12054 		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12055 	}
12056 
12057 	/* Stick in the address of the form "wWWN,LUN" */
12058 	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12059 
12060 	ASSERT(numChars < len);
12061 	if (numChars >= len) {
12062 		fcp_log(CE_WARN, pptr->port_dip,
12063 		    "!fcp_scsi_get_name: "
12064 		    "name parameter length too small, it needs to be %d",
12065 		    numChars+1);
12066 	}
12067 
12068 	ddi_prop_free(bytes);
12069 
12070 	return (1);
12071 }
12072 
12073 
12074 /*
12075  * called by the transport to get the SCSI target id value, returning
12076  * it in "name"
12077  *
12078  * this isn't needed/used on sun4m
12079  *
12080  * return 1 for success else return 0
12081  */
12082 /* ARGSUSED */
12083 static int
12084 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12085 {
12086 	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
12087 	struct fcp_tgt	*ptgt;
12088 	int    numChars;
12089 
12090 	if (plun == NULL) {
12091 		return (0);
12092 	}
12093 
12094 	if ((ptgt = plun->lun_tgt) == NULL) {
12095 		return (0);
12096 	}
12097 
12098 	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12099 
12100 	ASSERT(numChars < len);
12101 	if (numChars >= len) {
12102 		fcp_log(CE_WARN, NULL,
12103 		    "!fcp_scsi_get_bus_addr: "
12104 		    "name parameter length too small, it needs to be %d",
12105 		    numChars+1);
12106 	}
12107 
12108 	return (1);
12109 }
12110 
12111 
12112 /*
12113  * called internally to reset the link where the specified port lives
12114  */
12115 static int
12116 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12117 {
12118 	la_wwn_t		wwn;
12119 	struct fcp_lun	*plun;
12120 	struct fcp_tgt	*ptgt;
12121 
12122 	/* disable restart of lip if we're suspended */
12123 	mutex_enter(&pptr->port_mutex);
12124 
12125 	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12126 	    FCP_STATE_POWER_DOWN)) {
12127 		mutex_exit(&pptr->port_mutex);
12128 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12129 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12130 		    "fcp_linkreset, fcp%d: link reset "
12131 		    "disabled due to DDI_SUSPEND",
12132 		    ddi_get_instance(pptr->port_dip));
12133 		return (FC_FAILURE);
12134 	}
12135 
12136 	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12137 		mutex_exit(&pptr->port_mutex);
12138 		return (FC_SUCCESS);
12139 	}
12140 
12141 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12142 	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12143 
12144 	/*
12145 	 * If ap == NULL assume local link reset.
12146 	 */
12147 	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12148 		plun = ADDR2LUN(ap);
12149 		ptgt = plun->lun_tgt;
12150 		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12151 	} else {
12152 		bzero((caddr_t)&wwn, sizeof (wwn));
12153 	}
12154 	mutex_exit(&pptr->port_mutex);
12155 
12156 	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12157 }
12158 
12159 
12160 /*
12161  * called from fcp_port_attach() to resume a port
12162  * return DDI_* success/failure status
12163  * acquires and releases the global mutex
12164  * acquires and releases the port mutex
12165  */
12166 /*ARGSUSED*/
12167 
12168 static int
12169 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12170     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12171 {
12172 	int			res = DDI_FAILURE; /* default result */
12173 	struct fcp_port	*pptr;		/* port state ptr */
12174 	uint32_t		alloc_cnt;
12175 	uint32_t		max_cnt;
12176 	fc_portmap_t		*tmp_list = NULL;
12177 
12178 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12179 	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12180 	    instance);
12181 
12182 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12183 		cmn_err(CE_WARN, "fcp: bad soft state");
12184 		return (res);
12185 	}
12186 
12187 	mutex_enter(&pptr->port_mutex);
12188 	switch (cmd) {
12189 	case FC_CMD_RESUME:
12190 		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12191 		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12192 		break;
12193 
12194 	case FC_CMD_POWER_UP:
12195 		/*
12196 		 * If the port is DDI_SUSPENded, defer rediscovery
12197 		 * until DDI_RESUME occurs
12198 		 */
12199 		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12200 			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12201 			mutex_exit(&pptr->port_mutex);
12202 			return (DDI_SUCCESS);
12203 		}
12204 		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12205 	}
12206 	pptr->port_id = s_id;
12207 	pptr->port_state = FCP_STATE_INIT;
12208 	mutex_exit(&pptr->port_mutex);
12209 
12210 	/*
12211 	 * Make a copy of ulp_port_info as fctl allocates
12212 	 * a temp struct.
12213 	 */
12214 	(void) fcp_cp_pinfo(pptr, pinfo);
12215 
12216 	mutex_enter(&fcp_global_mutex);
12217 	if (fcp_watchdog_init++ == 0) {
12218 		fcp_watchdog_tick = fcp_watchdog_timeout *
12219 		    drv_usectohz(1000000);
12220 		fcp_watchdog_id = timeout(fcp_watch,
12221 		    NULL, fcp_watchdog_tick);
12222 	}
12223 	mutex_exit(&fcp_global_mutex);
12224 
12225 	/*
12226 	 * Handle various topologies and link states.
12227 	 */
12228 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12229 	case FC_STATE_OFFLINE:
12230 		/*
12231 		 * Wait for ONLINE, at which time a state
12232 		 * change will cause a statec_callback
12233 		 */
12234 		res = DDI_SUCCESS;
12235 		break;
12236 
12237 	case FC_STATE_ONLINE:
12238 
12239 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12240 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12241 			res = DDI_SUCCESS;
12242 			break;
12243 		}
12244 
12245 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12246 		    !fcp_enable_auto_configuration) {
12247 			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12248 			if (tmp_list == NULL) {
12249 				if (!alloc_cnt) {
12250 					res = DDI_SUCCESS;
12251 				}
12252 				break;
12253 			}
12254 			max_cnt = alloc_cnt;
12255 		} else {
12256 			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12257 
12258 			alloc_cnt = FCP_MAX_DEVICES;
12259 
12260 			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12261 			    (sizeof (fc_portmap_t)) * alloc_cnt,
12262 			    KM_NOSLEEP)) == NULL) {
12263 				fcp_log(CE_WARN, pptr->port_dip,
12264 				    "!fcp%d: failed to allocate portmap",
12265 				    instance);
12266 				break;
12267 			}
12268 
12269 			max_cnt = alloc_cnt;
12270 			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12271 			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12272 			    FC_SUCCESS) {
12273 				caddr_t msg;
12274 
12275 				(void) fc_ulp_error(res, &msg);
12276 
12277 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12278 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12279 				    "resume failed getportmap: reason=0x%x",
12280 				    res);
12281 
12282 				fcp_log(CE_WARN, pptr->port_dip,
12283 				    "!failed to get port map : %s", msg);
12284 				break;
12285 			}
12286 			if (max_cnt > alloc_cnt) {
12287 				alloc_cnt = max_cnt;
12288 			}
12289 		}
12290 
12291 		/*
12292 		 * do the SCSI device discovery and create
12293 		 * the devinfos
12294 		 */
12295 		fcp_statec_callback(ulph, pptr->port_fp_handle,
12296 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12297 		    max_cnt, pptr->port_id);
12298 
12299 		res = DDI_SUCCESS;
12300 		break;
12301 
12302 	default:
12303 		fcp_log(CE_WARN, pptr->port_dip,
12304 		    "!fcp%d: invalid port state at attach=0x%x",
12305 		    instance, pptr->port_phys_state);
12306 
12307 		mutex_enter(&pptr->port_mutex);
12308 		pptr->port_phys_state = FCP_STATE_OFFLINE;
12309 		mutex_exit(&pptr->port_mutex);
12310 		res = DDI_SUCCESS;
12311 
12312 		break;
12313 	}
12314 
12315 	if (tmp_list != NULL) {
12316 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12317 	}
12318 
12319 	return (res);
12320 }
12321 
12322 
12323 static void
12324 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12325 {
12326 	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12327 	pptr->port_dip = pinfo->port_dip;
12328 	pptr->port_fp_handle = pinfo->port_handle;
12329 	if (pinfo->port_acc_attr != NULL) {
12330 		/*
12331 		 * FCA supports DMA
12332 		 */
12333 		pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12334 		pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12335 		pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12336 		pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12337 	}
12338 	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12339 	pptr->port_max_exch = pinfo->port_fca_max_exch;
12340 	pptr->port_phys_state = pinfo->port_state;
12341 	pptr->port_topology = pinfo->port_flags;
12342 	pptr->port_reset_action = pinfo->port_reset_action;
12343 	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12344 	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12345 	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12346 	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12347 
12348 	/* Clear FMA caps to avoid fm-capability ereport */
12349 	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12350 		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12351 	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12352 		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12353 	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12354 		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12355 }
12356 
12357 /*
12358  * If the elements wait field is set to 1 then
12359  * another thread is waiting for the operation to complete. Once
12360  * it is complete, the waiting thread is signaled and the element is
12361  * freed by the waiting thread. If the elements wait field is set to 0
12362  * the element is freed.
12363  */
12364 static void
12365 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12366 {
12367 	ASSERT(elem != NULL);
12368 	mutex_enter(&elem->mutex);
12369 	elem->result = result;
12370 	if (elem->wait) {
12371 		elem->wait = 0;
12372 		cv_signal(&elem->cv);
12373 		mutex_exit(&elem->mutex);
12374 	} else {
12375 		mutex_exit(&elem->mutex);
12376 		cv_destroy(&elem->cv);
12377 		mutex_destroy(&elem->mutex);
12378 		kmem_free(elem, sizeof (struct fcp_hp_elem));
12379 	}
12380 }
12381 
12382 /*
12383  * This function is invoked from the taskq thread to allocate
12384  * devinfo nodes and to online/offline them.
12385  */
12386 static void
12387 fcp_hp_task(void *arg)
12388 {
12389 	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12390 	struct fcp_lun	*plun = elem->lun;
12391 	struct fcp_port		*pptr = elem->port;
12392 	int			result;
12393 
12394 	ASSERT(elem->what == FCP_ONLINE ||
12395 	    elem->what == FCP_OFFLINE ||
12396 	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12397 	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12398 
12399 	mutex_enter(&pptr->port_mutex);
12400 	mutex_enter(&plun->lun_mutex);
12401 	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12402 	    plun->lun_event_count != elem->event_cnt) ||
12403 	    pptr->port_state & (FCP_STATE_SUSPENDED |
12404 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12405 		mutex_exit(&plun->lun_mutex);
12406 		mutex_exit(&pptr->port_mutex);
12407 		fcp_process_elem(elem, NDI_FAILURE);
12408 		return;
12409 	}
12410 	mutex_exit(&plun->lun_mutex);
12411 	mutex_exit(&pptr->port_mutex);
12412 
12413 	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12414 	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12415 	fcp_process_elem(elem, result);
12416 }
12417 
12418 
12419 static child_info_t *
12420 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12421     int tcount)
12422 {
12423 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12424 
12425 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12426 		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12427 
12428 		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12429 		/*
12430 		 * Child has not been created yet. Create the child device
12431 		 * based on the per-Lun flags.
12432 		 */
12433 		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12434 			plun->lun_cip =
12435 			    CIP(fcp_create_dip(plun, lcount, tcount));
12436 			plun->lun_mpxio = 0;
12437 		} else {
12438 			plun->lun_cip =
12439 			    CIP(fcp_create_pip(plun, lcount, tcount));
12440 			plun->lun_mpxio = 1;
12441 		}
12442 	} else {
12443 		plun->lun_cip = cip;
12444 	}
12445 
12446 	return (plun->lun_cip);
12447 }
12448 
12449 
12450 static int
12451 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12452 {
12453 	int		rval = FC_FAILURE;
12454 	dev_info_t	*pdip;
12455 	struct dev_info	*dip;
12456 	int		circular;
12457 
12458 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12459 
12460 	pdip = plun->lun_tgt->tgt_port->port_dip;
12461 
12462 	if (plun->lun_cip == NULL) {
12463 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12464 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12465 		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12466 		    "plun: %p lun state: %x num: %d target state: %x",
12467 		    plun, plun->lun_state, plun->lun_num,
12468 		    plun->lun_tgt->tgt_port->port_state);
12469 		return (rval);
12470 	}
12471 	ndi_devi_enter(pdip, &circular);
12472 	dip = DEVI(pdip)->devi_child;
12473 	while (dip) {
12474 		if (dip == DEVI(cdip)) {
12475 			rval = FC_SUCCESS;
12476 			break;
12477 		}
12478 		dip = dip->devi_sibling;
12479 	}
12480 	ndi_devi_exit(pdip, circular);
12481 	return (rval);
12482 }
12483 
12484 static int
12485 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12486 {
12487 	int		rval = FC_FAILURE;
12488 
12489 	ASSERT(plun != NULL);
12490 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12491 
12492 	if (plun->lun_mpxio == 0) {
12493 		rval = fcp_is_dip_present(plun, DIP(cip));
12494 	} else {
12495 		rval = fcp_is_pip_present(plun, PIP(cip));
12496 	}
12497 
12498 	return (rval);
12499 }
12500 
12501 /*
12502  *     Function: fcp_create_dip
12503  *
12504  *  Description: Creates a dev_info_t structure for the LUN specified by the
12505  *		 caller.
12506  *
12507  *     Argument: plun		Lun structure
12508  *		 link_cnt	Link state count.
12509  *		 tgt_cnt	Target state change count.
12510  *
12511  * Return Value: NULL if it failed
12512  *		 dev_info_t structure address if it succeeded
12513  *
12514  *	Context: Kernel context
12515  */
12516 static dev_info_t *
12517 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12518 {
12519 	int			failure = 0;
12520 	uint32_t		tgt_id;
12521 	uint64_t		sam_lun;
12522 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12523 	struct fcp_port	*pptr = ptgt->tgt_port;
12524 	dev_info_t		*pdip = pptr->port_dip;
12525 	dev_info_t		*cdip = NULL;
12526 	dev_info_t		*old_dip = DIP(plun->lun_cip);
12527 	char			*nname = NULL;
12528 	char			**compatible = NULL;
12529 	int			ncompatible;
12530 	char			*scsi_binding_set;
12531 	char			t_pwwn[17];
12532 
12533 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12534 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12535 
12536 	/* get the 'scsi-binding-set' property */
12537 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12538 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12539 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12540 		scsi_binding_set = NULL;
12541 	}
12542 
12543 	/* determine the node name and compatible */
12544 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12545 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12546 	if (scsi_binding_set) {
12547 		ddi_prop_free(scsi_binding_set);
12548 	}
12549 
12550 	if (nname == NULL) {
12551 #ifdef	DEBUG
12552 		cmn_err(CE_WARN, "%s%d: no driver for "
12553 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12554 		    "	 compatible: %s",
12555 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12556 		    ptgt->tgt_port_wwn.raw_wwn[0],
12557 		    ptgt->tgt_port_wwn.raw_wwn[1],
12558 		    ptgt->tgt_port_wwn.raw_wwn[2],
12559 		    ptgt->tgt_port_wwn.raw_wwn[3],
12560 		    ptgt->tgt_port_wwn.raw_wwn[4],
12561 		    ptgt->tgt_port_wwn.raw_wwn[5],
12562 		    ptgt->tgt_port_wwn.raw_wwn[6],
12563 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12564 		    *compatible);
12565 #endif	/* DEBUG */
12566 		failure++;
12567 		goto end_of_fcp_create_dip;
12568 	}
12569 
12570 	cdip = fcp_find_existing_dip(plun, pdip, nname);
12571 
12572 	/*
12573 	 * if the old_dip does not match the cdip, that means there is
12574 	 * some property change. since we'll be using the cdip, we need
12575 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12576 	 * then the dtype for the device has been updated. Offline the
12577 	 * the old device and create a new device with the new device type
12578 	 * Refer to bug: 4764752
12579 	 */
12580 	if (old_dip && (cdip != old_dip ||
12581 	    plun->lun_state & FCP_LUN_CHANGED)) {
12582 		plun->lun_state &= ~(FCP_LUN_INIT);
12583 		mutex_exit(&plun->lun_mutex);
12584 		mutex_exit(&pptr->port_mutex);
12585 
12586 		mutex_enter(&ptgt->tgt_mutex);
12587 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12588 		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12589 		mutex_exit(&ptgt->tgt_mutex);
12590 
12591 #ifdef DEBUG
12592 		if (cdip != NULL) {
12593 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12594 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12595 			    "Old dip=%p; New dip=%p don't match", old_dip,
12596 			    cdip);
12597 		} else {
12598 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12599 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12600 			    "Old dip=%p; New dip=NULL don't match", old_dip);
12601 		}
12602 #endif
12603 
12604 		mutex_enter(&pptr->port_mutex);
12605 		mutex_enter(&plun->lun_mutex);
12606 	}
12607 
12608 	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12609 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12610 		if (ndi_devi_alloc(pptr->port_dip, nname,
12611 		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12612 			failure++;
12613 			goto end_of_fcp_create_dip;
12614 		}
12615 	}
12616 
12617 	/*
12618 	 * Previously all the properties for the devinfo were destroyed here
12619 	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12620 	 * the devid property (and other properties established by the target
12621 	 * driver or framework) which the code does not always recreate, this
12622 	 * call was removed.
12623 	 * This opens a theoretical possibility that we may return with a
12624 	 * stale devid on the node if the scsi entity behind the fibre channel
12625 	 * lun has changed.
12626 	 */
12627 
12628 	/* decorate the node with compatible */
12629 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12630 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12631 		failure++;
12632 		goto end_of_fcp_create_dip;
12633 	}
12634 
12635 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12636 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12637 		failure++;
12638 		goto end_of_fcp_create_dip;
12639 	}
12640 
12641 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12642 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12643 		failure++;
12644 		goto end_of_fcp_create_dip;
12645 	}
12646 
12647 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12648 	t_pwwn[16] = '\0';
12649 	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12650 	    != DDI_PROP_SUCCESS) {
12651 		failure++;
12652 		goto end_of_fcp_create_dip;
12653 	}
12654 
12655 	/*
12656 	 * If there is no hard address - We might have to deal with
12657 	 * that by using WWN - Having said that it is important to
12658 	 * recognize this problem early so ssd can be informed of
12659 	 * the right interconnect type.
12660 	 */
12661 	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12662 		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12663 	} else {
12664 		tgt_id = ptgt->tgt_d_id;
12665 	}
12666 
12667 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12668 	    tgt_id) != DDI_PROP_SUCCESS) {
12669 		failure++;
12670 		goto end_of_fcp_create_dip;
12671 	}
12672 
12673 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12674 	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12675 		failure++;
12676 		goto end_of_fcp_create_dip;
12677 	}
12678 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12679 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12680 	    sam_lun) != DDI_PROP_SUCCESS) {
12681 		failure++;
12682 		goto end_of_fcp_create_dip;
12683 	}
12684 
12685 end_of_fcp_create_dip:
12686 	scsi_hba_nodename_compatible_free(nname, compatible);
12687 
12688 	if (cdip != NULL && failure) {
12689 		(void) ndi_prop_remove_all(cdip);
12690 		(void) ndi_devi_free(cdip);
12691 		cdip = NULL;
12692 	}
12693 
12694 	return (cdip);
12695 }
12696 
12697 /*
12698  *     Function: fcp_create_pip
12699  *
12700  *  Description: Creates a Path Id for the LUN specified by the caller.
12701  *
12702  *     Argument: plun		Lun structure
12703  *		 link_cnt	Link state count.
12704  *		 tgt_cnt	Target state count.
12705  *
12706  * Return Value: NULL if it failed
12707  *		 mdi_pathinfo_t structure address if it succeeded
12708  *
12709  *	Context: Kernel context
12710  */
12711 static mdi_pathinfo_t *
12712 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12713 {
12714 	int			i;
12715 	char			buf[MAXNAMELEN];
12716 	char			uaddr[MAXNAMELEN];
12717 	int			failure = 0;
12718 	uint32_t		tgt_id;
12719 	uint64_t		sam_lun;
12720 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12721 	struct fcp_port	*pptr = ptgt->tgt_port;
12722 	dev_info_t		*pdip = pptr->port_dip;
12723 	mdi_pathinfo_t		*pip = NULL;
12724 	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12725 	char			*nname = NULL;
12726 	char			**compatible = NULL;
12727 	int			ncompatible;
12728 	char			*scsi_binding_set;
12729 	char			t_pwwn[17];
12730 
12731 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12732 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12733 
12734 	scsi_binding_set = "vhci";
12735 
12736 	/* determine the node name and compatible */
12737 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12738 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12739 
12740 	if (nname == NULL) {
12741 #ifdef	DEBUG
12742 		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12743 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12744 		    "	 compatible: %s",
12745 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12746 		    ptgt->tgt_port_wwn.raw_wwn[0],
12747 		    ptgt->tgt_port_wwn.raw_wwn[1],
12748 		    ptgt->tgt_port_wwn.raw_wwn[2],
12749 		    ptgt->tgt_port_wwn.raw_wwn[3],
12750 		    ptgt->tgt_port_wwn.raw_wwn[4],
12751 		    ptgt->tgt_port_wwn.raw_wwn[5],
12752 		    ptgt->tgt_port_wwn.raw_wwn[6],
12753 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12754 		    *compatible);
12755 #endif	/* DEBUG */
12756 		failure++;
12757 		goto end_of_fcp_create_pip;
12758 	}
12759 
12760 	pip = fcp_find_existing_pip(plun, pdip);
12761 
12762 	/*
12763 	 * if the old_dip does not match the cdip, that means there is
12764 	 * some property change. since we'll be using the cdip, we need
12765 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12766 	 * then the dtype for the device has been updated. Offline the
12767 	 * the old device and create a new device with the new device type
12768 	 * Refer to bug: 4764752
12769 	 */
12770 	if (old_pip && (pip != old_pip ||
12771 	    plun->lun_state & FCP_LUN_CHANGED)) {
12772 		plun->lun_state &= ~(FCP_LUN_INIT);
12773 		mutex_exit(&plun->lun_mutex);
12774 		mutex_exit(&pptr->port_mutex);
12775 
12776 		mutex_enter(&ptgt->tgt_mutex);
12777 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12778 		    FCP_OFFLINE, lcount, tcount,
12779 		    NDI_DEVI_REMOVE, 0);
12780 		mutex_exit(&ptgt->tgt_mutex);
12781 
12782 		if (pip != NULL) {
12783 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12784 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12785 			    "Old pip=%p; New pip=%p don't match",
12786 			    old_pip, pip);
12787 		} else {
12788 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12789 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12790 			    "Old pip=%p; New pip=NULL don't match",
12791 			    old_pip);
12792 		}
12793 
12794 		mutex_enter(&pptr->port_mutex);
12795 		mutex_enter(&plun->lun_mutex);
12796 	}
12797 
12798 	/*
12799 	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12800 	 * lun_guid_size which is dependent on the target, I don't
12801 	 * believe the same trancation happens here UNLESS the standards
12802 	 * change the FC_WWN_SIZE value to something larger than
12803 	 * MAXNAMELEN(currently 255 bytes).
12804 	 */
12805 
12806 	for (i = 0; i < FC_WWN_SIZE; i++) {
12807 		(void) sprintf(&buf[i << 1], "%02x",
12808 		    ptgt->tgt_port_wwn.raw_wwn[i]);
12809 	}
12810 
12811 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12812 	    buf, plun->lun_num);
12813 
12814 	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12815 		/*
12816 		 * Release the locks before calling into
12817 		 * mdi_pi_alloc_compatible() since this can result in a
12818 		 * callback into fcp which can result in a deadlock
12819 		 * (see bug # 4870272).
12820 		 *
12821 		 * Basically, what we are trying to avoid is the scenario where
12822 		 * one thread does ndi_devi_enter() and tries to grab
12823 		 * fcp_mutex and another does it the other way round.
12824 		 *
12825 		 * But before we do that, make sure that nobody releases the
12826 		 * port in the meantime. We can do this by setting a flag.
12827 		 */
12828 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12829 		pptr->port_state |= FCP_STATE_IN_MDI;
12830 		mutex_exit(&plun->lun_mutex);
12831 		mutex_exit(&pptr->port_mutex);
12832 		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12833 		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12834 			fcp_log(CE_WARN, pptr->port_dip,
12835 			    "!path alloc failed:0x%x", plun);
12836 			mutex_enter(&pptr->port_mutex);
12837 			mutex_enter(&plun->lun_mutex);
12838 			pptr->port_state &= ~FCP_STATE_IN_MDI;
12839 			failure++;
12840 			goto end_of_fcp_create_pip;
12841 		}
12842 		mutex_enter(&pptr->port_mutex);
12843 		mutex_enter(&plun->lun_mutex);
12844 		pptr->port_state &= ~FCP_STATE_IN_MDI;
12845 	} else {
12846 		(void) mdi_prop_remove(pip, NULL);
12847 	}
12848 
12849 	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12850 
12851 	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12852 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12853 	    != DDI_PROP_SUCCESS) {
12854 		failure++;
12855 		goto end_of_fcp_create_pip;
12856 	}
12857 
12858 	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12859 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12860 	    != DDI_PROP_SUCCESS) {
12861 		failure++;
12862 		goto end_of_fcp_create_pip;
12863 	}
12864 
12865 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12866 	t_pwwn[16] = '\0';
12867 	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12868 	    != DDI_PROP_SUCCESS) {
12869 		failure++;
12870 		goto end_of_fcp_create_pip;
12871 	}
12872 
12873 	/*
12874 	 * If there is no hard address - We might have to deal with
12875 	 * that by using WWN - Having said that it is important to
12876 	 * recognize this problem early so ssd can be informed of
12877 	 * the right interconnect type.
12878 	 */
12879 	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12880 	    ptgt->tgt_hard_addr != 0) {
12881 		tgt_id = (uint32_t)
12882 		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12883 	} else {
12884 		tgt_id = ptgt->tgt_d_id;
12885 	}
12886 
12887 	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12888 	    != DDI_PROP_SUCCESS) {
12889 		failure++;
12890 		goto end_of_fcp_create_pip;
12891 	}
12892 
12893 	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12894 	    != DDI_PROP_SUCCESS) {
12895 		failure++;
12896 		goto end_of_fcp_create_pip;
12897 	}
12898 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12899 	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12900 	    != DDI_PROP_SUCCESS) {
12901 		failure++;
12902 		goto end_of_fcp_create_pip;
12903 	}
12904 
12905 end_of_fcp_create_pip:
12906 	scsi_hba_nodename_compatible_free(nname, compatible);
12907 
12908 	if (pip != NULL && failure) {
12909 		(void) mdi_prop_remove(pip, NULL);
12910 		mutex_exit(&plun->lun_mutex);
12911 		mutex_exit(&pptr->port_mutex);
12912 		(void) mdi_pi_free(pip, 0);
12913 		mutex_enter(&pptr->port_mutex);
12914 		mutex_enter(&plun->lun_mutex);
12915 		pip = NULL;
12916 	}
12917 
12918 	return (pip);
12919 }
12920 
12921 static dev_info_t *
12922 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12923 {
12924 	uint_t			nbytes;
12925 	uchar_t			*bytes;
12926 	uint_t			nwords;
12927 	uint32_t		tgt_id;
12928 	int			*words;
12929 	dev_info_t		*cdip;
12930 	dev_info_t		*ndip;
12931 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12932 	struct fcp_port	*pptr = ptgt->tgt_port;
12933 	int			circular;
12934 
12935 	ndi_devi_enter(pdip, &circular);
12936 
12937 	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12938 	while ((cdip = ndip) != NULL) {
12939 		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12940 
12941 		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12942 			continue;
12943 		}
12944 
12945 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12946 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12947 		    &nbytes) != DDI_PROP_SUCCESS) {
12948 			continue;
12949 		}
12950 
12951 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12952 			if (bytes != NULL) {
12953 				ddi_prop_free(bytes);
12954 			}
12955 			continue;
12956 		}
12957 		ASSERT(bytes != NULL);
12958 
12959 		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12960 			ddi_prop_free(bytes);
12961 			continue;
12962 		}
12963 
12964 		ddi_prop_free(bytes);
12965 
12966 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12967 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12968 		    &nbytes) != DDI_PROP_SUCCESS) {
12969 			continue;
12970 		}
12971 
12972 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12973 			if (bytes != NULL) {
12974 				ddi_prop_free(bytes);
12975 			}
12976 			continue;
12977 		}
12978 		ASSERT(bytes != NULL);
12979 
12980 		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12981 			ddi_prop_free(bytes);
12982 			continue;
12983 		}
12984 
12985 		ddi_prop_free(bytes);
12986 
12987 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12988 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12989 		    &nwords) != DDI_PROP_SUCCESS) {
12990 			continue;
12991 		}
12992 
12993 		if (nwords != 1 || words == NULL) {
12994 			if (words != NULL) {
12995 				ddi_prop_free(words);
12996 			}
12997 			continue;
12998 		}
12999 		ASSERT(words != NULL);
13000 
13001 		/*
13002 		 * If there is no hard address - We might have to deal with
13003 		 * that by using WWN - Having said that it is important to
13004 		 * recognize this problem early so ssd can be informed of
13005 		 * the right interconnect type.
13006 		 */
13007 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13008 		    ptgt->tgt_hard_addr != 0) {
13009 			tgt_id =
13010 			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13011 		} else {
13012 			tgt_id = ptgt->tgt_d_id;
13013 		}
13014 
13015 		if (tgt_id != (uint32_t)*words) {
13016 			ddi_prop_free(words);
13017 			continue;
13018 		}
13019 		ddi_prop_free(words);
13020 
13021 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13022 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13023 		    &nwords) != DDI_PROP_SUCCESS) {
13024 			continue;
13025 		}
13026 
13027 		if (nwords != 1 || words == NULL) {
13028 			if (words != NULL) {
13029 				ddi_prop_free(words);
13030 			}
13031 			continue;
13032 		}
13033 		ASSERT(words != NULL);
13034 
13035 		if (plun->lun_num == (uint16_t)*words) {
13036 			ddi_prop_free(words);
13037 			break;
13038 		}
13039 		ddi_prop_free(words);
13040 	}
13041 	ndi_devi_exit(pdip, circular);
13042 
13043 	return (cdip);
13044 }
13045 
13046 
13047 static int
13048 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13049 {
13050 	dev_info_t	*pdip;
13051 	char		buf[MAXNAMELEN];
13052 	char		uaddr[MAXNAMELEN];
13053 	int		rval = FC_FAILURE;
13054 
13055 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13056 
13057 	pdip = plun->lun_tgt->tgt_port->port_dip;
13058 
13059 	/*
13060 	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13061 	 * non-NULL even when the LUN is not there as in the case when a LUN is
13062 	 * configured and then deleted on the device end (for T3/T4 case). In
13063 	 * such cases, pip will be NULL.
13064 	 *
13065 	 * If the device generates an RSCN, it will end up getting offlined when
13066 	 * it disappeared and a new LUN will get created when it is rediscovered
13067 	 * on the device. If we check for lun_cip here, the LUN will not end
13068 	 * up getting onlined since this function will end up returning a
13069 	 * FC_SUCCESS.
13070 	 *
13071 	 * The behavior is different on other devices. For instance, on a HDS,
13072 	 * there was no RSCN generated by the device but the next I/O generated
13073 	 * a check condition and rediscovery got triggered that way. So, in
13074 	 * such cases, this path will not be exercised
13075 	 */
13076 	if (pip == NULL) {
13077 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13078 		    fcp_trace, FCP_BUF_LEVEL_4, 0,
13079 		    "fcp_is_pip_present: plun->lun_cip is NULL: "
13080 		    "plun: %p lun state: %x num: %d target state: %x",
13081 		    plun, plun->lun_state, plun->lun_num,
13082 		    plun->lun_tgt->tgt_port->port_state);
13083 		return (rval);
13084 	}
13085 
13086 	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13087 
13088 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13089 
13090 	if (plun->lun_old_guid) {
13091 		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13092 			rval = FC_SUCCESS;
13093 		}
13094 	} else {
13095 		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13096 			rval = FC_SUCCESS;
13097 		}
13098 	}
13099 	return (rval);
13100 }
13101 
13102 static mdi_pathinfo_t *
13103 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13104 {
13105 	char			buf[MAXNAMELEN];
13106 	char			uaddr[MAXNAMELEN];
13107 	mdi_pathinfo_t		*pip;
13108 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13109 	struct fcp_port	*pptr = ptgt->tgt_port;
13110 
13111 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13112 
13113 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13114 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13115 
13116 	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13117 
13118 	return (pip);
13119 }
13120 
13121 
13122 static int
13123 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13124     int tcount, int flags, int *circ)
13125 {
13126 	int			rval;
13127 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13128 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13129 	dev_info_t		*cdip = NULL;
13130 
13131 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13132 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13133 
13134 	if (plun->lun_cip == NULL) {
13135 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13136 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13137 		    "fcp_online_child: plun->lun_cip is NULL: "
13138 		    "plun: %p state: %x num: %d target state: %x",
13139 		    plun, plun->lun_state, plun->lun_num,
13140 		    plun->lun_tgt->tgt_port->port_state);
13141 		return (NDI_FAILURE);
13142 	}
13143 again:
13144 	if (plun->lun_mpxio == 0) {
13145 		cdip = DIP(cip);
13146 		mutex_exit(&plun->lun_mutex);
13147 		mutex_exit(&pptr->port_mutex);
13148 
13149 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13150 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13151 		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13152 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13153 
13154 		/*
13155 		 * We could check for FCP_LUN_INIT here but chances
13156 		 * of getting here when it's already in FCP_LUN_INIT
13157 		 * is rare and a duplicate ndi_devi_online wouldn't
13158 		 * hurt either (as the node would already have been
13159 		 * in CF2)
13160 		 */
13161 		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13162 			rval = ndi_devi_bind_driver(cdip, flags);
13163 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13164 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13165 			    "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13166 		} else {
13167 			rval = ndi_devi_online(cdip, flags);
13168 		}
13169 
13170 		/*
13171 		 * We log the message into trace buffer if the device
13172 		 * is "ses" and into syslog for any other device
13173 		 * type. This is to prevent the ndi_devi_online failure
13174 		 * message that appears for V880/A5K ses devices.
13175 		 */
13176 		if (rval == NDI_SUCCESS) {
13177 			mutex_enter(&ptgt->tgt_mutex);
13178 			plun->lun_state |= FCP_LUN_INIT;
13179 			mutex_exit(&ptgt->tgt_mutex);
13180 		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13181 			fcp_log(CE_NOTE, pptr->port_dip,
13182 			    "!ndi_devi_online:"
13183 			    " failed for %s: target=%x lun=%x %x",
13184 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13185 			    plun->lun_num, rval);
13186 		} else {
13187 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13188 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13189 			    " !ndi_devi_online:"
13190 			    " failed for %s: target=%x lun=%x %x",
13191 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13192 			    plun->lun_num, rval);
13193 		}
13194 	} else {
13195 		cdip = mdi_pi_get_client(PIP(cip));
13196 		mutex_exit(&plun->lun_mutex);
13197 		mutex_exit(&pptr->port_mutex);
13198 
13199 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13200 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13201 		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13202 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13203 
13204 		/*
13205 		 * Hold path and exit phci to avoid deadlock with power
13206 		 * management code during mdi_pi_online.
13207 		 */
13208 		mdi_hold_path(PIP(cip));
13209 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13210 
13211 		rval = mdi_pi_online(PIP(cip), flags);
13212 
13213 		mdi_devi_enter_phci(pptr->port_dip, circ);
13214 		mdi_rele_path(PIP(cip));
13215 
13216 		if (rval == MDI_SUCCESS) {
13217 			mutex_enter(&ptgt->tgt_mutex);
13218 			plun->lun_state |= FCP_LUN_INIT;
13219 			mutex_exit(&ptgt->tgt_mutex);
13220 
13221 			/*
13222 			 * Clear MPxIO path permanent disable in case
13223 			 * fcp hotplug dropped the offline event.
13224 			 */
13225 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13226 
13227 		} else if (rval == MDI_NOT_SUPPORTED) {
13228 			child_info_t	*old_cip = cip;
13229 
13230 			/*
13231 			 * MPxIO does not support this device yet.
13232 			 * Enumerate in legacy mode.
13233 			 */
13234 			mutex_enter(&pptr->port_mutex);
13235 			mutex_enter(&plun->lun_mutex);
13236 			plun->lun_mpxio = 0;
13237 			plun->lun_cip = NULL;
13238 			cdip = fcp_create_dip(plun, lcount, tcount);
13239 			plun->lun_cip = cip = CIP(cdip);
13240 			if (cip == NULL) {
13241 				fcp_log(CE_WARN, pptr->port_dip,
13242 				    "!fcp_online_child: "
13243 				    "Create devinfo failed for LU=%p", plun);
13244 				mutex_exit(&plun->lun_mutex);
13245 
13246 				mutex_enter(&ptgt->tgt_mutex);
13247 				plun->lun_state |= FCP_LUN_OFFLINE;
13248 				mutex_exit(&ptgt->tgt_mutex);
13249 
13250 				mutex_exit(&pptr->port_mutex);
13251 
13252 				/*
13253 				 * free the mdi_pathinfo node
13254 				 */
13255 				(void) mdi_pi_free(PIP(old_cip), 0);
13256 			} else {
13257 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13258 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13259 				    "fcp_online_child: creating devinfo "
13260 				    "node 0x%p for plun 0x%p",
13261 				    cip, plun);
13262 				mutex_exit(&plun->lun_mutex);
13263 				mutex_exit(&pptr->port_mutex);
13264 				/*
13265 				 * free the mdi_pathinfo node
13266 				 */
13267 				(void) mdi_pi_free(PIP(old_cip), 0);
13268 				mutex_enter(&pptr->port_mutex);
13269 				mutex_enter(&plun->lun_mutex);
13270 				goto again;
13271 			}
13272 		} else {
13273 			if (cdip) {
13274 				fcp_log(CE_NOTE, pptr->port_dip,
13275 				    "!fcp_online_child: mdi_pi_online:"
13276 				    " failed for %s: target=%x lun=%x %x",
13277 				    ddi_get_name(cdip), ptgt->tgt_d_id,
13278 				    plun->lun_num, rval);
13279 			}
13280 		}
13281 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13282 	}
13283 
13284 	if (rval == NDI_SUCCESS) {
13285 		if (cdip) {
13286 			(void) ndi_event_retrieve_cookie(
13287 			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13288 			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13289 			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13290 			    cdip, fcp_insert_eid, NULL);
13291 		}
13292 	}
13293 	mutex_enter(&pptr->port_mutex);
13294 	mutex_enter(&plun->lun_mutex);
13295 	return (rval);
13296 }
13297 
13298 /* ARGSUSED */
13299 static int
13300 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13301     int tcount, int flags, int *circ)
13302 {
13303 	int rval;
13304 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13305 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13306 	dev_info_t		*cdip;
13307 
13308 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13309 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13310 
13311 	if (plun->lun_cip == NULL) {
13312 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13313 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13314 		    "fcp_offline_child: plun->lun_cip is NULL: "
13315 		    "plun: %p lun state: %x num: %d target state: %x",
13316 		    plun, plun->lun_state, plun->lun_num,
13317 		    plun->lun_tgt->tgt_port->port_state);
13318 		return (NDI_FAILURE);
13319 	}
13320 
13321 	if (plun->lun_mpxio == 0) {
13322 		cdip = DIP(cip);
13323 		mutex_exit(&plun->lun_mutex);
13324 		mutex_exit(&pptr->port_mutex);
13325 		rval = ndi_devi_offline(DIP(cip), flags);
13326 		if (rval != NDI_SUCCESS) {
13327 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13328 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13329 			    "fcp_offline_child: ndi_devi_offline failed "
13330 			    "rval=%x cip=%p", rval, cip);
13331 		}
13332 	} else {
13333 		cdip = mdi_pi_get_client(PIP(cip));
13334 		mutex_exit(&plun->lun_mutex);
13335 		mutex_exit(&pptr->port_mutex);
13336 
13337 		/*
13338 		 * Exit phci to avoid deadlock with power management code
13339 		 * during mdi_pi_offline
13340 		 */
13341 		mdi_hold_path(PIP(cip));
13342 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13343 
13344 		rval = mdi_pi_offline(PIP(cip), flags);
13345 
13346 		mdi_devi_enter_phci(pptr->port_dip, circ);
13347 		mdi_rele_path(PIP(cip));
13348 
13349 		if (rval == MDI_SUCCESS) {
13350 			/*
13351 			 * Clear MPxIO path permanent disable as the path is
13352 			 * already offlined.
13353 			 */
13354 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13355 
13356 			if (flags & NDI_DEVI_REMOVE) {
13357 				(void) mdi_pi_free(PIP(cip), 0);
13358 			}
13359 		} else {
13360 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13361 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13362 			    "fcp_offline_child: mdi_pi_offline failed "
13363 			    "rval=%x cip=%p", rval, cip);
13364 		}
13365 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13366 	}
13367 
13368 	mutex_enter(&ptgt->tgt_mutex);
13369 	plun->lun_state &= ~FCP_LUN_INIT;
13370 	mutex_exit(&ptgt->tgt_mutex);
13371 
13372 	mutex_enter(&pptr->port_mutex);
13373 	mutex_enter(&plun->lun_mutex);
13374 
13375 	if (rval == NDI_SUCCESS) {
13376 		cdip = NULL;
13377 		if (flags & NDI_DEVI_REMOVE) {
13378 			/*
13379 			 * If the guid of the LUN changes, lun_cip will not
13380 			 * equal to cip, and after offlining the LUN with the
13381 			 * old guid, we should keep lun_cip since it's the cip
13382 			 * of the LUN with the new guid.
13383 			 * Otherwise remove our reference to child node.
13384 			 */
13385 			if (plun->lun_cip == cip) {
13386 				plun->lun_cip = NULL;
13387 			}
13388 			if (plun->lun_old_guid) {
13389 				kmem_free(plun->lun_old_guid,
13390 				    plun->lun_old_guid_size);
13391 				plun->lun_old_guid = NULL;
13392 				plun->lun_old_guid_size = 0;
13393 			}
13394 		}
13395 	}
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 	int circ;
13411 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13412 
13413 	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13414 		if (plun->lun_mpxio == 0) {
13415 			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13416 			(void) ndi_devi_free(DIP(plun->lun_cip));
13417 		} else {
13418 			mutex_exit(&plun->lun_mutex);
13419 			mutex_exit(&plun->lun_tgt->tgt_mutex);
13420 			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13421 			mdi_devi_enter(
13422 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13423 			mdi_hold_path(PIP(plun->lun_cip));
13424 			mdi_devi_exit_phci(
13425 			    plun->lun_tgt->tgt_port->port_dip, circ);
13426 			(void) mdi_pi_offline(PIP(plun->lun_cip),
13427 			    NDI_DEVI_REMOVE);
13428 			mdi_devi_enter_phci(
13429 			    plun->lun_tgt->tgt_port->port_dip, &circ);
13430 			mdi_rele_path(PIP(plun->lun_cip));
13431 			mdi_devi_exit_phci(
13432 			    plun->lun_tgt->tgt_port->port_dip, circ);
13433 			FCP_TRACE(fcp_logq,
13434 			    plun->lun_tgt->tgt_port->port_instbuf,
13435 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13436 			    "lun=%p pip freed %p", plun, plun->lun_cip);
13437 			(void) mdi_prop_remove(PIP(plun->lun_cip), NULL);
13438 			(void) mdi_pi_free(PIP(plun->lun_cip), 0);
13439 			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13440 			mutex_enter(&plun->lun_tgt->tgt_mutex);
13441 			mutex_enter(&plun->lun_mutex);
13442 		}
13443 	}
13444 
13445 	plun->lun_cip = NULL;
13446 }
13447 
13448 /*
13449  * called when a timeout occurs
13450  *
13451  * can be scheduled during an attach or resume (if not already running)
13452  *
13453  * one timeout is set up for all ports
13454  *
13455  * acquires and releases the global mutex
13456  */
13457 /*ARGSUSED*/
13458 static void
13459 fcp_watch(void *arg)
13460 {
13461 	struct fcp_port	*pptr;
13462 	struct fcp_ipkt	*icmd;
13463 	struct fcp_ipkt	*nicmd;
13464 	struct fcp_pkt	*cmd;
13465 	struct fcp_pkt	*ncmd;
13466 	struct fcp_pkt	*tail;
13467 	struct fcp_pkt	*pcmd;
13468 	struct fcp_pkt	*save_head;
13469 	struct fcp_port	*save_port;
13470 
13471 	/* increment global watchdog time */
13472 	fcp_watchdog_time += fcp_watchdog_timeout;
13473 
13474 	mutex_enter(&fcp_global_mutex);
13475 
13476 	/* scan each port in our list */
13477 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13478 		save_port = fcp_port_head;
13479 		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13480 		mutex_exit(&fcp_global_mutex);
13481 
13482 		mutex_enter(&pptr->port_mutex);
13483 		if (pptr->port_ipkt_list == NULL &&
13484 		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13485 		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13486 			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13487 			mutex_exit(&pptr->port_mutex);
13488 			mutex_enter(&fcp_global_mutex);
13489 			goto end_of_watchdog;
13490 		}
13491 
13492 		/*
13493 		 * We check if a list of targets need to be offlined.
13494 		 */
13495 		if (pptr->port_offline_tgts) {
13496 			fcp_scan_offline_tgts(pptr);
13497 		}
13498 
13499 		/*
13500 		 * We check if a list of luns need to be offlined.
13501 		 */
13502 		if (pptr->port_offline_luns) {
13503 			fcp_scan_offline_luns(pptr);
13504 		}
13505 
13506 		/*
13507 		 * We check if a list of targets or luns need to be reset.
13508 		 */
13509 		if (pptr->port_reset_list) {
13510 			fcp_check_reset_delay(pptr);
13511 		}
13512 
13513 		mutex_exit(&pptr->port_mutex);
13514 
13515 		/*
13516 		 * This is where the pending commands (pkt) are checked for
13517 		 * timeout.
13518 		 */
13519 		mutex_enter(&pptr->port_pkt_mutex);
13520 		tail = pptr->port_pkt_tail;
13521 
13522 		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13523 		    cmd != NULL; cmd = ncmd) {
13524 			ncmd = cmd->cmd_next;
13525 			/*
13526 			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13527 			 * must be set.
13528 			 */
13529 			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13530 			/*
13531 			 * FCP_INVALID_TIMEOUT will be set for those
13532 			 * command that need to be failed. Mostly those
13533 			 * cmds that could not be queued down for the
13534 			 * "timeout" value. cmd->cmd_timeout is used
13535 			 * to try and requeue the command regularly.
13536 			 */
13537 			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13538 				/*
13539 				 * This command hasn't timed out yet.  Let's
13540 				 * go to the next one.
13541 				 */
13542 				pcmd = cmd;
13543 				goto end_of_loop;
13544 			}
13545 
13546 			if (cmd == pptr->port_pkt_head) {
13547 				ASSERT(pcmd == NULL);
13548 				pptr->port_pkt_head = cmd->cmd_next;
13549 			} else {
13550 				ASSERT(pcmd != NULL);
13551 				pcmd->cmd_next = cmd->cmd_next;
13552 			}
13553 
13554 			if (cmd == pptr->port_pkt_tail) {
13555 				ASSERT(cmd->cmd_next == NULL);
13556 				pptr->port_pkt_tail = pcmd;
13557 				if (pcmd) {
13558 					pcmd->cmd_next = NULL;
13559 				}
13560 			}
13561 			cmd->cmd_next = NULL;
13562 
13563 			/*
13564 			 * save the current head before dropping the
13565 			 * mutex - If the head doesn't remain the
13566 			 * same after re acquiring the mutex, just
13567 			 * bail out and revisit on next tick.
13568 			 *
13569 			 * PS: The tail pointer can change as the commands
13570 			 * get requeued after failure to retransport
13571 			 */
13572 			save_head = pptr->port_pkt_head;
13573 			mutex_exit(&pptr->port_pkt_mutex);
13574 
13575 			if (cmd->cmd_fp_pkt->pkt_timeout ==
13576 			    FCP_INVALID_TIMEOUT) {
13577 				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13578 				struct fcp_lun	*plun;
13579 				struct fcp_tgt	*ptgt;
13580 
13581 				plun = ADDR2LUN(&pkt->pkt_address);
13582 				ptgt = plun->lun_tgt;
13583 
13584 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13585 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13586 				    "SCSI cmd 0x%x to D_ID=%x timed out",
13587 				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13588 
13589 				cmd->cmd_state == FCP_PKT_ABORTING ?
13590 				    fcp_fail_cmd(cmd, CMD_RESET,
13591 				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13592 				    CMD_TIMEOUT, STAT_ABORTED);
13593 			} else {
13594 				fcp_retransport_cmd(pptr, cmd);
13595 			}
13596 			mutex_enter(&pptr->port_pkt_mutex);
13597 			if (save_head && save_head != pptr->port_pkt_head) {
13598 				/*
13599 				 * Looks like linked list got changed (mostly
13600 				 * happens when an an OFFLINE LUN code starts
13601 				 * returning overflow queue commands in
13602 				 * parallel. So bail out and revisit during
13603 				 * next tick
13604 				 */
13605 				break;
13606 			}
13607 		end_of_loop:
13608 			/*
13609 			 * Scan only upto the previously known tail pointer
13610 			 * to avoid excessive processing - lots of new packets
13611 			 * could have been added to the tail or the old ones
13612 			 * re-queued.
13613 			 */
13614 			if (cmd == tail) {
13615 				break;
13616 			}
13617 		}
13618 		mutex_exit(&pptr->port_pkt_mutex);
13619 
13620 		mutex_enter(&pptr->port_mutex);
13621 		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13622 			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13623 
13624 			nicmd = icmd->ipkt_next;
13625 			if ((icmd->ipkt_restart != 0) &&
13626 			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13627 				/* packet has not timed out */
13628 				continue;
13629 			}
13630 
13631 			/* time for packet re-transport */
13632 			if (icmd == pptr->port_ipkt_list) {
13633 				pptr->port_ipkt_list = icmd->ipkt_next;
13634 				if (pptr->port_ipkt_list) {
13635 					pptr->port_ipkt_list->ipkt_prev =
13636 					    NULL;
13637 				}
13638 			} else {
13639 				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13640 				if (icmd->ipkt_next) {
13641 					icmd->ipkt_next->ipkt_prev =
13642 					    icmd->ipkt_prev;
13643 				}
13644 			}
13645 			icmd->ipkt_next = NULL;
13646 			icmd->ipkt_prev = NULL;
13647 			mutex_exit(&pptr->port_mutex);
13648 
13649 			if (fcp_is_retryable(icmd)) {
13650 				fc_ulp_rscn_info_t *rscnp =
13651 				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13652 				    pkt_ulp_rscn_infop;
13653 
13654 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13655 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13656 				    "%x to D_ID=%x Retrying..",
13657 				    icmd->ipkt_opcode,
13658 				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13659 
13660 				/*
13661 				 * Update the RSCN count in the packet
13662 				 * before resending.
13663 				 */
13664 
13665 				if (rscnp != NULL) {
13666 					rscnp->ulp_rscn_count =
13667 					    fc_ulp_get_rscn_count(pptr->
13668 					    port_fp_handle);
13669 				}
13670 
13671 				mutex_enter(&pptr->port_mutex);
13672 				mutex_enter(&ptgt->tgt_mutex);
13673 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13674 					mutex_exit(&ptgt->tgt_mutex);
13675 					mutex_exit(&pptr->port_mutex);
13676 					switch (icmd->ipkt_opcode) {
13677 						int rval;
13678 					case LA_ELS_PLOGI:
13679 						if ((rval = fc_ulp_login(
13680 						    pptr->port_fp_handle,
13681 						    &icmd->ipkt_fpkt, 1)) ==
13682 						    FC_SUCCESS) {
13683 							mutex_enter(
13684 							    &pptr->port_mutex);
13685 							continue;
13686 						}
13687 						if (fcp_handle_ipkt_errors(
13688 						    pptr, ptgt, icmd, rval,
13689 						    "PLOGI") == DDI_SUCCESS) {
13690 							mutex_enter(
13691 							    &pptr->port_mutex);
13692 							continue;
13693 						}
13694 						break;
13695 
13696 					case LA_ELS_PRLI:
13697 						if ((rval = fc_ulp_issue_els(
13698 						    pptr->port_fp_handle,
13699 						    icmd->ipkt_fpkt)) ==
13700 						    FC_SUCCESS) {
13701 							mutex_enter(
13702 							    &pptr->port_mutex);
13703 							continue;
13704 						}
13705 						if (fcp_handle_ipkt_errors(
13706 						    pptr, ptgt, icmd, rval,
13707 						    "PRLI") == DDI_SUCCESS) {
13708 							mutex_enter(
13709 							    &pptr->port_mutex);
13710 							continue;
13711 						}
13712 						break;
13713 
13714 					default:
13715 						if ((rval = fcp_transport(
13716 						    pptr->port_fp_handle,
13717 						    icmd->ipkt_fpkt, 1)) ==
13718 						    FC_SUCCESS) {
13719 							mutex_enter(
13720 							    &pptr->port_mutex);
13721 							continue;
13722 						}
13723 						if (fcp_handle_ipkt_errors(
13724 						    pptr, ptgt, icmd, rval,
13725 						    "PRLI") == DDI_SUCCESS) {
13726 							mutex_enter(
13727 							    &pptr->port_mutex);
13728 							continue;
13729 						}
13730 						break;
13731 					}
13732 				} else {
13733 					mutex_exit(&ptgt->tgt_mutex);
13734 					mutex_exit(&pptr->port_mutex);
13735 				}
13736 			} else {
13737 				fcp_print_error(icmd->ipkt_fpkt);
13738 			}
13739 
13740 			(void) fcp_call_finish_init(pptr, ptgt,
13741 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13742 			    icmd->ipkt_cause);
13743 			fcp_icmd_free(pptr, icmd);
13744 			mutex_enter(&pptr->port_mutex);
13745 		}
13746 
13747 		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13748 		mutex_exit(&pptr->port_mutex);
13749 		mutex_enter(&fcp_global_mutex);
13750 
13751 	end_of_watchdog:
13752 		/*
13753 		 * Bail out early before getting into trouble
13754 		 */
13755 		if (save_port != fcp_port_head) {
13756 			break;
13757 		}
13758 	}
13759 
13760 	if (fcp_watchdog_init > 0) {
13761 		/* reschedule timeout to go again */
13762 		fcp_watchdog_id =
13763 		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13764 	}
13765 	mutex_exit(&fcp_global_mutex);
13766 }
13767 
13768 
13769 static void
13770 fcp_check_reset_delay(struct fcp_port *pptr)
13771 {
13772 	uint32_t		tgt_cnt;
13773 	int			level;
13774 	struct fcp_tgt	*ptgt;
13775 	struct fcp_lun	*plun;
13776 	struct fcp_reset_elem *cur = NULL;
13777 	struct fcp_reset_elem *next = NULL;
13778 	struct fcp_reset_elem *prev = NULL;
13779 
13780 	ASSERT(mutex_owned(&pptr->port_mutex));
13781 
13782 	next = pptr->port_reset_list;
13783 	while ((cur = next) != NULL) {
13784 		next = cur->next;
13785 
13786 		if (cur->timeout < fcp_watchdog_time) {
13787 			prev = cur;
13788 			continue;
13789 		}
13790 
13791 		ptgt = cur->tgt;
13792 		plun = cur->lun;
13793 		tgt_cnt = cur->tgt_cnt;
13794 
13795 		if (ptgt) {
13796 			level = RESET_TARGET;
13797 		} else {
13798 			ASSERT(plun != NULL);
13799 			level = RESET_LUN;
13800 			ptgt = plun->lun_tgt;
13801 		}
13802 		if (prev) {
13803 			prev->next = next;
13804 		} else {
13805 			/*
13806 			 * Because we drop port mutex while doing aborts for
13807 			 * packets, we can't rely on reset_list pointing to
13808 			 * our head
13809 			 */
13810 			if (cur == pptr->port_reset_list) {
13811 				pptr->port_reset_list = next;
13812 			} else {
13813 				struct fcp_reset_elem *which;
13814 
13815 				which = pptr->port_reset_list;
13816 				while (which && which->next != cur) {
13817 					which = which->next;
13818 				}
13819 				ASSERT(which != NULL);
13820 
13821 				which->next = next;
13822 				prev = which;
13823 			}
13824 		}
13825 
13826 		kmem_free(cur, sizeof (*cur));
13827 
13828 		if (tgt_cnt == ptgt->tgt_change_cnt) {
13829 			mutex_enter(&ptgt->tgt_mutex);
13830 			if (level == RESET_TARGET) {
13831 				fcp_update_tgt_state(ptgt,
13832 				    FCP_RESET, FCP_LUN_BUSY);
13833 			} else {
13834 				fcp_update_lun_state(plun,
13835 				    FCP_RESET, FCP_LUN_BUSY);
13836 			}
13837 			mutex_exit(&ptgt->tgt_mutex);
13838 
13839 			mutex_exit(&pptr->port_mutex);
13840 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13841 			mutex_enter(&pptr->port_mutex);
13842 		}
13843 	}
13844 }
13845 
13846 
13847 static void
13848 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13849     struct fcp_lun *rlun, int tgt_cnt)
13850 {
13851 	int			rval;
13852 	struct fcp_lun	*tlun, *nlun;
13853 	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13854 	    *cmd = NULL, *head = NULL,
13855 	    *tail = NULL;
13856 
13857 	mutex_enter(&pptr->port_pkt_mutex);
13858 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13859 		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13860 		struct fcp_tgt *ptgt = plun->lun_tgt;
13861 
13862 		ncmd = cmd->cmd_next;
13863 
13864 		if (ptgt != ttgt && plun != rlun) {
13865 			pcmd = cmd;
13866 			continue;
13867 		}
13868 
13869 		if (pcmd != NULL) {
13870 			ASSERT(pptr->port_pkt_head != cmd);
13871 			pcmd->cmd_next = ncmd;
13872 		} else {
13873 			ASSERT(cmd == pptr->port_pkt_head);
13874 			pptr->port_pkt_head = ncmd;
13875 		}
13876 		if (pptr->port_pkt_tail == cmd) {
13877 			ASSERT(cmd->cmd_next == NULL);
13878 			pptr->port_pkt_tail = pcmd;
13879 			if (pcmd != NULL) {
13880 				pcmd->cmd_next = NULL;
13881 			}
13882 		}
13883 
13884 		if (head == NULL) {
13885 			head = tail = cmd;
13886 		} else {
13887 			ASSERT(tail != NULL);
13888 			tail->cmd_next = cmd;
13889 			tail = cmd;
13890 		}
13891 		cmd->cmd_next = NULL;
13892 	}
13893 	mutex_exit(&pptr->port_pkt_mutex);
13894 
13895 	for (cmd = head; cmd != NULL; cmd = ncmd) {
13896 		struct scsi_pkt *pkt = cmd->cmd_pkt;
13897 
13898 		ncmd = cmd->cmd_next;
13899 		ASSERT(pkt != NULL);
13900 
13901 		mutex_enter(&pptr->port_mutex);
13902 		if (ttgt->tgt_change_cnt == tgt_cnt) {
13903 			mutex_exit(&pptr->port_mutex);
13904 			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13905 			pkt->pkt_reason = CMD_RESET;
13906 			pkt->pkt_statistics |= STAT_DEV_RESET;
13907 			cmd->cmd_state = FCP_PKT_IDLE;
13908 			fcp_post_callback(cmd);
13909 		} else {
13910 			mutex_exit(&pptr->port_mutex);
13911 		}
13912 	}
13913 
13914 	/*
13915 	 * If the FCA will return all the commands in its queue then our
13916 	 * work is easy, just return.
13917 	 */
13918 
13919 	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13920 		return;
13921 	}
13922 
13923 	/*
13924 	 * For RESET_LUN get hold of target pointer
13925 	 */
13926 	if (ttgt == NULL) {
13927 		ASSERT(rlun != NULL);
13928 
13929 		ttgt = rlun->lun_tgt;
13930 
13931 		ASSERT(ttgt != NULL);
13932 	}
13933 
13934 	/*
13935 	 * There are some severe race conditions here.
13936 	 * While we are trying to abort the pkt, it might be completing
13937 	 * so mark it aborted and if the abort does not succeed then
13938 	 * handle it in the watch thread.
13939 	 */
13940 	mutex_enter(&ttgt->tgt_mutex);
13941 	nlun = ttgt->tgt_lun;
13942 	mutex_exit(&ttgt->tgt_mutex);
13943 	while ((tlun = nlun) != NULL) {
13944 		int restart = 0;
13945 		if (rlun && rlun != tlun) {
13946 			mutex_enter(&ttgt->tgt_mutex);
13947 			nlun = tlun->lun_next;
13948 			mutex_exit(&ttgt->tgt_mutex);
13949 			continue;
13950 		}
13951 		mutex_enter(&tlun->lun_mutex);
13952 		cmd = tlun->lun_pkt_head;
13953 		while (cmd != NULL) {
13954 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13955 				struct scsi_pkt *pkt;
13956 
13957 				restart = 1;
13958 				cmd->cmd_state = FCP_PKT_ABORTING;
13959 				mutex_exit(&tlun->lun_mutex);
13960 				rval = fc_ulp_abort(pptr->port_fp_handle,
13961 				    cmd->cmd_fp_pkt, KM_SLEEP);
13962 				if (rval == FC_SUCCESS) {
13963 					pkt = cmd->cmd_pkt;
13964 					pkt->pkt_reason = CMD_RESET;
13965 					pkt->pkt_statistics |= STAT_DEV_RESET;
13966 					cmd->cmd_state = FCP_PKT_IDLE;
13967 					fcp_post_callback(cmd);
13968 				} else {
13969 					caddr_t msg;
13970 
13971 					(void) fc_ulp_error(rval, &msg);
13972 
13973 					/*
13974 					 * This part is tricky. The abort
13975 					 * failed and now the command could
13976 					 * be completing.  The cmd_state ==
13977 					 * FCP_PKT_ABORTING should save
13978 					 * us in fcp_cmd_callback. If we
13979 					 * are already aborting ignore the
13980 					 * command in fcp_cmd_callback.
13981 					 * Here we leave this packet for 20
13982 					 * sec to be aborted in the
13983 					 * fcp_watch thread.
13984 					 */
13985 					fcp_log(CE_WARN, pptr->port_dip,
13986 					    "!Abort failed after reset %s",
13987 					    msg);
13988 
13989 					cmd->cmd_timeout =
13990 					    fcp_watchdog_time +
13991 					    cmd->cmd_pkt->pkt_time +
13992 					    FCP_FAILED_DELAY;
13993 
13994 					cmd->cmd_fp_pkt->pkt_timeout =
13995 					    FCP_INVALID_TIMEOUT;
13996 					/*
13997 					 * This is a hack, cmd is put in the
13998 					 * overflow queue so that it can be
13999 					 * timed out finally
14000 					 */
14001 					cmd->cmd_flags |= CFLAG_IN_QUEUE;
14002 
14003 					mutex_enter(&pptr->port_pkt_mutex);
14004 					if (pptr->port_pkt_head) {
14005 						ASSERT(pptr->port_pkt_tail
14006 						    != NULL);
14007 						pptr->port_pkt_tail->cmd_next
14008 						    = cmd;
14009 						pptr->port_pkt_tail = cmd;
14010 					} else {
14011 						ASSERT(pptr->port_pkt_tail
14012 						    == NULL);
14013 						pptr->port_pkt_head =
14014 						    pptr->port_pkt_tail
14015 						    = cmd;
14016 					}
14017 					cmd->cmd_next = NULL;
14018 					mutex_exit(&pptr->port_pkt_mutex);
14019 				}
14020 				mutex_enter(&tlun->lun_mutex);
14021 				cmd = tlun->lun_pkt_head;
14022 			} else {
14023 				cmd = cmd->cmd_forw;
14024 			}
14025 		}
14026 		mutex_exit(&tlun->lun_mutex);
14027 
14028 		mutex_enter(&ttgt->tgt_mutex);
14029 		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14030 		mutex_exit(&ttgt->tgt_mutex);
14031 
14032 		mutex_enter(&pptr->port_mutex);
14033 		if (tgt_cnt != ttgt->tgt_change_cnt) {
14034 			mutex_exit(&pptr->port_mutex);
14035 			return;
14036 		} else {
14037 			mutex_exit(&pptr->port_mutex);
14038 		}
14039 	}
14040 }
14041 
14042 
14043 /*
14044  * unlink the soft state, returning the soft state found (if any)
14045  *
14046  * acquires and releases the global mutex
14047  */
14048 struct fcp_port *
14049 fcp_soft_state_unlink(struct fcp_port *pptr)
14050 {
14051 	struct fcp_port	*hptr;		/* ptr index */
14052 	struct fcp_port	*tptr;		/* prev hptr */
14053 
14054 	mutex_enter(&fcp_global_mutex);
14055 	for (hptr = fcp_port_head, tptr = NULL;
14056 	    hptr != NULL;
14057 	    tptr = hptr, hptr = hptr->port_next) {
14058 		if (hptr == pptr) {
14059 			/* we found a match -- remove this item */
14060 			if (tptr == NULL) {
14061 				/* we're at the head of the list */
14062 				fcp_port_head = hptr->port_next;
14063 			} else {
14064 				tptr->port_next = hptr->port_next;
14065 			}
14066 			break;			/* success */
14067 		}
14068 	}
14069 	if (fcp_port_head == NULL) {
14070 		fcp_cleanup_blacklist(&fcp_lun_blacklist);
14071 	}
14072 	mutex_exit(&fcp_global_mutex);
14073 	return (hptr);
14074 }
14075 
14076 
14077 /*
14078  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14079  * WWN and a LUN number
14080  */
14081 /* ARGSUSED */
14082 static struct fcp_lun *
14083 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14084 {
14085 	int hash;
14086 	struct fcp_tgt *ptgt;
14087 	struct fcp_lun *plun;
14088 
14089 	ASSERT(mutex_owned(&pptr->port_mutex));
14090 
14091 	hash = FCP_HASH(wwn);
14092 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14093 	    ptgt = ptgt->tgt_next) {
14094 		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14095 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
14096 			mutex_enter(&ptgt->tgt_mutex);
14097 			for (plun = ptgt->tgt_lun;
14098 			    plun != NULL;
14099 			    plun = plun->lun_next) {
14100 				if (plun->lun_num == lun) {
14101 					mutex_exit(&ptgt->tgt_mutex);
14102 					return (plun);
14103 				}
14104 			}
14105 			mutex_exit(&ptgt->tgt_mutex);
14106 			return (NULL);
14107 		}
14108 	}
14109 	return (NULL);
14110 }
14111 
14112 /*
14113  *     Function: fcp_prepare_pkt
14114  *
14115  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14116  *		 for fcp_start(). It binds the data or partially maps it.
14117  *		 Builds the FCP header and starts the initialization of the
14118  *		 Fibre Channel header.
14119  *
14120  *     Argument: *pptr		FCP port.
14121  *		 *cmd		FCP packet.
14122  *		 *plun		LUN the command will be sent to.
14123  *
14124  *	Context: User, Kernel and Interrupt context.
14125  */
14126 static void
14127 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14128     struct fcp_lun *plun)
14129 {
14130 	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
14131 	struct fcp_tgt		*ptgt = plun->lun_tgt;
14132 	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
14133 
14134 	ASSERT(cmd->cmd_pkt->pkt_comp ||
14135 	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14136 
14137 	if (cmd->cmd_pkt->pkt_numcookies) {
14138 		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14139 			fcmd->fcp_cntl.cntl_read_data = 1;
14140 			fcmd->fcp_cntl.cntl_write_data = 0;
14141 			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14142 		} else {
14143 			fcmd->fcp_cntl.cntl_read_data = 0;
14144 			fcmd->fcp_cntl.cntl_write_data = 1;
14145 			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14146 		}
14147 
14148 		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14149 
14150 		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14151 		ASSERT(fpkt->pkt_data_cookie_cnt <=
14152 		    pptr->port_data_dma_attr.dma_attr_sgllen);
14153 
14154 		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14155 
14156 		/* FCA needs pkt_datalen to be set */
14157 		fpkt->pkt_datalen = cmd->cmd_dmacount;
14158 		fcmd->fcp_data_len = cmd->cmd_dmacount;
14159 	} else {
14160 		fcmd->fcp_cntl.cntl_read_data = 0;
14161 		fcmd->fcp_cntl.cntl_write_data = 0;
14162 		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14163 		fpkt->pkt_datalen = 0;
14164 		fcmd->fcp_data_len = 0;
14165 	}
14166 
14167 	/* set up the Tagged Queuing type */
14168 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14169 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14170 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14171 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14172 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14173 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14174 	} else {
14175 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14176 	}
14177 
14178 	fcmd->fcp_ent_addr = plun->lun_addr;
14179 
14180 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14181 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14182 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14183 	} else {
14184 		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14185 	}
14186 
14187 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14188 	cmd->cmd_pkt->pkt_state = 0;
14189 	cmd->cmd_pkt->pkt_statistics = 0;
14190 	cmd->cmd_pkt->pkt_resid = 0;
14191 
14192 	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14193 
14194 	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14195 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14196 		fpkt->pkt_comp = NULL;
14197 	} else {
14198 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14199 		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14200 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14201 		}
14202 		fpkt->pkt_comp = fcp_cmd_callback;
14203 	}
14204 
14205 	mutex_enter(&pptr->port_mutex);
14206 	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14207 		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14208 	}
14209 	mutex_exit(&pptr->port_mutex);
14210 
14211 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14212 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14213 
14214 	/*
14215 	 * Save a few kernel cycles here
14216 	 */
14217 #ifndef	__lock_lint
14218 	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14219 #endif /* __lock_lint */
14220 }
14221 
14222 static void
14223 fcp_post_callback(struct fcp_pkt *cmd)
14224 {
14225 	scsi_hba_pkt_comp(cmd->cmd_pkt);
14226 }
14227 
14228 
14229 /*
14230  * called to do polled I/O by fcp_start()
14231  *
14232  * return a transport status value, i.e. TRAN_ACCECPT for success
14233  */
14234 static int
14235 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14236 {
14237 	int	rval;
14238 
14239 #ifdef	DEBUG
14240 	mutex_enter(&pptr->port_pkt_mutex);
14241 	pptr->port_npkts++;
14242 	mutex_exit(&pptr->port_pkt_mutex);
14243 #endif /* DEBUG */
14244 
14245 	if (cmd->cmd_fp_pkt->pkt_timeout) {
14246 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14247 	} else {
14248 		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14249 	}
14250 
14251 	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14252 
14253 	cmd->cmd_state = FCP_PKT_ISSUED;
14254 
14255 	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14256 
14257 #ifdef	DEBUG
14258 	mutex_enter(&pptr->port_pkt_mutex);
14259 	pptr->port_npkts--;
14260 	mutex_exit(&pptr->port_pkt_mutex);
14261 #endif /* DEBUG */
14262 
14263 	cmd->cmd_state = FCP_PKT_IDLE;
14264 
14265 	switch (rval) {
14266 	case FC_SUCCESS:
14267 		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14268 			fcp_complete_pkt(cmd->cmd_fp_pkt);
14269 			rval = TRAN_ACCEPT;
14270 		} else {
14271 			rval = TRAN_FATAL_ERROR;
14272 		}
14273 		break;
14274 
14275 	case FC_TRAN_BUSY:
14276 		rval = TRAN_BUSY;
14277 		cmd->cmd_pkt->pkt_resid = 0;
14278 		break;
14279 
14280 	case FC_BADPACKET:
14281 		rval = TRAN_BADPKT;
14282 		break;
14283 
14284 	default:
14285 		rval = TRAN_FATAL_ERROR;
14286 		break;
14287 	}
14288 
14289 	return (rval);
14290 }
14291 
14292 
14293 /*
14294  * called by some of the following transport-called routines to convert
14295  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14296  */
14297 static struct fcp_port *
14298 fcp_dip2port(dev_info_t *dip)
14299 {
14300 	int	instance;
14301 
14302 	instance = ddi_get_instance(dip);
14303 	return (ddi_get_soft_state(fcp_softstate, instance));
14304 }
14305 
14306 
14307 /*
14308  * called internally to return a LUN given a dip
14309  */
14310 struct fcp_lun *
14311 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14312 {
14313 	struct fcp_tgt *ptgt;
14314 	struct fcp_lun *plun;
14315 	int i;
14316 
14317 
14318 	ASSERT(mutex_owned(&pptr->port_mutex));
14319 
14320 	for (i = 0; i < FCP_NUM_HASH; i++) {
14321 		for (ptgt = pptr->port_tgt_hash_table[i];
14322 		    ptgt != NULL;
14323 		    ptgt = ptgt->tgt_next) {
14324 			mutex_enter(&ptgt->tgt_mutex);
14325 			for (plun = ptgt->tgt_lun; plun != NULL;
14326 			    plun = plun->lun_next) {
14327 				mutex_enter(&plun->lun_mutex);
14328 				if (plun->lun_cip == cip) {
14329 					mutex_exit(&plun->lun_mutex);
14330 					mutex_exit(&ptgt->tgt_mutex);
14331 					return (plun); /* match found */
14332 				}
14333 				mutex_exit(&plun->lun_mutex);
14334 			}
14335 			mutex_exit(&ptgt->tgt_mutex);
14336 		}
14337 	}
14338 	return (NULL);				/* no LUN found */
14339 }
14340 
14341 /*
14342  * pass an element to the hotplug list, kick the hotplug thread
14343  * and wait for the element to get processed by the hotplug thread.
14344  * on return the element is freed.
14345  *
14346  * return zero success and non-zero on failure
14347  *
14348  * acquires/releases the target mutex
14349  *
14350  */
14351 static int
14352 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14353     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14354 {
14355 	struct fcp_hp_elem	*elem;
14356 	int			rval;
14357 
14358 	mutex_enter(&plun->lun_tgt->tgt_mutex);
14359 	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14360 	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14361 		mutex_exit(&plun->lun_tgt->tgt_mutex);
14362 		fcp_log(CE_CONT, pptr->port_dip,
14363 		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14364 		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14365 		return (NDI_FAILURE);
14366 	}
14367 	mutex_exit(&plun->lun_tgt->tgt_mutex);
14368 	mutex_enter(&elem->mutex);
14369 	if (elem->wait) {
14370 		while (elem->wait) {
14371 			cv_wait(&elem->cv, &elem->mutex);
14372 		}
14373 	}
14374 	rval = (elem->result);
14375 	mutex_exit(&elem->mutex);
14376 	mutex_destroy(&elem->mutex);
14377 	cv_destroy(&elem->cv);
14378 	kmem_free(elem, sizeof (struct fcp_hp_elem));
14379 	return (rval);
14380 }
14381 
14382 /*
14383  * pass an element to the hotplug list, and then
14384  * kick the hotplug thread
14385  *
14386  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14387  *
14388  * acquires/releases the hotplug mutex
14389  *
14390  * called with the target mutex owned
14391  *
14392  * memory acquired in NOSLEEP mode
14393  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14394  *	 for the hp daemon to process the request and is responsible for
14395  *	 freeing the element
14396  */
14397 static struct fcp_hp_elem *
14398 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14399     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14400 {
14401 	struct fcp_hp_elem	*elem;
14402 	dev_info_t *pdip;
14403 
14404 	ASSERT(pptr != NULL);
14405 	ASSERT(plun != NULL);
14406 	ASSERT(plun->lun_tgt != NULL);
14407 	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14408 
14409 	/* create space for a hotplug element */
14410 	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14411 	    == NULL) {
14412 		fcp_log(CE_WARN, NULL,
14413 		    "!can't allocate memory for hotplug element");
14414 		return (NULL);
14415 	}
14416 
14417 	/* fill in hotplug element */
14418 	elem->port = pptr;
14419 	elem->lun = plun;
14420 	elem->cip = cip;
14421 	elem->old_lun_mpxio = plun->lun_mpxio;
14422 	elem->what = what;
14423 	elem->flags = flags;
14424 	elem->link_cnt = link_cnt;
14425 	elem->tgt_cnt = tgt_cnt;
14426 	elem->wait = wait;
14427 	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14428 	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14429 
14430 	/* schedule the hotplug task */
14431 	pdip = pptr->port_dip;
14432 	mutex_enter(&plun->lun_mutex);
14433 	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14434 		plun->lun_event_count++;
14435 		elem->event_cnt = plun->lun_event_count;
14436 	}
14437 	mutex_exit(&plun->lun_mutex);
14438 	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14439 	    (void *)elem, KM_NOSLEEP) == NULL) {
14440 		mutex_enter(&plun->lun_mutex);
14441 		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14442 			plun->lun_event_count--;
14443 		}
14444 		mutex_exit(&plun->lun_mutex);
14445 		kmem_free(elem, sizeof (*elem));
14446 		return (0);
14447 	}
14448 
14449 	return (elem);
14450 }
14451 
14452 
14453 static void
14454 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14455 {
14456 	int			rval;
14457 	struct scsi_address	*ap;
14458 	struct fcp_lun	*plun;
14459 	struct fcp_tgt	*ptgt;
14460 	fc_packet_t	*fpkt;
14461 
14462 	ap = &cmd->cmd_pkt->pkt_address;
14463 	plun = ADDR2LUN(ap);
14464 	ptgt = plun->lun_tgt;
14465 
14466 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14467 
14468 	cmd->cmd_state = FCP_PKT_IDLE;
14469 
14470 	mutex_enter(&pptr->port_mutex);
14471 	mutex_enter(&ptgt->tgt_mutex);
14472 	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14473 	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14474 		fc_ulp_rscn_info_t *rscnp;
14475 
14476 		cmd->cmd_state = FCP_PKT_ISSUED;
14477 
14478 		/*
14479 		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14480 		 * originally NULL, hence we try to set it to the pd pointed
14481 		 * to by the SCSI device we're trying to get to.
14482 		 */
14483 
14484 		fpkt = cmd->cmd_fp_pkt;
14485 		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14486 			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14487 			/*
14488 			 * We need to notify the transport that we now have a
14489 			 * reference to the remote port handle.
14490 			 */
14491 			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14492 		}
14493 
14494 		mutex_exit(&ptgt->tgt_mutex);
14495 		mutex_exit(&pptr->port_mutex);
14496 
14497 		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14498 
14499 		/* prepare the packet */
14500 
14501 		fcp_prepare_pkt(pptr, cmd, plun);
14502 
14503 		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14504 		    pkt_ulp_rscn_infop;
14505 
14506 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14507 		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14508 
14509 		if (rscnp != NULL) {
14510 			rscnp->ulp_rscn_count =
14511 			    fc_ulp_get_rscn_count(pptr->
14512 			    port_fp_handle);
14513 		}
14514 
14515 		rval = fcp_transport(pptr->port_fp_handle,
14516 		    cmd->cmd_fp_pkt, 0);
14517 
14518 		if (rval == FC_SUCCESS) {
14519 			return;
14520 		}
14521 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14522 	} else {
14523 		mutex_exit(&ptgt->tgt_mutex);
14524 		mutex_exit(&pptr->port_mutex);
14525 	}
14526 
14527 	fcp_queue_pkt(pptr, cmd);
14528 }
14529 
14530 
14531 static void
14532 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14533 {
14534 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14535 
14536 	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14537 	cmd->cmd_state = FCP_PKT_IDLE;
14538 
14539 	cmd->cmd_pkt->pkt_reason = reason;
14540 	cmd->cmd_pkt->pkt_state = 0;
14541 	cmd->cmd_pkt->pkt_statistics = statistics;
14542 
14543 	fcp_post_callback(cmd);
14544 }
14545 
14546 /*
14547  *     Function: fcp_queue_pkt
14548  *
14549  *  Description: This function queues the packet passed by the caller into
14550  *		 the list of packets of the FCP port.
14551  *
14552  *     Argument: *pptr		FCP port.
14553  *		 *cmd		FCP packet to queue.
14554  *
14555  * Return Value: None
14556  *
14557  *	Context: User, Kernel and Interrupt context.
14558  */
14559 static void
14560 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14561 {
14562 	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14563 
14564 	mutex_enter(&pptr->port_pkt_mutex);
14565 	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14566 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14567 	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14568 
14569 	/*
14570 	 * zero pkt_time means hang around for ever
14571 	 */
14572 	if (cmd->cmd_pkt->pkt_time) {
14573 		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14574 			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14575 		} else {
14576 			/*
14577 			 * Indicate the watch thread to fail the
14578 			 * command by setting it to highest value
14579 			 */
14580 			cmd->cmd_timeout = fcp_watchdog_time;
14581 			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14582 		}
14583 	}
14584 
14585 	if (pptr->port_pkt_head) {
14586 		ASSERT(pptr->port_pkt_tail != NULL);
14587 
14588 		pptr->port_pkt_tail->cmd_next = cmd;
14589 		pptr->port_pkt_tail = cmd;
14590 	} else {
14591 		ASSERT(pptr->port_pkt_tail == NULL);
14592 
14593 		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14594 	}
14595 	cmd->cmd_next = NULL;
14596 	mutex_exit(&pptr->port_pkt_mutex);
14597 }
14598 
14599 /*
14600  *     Function: fcp_update_targets
14601  *
14602  *  Description: This function applies the specified change of state to all
14603  *		 the targets listed.  The operation applied is 'set'.
14604  *
14605  *     Argument: *pptr		FCP port.
14606  *		 *dev_list	Array of fc_portmap_t structures.
14607  *		 count		Length of dev_list.
14608  *		 state		State bits to update.
14609  *		 cause		Reason for the update.
14610  *
14611  * Return Value: None
14612  *
14613  *	Context: User, Kernel and Interrupt context.
14614  *		 The mutex pptr->port_mutex must be held.
14615  */
14616 static void
14617 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14618     uint32_t count, uint32_t state, int cause)
14619 {
14620 	fc_portmap_t		*map_entry;
14621 	struct fcp_tgt	*ptgt;
14622 
14623 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14624 
14625 	while (count--) {
14626 		map_entry = &(dev_list[count]);
14627 		ptgt = fcp_lookup_target(pptr,
14628 		    (uchar_t *)&(map_entry->map_pwwn));
14629 		if (ptgt == NULL) {
14630 			continue;
14631 		}
14632 
14633 		mutex_enter(&ptgt->tgt_mutex);
14634 		ptgt->tgt_trace = 0;
14635 		ptgt->tgt_change_cnt++;
14636 		ptgt->tgt_statec_cause = cause;
14637 		ptgt->tgt_tmp_cnt = 1;
14638 		fcp_update_tgt_state(ptgt, FCP_SET, state);
14639 		mutex_exit(&ptgt->tgt_mutex);
14640 	}
14641 }
14642 
14643 static int
14644 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14645     int lcount, int tcount, int cause)
14646 {
14647 	int rval;
14648 
14649 	mutex_enter(&pptr->port_mutex);
14650 	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14651 	mutex_exit(&pptr->port_mutex);
14652 
14653 	return (rval);
14654 }
14655 
14656 
14657 static int
14658 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14659     int lcount, int tcount, int cause)
14660 {
14661 	int	finish_init = 0;
14662 	int	finish_tgt = 0;
14663 	int	do_finish_init = 0;
14664 	int	rval = FCP_NO_CHANGE;
14665 
14666 	if (cause == FCP_CAUSE_LINK_CHANGE ||
14667 	    cause == FCP_CAUSE_LINK_DOWN) {
14668 		do_finish_init = 1;
14669 	}
14670 
14671 	if (ptgt != NULL) {
14672 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14673 		    FCP_BUF_LEVEL_2, 0,
14674 		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14675 		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14676 		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14677 		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14678 		    ptgt->tgt_d_id, ptgt->tgt_done);
14679 
14680 		mutex_enter(&ptgt->tgt_mutex);
14681 
14682 		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14683 			rval = FCP_DEV_CHANGE;
14684 			if (do_finish_init && ptgt->tgt_done == 0) {
14685 				ptgt->tgt_done++;
14686 				finish_init = 1;
14687 			}
14688 		} else {
14689 			if (--ptgt->tgt_tmp_cnt <= 0) {
14690 				ptgt->tgt_tmp_cnt = 0;
14691 				finish_tgt = 1;
14692 
14693 				if (do_finish_init) {
14694 					finish_init = 1;
14695 				}
14696 			}
14697 		}
14698 		mutex_exit(&ptgt->tgt_mutex);
14699 	} else {
14700 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14701 		    FCP_BUF_LEVEL_2, 0,
14702 		    "Call Finish Init for NO target");
14703 
14704 		if (do_finish_init) {
14705 			finish_init = 1;
14706 		}
14707 	}
14708 
14709 	if (finish_tgt) {
14710 		ASSERT(ptgt != NULL);
14711 
14712 		mutex_enter(&ptgt->tgt_mutex);
14713 #ifdef	DEBUG
14714 		bzero(ptgt->tgt_tmp_cnt_stack,
14715 		    sizeof (ptgt->tgt_tmp_cnt_stack));
14716 
14717 		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14718 		    FCP_STACK_DEPTH);
14719 #endif /* DEBUG */
14720 		mutex_exit(&ptgt->tgt_mutex);
14721 
14722 		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14723 	}
14724 
14725 	if (finish_init && lcount == pptr->port_link_cnt) {
14726 		ASSERT(pptr->port_tmp_cnt > 0);
14727 		if (--pptr->port_tmp_cnt == 0) {
14728 			fcp_finish_init(pptr);
14729 		}
14730 	} else if (lcount != pptr->port_link_cnt) {
14731 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14732 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14733 		    "fcp_call_finish_init_held,1: state change occured"
14734 		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14735 	}
14736 
14737 	return (rval);
14738 }
14739 
14740 static void
14741 fcp_reconfigure_luns(void * tgt_handle)
14742 {
14743 	uint32_t		dev_cnt;
14744 	fc_portmap_t		*devlist;
14745 	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14746 	struct fcp_port		*pptr = ptgt->tgt_port;
14747 
14748 	/*
14749 	 * If the timer that fires this off got canceled too late, the
14750 	 * target could have been destroyed.
14751 	 */
14752 
14753 	if (ptgt->tgt_tid == NULL) {
14754 		return;
14755 	}
14756 
14757 	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14758 	if (devlist == NULL) {
14759 		fcp_log(CE_WARN, pptr->port_dip,
14760 		    "!fcp%d: failed to allocate for portmap",
14761 		    pptr->port_instance);
14762 		return;
14763 	}
14764 
14765 	dev_cnt = 1;
14766 	devlist->map_pd = ptgt->tgt_pd_handle;
14767 	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14768 	devlist->map_did.port_id = ptgt->tgt_d_id;
14769 
14770 	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14771 	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14772 
14773 	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14774 	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14775 	devlist->map_flags = 0;
14776 
14777 	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14778 	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14779 
14780 	/*
14781 	 * Clear the tgt_tid after no more references to
14782 	 * the fcp_tgt
14783 	 */
14784 	mutex_enter(&ptgt->tgt_mutex);
14785 	ptgt->tgt_tid = NULL;
14786 	mutex_exit(&ptgt->tgt_mutex);
14787 
14788 	kmem_free(devlist, sizeof (*devlist));
14789 }
14790 
14791 
14792 static void
14793 fcp_free_targets(struct fcp_port *pptr)
14794 {
14795 	int			i;
14796 	struct fcp_tgt	*ptgt;
14797 
14798 	mutex_enter(&pptr->port_mutex);
14799 	for (i = 0; i < FCP_NUM_HASH; i++) {
14800 		ptgt = pptr->port_tgt_hash_table[i];
14801 		while (ptgt != NULL) {
14802 			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14803 
14804 			fcp_free_target(ptgt);
14805 			ptgt = next_tgt;
14806 		}
14807 	}
14808 	mutex_exit(&pptr->port_mutex);
14809 }
14810 
14811 
14812 static void
14813 fcp_free_target(struct fcp_tgt *ptgt)
14814 {
14815 	struct fcp_lun	*plun;
14816 	timeout_id_t		tid;
14817 
14818 	mutex_enter(&ptgt->tgt_mutex);
14819 	tid = ptgt->tgt_tid;
14820 
14821 	/*
14822 	 * Cancel any pending timeouts for this target.
14823 	 */
14824 
14825 	if (tid != NULL) {
14826 		/*
14827 		 * Set tgt_tid to NULL first to avoid a race in the callback.
14828 		 * If tgt_tid is NULL, the callback will simply return.
14829 		 */
14830 		ptgt->tgt_tid = NULL;
14831 		mutex_exit(&ptgt->tgt_mutex);
14832 		(void) untimeout(tid);
14833 		mutex_enter(&ptgt->tgt_mutex);
14834 	}
14835 
14836 	plun = ptgt->tgt_lun;
14837 	while (plun != NULL) {
14838 		struct fcp_lun *next_lun = plun->lun_next;
14839 
14840 		fcp_dealloc_lun(plun);
14841 		plun = next_lun;
14842 	}
14843 
14844 	mutex_exit(&ptgt->tgt_mutex);
14845 	fcp_dealloc_tgt(ptgt);
14846 }
14847 
14848 /*
14849  *     Function: fcp_is_retryable
14850  *
14851  *  Description: Indicates if the internal packet is retryable.
14852  *
14853  *     Argument: *icmd		FCP internal packet.
14854  *
14855  * Return Value: 0	Not retryable
14856  *		 1	Retryable
14857  *
14858  *	Context: User, Kernel and Interrupt context
14859  */
14860 static int
14861 fcp_is_retryable(struct fcp_ipkt *icmd)
14862 {
14863 	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14864 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14865 		return (0);
14866 	}
14867 
14868 	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14869 	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14870 }
14871 
14872 /*
14873  *     Function: fcp_create_on_demand
14874  *
14875  *     Argument: *pptr		FCP port.
14876  *		 *pwwn		Port WWN.
14877  *
14878  * Return Value: 0	Success
14879  *		 EIO
14880  *		 ENOMEM
14881  *		 EBUSY
14882  *		 EINVAL
14883  *
14884  *	Context: User and Kernel context
14885  */
14886 static int
14887 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14888 {
14889 	int			wait_ms;
14890 	int			tcount;
14891 	int			lcount;
14892 	int			ret;
14893 	int			error;
14894 	int			rval = EIO;
14895 	int			ntries;
14896 	fc_portmap_t		*devlist;
14897 	opaque_t		pd;
14898 	struct fcp_lun		*plun;
14899 	struct fcp_tgt		*ptgt;
14900 	int			old_manual = 0;
14901 
14902 	/* Allocates the fc_portmap_t structure. */
14903 	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14904 
14905 	/*
14906 	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14907 	 * in the commented statement below:
14908 	 *
14909 	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14910 	 *
14911 	 * Below, the deadline for the discovery process is set.
14912 	 */
14913 	mutex_enter(&pptr->port_mutex);
14914 	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14915 	mutex_exit(&pptr->port_mutex);
14916 
14917 	/*
14918 	 * We try to find the remote port based on the WWN provided by the
14919 	 * caller.  We actually ask fp/fctl if it has it.
14920 	 */
14921 	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14922 	    (la_wwn_t *)pwwn, &error, 1);
14923 
14924 	if (pd == NULL) {
14925 		kmem_free(devlist, sizeof (*devlist));
14926 		return (rval);
14927 	}
14928 
14929 	/*
14930 	 * The remote port was found.  We ask fp/fctl to update our
14931 	 * fc_portmap_t structure.
14932 	 */
14933 	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14934 	    (la_wwn_t *)pwwn, devlist);
14935 	if (ret != FC_SUCCESS) {
14936 		kmem_free(devlist, sizeof (*devlist));
14937 		return (rval);
14938 	}
14939 
14940 	/*
14941 	 * The map flag field is set to indicates that the creation is being
14942 	 * done at the user request (Ioclt probably luxadm or cfgadm).
14943 	 */
14944 	devlist->map_type = PORT_DEVICE_USER_CREATE;
14945 
14946 	mutex_enter(&pptr->port_mutex);
14947 
14948 	/*
14949 	 * We check to see if fcp already has a target that describes the
14950 	 * device being created.  If not it is created.
14951 	 */
14952 	ptgt = fcp_lookup_target(pptr, pwwn);
14953 	if (ptgt == NULL) {
14954 		lcount = pptr->port_link_cnt;
14955 		mutex_exit(&pptr->port_mutex);
14956 
14957 		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14958 		if (ptgt == NULL) {
14959 			fcp_log(CE_WARN, pptr->port_dip,
14960 			    "!FC target allocation failed");
14961 			return (ENOMEM);
14962 		}
14963 
14964 		mutex_enter(&pptr->port_mutex);
14965 	}
14966 
14967 	mutex_enter(&ptgt->tgt_mutex);
14968 	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
14969 	ptgt->tgt_tmp_cnt = 1;
14970 	ptgt->tgt_device_created = 0;
14971 	/*
14972 	 * If fabric and auto config is set but the target was
14973 	 * manually unconfigured then reset to the manual_config_only to
14974 	 * 0 so the device will get configured.
14975 	 */
14976 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14977 	    fcp_enable_auto_configuration &&
14978 	    ptgt->tgt_manual_config_only == 1) {
14979 		old_manual = 1;
14980 		ptgt->tgt_manual_config_only = 0;
14981 	}
14982 	mutex_exit(&ptgt->tgt_mutex);
14983 
14984 	fcp_update_targets(pptr, devlist, 1,
14985 	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
14986 
14987 	lcount = pptr->port_link_cnt;
14988 	tcount = ptgt->tgt_change_cnt;
14989 
14990 	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
14991 	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
14992 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14993 		    fcp_enable_auto_configuration && old_manual) {
14994 			mutex_enter(&ptgt->tgt_mutex);
14995 			ptgt->tgt_manual_config_only = 1;
14996 			mutex_exit(&ptgt->tgt_mutex);
14997 		}
14998 
14999 		if (pptr->port_link_cnt != lcount ||
15000 		    ptgt->tgt_change_cnt != tcount) {
15001 			rval = EBUSY;
15002 		}
15003 		mutex_exit(&pptr->port_mutex);
15004 
15005 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15006 		    FCP_BUF_LEVEL_3, 0,
15007 		    "fcp_create_on_demand: mapflags ptgt=%x, "
15008 		    "lcount=%x::port_link_cnt=%x, "
15009 		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
15010 		    ptgt, lcount, pptr->port_link_cnt,
15011 		    tcount, ptgt->tgt_change_cnt, rval);
15012 		return (rval);
15013 	}
15014 
15015 	/*
15016 	 * Due to lack of synchronization mechanisms, we perform
15017 	 * periodic monitoring of our request; Because requests
15018 	 * get dropped when another one supercedes (either because
15019 	 * of a link change or a target change), it is difficult to
15020 	 * provide a clean synchronization mechanism (such as a
15021 	 * semaphore or a conditional variable) without exhaustively
15022 	 * rewriting the mainline discovery code of this driver.
15023 	 */
15024 	wait_ms = 500;
15025 
15026 	ntries = fcp_max_target_retries;
15027 
15028 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15029 	    FCP_BUF_LEVEL_3, 0,
15030 	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15031 	    "lcount=%x::port_link_cnt=%x, "
15032 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15033 	    "tgt_tmp_cnt =%x",
15034 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15035 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15036 	    ptgt->tgt_tmp_cnt);
15037 
15038 	mutex_enter(&ptgt->tgt_mutex);
15039 	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15040 	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15041 		mutex_exit(&ptgt->tgt_mutex);
15042 		mutex_exit(&pptr->port_mutex);
15043 
15044 		delay(drv_usectohz(wait_ms * 1000));
15045 
15046 		mutex_enter(&pptr->port_mutex);
15047 		mutex_enter(&ptgt->tgt_mutex);
15048 	}
15049 
15050 
15051 	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15052 		rval = EBUSY;
15053 	} else {
15054 		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15055 		    FCP_TGT_NODE_PRESENT) {
15056 			rval = 0;
15057 		}
15058 	}
15059 
15060 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15061 	    FCP_BUF_LEVEL_3, 0,
15062 	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15063 	    "lcount=%x::port_link_cnt=%x, "
15064 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15065 	    "tgt_tmp_cnt =%x",
15066 	    ntries, ptgt, lcount, pptr->port_link_cnt,
15067 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15068 	    ptgt->tgt_tmp_cnt);
15069 
15070 	if (rval) {
15071 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15072 		    fcp_enable_auto_configuration && old_manual) {
15073 			ptgt->tgt_manual_config_only = 1;
15074 		}
15075 		mutex_exit(&ptgt->tgt_mutex);
15076 		mutex_exit(&pptr->port_mutex);
15077 		kmem_free(devlist, sizeof (*devlist));
15078 
15079 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15080 		    FCP_BUF_LEVEL_3, 0,
15081 		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15082 		    "lcount=%x::port_link_cnt=%x, "
15083 		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15084 		    "tgt_device_created=%x, tgt D_ID=%x",
15085 		    ntries, ptgt, lcount, pptr->port_link_cnt,
15086 		    tcount, ptgt->tgt_change_cnt, rval,
15087 		    ptgt->tgt_device_created, ptgt->tgt_d_id);
15088 		return (rval);
15089 	}
15090 
15091 	if ((plun = ptgt->tgt_lun) != NULL) {
15092 		tcount = plun->lun_tgt->tgt_change_cnt;
15093 	} else {
15094 		rval = EINVAL;
15095 	}
15096 	lcount = pptr->port_link_cnt;
15097 
15098 	/*
15099 	 * Configuring the target with no LUNs will fail. We
15100 	 * should reset the node state so that it is not
15101 	 * automatically configured when the LUNs are added
15102 	 * to this target.
15103 	 */
15104 	if (ptgt->tgt_lun_cnt == 0) {
15105 		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15106 	}
15107 	mutex_exit(&ptgt->tgt_mutex);
15108 	mutex_exit(&pptr->port_mutex);
15109 
15110 	while (plun) {
15111 		child_info_t	*cip;
15112 
15113 		mutex_enter(&plun->lun_mutex);
15114 		cip = plun->lun_cip;
15115 		mutex_exit(&plun->lun_mutex);
15116 
15117 		mutex_enter(&ptgt->tgt_mutex);
15118 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15119 			mutex_exit(&ptgt->tgt_mutex);
15120 
15121 			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15122 			    FCP_ONLINE, lcount, tcount,
15123 			    NDI_ONLINE_ATTACH);
15124 			if (rval != NDI_SUCCESS) {
15125 				FCP_TRACE(fcp_logq,
15126 				    pptr->port_instbuf, fcp_trace,
15127 				    FCP_BUF_LEVEL_3, 0,
15128 				    "fcp_create_on_demand: "
15129 				    "pass_to_hp_and_wait failed "
15130 				    "rval=%x", rval);
15131 				rval = EIO;
15132 			} else {
15133 				mutex_enter(&LUN_TGT->tgt_mutex);
15134 				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15135 				    FCP_LUN_BUSY);
15136 				mutex_exit(&LUN_TGT->tgt_mutex);
15137 			}
15138 			mutex_enter(&ptgt->tgt_mutex);
15139 		}
15140 
15141 		plun = plun->lun_next;
15142 		mutex_exit(&ptgt->tgt_mutex);
15143 	}
15144 
15145 	kmem_free(devlist, sizeof (*devlist));
15146 
15147 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15148 	    fcp_enable_auto_configuration && old_manual) {
15149 		mutex_enter(&ptgt->tgt_mutex);
15150 		/* if successful then set manual to 0 */
15151 		if (rval == 0) {
15152 			ptgt->tgt_manual_config_only = 0;
15153 		} else {
15154 			/* reset to 1 so the user has to do the config */
15155 			ptgt->tgt_manual_config_only = 1;
15156 		}
15157 		mutex_exit(&ptgt->tgt_mutex);
15158 	}
15159 
15160 	return (rval);
15161 }
15162 
15163 
15164 static void
15165 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15166 {
15167 	int		count;
15168 	uchar_t		byte;
15169 
15170 	count = 0;
15171 	while (*string) {
15172 		byte = FCP_ATOB(*string); string++;
15173 		byte = byte << 4 | FCP_ATOB(*string); string++;
15174 		bytes[count++] = byte;
15175 
15176 		if (count >= byte_len) {
15177 			break;
15178 		}
15179 	}
15180 }
15181 
15182 static void
15183 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15184 {
15185 	int		i;
15186 
15187 	for (i = 0; i < FC_WWN_SIZE; i++) {
15188 		(void) sprintf(string + (i * 2),
15189 		    "%02x", wwn[i]);
15190 	}
15191 
15192 }
15193 
15194 static void
15195 fcp_print_error(fc_packet_t *fpkt)
15196 {
15197 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15198 	    fpkt->pkt_ulp_private;
15199 	struct fcp_port	*pptr;
15200 	struct fcp_tgt	*ptgt;
15201 	struct fcp_lun	*plun;
15202 	caddr_t			buf;
15203 	int			scsi_cmd = 0;
15204 
15205 	ptgt = icmd->ipkt_tgt;
15206 	plun = icmd->ipkt_lun;
15207 	pptr = ptgt->tgt_port;
15208 
15209 	buf = kmem_zalloc(256, KM_NOSLEEP);
15210 	if (buf == NULL) {
15211 		return;
15212 	}
15213 
15214 	switch (icmd->ipkt_opcode) {
15215 	case SCMD_REPORT_LUN:
15216 		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15217 		    " lun=0x%%x failed");
15218 		scsi_cmd++;
15219 		break;
15220 
15221 	case SCMD_INQUIRY_PAGE83:
15222 		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15223 		    " lun=0x%%x failed");
15224 		scsi_cmd++;
15225 		break;
15226 
15227 	case SCMD_INQUIRY:
15228 		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15229 		    " lun=0x%%x failed");
15230 		scsi_cmd++;
15231 		break;
15232 
15233 	case LA_ELS_PLOGI:
15234 		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15235 		break;
15236 
15237 	case LA_ELS_PRLI:
15238 		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15239 		break;
15240 	}
15241 
15242 	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15243 		struct fcp_rsp		response, *rsp;
15244 		uchar_t			asc, ascq;
15245 		caddr_t			sense_key = NULL;
15246 		struct fcp_rsp_info	fcp_rsp_err, *bep;
15247 
15248 		if (icmd->ipkt_nodma) {
15249 			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15250 			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15251 			    sizeof (struct fcp_rsp));
15252 		} else {
15253 			rsp = &response;
15254 			bep = &fcp_rsp_err;
15255 
15256 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15257 			    sizeof (struct fcp_rsp));
15258 
15259 			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15260 			    bep, fpkt->pkt_resp_acc,
15261 			    sizeof (struct fcp_rsp_info));
15262 		}
15263 
15264 
15265 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15266 			(void) sprintf(buf + strlen(buf),
15267 			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15268 			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15269 			    " senselen=%%x. Giving up");
15270 
15271 			fcp_log(CE_WARN, pptr->port_dip, buf,
15272 			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15273 			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15274 			    rsp->fcp_u.fcp_status.reserved_1,
15275 			    rsp->fcp_response_len, rsp->fcp_sense_len);
15276 
15277 			kmem_free(buf, 256);
15278 			return;
15279 		}
15280 
15281 		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15282 		    bep->rsp_code != FCP_NO_FAILURE) {
15283 			(void) sprintf(buf + strlen(buf),
15284 			    " FCP Response code = 0x%x", bep->rsp_code);
15285 		}
15286 
15287 		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15288 			struct scsi_extended_sense sense_info, *sense_ptr;
15289 
15290 			if (icmd->ipkt_nodma) {
15291 				sense_ptr = (struct scsi_extended_sense *)
15292 				    ((caddr_t)fpkt->pkt_resp +
15293 				    sizeof (struct fcp_rsp) +
15294 				    rsp->fcp_response_len);
15295 			} else {
15296 				sense_ptr = &sense_info;
15297 
15298 				FCP_CP_IN(fpkt->pkt_resp +
15299 				    sizeof (struct fcp_rsp) +
15300 				    rsp->fcp_response_len, &sense_info,
15301 				    fpkt->pkt_resp_acc,
15302 				    sizeof (struct scsi_extended_sense));
15303 			}
15304 
15305 			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15306 			    NUM_IMPL_SENSE_KEYS) {
15307 				sense_key = sense_keys[sense_ptr->es_key];
15308 			} else {
15309 				sense_key = "Undefined";
15310 			}
15311 
15312 			asc = sense_ptr->es_add_code;
15313 			ascq = sense_ptr->es_qual_code;
15314 
15315 			(void) sprintf(buf + strlen(buf),
15316 			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15317 			    " Giving up");
15318 
15319 			fcp_log(CE_WARN, pptr->port_dip, buf,
15320 			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15321 			    asc, ascq);
15322 		} else {
15323 			(void) sprintf(buf + strlen(buf),
15324 			    " : SCSI status=%%x. Giving up");
15325 
15326 			fcp_log(CE_WARN, pptr->port_dip, buf,
15327 			    ptgt->tgt_d_id, plun->lun_num,
15328 			    rsp->fcp_u.fcp_status.scsi_status);
15329 		}
15330 	} else {
15331 		caddr_t state, reason, action, expln;
15332 
15333 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15334 		    &action, &expln);
15335 
15336 		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15337 		    " Reason:%%s. Giving up");
15338 
15339 		if (scsi_cmd) {
15340 			fcp_log(CE_WARN, pptr->port_dip, buf,
15341 			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15342 		} else {
15343 			fcp_log(CE_WARN, pptr->port_dip, buf,
15344 			    ptgt->tgt_d_id, state, reason);
15345 		}
15346 	}
15347 
15348 	kmem_free(buf, 256);
15349 }
15350 
15351 
15352 static int
15353 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15354     struct fcp_ipkt *icmd, int rval, caddr_t op)
15355 {
15356 	int	ret = DDI_FAILURE;
15357 	char	*error;
15358 
15359 	switch (rval) {
15360 	case FC_DEVICE_BUSY_NEW_RSCN:
15361 		/*
15362 		 * This means that there was a new RSCN that the transport
15363 		 * knows about (which the ULP *may* know about too) but the
15364 		 * pkt that was sent down was related to an older RSCN. So, we
15365 		 * are just going to reset the retry count and deadline and
15366 		 * continue to retry. The idea is that transport is currently
15367 		 * working on the new RSCN and will soon let the ULPs know
15368 		 * about it and when it does the existing logic will kick in
15369 		 * where it will change the tcount to indicate that something
15370 		 * changed on the target. So, rediscovery will start and there
15371 		 * will not be an infinite retry.
15372 		 *
15373 		 * For a full flow of how the RSCN info is transferred back and
15374 		 * forth, see fp.c
15375 		 */
15376 		icmd->ipkt_retries = 0;
15377 		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15378 		    FCP_ICMD_DEADLINE;
15379 
15380 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15381 		    FCP_BUF_LEVEL_3, 0,
15382 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15383 		    rval, ptgt->tgt_d_id);
15384 		/* FALLTHROUGH */
15385 
15386 	case FC_STATEC_BUSY:
15387 	case FC_DEVICE_BUSY:
15388 	case FC_PBUSY:
15389 	case FC_FBUSY:
15390 	case FC_TRAN_BUSY:
15391 	case FC_OFFLINE:
15392 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15393 		    FCP_BUF_LEVEL_3, 0,
15394 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15395 		    rval, ptgt->tgt_d_id);
15396 		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15397 		    fcp_is_retryable(icmd)) {
15398 			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15399 			ret = DDI_SUCCESS;
15400 		}
15401 		break;
15402 
15403 	case FC_LOGINREQ:
15404 		/*
15405 		 * FC_LOGINREQ used to be handled just like all the cases
15406 		 * above. It has been changed to handled a PRLI that fails
15407 		 * with FC_LOGINREQ different than other ipkts that fail
15408 		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15409 		 * a simple matter to turn it into a PLOGI instead, so that's
15410 		 * exactly what we do here.
15411 		 */
15412 		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15413 			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15414 			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15415 			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15416 		} else {
15417 			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15418 			    FCP_BUF_LEVEL_3, 0,
15419 			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15420 			    rval, ptgt->tgt_d_id);
15421 			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15422 			    fcp_is_retryable(icmd)) {
15423 				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15424 				ret = DDI_SUCCESS;
15425 			}
15426 		}
15427 		break;
15428 
15429 	default:
15430 		mutex_enter(&pptr->port_mutex);
15431 		mutex_enter(&ptgt->tgt_mutex);
15432 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15433 			mutex_exit(&ptgt->tgt_mutex);
15434 			mutex_exit(&pptr->port_mutex);
15435 
15436 			(void) fc_ulp_error(rval, &error);
15437 			fcp_log(CE_WARN, pptr->port_dip,
15438 			    "!Failed to send %s to D_ID=%x error=%s",
15439 			    op, ptgt->tgt_d_id, error);
15440 		} else {
15441 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15442 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15443 			    "fcp_handle_ipkt_errors,1: state change occured"
15444 			    " for D_ID=0x%x", ptgt->tgt_d_id);
15445 			mutex_exit(&ptgt->tgt_mutex);
15446 			mutex_exit(&pptr->port_mutex);
15447 		}
15448 		break;
15449 	}
15450 
15451 	return (ret);
15452 }
15453 
15454 
15455 /*
15456  * Check of outstanding commands on any LUN for this target
15457  */
15458 static int
15459 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15460 {
15461 	struct	fcp_lun	*plun;
15462 	struct	fcp_pkt	*cmd;
15463 
15464 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15465 		mutex_enter(&plun->lun_mutex);
15466 		for (cmd = plun->lun_pkt_head; cmd != NULL;
15467 		    cmd = cmd->cmd_forw) {
15468 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15469 				mutex_exit(&plun->lun_mutex);
15470 				return (FC_SUCCESS);
15471 			}
15472 		}
15473 		mutex_exit(&plun->lun_mutex);
15474 	}
15475 
15476 	return (FC_FAILURE);
15477 }
15478 
15479 static fc_portmap_t *
15480 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15481 {
15482 	int			i;
15483 	fc_portmap_t		*devlist;
15484 	fc_portmap_t		*devptr = NULL;
15485 	struct fcp_tgt	*ptgt;
15486 
15487 	mutex_enter(&pptr->port_mutex);
15488 	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15489 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15490 		    ptgt = ptgt->tgt_next) {
15491 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15492 				++*dev_cnt;
15493 			}
15494 		}
15495 	}
15496 
15497 	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15498 	    KM_NOSLEEP);
15499 	if (devlist == NULL) {
15500 		mutex_exit(&pptr->port_mutex);
15501 		fcp_log(CE_WARN, pptr->port_dip,
15502 		    "!fcp%d: failed to allocate for portmap for construct map",
15503 		    pptr->port_instance);
15504 		return (devptr);
15505 	}
15506 
15507 	for (i = 0; i < FCP_NUM_HASH; i++) {
15508 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15509 		    ptgt = ptgt->tgt_next) {
15510 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15511 				int ret;
15512 
15513 				ret = fc_ulp_pwwn_to_portmap(
15514 				    pptr->port_fp_handle,
15515 				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15516 				    devlist);
15517 
15518 				if (ret == FC_SUCCESS) {
15519 					devlist++;
15520 					continue;
15521 				}
15522 
15523 				devlist->map_pd = NULL;
15524 				devlist->map_did.port_id = ptgt->tgt_d_id;
15525 				devlist->map_hard_addr.hard_addr =
15526 				    ptgt->tgt_hard_addr;
15527 
15528 				devlist->map_state = PORT_DEVICE_INVALID;
15529 				devlist->map_type = PORT_DEVICE_OLD;
15530 
15531 				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15532 				    &devlist->map_nwwn, FC_WWN_SIZE);
15533 
15534 				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15535 				    &devlist->map_pwwn, FC_WWN_SIZE);
15536 
15537 				devlist++;
15538 			}
15539 		}
15540 	}
15541 
15542 	mutex_exit(&pptr->port_mutex);
15543 
15544 	return (devptr);
15545 }
15546 /*
15547  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15548  */
15549 static void
15550 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15551 {
15552 	int i;
15553 	struct fcp_tgt	*ptgt;
15554 	struct fcp_lun	*plun;
15555 
15556 	for (i = 0; i < FCP_NUM_HASH; i++) {
15557 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15558 		    ptgt = ptgt->tgt_next) {
15559 			mutex_enter(&ptgt->tgt_mutex);
15560 			for (plun = ptgt->tgt_lun; plun != NULL;
15561 			    plun = plun->lun_next) {
15562 				if (plun->lun_mpxio &&
15563 				    plun->lun_state & FCP_LUN_BUSY) {
15564 					if (!fcp_pass_to_hp(pptr, plun,
15565 					    plun->lun_cip,
15566 					    FCP_MPXIO_PATH_SET_BUSY,
15567 					    pptr->port_link_cnt,
15568 					    ptgt->tgt_change_cnt, 0, 0)) {
15569 						FCP_TRACE(fcp_logq,
15570 						    pptr->port_instbuf,
15571 						    fcp_trace,
15572 						    FCP_BUF_LEVEL_2, 0,
15573 						    "path_verifybusy: "
15574 						    "disable lun %p failed!",
15575 						    plun);
15576 					}
15577 				}
15578 			}
15579 			mutex_exit(&ptgt->tgt_mutex);
15580 		}
15581 	}
15582 }
15583 
15584 static int
15585 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15586 {
15587 	dev_info_t		*cdip = NULL;
15588 	dev_info_t		*pdip = NULL;
15589 
15590 	ASSERT(plun);
15591 
15592 	mutex_enter(&plun->lun_mutex);
15593 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15594 		mutex_exit(&plun->lun_mutex);
15595 		return (NDI_FAILURE);
15596 	}
15597 	mutex_exit(&plun->lun_mutex);
15598 	cdip = mdi_pi_get_client(PIP(cip));
15599 	pdip = mdi_pi_get_phci(PIP(cip));
15600 
15601 	ASSERT(cdip != NULL);
15602 	ASSERT(pdip != NULL);
15603 
15604 	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15605 		/* LUN ready for IO */
15606 		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15607 	} else {
15608 		/* LUN busy to accept IO */
15609 		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15610 	}
15611 	return (NDI_SUCCESS);
15612 }
15613 
15614 /*
15615  * Caller must free the returned string of MAXPATHLEN len
15616  * If the device is offline (-1 instance number) NULL
15617  * will be returned.
15618  */
15619 static char *
15620 fcp_get_lun_path(struct fcp_lun *plun) {
15621 	dev_info_t	*dip = NULL;
15622 	char	*path = NULL;
15623 	if (plun == NULL) {
15624 		return (NULL);
15625 	}
15626 	if (plun->lun_mpxio == 0) {
15627 		dip = DIP(plun->lun_cip);
15628 	} else {
15629 		dip = mdi_pi_get_client(PIP(plun->lun_cip));
15630 	}
15631 	if (dip == NULL) {
15632 		return (NULL);
15633 	}
15634 	if (ddi_get_instance(dip) < 0) {
15635 		return (NULL);
15636 	}
15637 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15638 	if (path == NULL) {
15639 		return (NULL);
15640 	}
15641 
15642 	(void) ddi_pathname(dip, path);
15643 	/*
15644 	 * In reality, the user wants a fully valid path (one they can open)
15645 	 * but this string is lacking the mount point, and the minor node.
15646 	 * It would be nice if we could "figure these out" somehow
15647 	 * and fill them in.  Otherwise, the userland code has to understand
15648 	 * driver specific details of which minor node is the "best" or
15649 	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15650 	 * which tape doesn't rewind)
15651 	 */
15652 	return (path);
15653 }
15654 
15655 static int
15656 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15657     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15658 {
15659 	int64_t reset_delay;
15660 	int rval, retry = 0;
15661 	struct fcp_port *pptr = fcp_dip2port(parent);
15662 
15663 	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15664 	    (lbolt64 - pptr->port_attach_time);
15665 	if (reset_delay < 0) {
15666 		reset_delay = 0;
15667 	}
15668 
15669 	if (fcp_bus_config_debug) {
15670 		flag |= NDI_DEVI_DEBUG;
15671 	}
15672 
15673 	switch (op) {
15674 	case BUS_CONFIG_ONE:
15675 		/*
15676 		 * Retry the command since we need to ensure
15677 		 * the fabric devices are available for root
15678 		 */
15679 		while (retry++ < fcp_max_bus_config_retries) {
15680 			rval =	(ndi_busop_bus_config(parent,
15681 			    flag | NDI_MDI_FALLBACK, op,
15682 			    arg, childp, (clock_t)reset_delay));
15683 			if (rval == 0) {
15684 				return (rval);
15685 			}
15686 		}
15687 
15688 		/*
15689 		 * drain taskq to make sure nodes are created and then
15690 		 * try again.
15691 		 */
15692 		taskq_wait(DEVI(parent)->devi_taskq);
15693 		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15694 		    op, arg, childp, 0));
15695 
15696 	case BUS_CONFIG_DRIVER:
15697 	case BUS_CONFIG_ALL: {
15698 		/*
15699 		 * delay till all devices report in (port_tmp_cnt == 0)
15700 		 * or FCP_INIT_WAIT_TIMEOUT
15701 		 */
15702 		mutex_enter(&pptr->port_mutex);
15703 		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15704 			(void) cv_timedwait(&pptr->port_config_cv,
15705 			    &pptr->port_mutex,
15706 			    ddi_get_lbolt() + (clock_t)reset_delay);
15707 			reset_delay =
15708 			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15709 			    (lbolt64 - pptr->port_attach_time);
15710 		}
15711 		mutex_exit(&pptr->port_mutex);
15712 		/* drain taskq to make sure nodes are created */
15713 		taskq_wait(DEVI(parent)->devi_taskq);
15714 		return (ndi_busop_bus_config(parent, flag, op,
15715 		    arg, childp, 0));
15716 	}
15717 
15718 	default:
15719 		return (NDI_FAILURE);
15720 	}
15721 	/*NOTREACHED*/
15722 }
15723 
15724 static int
15725 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15726     ddi_bus_config_op_t op, void *arg)
15727 {
15728 	if (fcp_bus_config_debug) {
15729 		flag |= NDI_DEVI_DEBUG;
15730 	}
15731 
15732 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15733 }
15734 
15735 
15736 /*
15737  * Routine to copy GUID into the lun structure.
15738  * returns 0 if copy was successful and 1 if encountered a
15739  * failure and did not copy the guid.
15740  */
15741 static int
15742 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15743 {
15744 
15745 	int retval = 0;
15746 
15747 	/* add one for the null terminator */
15748 	const unsigned int len = strlen(guidp) + 1;
15749 
15750 	if ((guidp == NULL) || (plun == NULL)) {
15751 		return (1);
15752 	}
15753 
15754 	/*
15755 	 * if the plun->lun_guid already has been allocated,
15756 	 * then check the size. if the size is exact, reuse
15757 	 * it....if not free it an allocate the required size.
15758 	 * The reallocation should NOT typically happen
15759 	 * unless the GUIDs reported changes between passes.
15760 	 * We free up and alloc again even if the
15761 	 * size was more than required. This is due to the
15762 	 * fact that the field lun_guid_size - serves
15763 	 * dual role of indicating the size of the wwn
15764 	 * size and ALSO the allocation size.
15765 	 */
15766 	if (plun->lun_guid) {
15767 		if (plun->lun_guid_size != len) {
15768 			/*
15769 			 * free the allocated memory and
15770 			 * initialize the field
15771 			 * lun_guid_size to 0.
15772 			 */
15773 			kmem_free(plun->lun_guid, plun->lun_guid_size);
15774 			plun->lun_guid = NULL;
15775 			plun->lun_guid_size = 0;
15776 		}
15777 	}
15778 	/*
15779 	 * alloc only if not already done.
15780 	 */
15781 	if (plun->lun_guid == NULL) {
15782 		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15783 		if (plun->lun_guid == NULL) {
15784 			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15785 			    "Unable to allocate"
15786 			    "Memory for GUID!!! size %d", len);
15787 			retval = 1;
15788 		} else {
15789 			plun->lun_guid_size = len;
15790 		}
15791 	}
15792 	if (plun->lun_guid) {
15793 		/*
15794 		 * now copy the GUID
15795 		 */
15796 		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15797 	}
15798 	return (retval);
15799 }
15800 
15801 /*
15802  * fcp_reconfig_wait
15803  *
15804  * Wait for a rediscovery/reconfiguration to complete before continuing.
15805  */
15806 
15807 static void
15808 fcp_reconfig_wait(struct fcp_port *pptr)
15809 {
15810 	clock_t		reconfig_start, wait_timeout;
15811 
15812 	/*
15813 	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15814 	 * reconfiguration in progress.
15815 	 */
15816 
15817 	mutex_enter(&pptr->port_mutex);
15818 	if (pptr->port_tmp_cnt == 0) {
15819 		mutex_exit(&pptr->port_mutex);
15820 		return;
15821 	}
15822 	mutex_exit(&pptr->port_mutex);
15823 
15824 	/*
15825 	 * If we cause a reconfig by raising power, delay until all devices
15826 	 * report in (port_tmp_cnt returns to 0)
15827 	 */
15828 
15829 	reconfig_start = ddi_get_lbolt();
15830 	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15831 
15832 	mutex_enter(&pptr->port_mutex);
15833 
15834 	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15835 	    pptr->port_tmp_cnt) {
15836 
15837 		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15838 		    reconfig_start + wait_timeout);
15839 	}
15840 
15841 	mutex_exit(&pptr->port_mutex);
15842 
15843 	/*
15844 	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15845 	 * we want may still be ok.  If not, it will error out later
15846 	 */
15847 }
15848 
15849 /*
15850  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15851  * We rely on the fcp_global_mutex to provide protection against changes to
15852  * the fcp_lun_blacklist.
15853  *
15854  * You can describe a list of target port WWNs and LUN numbers which will
15855  * not be configured. LUN numbers will be interpreted as decimal. White
15856  * spaces and ',' can be used in the list of LUN numbers.
15857  *
15858  * To prevent LUNs 1 and 2 from being configured for target
15859  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15860  *
15861  * pwwn-lun-blacklist=
15862  * "510000f010fd92a1,1,2",
15863  * "510000e012079df1,1,2";
15864  */
15865 static void
15866 fcp_read_blacklist(dev_info_t *dip,
15867     struct fcp_black_list_entry **pplun_blacklist) {
15868 	char **prop_array	= NULL;
15869 	char *curr_pwwn		= NULL;
15870 	char *curr_lun		= NULL;
15871 	uint32_t prop_item	= 0;
15872 	int idx			= 0;
15873 	int len			= 0;
15874 
15875 	ASSERT(mutex_owned(&fcp_global_mutex));
15876 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15877 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15878 	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15879 		return;
15880 	}
15881 
15882 	for (idx = 0; idx < prop_item; idx++) {
15883 
15884 		curr_pwwn = prop_array[idx];
15885 		while (*curr_pwwn == ' ') {
15886 			curr_pwwn++;
15887 		}
15888 		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15889 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15890 			    ", please check.", curr_pwwn);
15891 			continue;
15892 		}
15893 		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15894 		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15895 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15896 			    ", please check.", curr_pwwn);
15897 			continue;
15898 		}
15899 		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15900 			if (isxdigit(curr_pwwn[len]) != TRUE) {
15901 				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15902 				    "blacklist, please check.", curr_pwwn);
15903 				break;
15904 			}
15905 		}
15906 		if (len != sizeof (la_wwn_t) * 2) {
15907 			continue;
15908 		}
15909 
15910 		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15911 		*(curr_lun - 1) = '\0';
15912 		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15913 	}
15914 
15915 	ddi_prop_free(prop_array);
15916 }
15917 
15918 /*
15919  * Get the masking info about one remote target port designated by wwn.
15920  * Lun ids could be separated by ',' or white spaces.
15921  */
15922 static void
15923 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15924     struct fcp_black_list_entry **pplun_blacklist) {
15925 	int		idx			= 0;
15926 	uint32_t	offset			= 0;
15927 	unsigned long	lun_id			= 0;
15928 	char		lunid_buf[16];
15929 	char		*pend			= NULL;
15930 	int		illegal_digit		= 0;
15931 
15932 	while (offset < strlen(curr_lun)) {
15933 		while ((curr_lun[offset + idx] != ',') &&
15934 		    (curr_lun[offset + idx] != '\0') &&
15935 		    (curr_lun[offset + idx] != ' ')) {
15936 			if (isdigit(curr_lun[offset + idx]) == 0) {
15937 				illegal_digit++;
15938 			}
15939 			idx++;
15940 		}
15941 		if (illegal_digit > 0) {
15942 			offset += (idx+1);	/* To the start of next lun */
15943 			idx = 0;
15944 			illegal_digit = 0;
15945 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15946 			    "the blacklist, please check digits.",
15947 			    curr_lun, curr_pwwn);
15948 			continue;
15949 		}
15950 		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
15951 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15952 			    "the blacklist, please check the length of LUN#.",
15953 			    curr_lun, curr_pwwn);
15954 			break;
15955 		}
15956 		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
15957 		    offset++;
15958 		    continue;
15959 		}
15960 
15961 		bcopy(curr_lun + offset, lunid_buf, idx);
15962 		lunid_buf[idx] = '\0';
15963 		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
15964 			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
15965 		} else {
15966 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15967 			    "the blacklist, please check %s.",
15968 			    curr_lun, curr_pwwn, lunid_buf);
15969 		}
15970 		offset += (idx+1);	/* To the start of next lun */
15971 		idx = 0;
15972 	}
15973 }
15974 
15975 /*
15976  * Add one masking record
15977  */
15978 static void
15979 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
15980     struct fcp_black_list_entry **pplun_blacklist) {
15981 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
15982 	struct fcp_black_list_entry	*new_entry	= NULL;
15983 	la_wwn_t			wwn;
15984 
15985 	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
15986 	while (tmp_entry) {
15987 		if ((bcmp(&tmp_entry->wwn, &wwn,
15988 		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
15989 			return;
15990 		}
15991 
15992 		tmp_entry = tmp_entry->next;
15993 	}
15994 
15995 	/* add to black list */
15996 	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
15997 	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
15998 	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
15999 	new_entry->lun = lun_id;
16000 	new_entry->masked = 0;
16001 	new_entry->next = *pplun_blacklist;
16002 	*pplun_blacklist = new_entry;
16003 }
16004 
16005 /*
16006  * Check if we should mask the specified lun of this fcp_tgt
16007  */
16008 static int
16009 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16010 	struct fcp_black_list_entry *remote_port;
16011 
16012 	remote_port = fcp_lun_blacklist;
16013 	while (remote_port != NULL) {
16014 		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16015 			if (remote_port->lun == lun_id) {
16016 				remote_port->masked++;
16017 				if (remote_port->masked == 1) {
16018 					fcp_log(CE_NOTE, NULL, "LUN %d of port "
16019 					    "%02x%02x%02x%02x%02x%02x%02x%02x "
16020 					    "is masked due to black listing.\n",
16021 					    lun_id, wwn->raw_wwn[0],
16022 					    wwn->raw_wwn[1], wwn->raw_wwn[2],
16023 					    wwn->raw_wwn[3], wwn->raw_wwn[4],
16024 					    wwn->raw_wwn[5], wwn->raw_wwn[6],
16025 					    wwn->raw_wwn[7]);
16026 				}
16027 				return (TRUE);
16028 			}
16029 		}
16030 		remote_port = remote_port->next;
16031 	}
16032 	return (FALSE);
16033 }
16034 
16035 /*
16036  * Release all allocated resources
16037  */
16038 static void
16039 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16040 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16041 	struct fcp_black_list_entry	*current_entry	= NULL;
16042 
16043 	ASSERT(mutex_owned(&fcp_global_mutex));
16044 	/*
16045 	 * Traverse all luns
16046 	 */
16047 	while (tmp_entry) {
16048 		current_entry = tmp_entry;
16049 		tmp_entry = tmp_entry->next;
16050 		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16051 	}
16052 	*pplun_blacklist = NULL;
16053 }
16054 
16055 /*
16056  * In fcp module,
16057  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16058  */
16059 static struct scsi_pkt *
16060 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16061     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16062     int flags, int (*callback)(), caddr_t arg)
16063 {
16064 	fcp_port_t	*pptr = ADDR2FCP(ap);
16065 	fcp_pkt_t	*cmd  = NULL;
16066 	fc_frame_hdr_t	*hp;
16067 
16068 	/*
16069 	 * First step: get the packet
16070 	 */
16071 	if (pkt == NULL) {
16072 		pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16073 		    tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16074 		    callback, arg);
16075 		if (pkt == NULL) {
16076 			return (NULL);
16077 		}
16078 
16079 		/*
16080 		 * All fields in scsi_pkt will be initialized properly or
16081 		 * set to zero. We need do nothing for scsi_pkt.
16082 		 */
16083 		/*
16084 		 * But it's our responsibility to link other related data
16085 		 * structures. Their initialization will be done, just
16086 		 * before the scsi_pkt will be sent to FCA.
16087 		 */
16088 		cmd		= PKT2CMD(pkt);
16089 		cmd->cmd_pkt	= pkt;
16090 		cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16091 		/*
16092 		 * fc_packet_t
16093 		 */
16094 		cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16095 		cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16096 		    sizeof (struct fcp_pkt));
16097 		cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16098 		cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16099 		cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16100 		cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16101 		/*
16102 		 * Fill in the Fabric Channel Header
16103 		 */
16104 		hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16105 		hp->r_ctl = R_CTL_COMMAND;
16106 		hp->rsvd = 0;
16107 		hp->type = FC_TYPE_SCSI_FCP;
16108 		hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16109 		hp->seq_id = 0;
16110 		hp->df_ctl  = 0;
16111 		hp->seq_cnt = 0;
16112 		hp->ox_id = 0xffff;
16113 		hp->rx_id = 0xffff;
16114 		hp->ro = 0;
16115 	} else {
16116 		/*
16117 		 * We need think if we should reset any elements in
16118 		 * related data structures.
16119 		 */
16120 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
16121 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
16122 		    "reusing pkt, flags %d", flags);
16123 		cmd = PKT2CMD(pkt);
16124 		if (cmd->cmd_fp_pkt->pkt_pd) {
16125 			cmd->cmd_fp_pkt->pkt_pd = NULL;
16126 		}
16127 	}
16128 
16129 	/*
16130 	 * Second step:	 dma allocation/move
16131 	 */
16132 	if (bp && bp->b_bcount != 0) {
16133 		/*
16134 		 * Mark if it's read or write
16135 		 */
16136 		if (bp->b_flags & B_READ) {
16137 			cmd->cmd_flags |= CFLAG_IS_READ;
16138 		} else {
16139 			cmd->cmd_flags &= ~CFLAG_IS_READ;
16140 		}
16141 
16142 		bp_mapin(bp);
16143 		cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16144 		cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16145 		cmd->cmd_fp_pkt->pkt_data_resid = 0;
16146 	} else {
16147 		/*
16148 		 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16149 		 * to send zero-length read/write.
16150 		 */
16151 		cmd->cmd_fp_pkt->pkt_data = NULL;
16152 		cmd->cmd_fp_pkt->pkt_datalen = 0;
16153 	}
16154 
16155 	return (pkt);
16156 }
16157 
16158 static void
16159 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16160 {
16161 	fcp_port_t	*pptr = ADDR2FCP(ap);
16162 
16163 	/*
16164 	 * First we let FCA to uninitilize private part.
16165 	 */
16166 	fc_ulp_uninit_packet(pptr->port_fp_handle, PKT2CMD(pkt)->cmd_fp_pkt);
16167 
16168 	/*
16169 	 * Then we uninitialize fc_packet.
16170 	 */
16171 
16172 	/*
16173 	 * Thirdly, we uninitializae fcp_pkt.
16174 	 */
16175 
16176 	/*
16177 	 * In the end, we free scsi_pkt.
16178 	 */
16179 	scsi_hba_pkt_free(ap, pkt);
16180 }
16181 
16182 static int
16183 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16184 {
16185 	fcp_port_t	*pptr = ADDR2FCP(ap);
16186 	fcp_lun_t	*plun = ADDR2LUN(ap);
16187 	fcp_tgt_t	*ptgt = plun->lun_tgt;
16188 	fcp_pkt_t	*cmd  = PKT2CMD(pkt);
16189 	fcp_cmd_t	*fcmd = &cmd->cmd_fcp_cmd;
16190 	fc_packet_t	*fpkt = cmd->cmd_fp_pkt;
16191 	int		 rval;
16192 
16193 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
16194 	fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16195 
16196 	/*
16197 	 * Firstly, we need initialize fcp_pkt_t
16198 	 * Secondly, we need initialize fcp_cmd_t.
16199 	 */
16200 	bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16201 	fcmd->fcp_data_len = fpkt->pkt_datalen;
16202 	fcmd->fcp_ent_addr = plun->lun_addr;
16203 	if (pkt->pkt_flags & FLAG_HTAG) {
16204 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16205 	} else if (pkt->pkt_flags & FLAG_OTAG) {
16206 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16207 	} else if (pkt->pkt_flags & FLAG_STAG) {
16208 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16209 	} else {
16210 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16211 	}
16212 
16213 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16214 		fcmd->fcp_cntl.cntl_read_data = 1;
16215 		fcmd->fcp_cntl.cntl_write_data = 0;
16216 	} else {
16217 		fcmd->fcp_cntl.cntl_read_data = 0;
16218 		fcmd->fcp_cntl.cntl_write_data = 1;
16219 	}
16220 
16221 	/*
16222 	 * Then we need initialize fc_packet_t too.
16223 	 */
16224 	fpkt->pkt_timeout = pkt->pkt_time + 2;
16225 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16226 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16227 	if (cmd->cmd_flags & CFLAG_IS_READ) {
16228 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16229 	} else {
16230 		fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16231 	}
16232 
16233 	if (pkt->pkt_flags & FLAG_NOINTR) {
16234 		fpkt->pkt_comp = NULL;
16235 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16236 	} else {
16237 		fpkt->pkt_comp = fcp_cmd_callback;
16238 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16239 		if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16240 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16241 		}
16242 	}
16243 
16244 	/*
16245 	 * Lastly, we need initialize scsi_pkt
16246 	 */
16247 	pkt->pkt_reason = CMD_CMPLT;
16248 	pkt->pkt_state = 0;
16249 	pkt->pkt_statistics = 0;
16250 	pkt->pkt_resid = 0;
16251 
16252 	/*
16253 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
16254 	 * have to do polled I/O
16255 	 */
16256 	if (pkt->pkt_flags & FLAG_NOINTR) {
16257 		return (fcp_dopoll(pptr, cmd));
16258 	}
16259 
16260 	cmd->cmd_state = FCP_PKT_ISSUED;
16261 	rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16262 	if (rval == FC_SUCCESS) {
16263 		return (TRAN_ACCEPT);
16264 	}
16265 
16266 	/*
16267 	 * Need more consideration
16268 	 *
16269 	 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16270 	 */
16271 	cmd->cmd_state = FCP_PKT_IDLE;
16272 	if (rval == FC_TRAN_BUSY) {
16273 		return (TRAN_BUSY);
16274 	} else {
16275 		return (TRAN_FATAL_ERROR);
16276 	}
16277 }
16278 
16279 /*
16280  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16281  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16282  */
16283 static void
16284 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16285 {
16286 	FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16287 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16288 }
16289 
16290 /*
16291  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16292  */
16293 static void
16294 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16295 {
16296 	FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16297 	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16298 }
16299