xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/ulp/fcp.c (revision 24fe0b3bf671e123467ce1df0b67cadd3614c8e4)
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 extern struct mod_ops	mod_driverops;
629 /*
630  * This variable is defined in modctl.c and set to '1' after the root driver
631  * and fs are loaded.  It serves as an indication that the root filesystem can
632  * be used.
633  */
634 extern int		modrootloaded;
635 /*
636  * This table contains strings associated with the SCSI sense key codes.  It
637  * is used by FCP to print a clear explanation of the code returned in the
638  * sense information by a device.
639  */
640 extern char		*sense_keys[];
641 /*
642  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
643  * under this device that the paths to a physical device are created when
644  * MPxIO is used.
645  */
646 extern dev_info_t	*scsi_vhci_dip;
647 
648 /*
649  * Report lun processing
650  */
651 #define	FCP_LUN_ADDRESSING		0x80
652 #define	FCP_PD_ADDRESSING		0x00
653 #define	FCP_VOLUME_ADDRESSING		0x40
654 
655 #define	FCP_SVE_THROTTLE		0x28 /* Vicom */
656 #define	MAX_INT_DMA			0x7fffffff
657 #define	FCP_MAX_SENSE_LEN		252
658 #define	FCP_MAX_RESPONSE_LEN		0xffffff
659 /*
660  * Property definitions
661  */
662 #define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
663 #define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
664 #define	TARGET_PROP	(char *)fcp_target_prop
665 #define	LUN_PROP	(char *)fcp_lun_prop
666 #define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
667 #define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
668 #define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
669 #define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
670 #define	INIT_PORT_PROP	(char *)fcp_init_port_prop
671 #define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
672 #define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
673 /*
674  * Short hand macros.
675  */
676 #define	LUN_PORT	(plun->lun_tgt->tgt_port)
677 #define	LUN_TGT		(plun->lun_tgt)
678 
679 /*
680  * Driver private macros
681  */
682 #define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
683 			((x) >= 'a' && (x) <= 'f') ?			\
684 			((x) - 'a' + 10) : ((x) - 'A' + 10))
685 
686 #define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
687 
688 #define	FCP_N_NDI_EVENTS						\
689 	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
690 
691 #define	FCP_LINK_STATE_CHANGED(p, c)			\
692 	((p)->port_link_cnt != (c)->ipkt_link_cnt)
693 
694 #define	FCP_TGT_STATE_CHANGED(t, c)			\
695 	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
696 
697 #define	FCP_STATE_CHANGED(p, t, c)		\
698 	(FCP_TGT_STATE_CHANGED(t, c))
699 
700 #define	FCP_MUST_RETRY(fpkt)				\
701 	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
702 	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
703 	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
704 	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
705 	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
706 	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
707 	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
708 	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
709 
710 #define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
711 	((es)->es_key == KEY_UNIT_ATTENTION &&	\
712 	(es)->es_add_code == 0x3f &&		\
713 	(es)->es_qual_code == 0x0e)
714 
715 #define	FCP_SENSE_NO_LUN(es)			\
716 	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
717 	(es)->es_add_code == 0x25 &&		\
718 	(es)->es_qual_code == 0x0)
719 
720 #define	FCP_VERSION		"1.189"
721 #define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
722 
723 #define	FCP_NUM_ELEMENTS(array)			\
724 	(sizeof (array) / sizeof ((array)[0]))
725 
726 /*
727  * Debugging, Error reporting, and tracing
728  */
729 #define	FCP_LOG_SIZE		1024 * 1024
730 
731 #define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
732 #define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
733 #define	FCP_LEVEL_3		0x00004		/* state change, discovery */
734 #define	FCP_LEVEL_4		0x00008		/* ULP messages */
735 #define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
736 #define	FCP_LEVEL_6		0x00020		/* Transport failures */
737 #define	FCP_LEVEL_7		0x00040
738 #define	FCP_LEVEL_8		0x00080		/* I/O tracing */
739 #define	FCP_LEVEL_9		0x00100		/* I/O tracing */
740 
741 
742 
743 /*
744  * Log contents to system messages file
745  */
746 #define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
747 #define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
748 #define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
749 #define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
750 #define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
751 #define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
752 #define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
753 #define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
754 #define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
755 
756 
757 /*
758  * Log contents to trace buffer
759  */
760 #define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
761 #define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
762 #define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
763 #define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
764 #define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
765 #define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
766 #define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
767 #define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
768 #define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
769 
770 
771 /*
772  * Log contents to both system messages file and trace buffer
773  */
774 #define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
775 				FC_TRACE_LOG_MSG)
776 #define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
777 				FC_TRACE_LOG_MSG)
778 #define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
779 				FC_TRACE_LOG_MSG)
780 #define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
781 				FC_TRACE_LOG_MSG)
782 #define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
783 				FC_TRACE_LOG_MSG)
784 #define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
785 				FC_TRACE_LOG_MSG)
786 #define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
787 				FC_TRACE_LOG_MSG)
788 #define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
789 				FC_TRACE_LOG_MSG)
790 #define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
791 				FC_TRACE_LOG_MSG)
792 #ifdef DEBUG
793 #define	FCP_DTRACE	fc_trace_debug
794 #else
795 #define	FCP_DTRACE
796 #endif
797 
798 #define	FCP_TRACE	fc_trace_debug
799 
800 static struct cb_ops fcp_cb_ops = {
801 	fcp_open,			/* open */
802 	fcp_close,			/* close */
803 	nodev,				/* strategy */
804 	nodev,				/* print */
805 	nodev,				/* dump */
806 	nodev,				/* read */
807 	nodev,				/* write */
808 	fcp_ioctl,			/* ioctl */
809 	nodev,				/* devmap */
810 	nodev,				/* mmap */
811 	nodev,				/* segmap */
812 	nochpoll,			/* chpoll */
813 	ddi_prop_op,			/* cb_prop_op */
814 	0,				/* streamtab */
815 	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
816 	CB_REV,				/* rev */
817 	nodev,				/* aread */
818 	nodev				/* awrite */
819 };
820 
821 
822 static struct dev_ops fcp_ops = {
823 	DEVO_REV,
824 	0,
825 	ddi_getinfo_1to1,
826 	nulldev,		/* identify */
827 	nulldev,		/* probe */
828 	fcp_attach,		/* attach and detach are mandatory */
829 	fcp_detach,
830 	nodev,			/* reset */
831 	&fcp_cb_ops,		/* cb_ops */
832 	NULL,			/* bus_ops */
833 	NULL,			/* power */
834 };
835 
836 
837 char *fcp_version = FCP_NAME_VERSION;
838 
839 static struct modldrv modldrv = {
840 	&mod_driverops,
841 	FCP_NAME_VERSION,
842 	&fcp_ops
843 };
844 
845 
846 static struct modlinkage modlinkage = {
847 	MODREV_1,
848 	&modldrv,
849 	NULL
850 };
851 
852 
853 static fc_ulp_modinfo_t fcp_modinfo = {
854 	&fcp_modinfo,			/* ulp_handle */
855 	FCTL_ULP_MODREV_4,		/* ulp_rev */
856 	FC4_SCSI_FCP,			/* ulp_type */
857 	"fcp",				/* ulp_name */
858 	FCP_STATEC_MASK,		/* ulp_statec_mask */
859 	fcp_port_attach,		/* ulp_port_attach */
860 	fcp_port_detach,		/* ulp_port_detach */
861 	fcp_port_ioctl,			/* ulp_port_ioctl */
862 	fcp_els_callback,		/* ulp_els_callback */
863 	fcp_data_callback,		/* ulp_data_callback */
864 	fcp_statec_callback		/* ulp_statec_callback */
865 };
866 
867 #ifdef	DEBUG
868 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
869 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
870 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
871 				FCP_LEVEL_6 | FCP_LEVEL_7)
872 #else
873 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
874 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
875 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
876 				FCP_LEVEL_6 | FCP_LEVEL_7)
877 #endif
878 
879 /* FCP global variables */
880 int			fcp_bus_config_debug = 0;
881 static int		fcp_log_size = FCP_LOG_SIZE;
882 static int		fcp_trace = FCP_TRACE_DEFAULT;
883 static fc_trace_logq_t	*fcp_logq = NULL;
884 static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
885 /*
886  * The auto-configuration is set by default.  The only way of disabling it is
887  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
888  */
889 static int		fcp_enable_auto_configuration = 1;
890 static int		fcp_max_bus_config_retries	= 4;
891 static int		fcp_lun_ready_retry = 300;
892 /*
893  * The value assigned to the following variable has changed several times due
894  * to a problem with the data underruns reporting of some firmware(s).	The
895  * current value of 50 gives a timeout value of 25 seconds for a max number
896  * of 256 LUNs.
897  */
898 static int		fcp_max_target_retries = 50;
899 /*
900  * Watchdog variables
901  * ------------------
902  *
903  * fcp_watchdog_init
904  *
905  *	Indicates if the watchdog timer is running or not.  This is actually
906  *	a counter of the number of Fibre Channel ports that attached.  When
907  *	the first port attaches the watchdog is started.  When the last port
908  *	detaches the watchdog timer is stopped.
909  *
910  * fcp_watchdog_time
911  *
912  *	This is the watchdog clock counter.  It is incremented by
913  *	fcp_watchdog_time each time the watchdog timer expires.
914  *
915  * fcp_watchdog_timeout
916  *
917  *	Increment value of the variable fcp_watchdog_time as well as the
918  *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
919  *	is strange that this is not a #define	but a variable since the code
920  *	never changes this value.  The reason why it can be said that the
921  *	unit is 1 second is because the number of ticks for the watchdog
922  *	timer is determined like this:
923  *
924  *	    fcp_watchdog_tick = fcp_watchdog_timeout *
925  *				  drv_usectohz(1000000);
926  *
927  *	The value 1000000 is hard coded in the code.
928  *
929  * fcp_watchdog_tick
930  *
931  *	Watchdog timer value in ticks.
932  */
933 static int		fcp_watchdog_init = 0;
934 static int		fcp_watchdog_time = 0;
935 static int		fcp_watchdog_timeout = 1;
936 static int		fcp_watchdog_tick;
937 
938 /*
939  * fcp_offline_delay is a global variable to enable customisation of
940  * the timeout on link offlines or RSCNs. The default value is set
941  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
942  * specified in FCP4 Chapter 11 (see www.t10.org).
943  *
944  * The variable fcp_offline_delay is specified in SECONDS.
945  *
946  * If we made this a static var then the user would not be able to
947  * change it. This variable is set in fcp_attach().
948  */
949 unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
950 
951 static void		*fcp_softstate = NULL; /* for soft state */
952 static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
953 static kmutex_t		fcp_global_mutex;
954 static kmutex_t		fcp_ioctl_mutex;
955 static dev_info_t	*fcp_global_dip = NULL;
956 static timeout_id_t	fcp_watchdog_id;
957 const char		*fcp_lun_prop = "lun";
958 const char		*fcp_sam_lun_prop = "sam-lun";
959 const char		*fcp_target_prop = "target";
960 /*
961  * NOTE: consumers of "node-wwn" property include stmsboot in ON
962  * consolidation.
963  */
964 const char		*fcp_node_wwn_prop = "node-wwn";
965 const char		*fcp_port_wwn_prop = "port-wwn";
966 const char		*fcp_conf_wwn_prop = "fc-port-wwn";
967 const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
968 const char		*fcp_manual_config_only = "manual_configuration_only";
969 const char		*fcp_init_port_prop = "initiator-port";
970 const char		*fcp_tgt_port_prop = "target-port";
971 const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
972 
973 static struct fcp_port	*fcp_port_head = NULL;
974 static ddi_eventcookie_t	fcp_insert_eid;
975 static ddi_eventcookie_t	fcp_remove_eid;
976 
977 static ndi_event_definition_t	fcp_ndi_event_defs[] = {
978 	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
979 	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
980 };
981 
982 /*
983  * List of valid commands for the scsi_ioctl call
984  */
985 static uint8_t scsi_ioctl_list[] = {
986 	SCMD_INQUIRY,
987 	SCMD_REPORT_LUN,
988 	SCMD_READ_CAPACITY
989 };
990 
991 /*
992  * this is used to dummy up a report lun response for cases
993  * where the target doesn't support it
994  */
995 static uchar_t fcp_dummy_lun[] = {
996 	0x00,		/* MSB length (length = no of luns * 8) */
997 	0x00,
998 	0x00,
999 	0x08,		/* LSB length */
1000 	0x00,		/* MSB reserved */
1001 	0x00,
1002 	0x00,
1003 	0x00,		/* LSB reserved */
1004 	FCP_PD_ADDRESSING,
1005 	0x00,		/* LUN is ZERO at the first level */
1006 	0x00,
1007 	0x00,		/* second level is zero */
1008 	0x00,
1009 	0x00,		/* third level is zero */
1010 	0x00,
1011 	0x00		/* fourth level is zero */
1012 };
1013 
1014 static uchar_t fcp_alpa_to_switch[] = {
1015 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1016 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1017 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1018 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1019 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1020 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1021 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1022 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1023 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1024 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1025 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1026 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1027 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1028 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1029 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1030 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1031 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1032 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1033 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1034 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1035 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1036 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1037 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1038 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039 };
1040 
1041 static caddr_t pid = "SESS01	      ";
1042 
1043 #if	!defined(lint)
1044 
1045 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1046     fcp_port::fcp_next fcp_watchdog_id))
1047 
1048 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1049 
1050 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1051     fcp_insert_eid
1052     fcp_remove_eid
1053     fcp_watchdog_time))
1054 
1055 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1056     fcp_cb_ops
1057     fcp_ops
1058     callb_cpr))
1059 
1060 #endif /* lint */
1061 
1062 /*
1063  * This table is used to determine whether or not it's safe to copy in
1064  * the target node name for a lun.  Since all luns behind the same target
1065  * have the same wwnn, only tagets that do not support multiple luns are
1066  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1067  */
1068 
1069 char *fcp_symmetric_disk_table[] = {
1070 	"SEAGATE ST",
1071 	"IBM	 DDYFT",
1072 	"SUNW	 SUNWGS",	/* Daktari enclosure */
1073 	"SUN	 SENA",		/* SES device */
1074 	"SUN	 SESS01"	/* VICOM SVE box */
1075 };
1076 
1077 int fcp_symmetric_disk_table_size =
1078 	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1079 
1080 /*
1081  * The _init(9e) return value should be that of mod_install(9f). Under
1082  * some circumstances, a failure may not be related mod_install(9f) and
1083  * one would then require a return value to indicate the failure. Looking
1084  * at mod_install(9f), it is expected to return 0 for success and non-zero
1085  * for failure. mod_install(9f) for device drivers, further goes down the
1086  * calling chain and ends up in ddi_installdrv(), whose return values are
1087  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1088  * calling chain of mod_install(9f) which return values like EINVAL and
1089  * in some even return -1.
1090  *
1091  * To work around the vagaries of the mod_install() calling chain, return
1092  * either 0 or ENODEV depending on the success or failure of mod_install()
1093  */
1094 int
1095 _init(void)
1096 {
1097 	int rval;
1098 
1099 	/*
1100 	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1101 	 * before registering with the transport first.
1102 	 */
1103 	if (ddi_soft_state_init(&fcp_softstate,
1104 	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1105 		return (EINVAL);
1106 	}
1107 
1108 	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1109 	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1110 
1111 	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1112 		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1113 		mutex_destroy(&fcp_global_mutex);
1114 		mutex_destroy(&fcp_ioctl_mutex);
1115 		ddi_soft_state_fini(&fcp_softstate);
1116 		return (ENODEV);
1117 	}
1118 
1119 	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1120 
1121 	if ((rval = mod_install(&modlinkage)) != 0) {
1122 		fc_trace_free_logq(fcp_logq);
1123 		(void) fc_ulp_remove(&fcp_modinfo);
1124 		mutex_destroy(&fcp_global_mutex);
1125 		mutex_destroy(&fcp_ioctl_mutex);
1126 		ddi_soft_state_fini(&fcp_softstate);
1127 		rval = ENODEV;
1128 	}
1129 
1130 	return (rval);
1131 }
1132 
1133 
1134 /*
1135  * the system is done with us as a driver, so clean up
1136  */
1137 int
1138 _fini(void)
1139 {
1140 	int rval;
1141 
1142 	/*
1143 	 * don't start cleaning up until we know that the module remove
1144 	 * has worked  -- if this works, then we know that each instance
1145 	 * has successfully been DDI_DETACHed
1146 	 */
1147 	if ((rval = mod_remove(&modlinkage)) != 0) {
1148 		return (rval);
1149 	}
1150 
1151 	(void) fc_ulp_remove(&fcp_modinfo);
1152 
1153 	ddi_soft_state_fini(&fcp_softstate);
1154 	mutex_destroy(&fcp_global_mutex);
1155 	mutex_destroy(&fcp_ioctl_mutex);
1156 	fc_trace_free_logq(fcp_logq);
1157 
1158 	return (rval);
1159 }
1160 
1161 
1162 int
1163 _info(struct modinfo *modinfop)
1164 {
1165 	return (mod_info(&modlinkage, modinfop));
1166 }
1167 
1168 
1169 /*
1170  * attach the module
1171  */
1172 static int
1173 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1174 {
1175 	int rval = DDI_SUCCESS;
1176 
1177 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1178 	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1179 
1180 	if (cmd == DDI_ATTACH) {
1181 		/* The FCP pseudo device is created here. */
1182 		mutex_enter(&fcp_global_mutex);
1183 		fcp_global_dip = devi;
1184 		mutex_exit(&fcp_global_mutex);
1185 
1186 		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1187 		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1188 			ddi_report_dev(fcp_global_dip);
1189 		} else {
1190 			cmn_err(CE_WARN, "FCP: Cannot create minor node");
1191 			mutex_enter(&fcp_global_mutex);
1192 			fcp_global_dip = NULL;
1193 			mutex_exit(&fcp_global_mutex);
1194 
1195 			rval = DDI_FAILURE;
1196 		}
1197 		/*
1198 		 * We check the fcp_offline_delay property at this
1199 		 * point. This variable is global for the driver,
1200 		 * not specific to an instance.
1201 		 *
1202 		 * We do not recommend setting the value to less
1203 		 * than 10 seconds (RA_TOV_els), or greater than
1204 		 * 60 seconds.
1205 		 */
1206 		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1207 		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1208 		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
1209 		if ((fcp_offline_delay < 10) ||
1210 		    (fcp_offline_delay > 60)) {
1211 			cmn_err(CE_WARN, "Setting fcp_offline_delay "
1212 			    "to %d second(s). This is outside the "
1213 			    "recommended range of 10..60 seconds.",
1214 			    fcp_offline_delay);
1215 		}
1216 	}
1217 
1218 	return (rval);
1219 }
1220 
1221 
1222 /*ARGSUSED*/
1223 static int
1224 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1225 {
1226 	int	res = DDI_SUCCESS;
1227 
1228 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1229 	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
1230 
1231 	if (cmd == DDI_DETACH) {
1232 		/*
1233 		 * Check if there are active ports/threads. If there
1234 		 * are any, we will fail, else we will succeed (there
1235 		 * should not be much to clean up)
1236 		 */
1237 		mutex_enter(&fcp_global_mutex);
1238 		FCP_DTRACE(fcp_logq, "fcp",
1239 		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1240 		    (void *) fcp_port_head);
1241 
1242 		if (fcp_port_head == NULL) {
1243 			ddi_remove_minor_node(fcp_global_dip, NULL);
1244 			fcp_global_dip = NULL;
1245 			mutex_exit(&fcp_global_mutex);
1246 		} else {
1247 			mutex_exit(&fcp_global_mutex);
1248 			res = DDI_FAILURE;
1249 		}
1250 	}
1251 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1252 	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
1253 
1254 	return (res);
1255 }
1256 
1257 
1258 /* ARGSUSED */
1259 static int
1260 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1261 {
1262 	if (otype != OTYP_CHR) {
1263 		return (EINVAL);
1264 	}
1265 
1266 	/*
1267 	 * Allow only root to talk;
1268 	 */
1269 	if (drv_priv(credp)) {
1270 		return (EPERM);
1271 	}
1272 
1273 	mutex_enter(&fcp_global_mutex);
1274 	if (fcp_oflag & FCP_EXCL) {
1275 		mutex_exit(&fcp_global_mutex);
1276 		return (EBUSY);
1277 	}
1278 
1279 	if (flag & FEXCL) {
1280 		if (fcp_oflag & FCP_OPEN) {
1281 			mutex_exit(&fcp_global_mutex);
1282 			return (EBUSY);
1283 		}
1284 		fcp_oflag |= FCP_EXCL;
1285 	}
1286 	fcp_oflag |= FCP_OPEN;
1287 	mutex_exit(&fcp_global_mutex);
1288 
1289 	return (0);
1290 }
1291 
1292 
1293 /* ARGSUSED */
1294 static int
1295 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1296 {
1297 	if (otype != OTYP_CHR) {
1298 		return (EINVAL);
1299 	}
1300 
1301 	mutex_enter(&fcp_global_mutex);
1302 	if (!(fcp_oflag & FCP_OPEN)) {
1303 		mutex_exit(&fcp_global_mutex);
1304 		return (ENODEV);
1305 	}
1306 	fcp_oflag = FCP_IDLE;
1307 	mutex_exit(&fcp_global_mutex);
1308 
1309 	return (0);
1310 }
1311 
1312 
1313 /*
1314  * fcp_ioctl
1315  *	Entry point for the FCP ioctls
1316  *
1317  * Input:
1318  *	See ioctl(9E)
1319  *
1320  * Output:
1321  *	See ioctl(9E)
1322  *
1323  * Returns:
1324  *	See ioctl(9E)
1325  *
1326  * Context:
1327  *	Kernel context.
1328  */
1329 /* ARGSUSED */
1330 static int
1331 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1332     int *rval)
1333 {
1334 	int			ret = 0;
1335 
1336 	mutex_enter(&fcp_global_mutex);
1337 	if (!(fcp_oflag & FCP_OPEN)) {
1338 		mutex_exit(&fcp_global_mutex);
1339 		return (ENXIO);
1340 	}
1341 	mutex_exit(&fcp_global_mutex);
1342 
1343 	switch (cmd) {
1344 	case FCP_TGT_INQUIRY:
1345 	case FCP_TGT_CREATE:
1346 	case FCP_TGT_DELETE:
1347 		ret = fcp_setup_device_data_ioctl(cmd,
1348 		    (struct fcp_ioctl *)data, mode, rval);
1349 		break;
1350 
1351 	case FCP_TGT_SEND_SCSI:
1352 		mutex_enter(&fcp_ioctl_mutex);
1353 		ret = fcp_setup_scsi_ioctl(
1354 		    (struct fcp_scsi_cmd *)data, mode, rval);
1355 		mutex_exit(&fcp_ioctl_mutex);
1356 		break;
1357 
1358 	case FCP_STATE_COUNT:
1359 		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1360 		    mode, rval);
1361 		break;
1362 	case FCP_GET_TARGET_MAPPINGS:
1363 		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1364 		    mode, rval);
1365 		break;
1366 	default:
1367 		fcp_log(CE_WARN, NULL,
1368 		    "!Invalid ioctl opcode = 0x%x", cmd);
1369 		ret	= EINVAL;
1370 	}
1371 
1372 	return (ret);
1373 }
1374 
1375 
1376 /*
1377  * fcp_setup_device_data_ioctl
1378  *	Setup handler for the "device data" style of
1379  *	ioctl for FCP.	See "fcp_util.h" for data structure
1380  *	definition.
1381  *
1382  * Input:
1383  *	cmd	= FCP ioctl command
1384  *	data	= ioctl data
1385  *	mode	= See ioctl(9E)
1386  *
1387  * Output:
1388  *	data	= ioctl data
1389  *	rval	= return value - see ioctl(9E)
1390  *
1391  * Returns:
1392  *	See ioctl(9E)
1393  *
1394  * Context:
1395  *	Kernel context.
1396  */
1397 /* ARGSUSED */
1398 static int
1399 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1400     int *rval)
1401 {
1402 	struct fcp_port	*pptr;
1403 	struct	device_data	*dev_data;
1404 	uint32_t		link_cnt;
1405 	la_wwn_t		*wwn_ptr = NULL;
1406 	struct fcp_tgt		*ptgt = NULL;
1407 	struct fcp_lun		*plun = NULL;
1408 	int			i, error;
1409 	struct fcp_ioctl	fioctl;
1410 
1411 #ifdef	_MULTI_DATAMODEL
1412 	switch (ddi_model_convert_from(mode & FMODELS)) {
1413 	case DDI_MODEL_ILP32: {
1414 		struct fcp32_ioctl f32_ioctl;
1415 
1416 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1417 		    sizeof (struct fcp32_ioctl), mode)) {
1418 			return (EFAULT);
1419 		}
1420 		fioctl.fp_minor = f32_ioctl.fp_minor;
1421 		fioctl.listlen = f32_ioctl.listlen;
1422 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1423 		break;
1424 	}
1425 	case DDI_MODEL_NONE:
1426 		if (ddi_copyin((void *)data, (void *)&fioctl,
1427 		    sizeof (struct fcp_ioctl), mode)) {
1428 			return (EFAULT);
1429 		}
1430 		break;
1431 	}
1432 
1433 #else	/* _MULTI_DATAMODEL */
1434 	if (ddi_copyin((void *)data, (void *)&fioctl,
1435 	    sizeof (struct fcp_ioctl), mode)) {
1436 		return (EFAULT);
1437 	}
1438 #endif	/* _MULTI_DATAMODEL */
1439 
1440 	/*
1441 	 * Right now we can assume that the minor number matches with
1442 	 * this instance of fp. If this changes we will need to
1443 	 * revisit this logic.
1444 	 */
1445 	mutex_enter(&fcp_global_mutex);
1446 	pptr = fcp_port_head;
1447 	while (pptr) {
1448 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1449 			break;
1450 		} else {
1451 			pptr = pptr->port_next;
1452 		}
1453 	}
1454 	mutex_exit(&fcp_global_mutex);
1455 	if (pptr == NULL) {
1456 		return (ENXIO);
1457 	}
1458 	mutex_enter(&pptr->port_mutex);
1459 
1460 
1461 	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1462 	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
1463 		mutex_exit(&pptr->port_mutex);
1464 		return (ENOMEM);
1465 	}
1466 
1467 	if (ddi_copyin(fioctl.list, dev_data,
1468 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1469 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1470 		mutex_exit(&pptr->port_mutex);
1471 		return (EFAULT);
1472 	}
1473 	link_cnt = pptr->port_link_cnt;
1474 
1475 	if (cmd == FCP_TGT_INQUIRY) {
1476 		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1477 		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1478 		    sizeof (wwn_ptr->raw_wwn)) == 0) {
1479 			/* This ioctl is requesting INQ info of local HBA */
1480 			mutex_exit(&pptr->port_mutex);
1481 			dev_data[0].dev0_type = DTYPE_UNKNOWN;
1482 			dev_data[0].dev_status = 0;
1483 			if (ddi_copyout(dev_data, fioctl.list,
1484 			    (sizeof (struct device_data)) * fioctl.listlen,
1485 			    mode)) {
1486 				kmem_free(dev_data,
1487 				    sizeof (*dev_data) * fioctl.listlen);
1488 				return (EFAULT);
1489 			}
1490 			kmem_free(dev_data,
1491 			    sizeof (*dev_data) * fioctl.listlen);
1492 #ifdef	_MULTI_DATAMODEL
1493 			switch (ddi_model_convert_from(mode & FMODELS)) {
1494 			case DDI_MODEL_ILP32: {
1495 				struct fcp32_ioctl f32_ioctl;
1496 				f32_ioctl.fp_minor = fioctl.fp_minor;
1497 				f32_ioctl.listlen = fioctl.listlen;
1498 				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1499 				if (ddi_copyout((void *)&f32_ioctl,
1500 				    (void *)data,
1501 				    sizeof (struct fcp32_ioctl), mode)) {
1502 					return (EFAULT);
1503 				}
1504 				break;
1505 			}
1506 			case DDI_MODEL_NONE:
1507 				if (ddi_copyout((void *)&fioctl, (void *)data,
1508 				    sizeof (struct fcp_ioctl), mode)) {
1509 					return (EFAULT);
1510 				}
1511 				break;
1512 			}
1513 #else	/* _MULTI_DATAMODEL */
1514 			if (ddi_copyout((void *)&fioctl, (void *)data,
1515 			    sizeof (struct fcp_ioctl), mode)) {
1516 				return (EFAULT);
1517 			}
1518 #endif	/* _MULTI_DATAMODEL */
1519 			return (0);
1520 		}
1521 	}
1522 
1523 	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1524 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1525 		mutex_exit(&pptr->port_mutex);
1526 		return (ENXIO);
1527 	}
1528 
1529 	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1530 	    i++) {
1531 		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1532 
1533 		dev_data[i].dev0_type = DTYPE_UNKNOWN;
1534 
1535 
1536 		dev_data[i].dev_status = ENXIO;
1537 
1538 		if ((ptgt = fcp_lookup_target(pptr,
1539 		    (uchar_t *)wwn_ptr)) == NULL) {
1540 			mutex_exit(&pptr->port_mutex);
1541 			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1542 			    wwn_ptr, &error, 0) == NULL) {
1543 				dev_data[i].dev_status = ENODEV;
1544 				mutex_enter(&pptr->port_mutex);
1545 				continue;
1546 			} else {
1547 
1548 				dev_data[i].dev_status = EAGAIN;
1549 
1550 				mutex_enter(&pptr->port_mutex);
1551 				continue;
1552 			}
1553 		} else {
1554 			mutex_enter(&ptgt->tgt_mutex);
1555 			if (ptgt->tgt_state & (FCP_TGT_MARK |
1556 			    FCP_TGT_BUSY)) {
1557 				dev_data[i].dev_status = EAGAIN;
1558 				mutex_exit(&ptgt->tgt_mutex);
1559 				continue;
1560 			}
1561 
1562 			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1563 				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1564 					dev_data[i].dev_status = ENOTSUP;
1565 				} else {
1566 					dev_data[i].dev_status = ENXIO;
1567 				}
1568 				mutex_exit(&ptgt->tgt_mutex);
1569 				continue;
1570 			}
1571 
1572 			switch (cmd) {
1573 			case FCP_TGT_INQUIRY:
1574 				/*
1575 				 * The reason we give device type of
1576 				 * lun 0 only even though in some
1577 				 * cases(like maxstrat) lun 0 device
1578 				 * type may be 0x3f(invalid) is that
1579 				 * for bridge boxes target will appear
1580 				 * as luns and the first lun could be
1581 				 * a device that utility may not care
1582 				 * about (like a tape device).
1583 				 */
1584 				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1585 				dev_data[i].dev_status = 0;
1586 				mutex_exit(&ptgt->tgt_mutex);
1587 
1588 				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1589 					dev_data[i].dev0_type = DTYPE_UNKNOWN;
1590 				} else {
1591 					dev_data[i].dev0_type = plun->lun_type;
1592 				}
1593 				mutex_enter(&ptgt->tgt_mutex);
1594 				break;
1595 
1596 			case FCP_TGT_CREATE:
1597 				mutex_exit(&ptgt->tgt_mutex);
1598 				mutex_exit(&pptr->port_mutex);
1599 
1600 				/*
1601 				 * serialize state change call backs.
1602 				 * only one call back will be handled
1603 				 * at a time.
1604 				 */
1605 				mutex_enter(&fcp_global_mutex);
1606 				if (fcp_oflag & FCP_BUSY) {
1607 					mutex_exit(&fcp_global_mutex);
1608 					if (dev_data) {
1609 						kmem_free(dev_data,
1610 						    sizeof (*dev_data) *
1611 						    fioctl.listlen);
1612 					}
1613 					return (EBUSY);
1614 				}
1615 				fcp_oflag |= FCP_BUSY;
1616 				mutex_exit(&fcp_global_mutex);
1617 
1618 				dev_data[i].dev_status =
1619 				    fcp_create_on_demand(pptr,
1620 				    wwn_ptr->raw_wwn);
1621 
1622 				if (dev_data[i].dev_status != 0) {
1623 					char	buf[25];
1624 
1625 					for (i = 0; i < FC_WWN_SIZE; i++) {
1626 						(void) sprintf(&buf[i << 1],
1627 						    "%02x",
1628 						    wwn_ptr->raw_wwn[i]);
1629 					}
1630 
1631 					fcp_log(CE_WARN, pptr->port_dip,
1632 					    "!Failed to create nodes for"
1633 					    " pwwn=%s; error=%x", buf,
1634 					    dev_data[i].dev_status);
1635 				}
1636 
1637 				/* allow state change call backs again */
1638 				mutex_enter(&fcp_global_mutex);
1639 				fcp_oflag &= ~FCP_BUSY;
1640 				mutex_exit(&fcp_global_mutex);
1641 
1642 				mutex_enter(&pptr->port_mutex);
1643 				mutex_enter(&ptgt->tgt_mutex);
1644 
1645 				break;
1646 
1647 			case FCP_TGT_DELETE:
1648 				break;
1649 
1650 			default:
1651 				fcp_log(CE_WARN, pptr->port_dip,
1652 				    "!Invalid device data ioctl "
1653 				    "opcode = 0x%x", cmd);
1654 			}
1655 			mutex_exit(&ptgt->tgt_mutex);
1656 		}
1657 	}
1658 	mutex_exit(&pptr->port_mutex);
1659 
1660 	if (ddi_copyout(dev_data, fioctl.list,
1661 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1662 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1663 		return (EFAULT);
1664 	}
1665 	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1666 
1667 #ifdef	_MULTI_DATAMODEL
1668 	switch (ddi_model_convert_from(mode & FMODELS)) {
1669 	case DDI_MODEL_ILP32: {
1670 		struct fcp32_ioctl f32_ioctl;
1671 
1672 		f32_ioctl.fp_minor = fioctl.fp_minor;
1673 		f32_ioctl.listlen = fioctl.listlen;
1674 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1675 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1676 		    sizeof (struct fcp32_ioctl), mode)) {
1677 			return (EFAULT);
1678 		}
1679 		break;
1680 	}
1681 	case DDI_MODEL_NONE:
1682 		if (ddi_copyout((void *)&fioctl, (void *)data,
1683 		    sizeof (struct fcp_ioctl), mode)) {
1684 			return (EFAULT);
1685 		}
1686 		break;
1687 	}
1688 #else	/* _MULTI_DATAMODEL */
1689 
1690 	if (ddi_copyout((void *)&fioctl, (void *)data,
1691 	    sizeof (struct fcp_ioctl), mode)) {
1692 		return (EFAULT);
1693 	}
1694 #endif	/* _MULTI_DATAMODEL */
1695 
1696 	return (0);
1697 }
1698 
1699 /*
1700  * Fetch the target mappings (path, etc.) for all LUNs
1701  * on this port.
1702  */
1703 /* ARGSUSED */
1704 static int
1705 fcp_get_target_mappings(struct fcp_ioctl *data,
1706     int mode, int *rval)
1707 {
1708 	struct fcp_port	    *pptr;
1709 	fc_hba_target_mappings_t    *mappings;
1710 	fc_hba_mapping_entry_t	    *map;
1711 	struct fcp_tgt	    *ptgt = NULL;
1712 	struct fcp_lun	    *plun = NULL;
1713 	int			    i, mapIndex, mappingSize;
1714 	int			    listlen;
1715 	struct fcp_ioctl	    fioctl;
1716 	char			    *path;
1717 	fcp_ent_addr_t		    sam_lun_addr;
1718 
1719 #ifdef	_MULTI_DATAMODEL
1720 	switch (ddi_model_convert_from(mode & FMODELS)) {
1721 	case DDI_MODEL_ILP32: {
1722 		struct fcp32_ioctl f32_ioctl;
1723 
1724 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1725 		    sizeof (struct fcp32_ioctl), mode)) {
1726 			return (EFAULT);
1727 		}
1728 		fioctl.fp_minor = f32_ioctl.fp_minor;
1729 		fioctl.listlen = f32_ioctl.listlen;
1730 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1731 		break;
1732 	}
1733 	case DDI_MODEL_NONE:
1734 		if (ddi_copyin((void *)data, (void *)&fioctl,
1735 		    sizeof (struct fcp_ioctl), mode)) {
1736 			return (EFAULT);
1737 		}
1738 		break;
1739 	}
1740 
1741 #else	/* _MULTI_DATAMODEL */
1742 	if (ddi_copyin((void *)data, (void *)&fioctl,
1743 	    sizeof (struct fcp_ioctl), mode)) {
1744 		return (EFAULT);
1745 	}
1746 #endif	/* _MULTI_DATAMODEL */
1747 
1748 	/*
1749 	 * Right now we can assume that the minor number matches with
1750 	 * this instance of fp. If this changes we will need to
1751 	 * revisit this logic.
1752 	 */
1753 	mutex_enter(&fcp_global_mutex);
1754 	pptr = fcp_port_head;
1755 	while (pptr) {
1756 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1757 			break;
1758 		} else {
1759 			pptr = pptr->port_next;
1760 		}
1761 	}
1762 	mutex_exit(&fcp_global_mutex);
1763 	if (pptr == NULL) {
1764 		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1765 		    fioctl.fp_minor);
1766 		return (ENXIO);
1767 	}
1768 
1769 
1770 	/* We use listlen to show the total buffer size */
1771 	mappingSize = fioctl.listlen;
1772 
1773 	/* Now calculate how many mapping entries will fit */
1774 	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1775 	    - sizeof (fc_hba_target_mappings_t);
1776 	if (listlen <= 0) {
1777 		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1778 		return (ENXIO);
1779 	}
1780 	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1781 
1782 	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1783 		return (ENOMEM);
1784 	}
1785 	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1786 
1787 	/* Now get to work */
1788 	mapIndex = 0;
1789 
1790 	mutex_enter(&pptr->port_mutex);
1791 	/* Loop through all targets on this port */
1792 	for (i = 0; i < FCP_NUM_HASH; i++) {
1793 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1794 		    ptgt = ptgt->tgt_next) {
1795 
1796 
1797 			/* Loop through all LUNs on this target */
1798 			for (plun = ptgt->tgt_lun; plun != NULL;
1799 			    plun = plun->lun_next) {
1800 				if (plun->lun_state & FCP_LUN_OFFLINE) {
1801 					continue;
1802 				}
1803 
1804 				path = fcp_get_lun_path(plun);
1805 				if (path == NULL) {
1806 					continue;
1807 				}
1808 
1809 				if (mapIndex >= listlen) {
1810 					mapIndex ++;
1811 					kmem_free(path, MAXPATHLEN);
1812 					continue;
1813 				}
1814 				map = &mappings->entries[mapIndex++];
1815 				bcopy(path, map->targetDriver,
1816 				    sizeof (map->targetDriver));
1817 				map->d_id = ptgt->tgt_d_id;
1818 				map->busNumber = 0;
1819 				map->targetNumber = ptgt->tgt_d_id;
1820 				map->osLUN = plun->lun_num;
1821 
1822 				/*
1823 				 * We had swapped lun when we stored it in
1824 				 * lun_addr. We need to swap it back before
1825 				 * returning it to user land
1826 				 */
1827 
1828 				sam_lun_addr.ent_addr_0 =
1829 				    BE_16(plun->lun_addr.ent_addr_0);
1830 				sam_lun_addr.ent_addr_1 =
1831 				    BE_16(plun->lun_addr.ent_addr_1);
1832 				sam_lun_addr.ent_addr_2 =
1833 				    BE_16(plun->lun_addr.ent_addr_2);
1834 				sam_lun_addr.ent_addr_3 =
1835 				    BE_16(plun->lun_addr.ent_addr_3);
1836 
1837 				bcopy(&sam_lun_addr, &map->samLUN,
1838 				    FCP_LUN_SIZE);
1839 				bcopy(ptgt->tgt_node_wwn.raw_wwn,
1840 				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1841 				bcopy(ptgt->tgt_port_wwn.raw_wwn,
1842 				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1843 
1844 				if (plun->lun_guid) {
1845 
1846 					/* convert ascii wwn to bytes */
1847 					fcp_ascii_to_wwn(plun->lun_guid,
1848 					    map->guid, sizeof (map->guid));
1849 
1850 					if ((sizeof (map->guid)) <
1851 					    plun->lun_guid_size / 2) {
1852 						cmn_err(CE_WARN,
1853 						    "fcp_get_target_mappings:"
1854 						    "guid copy space "
1855 						    "insufficient."
1856 						    "Copy Truncation - "
1857 						    "available %d; need %d",
1858 						    (int)sizeof (map->guid),
1859 						    (int)
1860 						    plun->lun_guid_size / 2);
1861 					}
1862 				}
1863 				kmem_free(path, MAXPATHLEN);
1864 			}
1865 		}
1866 	}
1867 	mutex_exit(&pptr->port_mutex);
1868 	mappings->numLuns = mapIndex;
1869 
1870 	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1871 		kmem_free(mappings, mappingSize);
1872 		return (EFAULT);
1873 	}
1874 	kmem_free(mappings, mappingSize);
1875 
1876 #ifdef	_MULTI_DATAMODEL
1877 	switch (ddi_model_convert_from(mode & FMODELS)) {
1878 	case DDI_MODEL_ILP32: {
1879 		struct fcp32_ioctl f32_ioctl;
1880 
1881 		f32_ioctl.fp_minor = fioctl.fp_minor;
1882 		f32_ioctl.listlen = fioctl.listlen;
1883 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1884 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1885 		    sizeof (struct fcp32_ioctl), mode)) {
1886 			return (EFAULT);
1887 		}
1888 		break;
1889 	}
1890 	case DDI_MODEL_NONE:
1891 		if (ddi_copyout((void *)&fioctl, (void *)data,
1892 		    sizeof (struct fcp_ioctl), mode)) {
1893 			return (EFAULT);
1894 		}
1895 		break;
1896 	}
1897 #else	/* _MULTI_DATAMODEL */
1898 
1899 	if (ddi_copyout((void *)&fioctl, (void *)data,
1900 	    sizeof (struct fcp_ioctl), mode)) {
1901 		return (EFAULT);
1902 	}
1903 #endif	/* _MULTI_DATAMODEL */
1904 
1905 	return (0);
1906 }
1907 
1908 /*
1909  * fcp_setup_scsi_ioctl
1910  *	Setup handler for the "scsi passthru" style of
1911  *	ioctl for FCP.	See "fcp_util.h" for data structure
1912  *	definition.
1913  *
1914  * Input:
1915  *	u_fscsi	= ioctl data (user address space)
1916  *	mode	= See ioctl(9E)
1917  *
1918  * Output:
1919  *	u_fscsi	= ioctl data (user address space)
1920  *	rval	= return value - see ioctl(9E)
1921  *
1922  * Returns:
1923  *	0	= OK
1924  *	EAGAIN	= See errno.h
1925  *	EBUSY	= See errno.h
1926  *	EFAULT	= See errno.h
1927  *	EINTR	= See errno.h
1928  *	EINVAL	= See errno.h
1929  *	EIO	= See errno.h
1930  *	ENOMEM	= See errno.h
1931  *	ENXIO	= See errno.h
1932  *
1933  * Context:
1934  *	Kernel context.
1935  */
1936 /* ARGSUSED */
1937 static int
1938 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1939     int mode, int *rval)
1940 {
1941 	int			ret		= 0;
1942 	int			temp_ret;
1943 	caddr_t			k_cdbbufaddr	= NULL;
1944 	caddr_t			k_bufaddr	= NULL;
1945 	caddr_t			k_rqbufaddr	= NULL;
1946 	caddr_t			u_cdbbufaddr;
1947 	caddr_t			u_bufaddr;
1948 	caddr_t			u_rqbufaddr;
1949 	struct fcp_scsi_cmd	k_fscsi;
1950 
1951 	/*
1952 	 * Get fcp_scsi_cmd array element from user address space
1953 	 */
1954 	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1955 	    != 0) {
1956 		return (ret);
1957 	}
1958 
1959 
1960 	/*
1961 	 * Even though kmem_alloc() checks the validity of the
1962 	 * buffer length, this check is needed when the
1963 	 * kmem_flags set and the zero buffer length is passed.
1964 	 */
1965 	if ((k_fscsi.scsi_cdblen <= 0) ||
1966 	    (k_fscsi.scsi_buflen <= 0) ||
1967 	    (k_fscsi.scsi_buflen > FCP_MAX_RESPONSE_LEN) ||
1968 	    (k_fscsi.scsi_rqlen <= 0) ||
1969 	    (k_fscsi.scsi_rqlen > FCP_MAX_SENSE_LEN)) {
1970 		return (EINVAL);
1971 	}
1972 
1973 	/*
1974 	 * Allocate data for fcp_scsi_cmd pointer fields
1975 	 */
1976 	if (ret == 0) {
1977 		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
1978 		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
1979 		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
1980 
1981 		if (k_cdbbufaddr == NULL ||
1982 		    k_bufaddr	 == NULL ||
1983 		    k_rqbufaddr	 == NULL) {
1984 			ret = ENOMEM;
1985 		}
1986 	}
1987 
1988 	/*
1989 	 * Get fcp_scsi_cmd pointer fields from user
1990 	 * address space
1991 	 */
1992 	if (ret == 0) {
1993 		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
1994 		u_bufaddr    = k_fscsi.scsi_bufaddr;
1995 		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
1996 
1997 		if (ddi_copyin(u_cdbbufaddr,
1998 		    k_cdbbufaddr,
1999 		    k_fscsi.scsi_cdblen,
2000 		    mode)) {
2001 			ret = EFAULT;
2002 		} else if (ddi_copyin(u_bufaddr,
2003 		    k_bufaddr,
2004 		    k_fscsi.scsi_buflen,
2005 		    mode)) {
2006 			ret = EFAULT;
2007 		} else if (ddi_copyin(u_rqbufaddr,
2008 		    k_rqbufaddr,
2009 		    k_fscsi.scsi_rqlen,
2010 		    mode)) {
2011 			ret = EFAULT;
2012 		}
2013 	}
2014 
2015 	/*
2016 	 * Send scsi command (blocking)
2017 	 */
2018 	if (ret == 0) {
2019 		/*
2020 		 * Prior to sending the scsi command, the
2021 		 * fcp_scsi_cmd data structure must contain kernel,
2022 		 * not user, addresses.
2023 		 */
2024 		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
2025 		k_fscsi.scsi_bufaddr	= k_bufaddr;
2026 		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
2027 
2028 		ret = fcp_send_scsi_ioctl(&k_fscsi);
2029 
2030 		/*
2031 		 * After sending the scsi command, the
2032 		 * fcp_scsi_cmd data structure must contain user,
2033 		 * not kernel, addresses.
2034 		 */
2035 		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
2036 		k_fscsi.scsi_bufaddr	= u_bufaddr;
2037 		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
2038 	}
2039 
2040 	/*
2041 	 * Put fcp_scsi_cmd pointer fields to user address space
2042 	 */
2043 	if (ret == 0) {
2044 		if (ddi_copyout(k_cdbbufaddr,
2045 		    u_cdbbufaddr,
2046 		    k_fscsi.scsi_cdblen,
2047 		    mode)) {
2048 			ret = EFAULT;
2049 		} else if (ddi_copyout(k_bufaddr,
2050 		    u_bufaddr,
2051 		    k_fscsi.scsi_buflen,
2052 		    mode)) {
2053 			ret = EFAULT;
2054 		} else if (ddi_copyout(k_rqbufaddr,
2055 		    u_rqbufaddr,
2056 		    k_fscsi.scsi_rqlen,
2057 		    mode)) {
2058 			ret = EFAULT;
2059 		}
2060 	}
2061 
2062 	/*
2063 	 * Free data for fcp_scsi_cmd pointer fields
2064 	 */
2065 	if (k_cdbbufaddr != NULL) {
2066 		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2067 	}
2068 	if (k_bufaddr != NULL) {
2069 		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2070 	}
2071 	if (k_rqbufaddr != NULL) {
2072 		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2073 	}
2074 
2075 	/*
2076 	 * Put fcp_scsi_cmd array element to user address space
2077 	 */
2078 	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2079 	if (temp_ret != 0) {
2080 		ret = temp_ret;
2081 	}
2082 
2083 	/*
2084 	 * Return status
2085 	 */
2086 	return (ret);
2087 }
2088 
2089 
2090 /*
2091  * fcp_copyin_scsi_cmd
2092  *	Copy in fcp_scsi_cmd data structure from user address space.
2093  *	The data may be in 32 bit or 64 bit modes.
2094  *
2095  * Input:
2096  *	base_addr	= from address (user address space)
2097  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2098  *
2099  * Output:
2100  *	fscsi		= to address (kernel address space)
2101  *
2102  * Returns:
2103  *	0	= OK
2104  *	EFAULT	= Error
2105  *
2106  * Context:
2107  *	Kernel context.
2108  */
2109 static int
2110 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2111 {
2112 #ifdef	_MULTI_DATAMODEL
2113 	struct fcp32_scsi_cmd	f32scsi;
2114 
2115 	switch (ddi_model_convert_from(mode & FMODELS)) {
2116 	case DDI_MODEL_ILP32:
2117 		/*
2118 		 * Copy data from user address space
2119 		 */
2120 		if (ddi_copyin((void *)base_addr,
2121 		    &f32scsi,
2122 		    sizeof (struct fcp32_scsi_cmd),
2123 		    mode)) {
2124 			return (EFAULT);
2125 		}
2126 		/*
2127 		 * Convert from 32 bit to 64 bit
2128 		 */
2129 		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2130 		break;
2131 	case DDI_MODEL_NONE:
2132 		/*
2133 		 * Copy data from user address space
2134 		 */
2135 		if (ddi_copyin((void *)base_addr,
2136 		    fscsi,
2137 		    sizeof (struct fcp_scsi_cmd),
2138 		    mode)) {
2139 			return (EFAULT);
2140 		}
2141 		break;
2142 	}
2143 #else	/* _MULTI_DATAMODEL */
2144 	/*
2145 	 * Copy data from user address space
2146 	 */
2147 	if (ddi_copyin((void *)base_addr,
2148 	    fscsi,
2149 	    sizeof (struct fcp_scsi_cmd),
2150 	    mode)) {
2151 		return (EFAULT);
2152 	}
2153 #endif	/* _MULTI_DATAMODEL */
2154 
2155 	return (0);
2156 }
2157 
2158 
2159 /*
2160  * fcp_copyout_scsi_cmd
2161  *	Copy out fcp_scsi_cmd data structure to user address space.
2162  *	The data may be in 32 bit or 64 bit modes.
2163  *
2164  * Input:
2165  *	fscsi		= to address (kernel address space)
2166  *	mode		= See ioctl(9E) and ddi_copyin(9F)
2167  *
2168  * Output:
2169  *	base_addr	= from address (user address space)
2170  *
2171  * Returns:
2172  *	0	= OK
2173  *	EFAULT	= Error
2174  *
2175  * Context:
2176  *	Kernel context.
2177  */
2178 static int
2179 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2180 {
2181 #ifdef	_MULTI_DATAMODEL
2182 	struct fcp32_scsi_cmd	f32scsi;
2183 
2184 	switch (ddi_model_convert_from(mode & FMODELS)) {
2185 	case DDI_MODEL_ILP32:
2186 		/*
2187 		 * Convert from 64 bit to 32 bit
2188 		 */
2189 		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2190 		/*
2191 		 * Copy data to user address space
2192 		 */
2193 		if (ddi_copyout(&f32scsi,
2194 		    (void *)base_addr,
2195 		    sizeof (struct fcp32_scsi_cmd),
2196 		    mode)) {
2197 			return (EFAULT);
2198 		}
2199 		break;
2200 	case DDI_MODEL_NONE:
2201 		/*
2202 		 * Copy data to user address space
2203 		 */
2204 		if (ddi_copyout(fscsi,
2205 		    (void *)base_addr,
2206 		    sizeof (struct fcp_scsi_cmd),
2207 		    mode)) {
2208 			return (EFAULT);
2209 		}
2210 		break;
2211 	}
2212 #else	/* _MULTI_DATAMODEL */
2213 	/*
2214 	 * Copy data to user address space
2215 	 */
2216 	if (ddi_copyout(fscsi,
2217 	    (void *)base_addr,
2218 	    sizeof (struct fcp_scsi_cmd),
2219 	    mode)) {
2220 		return (EFAULT);
2221 	}
2222 #endif	/* _MULTI_DATAMODEL */
2223 
2224 	return (0);
2225 }
2226 
2227 
2228 /*
2229  * fcp_send_scsi_ioctl
2230  *	Sends the SCSI command in blocking mode.
2231  *
2232  * Input:
2233  *	fscsi		= SCSI command data structure
2234  *
2235  * Output:
2236  *	fscsi		= SCSI command data structure
2237  *
2238  * Returns:
2239  *	0	= OK
2240  *	EAGAIN	= See errno.h
2241  *	EBUSY	= See errno.h
2242  *	EINTR	= See errno.h
2243  *	EINVAL	= See errno.h
2244  *	EIO	= See errno.h
2245  *	ENOMEM	= See errno.h
2246  *	ENXIO	= See errno.h
2247  *
2248  * Context:
2249  *	Kernel context.
2250  */
2251 static int
2252 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2253 {
2254 	struct fcp_lun	*plun		= NULL;
2255 	struct fcp_port	*pptr		= NULL;
2256 	struct fcp_tgt	*ptgt		= NULL;
2257 	fc_packet_t		*fpkt		= NULL;
2258 	struct fcp_ipkt	*icmd		= NULL;
2259 	int			target_created	= FALSE;
2260 	fc_frame_hdr_t		*hp;
2261 	struct fcp_cmd		fcp_cmd;
2262 	struct fcp_cmd		*fcmd;
2263 	union scsi_cdb		*scsi_cdb;
2264 	la_wwn_t		*wwn_ptr;
2265 	int			nodma;
2266 	struct fcp_rsp		*rsp;
2267 	struct fcp_rsp_info	*rsp_info;
2268 	caddr_t			rsp_sense;
2269 	int			buf_len;
2270 	int			info_len;
2271 	int			sense_len;
2272 	struct scsi_extended_sense	*sense_to = NULL;
2273 	timeout_id_t		tid;
2274 	uint8_t			reconfig_lun = FALSE;
2275 	uint8_t			reconfig_pending = FALSE;
2276 	uint8_t			scsi_cmd;
2277 	int			rsp_len;
2278 	int			cmd_index;
2279 	int			fc_status;
2280 	int			pkt_state;
2281 	int			pkt_action;
2282 	int			pkt_reason;
2283 	int			ret, xport_retval = ~FC_SUCCESS;
2284 	int			lcount;
2285 	int			tcount;
2286 	int			reconfig_status;
2287 	int			port_busy = FALSE;
2288 	uchar_t			*lun_string;
2289 
2290 	/*
2291 	 * Check valid SCSI command
2292 	 */
2293 	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2294 	ret = EINVAL;
2295 	for (cmd_index = 0;
2296 	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2297 	    ret != 0;
2298 	    cmd_index++) {
2299 		/*
2300 		 * First byte of CDB is the SCSI command
2301 		 */
2302 		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2303 			ret = 0;
2304 		}
2305 	}
2306 
2307 	/*
2308 	 * Check inputs
2309 	 */
2310 	if (fscsi->scsi_flags != FCP_SCSI_READ) {
2311 		ret = EINVAL;
2312 	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2313 		/* no larger than */
2314 		ret = EINVAL;
2315 	}
2316 
2317 
2318 	/*
2319 	 * Find FC port
2320 	 */
2321 	if (ret == 0) {
2322 		/*
2323 		 * Acquire global mutex
2324 		 */
2325 		mutex_enter(&fcp_global_mutex);
2326 
2327 		pptr = fcp_port_head;
2328 		while (pptr) {
2329 			if (pptr->port_instance ==
2330 			    (uint32_t)fscsi->scsi_fc_port_num) {
2331 				break;
2332 			} else {
2333 				pptr = pptr->port_next;
2334 			}
2335 		}
2336 
2337 		if (pptr == NULL) {
2338 			ret = ENXIO;
2339 		} else {
2340 			/*
2341 			 * fc_ulp_busy_port can raise power
2342 			 *  so, we must not hold any mutexes involved in PM
2343 			 */
2344 			mutex_exit(&fcp_global_mutex);
2345 			ret = fc_ulp_busy_port(pptr->port_fp_handle);
2346 		}
2347 
2348 		if (ret == 0) {
2349 
2350 			/* remember port is busy, so we will release later */
2351 			port_busy = TRUE;
2352 
2353 			/*
2354 			 * If there is a reconfiguration in progress, wait
2355 			 * for it to complete.
2356 			 */
2357 
2358 			fcp_reconfig_wait(pptr);
2359 
2360 			/* reacquire mutexes in order */
2361 			mutex_enter(&fcp_global_mutex);
2362 			mutex_enter(&pptr->port_mutex);
2363 
2364 			/*
2365 			 * Will port accept DMA?
2366 			 */
2367 			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2368 			    ? 1 : 0;
2369 
2370 			/*
2371 			 * If init or offline, device not known
2372 			 *
2373 			 * If we are discovering (onlining), we can
2374 			 * NOT obviously provide reliable data about
2375 			 * devices until it is complete
2376 			 */
2377 			if (pptr->port_state &	  (FCP_STATE_INIT |
2378 			    FCP_STATE_OFFLINE)) {
2379 				ret = ENXIO;
2380 			} else if (pptr->port_state & FCP_STATE_ONLINING) {
2381 				ret = EBUSY;
2382 			} else {
2383 				/*
2384 				 * Find target from pwwn
2385 				 *
2386 				 * The wwn must be put into a local
2387 				 * variable to ensure alignment.
2388 				 */
2389 				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2390 				ptgt = fcp_lookup_target(pptr,
2391 				    (uchar_t *)wwn_ptr);
2392 
2393 				/*
2394 				 * If target not found,
2395 				 */
2396 				if (ptgt == NULL) {
2397 					/*
2398 					 * Note: Still have global &
2399 					 * port mutexes
2400 					 */
2401 					mutex_exit(&pptr->port_mutex);
2402 					ptgt = fcp_port_create_tgt(pptr,
2403 					    wwn_ptr, &ret, &fc_status,
2404 					    &pkt_state, &pkt_action,
2405 					    &pkt_reason);
2406 					mutex_enter(&pptr->port_mutex);
2407 
2408 					fscsi->scsi_fc_status  = fc_status;
2409 					fscsi->scsi_pkt_state  =
2410 					    (uchar_t)pkt_state;
2411 					fscsi->scsi_pkt_reason = pkt_reason;
2412 					fscsi->scsi_pkt_action =
2413 					    (uchar_t)pkt_action;
2414 
2415 					if (ptgt != NULL) {
2416 						target_created = TRUE;
2417 					} else if (ret == 0) {
2418 						ret = ENOMEM;
2419 					}
2420 				}
2421 
2422 				if (ret == 0) {
2423 					/*
2424 					 * Acquire target
2425 					 */
2426 					mutex_enter(&ptgt->tgt_mutex);
2427 
2428 					/*
2429 					 * If target is mark or busy,
2430 					 * then target can not be used
2431 					 */
2432 					if (ptgt->tgt_state &
2433 					    (FCP_TGT_MARK |
2434 					    FCP_TGT_BUSY)) {
2435 						ret = EBUSY;
2436 					} else {
2437 						/*
2438 						 * Mark target as busy
2439 						 */
2440 						ptgt->tgt_state |=
2441 						    FCP_TGT_BUSY;
2442 					}
2443 
2444 					/*
2445 					 * Release target
2446 					 */
2447 					lcount = pptr->port_link_cnt;
2448 					tcount = ptgt->tgt_change_cnt;
2449 					mutex_exit(&ptgt->tgt_mutex);
2450 				}
2451 			}
2452 
2453 			/*
2454 			 * Release port
2455 			 */
2456 			mutex_exit(&pptr->port_mutex);
2457 		}
2458 
2459 		/*
2460 		 * Release global mutex
2461 		 */
2462 		mutex_exit(&fcp_global_mutex);
2463 	}
2464 
2465 	if (ret == 0) {
2466 		uint64_t belun = BE_64(fscsi->scsi_lun);
2467 
2468 		/*
2469 		 * If it's a target device, find lun from pwwn
2470 		 * The wwn must be put into a local
2471 		 * variable to ensure alignment.
2472 		 */
2473 		mutex_enter(&pptr->port_mutex);
2474 		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2475 		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2476 			/* this is not a target */
2477 			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2478 			ret = ENXIO;
2479 		} else if ((belun << 16) != 0) {
2480 			/*
2481 			 * Since fcp only support PD and LU addressing method
2482 			 * so far, the last 6 bytes of a valid LUN are expected
2483 			 * to be filled with 00h.
2484 			 */
2485 			fscsi->scsi_fc_status = FC_INVALID_LUN;
2486 			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2487 			    " method 0x%02x with LUN number 0x%016" PRIx64,
2488 			    (uint8_t)(belun >> 62), belun);
2489 			ret = ENXIO;
2490 		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2491 		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2492 			/*
2493 			 * This is a SCSI target, but no LUN at this
2494 			 * address.
2495 			 *
2496 			 * In the future, we may want to send this to
2497 			 * the target, and let it respond
2498 			 * appropriately
2499 			 */
2500 			ret = ENXIO;
2501 		}
2502 		mutex_exit(&pptr->port_mutex);
2503 	}
2504 
2505 	/*
2506 	 * Finished grabbing external resources
2507 	 * Allocate internal packet (icmd)
2508 	 */
2509 	if (ret == 0) {
2510 		/*
2511 		 * Calc rsp len assuming rsp info included
2512 		 */
2513 		rsp_len = sizeof (struct fcp_rsp) +
2514 		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2515 
2516 		icmd = fcp_icmd_alloc(pptr, ptgt,
2517 		    sizeof (struct fcp_cmd),
2518 		    rsp_len,
2519 		    fscsi->scsi_buflen,
2520 		    nodma,
2521 		    lcount,			/* ipkt_link_cnt */
2522 		    tcount,			/* ipkt_change_cnt */
2523 		    0,				/* cause */
2524 		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
2525 
2526 		if (icmd == NULL) {
2527 			ret = ENOMEM;
2528 		} else {
2529 			/*
2530 			 * Setup internal packet as sema sync
2531 			 */
2532 			fcp_ipkt_sema_init(icmd);
2533 		}
2534 	}
2535 
2536 	if (ret == 0) {
2537 		/*
2538 		 * Init fpkt pointer for use.
2539 		 */
2540 
2541 		fpkt = icmd->ipkt_fpkt;
2542 
2543 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
2544 		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
2545 		fpkt->pkt_timeout	= fscsi->scsi_timeout;
2546 
2547 		/*
2548 		 * Init fcmd pointer for use by SCSI command
2549 		 */
2550 
2551 		if (nodma) {
2552 			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2553 		} else {
2554 			fcmd = &fcp_cmd;
2555 		}
2556 		bzero(fcmd, sizeof (struct fcp_cmd));
2557 		ptgt = plun->lun_tgt;
2558 
2559 		lun_string = (uchar_t *)&fscsi->scsi_lun;
2560 
2561 		fcmd->fcp_ent_addr.ent_addr_0 =
2562 		    BE_16(*(uint16_t *)&(lun_string[0]));
2563 		fcmd->fcp_ent_addr.ent_addr_1 =
2564 		    BE_16(*(uint16_t *)&(lun_string[2]));
2565 		fcmd->fcp_ent_addr.ent_addr_2 =
2566 		    BE_16(*(uint16_t *)&(lun_string[4]));
2567 		fcmd->fcp_ent_addr.ent_addr_3 =
2568 		    BE_16(*(uint16_t *)&(lun_string[6]));
2569 
2570 		/*
2571 		 * Setup internal packet(icmd)
2572 		 */
2573 		icmd->ipkt_lun		= plun;
2574 		icmd->ipkt_restart	= 0;
2575 		icmd->ipkt_retries	= 0;
2576 		icmd->ipkt_opcode	= 0;
2577 
2578 		/*
2579 		 * Init the frame HEADER Pointer for use
2580 		 */
2581 		hp = &fpkt->pkt_cmd_fhdr;
2582 
2583 		hp->s_id	= pptr->port_id;
2584 		hp->d_id	= ptgt->tgt_d_id;
2585 		hp->r_ctl	= R_CTL_COMMAND;
2586 		hp->type	= FC_TYPE_SCSI_FCP;
2587 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2588 		hp->rsvd	= 0;
2589 		hp->seq_id	= 0;
2590 		hp->seq_cnt	= 0;
2591 		hp->ox_id	= 0xffff;
2592 		hp->rx_id	= 0xffff;
2593 		hp->ro		= 0;
2594 
2595 		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
2596 		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
2597 		fcmd->fcp_cntl.cntl_write_data	= 0;
2598 		fcmd->fcp_data_len	= fscsi->scsi_buflen;
2599 
2600 		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2601 		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2602 		    fscsi->scsi_cdblen);
2603 
2604 		if (!nodma) {
2605 			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2606 			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2607 		}
2608 
2609 		/*
2610 		 * Send SCSI command to FC transport
2611 		 */
2612 
2613 		if (ret == 0) {
2614 			mutex_enter(&ptgt->tgt_mutex);
2615 
2616 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2617 				mutex_exit(&ptgt->tgt_mutex);
2618 				fscsi->scsi_fc_status = xport_retval =
2619 				    fc_ulp_transport(pptr->port_fp_handle,
2620 				    fpkt);
2621 				if (fscsi->scsi_fc_status != FC_SUCCESS) {
2622 					ret = EIO;
2623 				}
2624 			} else {
2625 				mutex_exit(&ptgt->tgt_mutex);
2626 				ret = EBUSY;
2627 			}
2628 		}
2629 	}
2630 
2631 	/*
2632 	 * Wait for completion only if fc_ulp_transport was called and it
2633 	 * returned a success. This is the only time callback will happen.
2634 	 * Otherwise, there is no point in waiting
2635 	 */
2636 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2637 		ret = fcp_ipkt_sema_wait(icmd);
2638 	}
2639 
2640 	/*
2641 	 * Copy data to IOCTL data structures
2642 	 */
2643 	rsp = NULL;
2644 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2645 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2646 
2647 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2648 			fcp_log(CE_WARN, pptr->port_dip,
2649 			    "!SCSI command to d_id=0x%x lun=0x%x"
2650 			    " failed, Bad FCP response values:"
2651 			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2652 			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2653 			    ptgt->tgt_d_id, plun->lun_num,
2654 			    rsp->reserved_0, rsp->reserved_1,
2655 			    rsp->fcp_u.fcp_status.reserved_0,
2656 			    rsp->fcp_u.fcp_status.reserved_1,
2657 			    rsp->fcp_response_len, rsp->fcp_sense_len);
2658 
2659 			ret = EIO;
2660 		}
2661 	}
2662 
2663 	if ((ret == 0) && (rsp != NULL)) {
2664 		/*
2665 		 * Calc response lengths
2666 		 */
2667 		sense_len = 0;
2668 		info_len = 0;
2669 
2670 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
2671 			info_len = rsp->fcp_response_len;
2672 		}
2673 
2674 		rsp_info   = (struct fcp_rsp_info *)
2675 		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2676 
2677 		/*
2678 		 * Get SCSI status
2679 		 */
2680 		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2681 		/*
2682 		 * If a lun was just added or removed and the next command
2683 		 * comes through this interface, we need to capture the check
2684 		 * condition so we can discover the new topology.
2685 		 */
2686 		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2687 		    rsp->fcp_u.fcp_status.sense_len_set) {
2688 			sense_len = rsp->fcp_sense_len;
2689 			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2690 			sense_to = (struct scsi_extended_sense *)rsp_sense;
2691 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2692 			    (FCP_SENSE_NO_LUN(sense_to))) {
2693 				reconfig_lun = TRUE;
2694 			}
2695 		}
2696 
2697 		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2698 		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2699 			if (reconfig_lun == FALSE) {
2700 				reconfig_status =
2701 				    fcp_is_reconfig_needed(ptgt, fpkt);
2702 			}
2703 
2704 			if ((reconfig_lun == TRUE) ||
2705 			    (reconfig_status == TRUE)) {
2706 				mutex_enter(&ptgt->tgt_mutex);
2707 				if (ptgt->tgt_tid == NULL) {
2708 					/*
2709 					 * Either we've been notified the
2710 					 * REPORT_LUN data has changed, or
2711 					 * we've determined on our own that
2712 					 * we're out of date.  Kick off
2713 					 * rediscovery.
2714 					 */
2715 					tid = timeout(fcp_reconfigure_luns,
2716 					    (caddr_t)ptgt, drv_usectohz(1));
2717 
2718 					ptgt->tgt_tid = tid;
2719 					ptgt->tgt_state |= FCP_TGT_BUSY;
2720 					ret = EBUSY;
2721 					reconfig_pending = TRUE;
2722 				}
2723 				mutex_exit(&ptgt->tgt_mutex);
2724 			}
2725 		}
2726 
2727 		/*
2728 		 * Calc residuals and buffer lengths
2729 		 */
2730 
2731 		if (ret == 0) {
2732 			buf_len = fscsi->scsi_buflen;
2733 			fscsi->scsi_bufresid	= 0;
2734 			if (rsp->fcp_u.fcp_status.resid_under) {
2735 				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2736 					fscsi->scsi_bufresid = rsp->fcp_resid;
2737 				} else {
2738 					cmn_err(CE_WARN, "fcp: bad residue %x "
2739 					    "for txfer len %x", rsp->fcp_resid,
2740 					    fscsi->scsi_buflen);
2741 					fscsi->scsi_bufresid =
2742 					    fscsi->scsi_buflen;
2743 				}
2744 				buf_len -= fscsi->scsi_bufresid;
2745 			}
2746 			if (rsp->fcp_u.fcp_status.resid_over) {
2747 				fscsi->scsi_bufresid = -rsp->fcp_resid;
2748 			}
2749 
2750 			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
2751 			if (fscsi->scsi_rqlen < sense_len) {
2752 				sense_len = fscsi->scsi_rqlen;
2753 			}
2754 
2755 			fscsi->scsi_fc_rspcode	= 0;
2756 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
2757 				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
2758 			}
2759 			fscsi->scsi_pkt_state	= fpkt->pkt_state;
2760 			fscsi->scsi_pkt_action	= fpkt->pkt_action;
2761 			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
2762 
2763 			/*
2764 			 * Copy data and request sense
2765 			 *
2766 			 * Data must be copied by using the FCP_CP_IN macro.
2767 			 * This will ensure the proper byte order since the data
2768 			 * is being copied directly from the memory mapped
2769 			 * device register.
2770 			 *
2771 			 * The response (and request sense) will be in the
2772 			 * correct byte order.	No special copy is necessary.
2773 			 */
2774 
2775 			if (buf_len) {
2776 				FCP_CP_IN(fpkt->pkt_data,
2777 				    fscsi->scsi_bufaddr,
2778 				    fpkt->pkt_data_acc,
2779 				    buf_len);
2780 			}
2781 			bcopy((void *)rsp_sense,
2782 			    (void *)fscsi->scsi_rqbufaddr,
2783 			    sense_len);
2784 		}
2785 	}
2786 
2787 	/*
2788 	 * Cleanup transport data structures if icmd was alloc-ed
2789 	 * So, cleanup happens in the same thread that icmd was alloc-ed
2790 	 */
2791 	if (icmd != NULL) {
2792 		fcp_ipkt_sema_cleanup(icmd);
2793 	}
2794 
2795 	/* restore pm busy/idle status */
2796 	if (port_busy) {
2797 		fc_ulp_idle_port(pptr->port_fp_handle);
2798 	}
2799 
2800 	/*
2801 	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2802 	 * flag, it'll be cleared when the reconfig is complete.
2803 	 */
2804 	if ((ptgt != NULL) && !reconfig_pending) {
2805 		/*
2806 		 * If target was created,
2807 		 */
2808 		if (target_created) {
2809 			mutex_enter(&ptgt->tgt_mutex);
2810 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2811 			mutex_exit(&ptgt->tgt_mutex);
2812 		} else {
2813 			/*
2814 			 * De-mark target as busy
2815 			 */
2816 			mutex_enter(&ptgt->tgt_mutex);
2817 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2818 			mutex_exit(&ptgt->tgt_mutex);
2819 		}
2820 	}
2821 	return (ret);
2822 }
2823 
2824 
2825 static int
2826 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2827     fc_packet_t	*fpkt)
2828 {
2829 	uchar_t			*lun_string;
2830 	uint16_t		lun_num, i;
2831 	int			num_luns;
2832 	int			actual_luns;
2833 	int			num_masked_luns;
2834 	int			lun_buflen;
2835 	struct fcp_lun	*plun	= NULL;
2836 	struct fcp_reportlun_resp	*report_lun;
2837 	uint8_t			reconfig_needed = FALSE;
2838 	uint8_t			lun_exists = FALSE;
2839 
2840 	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2841 
2842 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2843 	    fpkt->pkt_datalen);
2844 
2845 	/* get number of luns (which is supplied as LUNS * 8) */
2846 	num_luns = BE_32(report_lun->num_lun) >> 3;
2847 
2848 	/*
2849 	 * Figure out exactly how many lun strings our response buffer
2850 	 * can hold.
2851 	 */
2852 	lun_buflen = (fpkt->pkt_datalen -
2853 	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
2854 
2855 	/*
2856 	 * Is our response buffer full or not? We don't want to
2857 	 * potentially walk beyond the number of luns we have.
2858 	 */
2859 	if (num_luns <= lun_buflen) {
2860 		actual_luns = num_luns;
2861 	} else {
2862 		actual_luns = lun_buflen;
2863 	}
2864 
2865 	mutex_enter(&ptgt->tgt_mutex);
2866 
2867 	/* Scan each lun to see if we have masked it. */
2868 	num_masked_luns = 0;
2869 	if (fcp_lun_blacklist != NULL) {
2870 		for (i = 0; i < actual_luns; i++) {
2871 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2872 			switch (lun_string[0] & 0xC0) {
2873 			case FCP_LUN_ADDRESSING:
2874 			case FCP_PD_ADDRESSING:
2875 			case FCP_VOLUME_ADDRESSING:
2876 				lun_num = ((lun_string[0] & 0x3F) << 8)
2877 				    | lun_string[1];
2878 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
2879 				    lun_num) == TRUE) {
2880 					num_masked_luns++;
2881 				}
2882 				break;
2883 			default:
2884 				break;
2885 			}
2886 		}
2887 	}
2888 
2889 	/*
2890 	 * The quick and easy check.  If the number of LUNs reported
2891 	 * doesn't match the number we currently know about, we need
2892 	 * to reconfigure.
2893 	 */
2894 	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2895 		mutex_exit(&ptgt->tgt_mutex);
2896 		kmem_free(report_lun, fpkt->pkt_datalen);
2897 		return (TRUE);
2898 	}
2899 
2900 	/*
2901 	 * If the quick and easy check doesn't turn up anything, we walk
2902 	 * the list of luns from the REPORT_LUN response and look for
2903 	 * any luns we don't know about.  If we find one, we know we need
2904 	 * to reconfigure. We will skip LUNs that are masked because of the
2905 	 * blacklist.
2906 	 */
2907 	for (i = 0; i < actual_luns; i++) {
2908 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2909 		lun_exists = FALSE;
2910 		switch (lun_string[0] & 0xC0) {
2911 		case FCP_LUN_ADDRESSING:
2912 		case FCP_PD_ADDRESSING:
2913 		case FCP_VOLUME_ADDRESSING:
2914 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2915 
2916 			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2917 			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2918 				lun_exists = TRUE;
2919 				break;
2920 			}
2921 
2922 			for (plun = ptgt->tgt_lun; plun;
2923 			    plun = plun->lun_next) {
2924 				if (plun->lun_num == lun_num) {
2925 					lun_exists = TRUE;
2926 					break;
2927 				}
2928 			}
2929 			break;
2930 		default:
2931 			break;
2932 		}
2933 
2934 		if (lun_exists == FALSE) {
2935 			reconfig_needed = TRUE;
2936 			break;
2937 		}
2938 	}
2939 
2940 	mutex_exit(&ptgt->tgt_mutex);
2941 	kmem_free(report_lun, fpkt->pkt_datalen);
2942 
2943 	return (reconfig_needed);
2944 }
2945 
2946 /*
2947  * This function is called by fcp_handle_page83 and uses inquiry response data
2948  * stored in plun->lun_inq to determine whether or not a device is a member of
2949  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2950  * otherwise 1.
2951  */
2952 static int
2953 fcp_symmetric_device_probe(struct fcp_lun *plun)
2954 {
2955 	struct scsi_inquiry	*stdinq = &plun->lun_inq;
2956 	char			*devidptr;
2957 	int			i, len;
2958 
2959 	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2960 		devidptr = fcp_symmetric_disk_table[i];
2961 		len = (int)strlen(devidptr);
2962 
2963 		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
2964 			return (0);
2965 		}
2966 	}
2967 	return (1);
2968 }
2969 
2970 
2971 /*
2972  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
2973  * It basically returns the current count of # of state change callbacks
2974  * i.e the value of tgt_change_cnt.
2975  *
2976  * INPUT:
2977  *   fcp_ioctl.fp_minor -> The minor # of the fp port
2978  *   fcp_ioctl.listlen	-> 1
2979  *   fcp_ioctl.list	-> Pointer to a 32 bit integer
2980  */
2981 /*ARGSUSED2*/
2982 static int
2983 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
2984 {
2985 	int			ret;
2986 	uint32_t		link_cnt;
2987 	struct fcp_ioctl	fioctl;
2988 	struct fcp_port	*pptr = NULL;
2989 
2990 	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
2991 	    &pptr)) != 0) {
2992 		return (ret);
2993 	}
2994 
2995 	ASSERT(pptr != NULL);
2996 
2997 	if (fioctl.listlen != 1) {
2998 		return (EINVAL);
2999 	}
3000 
3001 	mutex_enter(&pptr->port_mutex);
3002 	if (pptr->port_state & FCP_STATE_OFFLINE) {
3003 		mutex_exit(&pptr->port_mutex);
3004 		return (ENXIO);
3005 	}
3006 
3007 	/*
3008 	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3009 	 * When the fcp initially attaches to the port and there are nothing
3010 	 * hanging out of the port or if there was a repeat offline state change
3011 	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3012 	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3013 	 * will differentiate the 2 cases.
3014 	 */
3015 	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3016 		mutex_exit(&pptr->port_mutex);
3017 		return (ENXIO);
3018 	}
3019 
3020 	link_cnt = pptr->port_link_cnt;
3021 	mutex_exit(&pptr->port_mutex);
3022 
3023 	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3024 		return (EFAULT);
3025 	}
3026 
3027 #ifdef	_MULTI_DATAMODEL
3028 	switch (ddi_model_convert_from(mode & FMODELS)) {
3029 	case DDI_MODEL_ILP32: {
3030 		struct fcp32_ioctl f32_ioctl;
3031 
3032 		f32_ioctl.fp_minor = fioctl.fp_minor;
3033 		f32_ioctl.listlen = fioctl.listlen;
3034 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3035 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3036 		    sizeof (struct fcp32_ioctl), mode)) {
3037 			return (EFAULT);
3038 		}
3039 		break;
3040 	}
3041 	case DDI_MODEL_NONE:
3042 		if (ddi_copyout((void *)&fioctl, (void *)data,
3043 		    sizeof (struct fcp_ioctl), mode)) {
3044 			return (EFAULT);
3045 		}
3046 		break;
3047 	}
3048 #else	/* _MULTI_DATAMODEL */
3049 
3050 	if (ddi_copyout((void *)&fioctl, (void *)data,
3051 	    sizeof (struct fcp_ioctl), mode)) {
3052 		return (EFAULT);
3053 	}
3054 #endif	/* _MULTI_DATAMODEL */
3055 
3056 	return (0);
3057 }
3058 
3059 /*
3060  * This function copies the fcp_ioctl structure passed in from user land
3061  * into kernel land. Handles 32 bit applications.
3062  */
3063 /*ARGSUSED*/
3064 static int
3065 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3066     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3067 {
3068 	struct fcp_port	*t_pptr;
3069 
3070 #ifdef	_MULTI_DATAMODEL
3071 	switch (ddi_model_convert_from(mode & FMODELS)) {
3072 	case DDI_MODEL_ILP32: {
3073 		struct fcp32_ioctl f32_ioctl;
3074 
3075 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3076 		    sizeof (struct fcp32_ioctl), mode)) {
3077 			return (EFAULT);
3078 		}
3079 		fioctl->fp_minor = f32_ioctl.fp_minor;
3080 		fioctl->listlen = f32_ioctl.listlen;
3081 		fioctl->list = (caddr_t)(long)f32_ioctl.list;
3082 		break;
3083 	}
3084 	case DDI_MODEL_NONE:
3085 		if (ddi_copyin((void *)data, (void *)fioctl,
3086 		    sizeof (struct fcp_ioctl), mode)) {
3087 			return (EFAULT);
3088 		}
3089 		break;
3090 	}
3091 
3092 #else	/* _MULTI_DATAMODEL */
3093 	if (ddi_copyin((void *)data, (void *)fioctl,
3094 	    sizeof (struct fcp_ioctl), mode)) {
3095 		return (EFAULT);
3096 	}
3097 #endif	/* _MULTI_DATAMODEL */
3098 
3099 	/*
3100 	 * Right now we can assume that the minor number matches with
3101 	 * this instance of fp. If this changes we will need to
3102 	 * revisit this logic.
3103 	 */
3104 	mutex_enter(&fcp_global_mutex);
3105 	t_pptr = fcp_port_head;
3106 	while (t_pptr) {
3107 		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3108 			break;
3109 		} else {
3110 			t_pptr = t_pptr->port_next;
3111 		}
3112 	}
3113 	*pptr = t_pptr;
3114 	mutex_exit(&fcp_global_mutex);
3115 	if (t_pptr == NULL) {
3116 		return (ENXIO);
3117 	}
3118 
3119 	return (0);
3120 }
3121 
3122 /*
3123  *     Function: fcp_port_create_tgt
3124  *
3125  *  Description: As the name suggest this function creates the target context
3126  *		 specified by the the WWN provided by the caller.  If the
3127  *		 creation goes well and the target is known by fp/fctl a PLOGI
3128  *		 followed by a PRLI are issued.
3129  *
3130  *     Argument: pptr		fcp port structure
3131  *		 pwwn		WWN of the target
3132  *		 ret_val	Address of the return code.  It could be:
3133  *				EIO, ENOMEM or 0.
3134  *		 fc_status	PLOGI or PRLI status completion
3135  *		 fc_pkt_state	PLOGI or PRLI state completion
3136  *		 fc_pkt_reason	PLOGI or PRLI reason completion
3137  *		 fc_pkt_action	PLOGI or PRLI action completion
3138  *
3139  * Return Value: NULL if it failed
3140  *		 Target structure address if it succeeds
3141  */
3142 static struct fcp_tgt *
3143 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3144     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3145 {
3146 	struct fcp_tgt	*ptgt = NULL;
3147 	fc_portmap_t		devlist;
3148 	int			lcount;
3149 	int			error;
3150 
3151 	*ret_val = 0;
3152 
3153 	/*
3154 	 * Check FC port device & get port map
3155 	 */
3156 	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3157 	    &error, 1) == NULL) {
3158 		*ret_val = EIO;
3159 	} else {
3160 		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3161 		    &devlist) != FC_SUCCESS) {
3162 			*ret_val = EIO;
3163 		}
3164 	}
3165 
3166 	/* Set port map flags */
3167 	devlist.map_type = PORT_DEVICE_USER_CREATE;
3168 
3169 	/* Allocate target */
3170 	if (*ret_val == 0) {
3171 		lcount = pptr->port_link_cnt;
3172 		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3173 		if (ptgt == NULL) {
3174 			fcp_log(CE_WARN, pptr->port_dip,
3175 			    "!FC target allocation failed");
3176 			*ret_val = ENOMEM;
3177 		} else {
3178 			/* Setup target */
3179 			mutex_enter(&ptgt->tgt_mutex);
3180 
3181 			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
3182 			ptgt->tgt_tmp_cnt	= 1;
3183 			ptgt->tgt_d_id		= devlist.map_did.port_id;
3184 			ptgt->tgt_hard_addr	=
3185 			    devlist.map_hard_addr.hard_addr;
3186 			ptgt->tgt_pd_handle	= devlist.map_pd;
3187 			ptgt->tgt_fca_dev	= NULL;
3188 
3189 			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3190 			    FC_WWN_SIZE);
3191 			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3192 			    FC_WWN_SIZE);
3193 
3194 			mutex_exit(&ptgt->tgt_mutex);
3195 		}
3196 	}
3197 
3198 	/* Release global mutex for PLOGI and PRLI */
3199 	mutex_exit(&fcp_global_mutex);
3200 
3201 	/* Send PLOGI (If necessary) */
3202 	if (*ret_val == 0) {
3203 		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3204 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3205 	}
3206 
3207 	/* Send PRLI (If necessary) */
3208 	if (*ret_val == 0) {
3209 		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3210 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3211 	}
3212 
3213 	mutex_enter(&fcp_global_mutex);
3214 
3215 	return (ptgt);
3216 }
3217 
3218 /*
3219  *     Function: fcp_tgt_send_plogi
3220  *
3221  *  Description: This function sends a PLOGI to the target specified by the
3222  *		 caller and waits till it completes.
3223  *
3224  *     Argument: ptgt		Target to send the plogi to.
3225  *		 fc_status	Status returned by fp/fctl in the PLOGI request.
3226  *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
3227  *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
3228  *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
3229  *
3230  * Return Value: 0
3231  *		 ENOMEM
3232  *		 EIO
3233  *
3234  *	Context: User context.
3235  */
3236 static int
3237 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3238     int *fc_pkt_reason, int *fc_pkt_action)
3239 {
3240 	struct fcp_port	*pptr;
3241 	struct fcp_ipkt	*icmd;
3242 	struct fc_packet	*fpkt;
3243 	fc_frame_hdr_t		*hp;
3244 	struct la_els_logi	logi;
3245 	int			tcount;
3246 	int			lcount;
3247 	int			ret, login_retval = ~FC_SUCCESS;
3248 
3249 	ret = 0;
3250 
3251 	pptr = ptgt->tgt_port;
3252 
3253 	lcount = pptr->port_link_cnt;
3254 	tcount = ptgt->tgt_change_cnt;
3255 
3256 	/* Alloc internal packet */
3257 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3258 	    sizeof (la_els_logi_t), 0, 0, lcount, tcount, 0,
3259 	    FC_INVALID_RSCN_COUNT);
3260 
3261 	if (icmd == NULL) {
3262 		ret = ENOMEM;
3263 	} else {
3264 		/*
3265 		 * Setup internal packet as sema sync
3266 		 */
3267 		fcp_ipkt_sema_init(icmd);
3268 
3269 		/*
3270 		 * Setup internal packet (icmd)
3271 		 */
3272 		icmd->ipkt_lun		= NULL;
3273 		icmd->ipkt_restart	= 0;
3274 		icmd->ipkt_retries	= 0;
3275 		icmd->ipkt_opcode	= LA_ELS_PLOGI;
3276 
3277 		/*
3278 		 * Setup fc_packet
3279 		 */
3280 		fpkt = icmd->ipkt_fpkt;
3281 
3282 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
3283 		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
3284 		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
3285 
3286 		/*
3287 		 * Setup FC frame header
3288 		 */
3289 		hp = &fpkt->pkt_cmd_fhdr;
3290 
3291 		hp->s_id	= pptr->port_id;	/* source ID */
3292 		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
3293 		hp->r_ctl	= R_CTL_ELS_REQ;
3294 		hp->type	= FC_TYPE_EXTENDED_LS;
3295 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3296 		hp->seq_id	= 0;
3297 		hp->rsvd	= 0;
3298 		hp->df_ctl	= 0;
3299 		hp->seq_cnt	= 0;
3300 		hp->ox_id	= 0xffff;		/* i.e. none */
3301 		hp->rx_id	= 0xffff;		/* i.e. none */
3302 		hp->ro		= 0;
3303 
3304 		/*
3305 		 * Setup PLOGI
3306 		 */
3307 		bzero(&logi, sizeof (struct la_els_logi));
3308 		logi.ls_code.ls_code = LA_ELS_PLOGI;
3309 
3310 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3311 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3312 
3313 		/*
3314 		 * Send PLOGI
3315 		 */
3316 		*fc_status = login_retval =
3317 		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3318 		if (*fc_status != FC_SUCCESS) {
3319 			ret = EIO;
3320 		}
3321 	}
3322 
3323 	/*
3324 	 * Wait for completion
3325 	 */
3326 	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3327 		ret = fcp_ipkt_sema_wait(icmd);
3328 
3329 		*fc_pkt_state	= fpkt->pkt_state;
3330 		*fc_pkt_reason	= fpkt->pkt_reason;
3331 		*fc_pkt_action	= fpkt->pkt_action;
3332 	}
3333 
3334 	/*
3335 	 * Cleanup transport data structures if icmd was alloc-ed AND if there
3336 	 * is going to be no callback (i.e if fc_ulp_login() failed).
3337 	 * Otherwise, cleanup happens in callback routine.
3338 	 */
3339 	if (icmd != NULL) {
3340 		fcp_ipkt_sema_cleanup(icmd);
3341 	}
3342 
3343 	return (ret);
3344 }
3345 
3346 /*
3347  *     Function: fcp_tgt_send_prli
3348  *
3349  *  Description: Does nothing as of today.
3350  *
3351  *     Argument: ptgt		Target to send the prli to.
3352  *		 fc_status	Status returned by fp/fctl in the PRLI request.
3353  *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
3354  *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
3355  *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
3356  *
3357  * Return Value: 0
3358  */
3359 /*ARGSUSED*/
3360 static int
3361 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3362     int *fc_pkt_reason, int *fc_pkt_action)
3363 {
3364 	return (0);
3365 }
3366 
3367 /*
3368  *     Function: fcp_ipkt_sema_init
3369  *
3370  *  Description: Initializes the semaphore contained in the internal packet.
3371  *
3372  *     Argument: icmd	Internal packet the semaphore of which must be
3373  *			initialized.
3374  *
3375  * Return Value: None
3376  *
3377  *	Context: User context only.
3378  */
3379 static void
3380 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3381 {
3382 	struct fc_packet	*fpkt;
3383 
3384 	fpkt = icmd->ipkt_fpkt;
3385 
3386 	/* Create semaphore for sync */
3387 	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3388 
3389 	/* Setup the completion callback */
3390 	fpkt->pkt_comp = fcp_ipkt_sema_callback;
3391 }
3392 
3393 /*
3394  *     Function: fcp_ipkt_sema_wait
3395  *
3396  *  Description: Wait on the semaphore embedded in the internal packet.	 The
3397  *		 semaphore is released in the callback.
3398  *
3399  *     Argument: icmd	Internal packet to wait on for completion.
3400  *
3401  * Return Value: 0
3402  *		 EIO
3403  *		 EBUSY
3404  *		 EAGAIN
3405  *
3406  *	Context: User context only.
3407  *
3408  * This function does a conversion between the field pkt_state of the fc_packet
3409  * embedded in the internal packet (icmd) and the code it returns.
3410  */
3411 static int
3412 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3413 {
3414 	struct fc_packet	*fpkt;
3415 	int	ret;
3416 
3417 	ret = EIO;
3418 	fpkt = icmd->ipkt_fpkt;
3419 
3420 	/*
3421 	 * Wait on semaphore
3422 	 */
3423 	sema_p(&(icmd->ipkt_sema));
3424 
3425 	/*
3426 	 * Check the status of the FC packet
3427 	 */
3428 	switch (fpkt->pkt_state) {
3429 	case FC_PKT_SUCCESS:
3430 		ret = 0;
3431 		break;
3432 	case FC_PKT_LOCAL_RJT:
3433 		switch (fpkt->pkt_reason) {
3434 		case FC_REASON_SEQ_TIMEOUT:
3435 		case FC_REASON_RX_BUF_TIMEOUT:
3436 			ret = EAGAIN;
3437 			break;
3438 		case FC_REASON_PKT_BUSY:
3439 			ret = EBUSY;
3440 			break;
3441 		}
3442 		break;
3443 	case FC_PKT_TIMEOUT:
3444 		ret = EAGAIN;
3445 		break;
3446 	case FC_PKT_LOCAL_BSY:
3447 	case FC_PKT_TRAN_BSY:
3448 	case FC_PKT_NPORT_BSY:
3449 	case FC_PKT_FABRIC_BSY:
3450 		ret = EBUSY;
3451 		break;
3452 	case FC_PKT_LS_RJT:
3453 	case FC_PKT_BA_RJT:
3454 		switch (fpkt->pkt_reason) {
3455 		case FC_REASON_LOGICAL_BSY:
3456 			ret = EBUSY;
3457 			break;
3458 		}
3459 		break;
3460 	case FC_PKT_FS_RJT:
3461 		switch (fpkt->pkt_reason) {
3462 		case FC_REASON_FS_LOGICAL_BUSY:
3463 			ret = EBUSY;
3464 			break;
3465 		}
3466 		break;
3467 	}
3468 
3469 	return (ret);
3470 }
3471 
3472 /*
3473  *     Function: fcp_ipkt_sema_callback
3474  *
3475  *  Description: Registered as the completion callback function for the FC
3476  *		 transport when the ipkt semaphore is used for sync. This will
3477  *		 cleanup the used data structures, if necessary and wake up
3478  *		 the user thread to complete the transaction.
3479  *
3480  *     Argument: fpkt	FC packet (points to the icmd)
3481  *
3482  * Return Value: None
3483  *
3484  *	Context: User context only
3485  */
3486 static void
3487 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3488 {
3489 	struct fcp_ipkt	*icmd;
3490 
3491 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3492 
3493 	/*
3494 	 * Wake up user thread
3495 	 */
3496 	sema_v(&(icmd->ipkt_sema));
3497 }
3498 
3499 /*
3500  *     Function: fcp_ipkt_sema_cleanup
3501  *
3502  *  Description: Called to cleanup (if necessary) the data structures used
3503  *		 when ipkt sema is used for sync.  This function will detect
3504  *		 whether the caller is the last thread (via counter) and
3505  *		 cleanup only if necessary.
3506  *
3507  *     Argument: icmd	Internal command packet
3508  *
3509  * Return Value: None
3510  *
3511  *	Context: User context only
3512  */
3513 static void
3514 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3515 {
3516 	struct fcp_tgt	*ptgt;
3517 	struct fcp_port	*pptr;
3518 
3519 	ptgt = icmd->ipkt_tgt;
3520 	pptr = icmd->ipkt_port;
3521 
3522 	/*
3523 	 * Acquire data structure
3524 	 */
3525 	mutex_enter(&ptgt->tgt_mutex);
3526 
3527 	/*
3528 	 * Destroy semaphore
3529 	 */
3530 	sema_destroy(&(icmd->ipkt_sema));
3531 
3532 	/*
3533 	 * Cleanup internal packet
3534 	 */
3535 	mutex_exit(&ptgt->tgt_mutex);
3536 	fcp_icmd_free(pptr, icmd);
3537 }
3538 
3539 /*
3540  *     Function: fcp_port_attach
3541  *
3542  *  Description: Called by the transport framework to resume, suspend or
3543  *		 attach a new port.
3544  *
3545  *     Argument: ulph		Port handle
3546  *		 *pinfo		Port information
3547  *		 cmd		Command
3548  *		 s_id		Port ID
3549  *
3550  * Return Value: FC_FAILURE or FC_SUCCESS
3551  */
3552 /*ARGSUSED*/
3553 static int
3554 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3555     fc_attach_cmd_t cmd, uint32_t s_id)
3556 {
3557 	int	instance;
3558 	int	res = FC_FAILURE; /* default result */
3559 
3560 	ASSERT(pinfo != NULL);
3561 
3562 	instance = ddi_get_instance(pinfo->port_dip);
3563 
3564 	switch (cmd) {
3565 	case FC_CMD_ATTACH:
3566 		/*
3567 		 * this port instance attaching for the first time (or after
3568 		 * being detached before)
3569 		 */
3570 		if (fcp_handle_port_attach(ulph, pinfo, s_id,
3571 		    instance) == DDI_SUCCESS) {
3572 			res = FC_SUCCESS;
3573 		} else {
3574 			ASSERT(ddi_get_soft_state(fcp_softstate,
3575 			    instance) == NULL);
3576 		}
3577 		break;
3578 
3579 	case FC_CMD_RESUME:
3580 	case FC_CMD_POWER_UP:
3581 		/*
3582 		 * this port instance was attached and the suspended and
3583 		 * will now be resumed
3584 		 */
3585 		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3586 		    instance) == DDI_SUCCESS) {
3587 			res = FC_SUCCESS;
3588 		}
3589 		break;
3590 
3591 	default:
3592 		/* shouldn't happen */
3593 		FCP_TRACE(fcp_logq, "fcp",
3594 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
3595 		    "port_attach: unknown cmdcommand: %d", cmd);
3596 		break;
3597 	}
3598 
3599 	/* return result */
3600 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3601 	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3602 
3603 	return (res);
3604 }
3605 
3606 
3607 /*
3608  * detach or suspend this port instance
3609  *
3610  * acquires and releases the global mutex
3611  *
3612  * acquires and releases the mutex for this port
3613  *
3614  * acquires and releases the hotplug mutex for this port
3615  */
3616 /*ARGSUSED*/
3617 static int
3618 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3619     fc_detach_cmd_t cmd)
3620 {
3621 	int			flag;
3622 	int			instance;
3623 	struct fcp_port		*pptr;
3624 
3625 	instance = ddi_get_instance(info->port_dip);
3626 	pptr = ddi_get_soft_state(fcp_softstate, instance);
3627 
3628 	switch (cmd) {
3629 	case FC_CMD_SUSPEND:
3630 		FCP_DTRACE(fcp_logq, "fcp",
3631 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3632 		    "port suspend called for port %d", instance);
3633 		flag = FCP_STATE_SUSPENDED;
3634 		break;
3635 
3636 	case FC_CMD_POWER_DOWN:
3637 		FCP_DTRACE(fcp_logq, "fcp",
3638 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3639 		    "port power down called for port %d", instance);
3640 		flag = FCP_STATE_POWER_DOWN;
3641 		break;
3642 
3643 	case FC_CMD_DETACH:
3644 		FCP_DTRACE(fcp_logq, "fcp",
3645 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3646 		    "port detach called for port %d", instance);
3647 		flag = FCP_STATE_DETACHING;
3648 		break;
3649 
3650 	default:
3651 		/* shouldn't happen */
3652 		return (FC_FAILURE);
3653 	}
3654 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3655 	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3656 
3657 	return (fcp_handle_port_detach(pptr, flag, instance));
3658 }
3659 
3660 
3661 /*
3662  * called for ioctls on the transport's devctl interface, and the transport
3663  * has passed it to us
3664  *
3665  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3666  *
3667  * return FC_SUCCESS if we decide to claim the ioctl,
3668  * else return FC_UNCLAIMED
3669  *
3670  * *rval is set iff we decide to claim the ioctl
3671  */
3672 /*ARGSUSED*/
3673 static int
3674 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3675     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3676 {
3677 	int			retval = FC_UNCLAIMED;	/* return value */
3678 	struct fcp_port		*pptr = NULL;		/* our soft state */
3679 	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
3680 	dev_info_t		*cdip;
3681 	mdi_pathinfo_t		*pip = NULL;
3682 	char			*ndi_nm;		/* NDI name */
3683 	char			*ndi_addr;		/* NDI addr */
3684 	int			is_mpxio, circ;
3685 	int			devi_entered = 0;
3686 	time_t			end_time;
3687 
3688 	ASSERT(rval != NULL);
3689 
3690 	FCP_DTRACE(fcp_logq, "fcp",
3691 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3692 	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3693 
3694 	/* if already claimed then forget it */
3695 	if (claimed) {
3696 		/*
3697 		 * for now, if this ioctl has already been claimed, then
3698 		 * we just ignore it
3699 		 */
3700 		return (retval);
3701 	}
3702 
3703 	/* get our port info */
3704 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
3705 		fcp_log(CE_WARN, NULL,
3706 		    "!fcp:Invalid port handle handle in ioctl");
3707 		*rval = ENXIO;
3708 		return (retval);
3709 	}
3710 	is_mpxio = pptr->port_mpxio;
3711 
3712 	switch (cmd) {
3713 	case DEVCTL_BUS_GETSTATE:
3714 	case DEVCTL_BUS_QUIESCE:
3715 	case DEVCTL_BUS_UNQUIESCE:
3716 	case DEVCTL_BUS_RESET:
3717 	case DEVCTL_BUS_RESETALL:
3718 
3719 	case DEVCTL_BUS_DEV_CREATE:
3720 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3721 			return (retval);
3722 		}
3723 		break;
3724 
3725 	case DEVCTL_DEVICE_GETSTATE:
3726 	case DEVCTL_DEVICE_OFFLINE:
3727 	case DEVCTL_DEVICE_ONLINE:
3728 	case DEVCTL_DEVICE_REMOVE:
3729 	case DEVCTL_DEVICE_RESET:
3730 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3731 			return (retval);
3732 		}
3733 
3734 		ASSERT(dcp != NULL);
3735 
3736 		/* ensure we have a name and address */
3737 		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3738 		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3739 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
3740 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
3741 			    "ioctl: can't get name (%s) or addr (%s)",
3742 			    ndi_nm ? ndi_nm : "<null ptr>",
3743 			    ndi_addr ? ndi_addr : "<null ptr>");
3744 			ndi_dc_freehdl(dcp);
3745 			return (retval);
3746 		}
3747 
3748 
3749 		/* get our child's DIP */
3750 		ASSERT(pptr != NULL);
3751 		if (is_mpxio) {
3752 			mdi_devi_enter(pptr->port_dip, &circ);
3753 		} else {
3754 			ndi_devi_enter(pptr->port_dip, &circ);
3755 		}
3756 		devi_entered = 1;
3757 
3758 		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3759 		    ndi_addr)) == NULL) {
3760 			/* Look for virtually enumerated devices. */
3761 			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3762 			if (pip == NULL ||
3763 			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3764 				*rval = ENXIO;
3765 				goto out;
3766 			}
3767 		}
3768 		break;
3769 
3770 	default:
3771 		*rval = ENOTTY;
3772 		return (retval);
3773 	}
3774 
3775 	/* this ioctl is ours -- process it */
3776 
3777 	retval = FC_SUCCESS;		/* just means we claim the ioctl */
3778 
3779 	/* we assume it will be a success; else we'll set error value */
3780 	*rval = 0;
3781 
3782 
3783 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3784 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3785 	    "ioctl: claiming this one");
3786 
3787 	/* handle ioctls now */
3788 	switch (cmd) {
3789 	case DEVCTL_DEVICE_GETSTATE:
3790 		ASSERT(cdip != NULL);
3791 		ASSERT(dcp != NULL);
3792 		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3793 			*rval = EFAULT;
3794 		}
3795 		break;
3796 
3797 	case DEVCTL_DEVICE_REMOVE:
3798 	case DEVCTL_DEVICE_OFFLINE: {
3799 		int			flag = 0;
3800 		int			lcount;
3801 		int			tcount;
3802 		struct fcp_pkt	*head = NULL;
3803 		struct fcp_lun	*plun;
3804 		child_info_t		*cip = CIP(cdip);
3805 		int			all = 1;
3806 		struct fcp_lun	*tplun;
3807 		struct fcp_tgt	*ptgt;
3808 
3809 		ASSERT(pptr != NULL);
3810 		ASSERT(cdip != NULL);
3811 
3812 		mutex_enter(&pptr->port_mutex);
3813 		if (pip != NULL) {
3814 			cip = CIP(pip);
3815 		}
3816 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3817 			mutex_exit(&pptr->port_mutex);
3818 			*rval = ENXIO;
3819 			break;
3820 		}
3821 
3822 		head = fcp_scan_commands(plun);
3823 		if (head != NULL) {
3824 			fcp_abort_commands(head, LUN_PORT);
3825 		}
3826 		lcount = pptr->port_link_cnt;
3827 		tcount = plun->lun_tgt->tgt_change_cnt;
3828 		mutex_exit(&pptr->port_mutex);
3829 
3830 		if (cmd == DEVCTL_DEVICE_REMOVE) {
3831 			flag = NDI_DEVI_REMOVE;
3832 		}
3833 
3834 		if (is_mpxio) {
3835 			mdi_devi_exit(pptr->port_dip, circ);
3836 		} else {
3837 			ndi_devi_exit(pptr->port_dip, circ);
3838 		}
3839 		devi_entered = 0;
3840 
3841 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3842 		    FCP_OFFLINE, lcount, tcount, flag);
3843 
3844 		if (*rval != NDI_SUCCESS) {
3845 			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3846 			break;
3847 		}
3848 
3849 		fcp_update_offline_flags(plun);
3850 
3851 		ptgt = plun->lun_tgt;
3852 		mutex_enter(&ptgt->tgt_mutex);
3853 		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3854 		    tplun->lun_next) {
3855 			mutex_enter(&tplun->lun_mutex);
3856 			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3857 				all = 0;
3858 			}
3859 			mutex_exit(&tplun->lun_mutex);
3860 		}
3861 
3862 		if (all) {
3863 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3864 			/*
3865 			 * The user is unconfiguring/offlining the device.
3866 			 * If fabric and the auto configuration is set
3867 			 * then make sure the user is the only one who
3868 			 * can reconfigure the device.
3869 			 */
3870 			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3871 			    fcp_enable_auto_configuration) {
3872 				ptgt->tgt_manual_config_only = 1;
3873 			}
3874 		}
3875 		mutex_exit(&ptgt->tgt_mutex);
3876 		break;
3877 	}
3878 
3879 	case DEVCTL_DEVICE_ONLINE: {
3880 		int			lcount;
3881 		int			tcount;
3882 		struct fcp_lun	*plun;
3883 		child_info_t		*cip = CIP(cdip);
3884 
3885 		ASSERT(cdip != NULL);
3886 		ASSERT(pptr != NULL);
3887 
3888 		mutex_enter(&pptr->port_mutex);
3889 		if (pip != NULL) {
3890 			cip = CIP(pip);
3891 		}
3892 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3893 			mutex_exit(&pptr->port_mutex);
3894 			*rval = ENXIO;
3895 			break;
3896 		}
3897 		lcount = pptr->port_link_cnt;
3898 		tcount = plun->lun_tgt->tgt_change_cnt;
3899 		mutex_exit(&pptr->port_mutex);
3900 
3901 		/*
3902 		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3903 		 * to allow the device attach to occur when the device is
3904 		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3905 		 * from the scsi_probe()).
3906 		 */
3907 		mutex_enter(&LUN_TGT->tgt_mutex);
3908 		plun->lun_state |= FCP_LUN_ONLINING;
3909 		mutex_exit(&LUN_TGT->tgt_mutex);
3910 
3911 		if (is_mpxio) {
3912 			mdi_devi_exit(pptr->port_dip, circ);
3913 		} else {
3914 			ndi_devi_exit(pptr->port_dip, circ);
3915 		}
3916 		devi_entered = 0;
3917 
3918 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3919 		    FCP_ONLINE, lcount, tcount, 0);
3920 
3921 		if (*rval != NDI_SUCCESS) {
3922 			/* Reset the FCP_LUN_ONLINING bit */
3923 			mutex_enter(&LUN_TGT->tgt_mutex);
3924 			plun->lun_state &= ~FCP_LUN_ONLINING;
3925 			mutex_exit(&LUN_TGT->tgt_mutex);
3926 			*rval = EIO;
3927 			break;
3928 		}
3929 		mutex_enter(&LUN_TGT->tgt_mutex);
3930 		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3931 		    FCP_LUN_ONLINING);
3932 		mutex_exit(&LUN_TGT->tgt_mutex);
3933 		break;
3934 	}
3935 
3936 	case DEVCTL_BUS_DEV_CREATE: {
3937 		uchar_t			*bytes = NULL;
3938 		uint_t			nbytes;
3939 		struct fcp_tgt		*ptgt = NULL;
3940 		struct fcp_lun		*plun = NULL;
3941 		dev_info_t		*useless_dip = NULL;
3942 
3943 		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3944 		    DEVCTL_CONSTRUCT, &useless_dip);
3945 		if (*rval != 0 || useless_dip == NULL) {
3946 			break;
3947 		}
3948 
3949 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3950 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3951 		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3952 			*rval = EINVAL;
3953 			(void) ndi_devi_free(useless_dip);
3954 			if (bytes != NULL) {
3955 				ddi_prop_free(bytes);
3956 			}
3957 			break;
3958 		}
3959 
3960 		*rval = fcp_create_on_demand(pptr, bytes);
3961 		if (*rval == 0) {
3962 			mutex_enter(&pptr->port_mutex);
3963 			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
3964 			if (ptgt) {
3965 				/*
3966 				 * We now have a pointer to the target that
3967 				 * was created. Lets point to the first LUN on
3968 				 * this new target.
3969 				 */
3970 				mutex_enter(&ptgt->tgt_mutex);
3971 
3972 				plun = ptgt->tgt_lun;
3973 				/*
3974 				 * There may be stale/offline LUN entries on
3975 				 * this list (this is by design) and so we have
3976 				 * to make sure we point to the first online
3977 				 * LUN
3978 				 */
3979 				while (plun &&
3980 				    plun->lun_state & FCP_LUN_OFFLINE) {
3981 					plun = plun->lun_next;
3982 				}
3983 
3984 				mutex_exit(&ptgt->tgt_mutex);
3985 			}
3986 			mutex_exit(&pptr->port_mutex);
3987 		}
3988 
3989 		if (*rval == 0 && ptgt && plun) {
3990 			mutex_enter(&plun->lun_mutex);
3991 			/*
3992 			 * Allow up to fcp_lun_ready_retry seconds to
3993 			 * configure all the luns behind the target.
3994 			 *
3995 			 * The intent here is to allow targets with long
3996 			 * reboot/reset-recovery times to become available
3997 			 * while limiting the maximum wait time for an
3998 			 * unresponsive target.
3999 			 */
4000 			end_time = ddi_get_lbolt() +
4001 			    SEC_TO_TICK(fcp_lun_ready_retry);
4002 
4003 			while (ddi_get_lbolt() < end_time) {
4004 				retval = FC_SUCCESS;
4005 
4006 				/*
4007 				 * The new ndi interfaces for on-demand creation
4008 				 * are inflexible, Do some more work to pass on
4009 				 * a path name of some LUN (design is broken !)
4010 				 */
4011 				if (plun->lun_cip) {
4012 					if (plun->lun_mpxio == 0) {
4013 						cdip = DIP(plun->lun_cip);
4014 					} else {
4015 						cdip = mdi_pi_get_client(
4016 						    PIP(plun->lun_cip));
4017 					}
4018 					if (cdip == NULL) {
4019 						*rval = ENXIO;
4020 						break;
4021 					}
4022 
4023 					if (!i_ddi_devi_attached(cdip)) {
4024 						mutex_exit(&plun->lun_mutex);
4025 						delay(drv_usectohz(1000000));
4026 						mutex_enter(&plun->lun_mutex);
4027 					} else {
4028 						/*
4029 						 * This Lun is ready, lets
4030 						 * check the next one.
4031 						 */
4032 						mutex_exit(&plun->lun_mutex);
4033 						plun = plun->lun_next;
4034 						while (plun && (plun->lun_state
4035 						    & FCP_LUN_OFFLINE)) {
4036 							plun = plun->lun_next;
4037 						}
4038 						if (!plun) {
4039 							break;
4040 						}
4041 						mutex_enter(&plun->lun_mutex);
4042 					}
4043 				} else {
4044 					/*
4045 					 * lun_cip field for a valid lun
4046 					 * should never be NULL. Fail the
4047 					 * command.
4048 					 */
4049 					*rval = ENXIO;
4050 					break;
4051 				}
4052 			}
4053 			if (plun) {
4054 				mutex_exit(&plun->lun_mutex);
4055 			} else {
4056 				char devnm[MAXNAMELEN];
4057 				int nmlen;
4058 
4059 				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4060 				    ddi_node_name(cdip),
4061 				    ddi_get_name_addr(cdip));
4062 
4063 				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4064 				    0) {
4065 					*rval = EFAULT;
4066 				}
4067 			}
4068 		} else {
4069 			int	i;
4070 			char	buf[25];
4071 
4072 			for (i = 0; i < FC_WWN_SIZE; i++) {
4073 				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4074 			}
4075 
4076 			fcp_log(CE_WARN, pptr->port_dip,
4077 			    "!Failed to create nodes for pwwn=%s; error=%x",
4078 			    buf, *rval);
4079 		}
4080 
4081 		(void) ndi_devi_free(useless_dip);
4082 		ddi_prop_free(bytes);
4083 		break;
4084 	}
4085 
4086 	case DEVCTL_DEVICE_RESET: {
4087 		struct fcp_lun		*plun;
4088 		child_info_t		*cip = CIP(cdip);
4089 
4090 		ASSERT(cdip != NULL);
4091 		ASSERT(pptr != NULL);
4092 		mutex_enter(&pptr->port_mutex);
4093 		if (pip != NULL) {
4094 			cip = CIP(pip);
4095 		}
4096 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4097 			mutex_exit(&pptr->port_mutex);
4098 			*rval = ENXIO;
4099 			break;
4100 		}
4101 		mutex_exit(&pptr->port_mutex);
4102 
4103 		mutex_enter(&plun->lun_tgt->tgt_mutex);
4104 		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4105 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4106 
4107 			*rval = ENXIO;
4108 			break;
4109 		}
4110 
4111 		if (plun->lun_sd == NULL) {
4112 			mutex_exit(&plun->lun_tgt->tgt_mutex);
4113 
4114 			*rval = ENXIO;
4115 			break;
4116 		}
4117 		mutex_exit(&plun->lun_tgt->tgt_mutex);
4118 
4119 		/*
4120 		 * set up ap so that fcp_reset can figure out
4121 		 * which target to reset
4122 		 */
4123 		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4124 		    RESET_TARGET) == FALSE) {
4125 			*rval = EIO;
4126 		}
4127 		break;
4128 	}
4129 
4130 	case DEVCTL_BUS_GETSTATE:
4131 		ASSERT(dcp != NULL);
4132 		ASSERT(pptr != NULL);
4133 		ASSERT(pptr->port_dip != NULL);
4134 		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4135 		    NDI_SUCCESS) {
4136 			*rval = EFAULT;
4137 		}
4138 		break;
4139 
4140 	case DEVCTL_BUS_QUIESCE:
4141 	case DEVCTL_BUS_UNQUIESCE:
4142 		*rval = ENOTSUP;
4143 		break;
4144 
4145 	case DEVCTL_BUS_RESET:
4146 	case DEVCTL_BUS_RESETALL:
4147 		ASSERT(pptr != NULL);
4148 		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4149 		break;
4150 
4151 	default:
4152 		ASSERT(dcp != NULL);
4153 		*rval = ENOTTY;
4154 		break;
4155 	}
4156 
4157 	/* all done -- clean up and return */
4158 out:	if (devi_entered) {
4159 		if (is_mpxio) {
4160 			mdi_devi_exit(pptr->port_dip, circ);
4161 		} else {
4162 			ndi_devi_exit(pptr->port_dip, circ);
4163 		}
4164 	}
4165 
4166 	if (dcp != NULL) {
4167 		ndi_dc_freehdl(dcp);
4168 	}
4169 
4170 	return (retval);
4171 }
4172 
4173 
4174 /*ARGSUSED*/
4175 static int
4176 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4177     uint32_t claimed)
4178 {
4179 	uchar_t			r_ctl;
4180 	uchar_t			ls_code;
4181 	struct fcp_port	*pptr;
4182 
4183 	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4184 		return (FC_UNCLAIMED);
4185 	}
4186 
4187 	mutex_enter(&pptr->port_mutex);
4188 	if (pptr->port_state & (FCP_STATE_DETACHING |
4189 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4190 		mutex_exit(&pptr->port_mutex);
4191 		return (FC_UNCLAIMED);
4192 	}
4193 	mutex_exit(&pptr->port_mutex);
4194 
4195 	r_ctl = buf->ub_frame.r_ctl;
4196 
4197 	switch (r_ctl & R_CTL_ROUTING) {
4198 	case R_CTL_EXTENDED_SVC:
4199 		if (r_ctl == R_CTL_ELS_REQ) {
4200 			ls_code = buf->ub_buffer[0];
4201 
4202 			switch (ls_code) {
4203 			case LA_ELS_PRLI:
4204 				/*
4205 				 * We really don't care if something fails.
4206 				 * If the PRLI was not sent out, then the
4207 				 * other end will time it out.
4208 				 */
4209 				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4210 					return (FC_SUCCESS);
4211 				}
4212 				return (FC_UNCLAIMED);
4213 				/* NOTREACHED */
4214 
4215 			default:
4216 				break;
4217 			}
4218 		}
4219 		/* FALLTHROUGH */
4220 
4221 	default:
4222 		return (FC_UNCLAIMED);
4223 	}
4224 }
4225 
4226 
4227 /*ARGSUSED*/
4228 static int
4229 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4230     uint32_t claimed)
4231 {
4232 	return (FC_UNCLAIMED);
4233 }
4234 
4235 /*
4236  *     Function: fcp_statec_callback
4237  *
4238  *  Description: The purpose of this function is to handle a port state change.
4239  *		 It is called from fp/fctl and, in a few instances, internally.
4240  *
4241  *     Argument: ulph		fp/fctl port handle
4242  *		 port_handle	fcp_port structure
4243  *		 port_state	Physical state of the port
4244  *		 port_top	Topology
4245  *		 *devlist	Pointer to the first entry of a table
4246  *				containing the remote ports that can be
4247  *				reached.
4248  *		 dev_cnt	Number of entries pointed by devlist.
4249  *		 port_sid	Port ID of the local port.
4250  *
4251  * Return Value: None
4252  */
4253 /*ARGSUSED*/
4254 static void
4255 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4256     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4257     uint32_t dev_cnt, uint32_t port_sid)
4258 {
4259 	uint32_t		link_count;
4260 	int			map_len = 0;
4261 	struct fcp_port	*pptr;
4262 	fcp_map_tag_t		*map_tag = NULL;
4263 
4264 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
4265 		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4266 		return;			/* nothing to work with! */
4267 	}
4268 
4269 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4270 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
4271 	    "fcp_statec_callback: port state/dev_cnt/top ="
4272 	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4273 	    dev_cnt, port_top);
4274 
4275 	mutex_enter(&pptr->port_mutex);
4276 
4277 	/*
4278 	 * If a thread is in detach, don't do anything.
4279 	 */
4280 	if (pptr->port_state & (FCP_STATE_DETACHING |
4281 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4282 		mutex_exit(&pptr->port_mutex);
4283 		return;
4284 	}
4285 
4286 	/*
4287 	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4288 	 * init_pkt is called, it knows whether or not the target's status
4289 	 * (or pd) might be changing.
4290 	 */
4291 
4292 	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4293 		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4294 	}
4295 
4296 	/*
4297 	 * the transport doesn't allocate or probe unless being
4298 	 * asked to by either the applications or ULPs
4299 	 *
4300 	 * in cases where the port is OFFLINE at the time of port
4301 	 * attach callback and the link comes ONLINE later, for
4302 	 * easier automatic node creation (i.e. without you having to
4303 	 * go out and run the utility to perform LOGINs) the
4304 	 * following conditional is helpful
4305 	 */
4306 	pptr->port_phys_state = port_state;
4307 
4308 	if (dev_cnt) {
4309 		mutex_exit(&pptr->port_mutex);
4310 
4311 		map_len = sizeof (*map_tag) * dev_cnt;
4312 		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4313 		if (map_tag == NULL) {
4314 			fcp_log(CE_WARN, pptr->port_dip,
4315 			    "!fcp%d: failed to allocate for map tags; "
4316 			    " state change will not be processed",
4317 			    pptr->port_instance);
4318 
4319 			mutex_enter(&pptr->port_mutex);
4320 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4321 			mutex_exit(&pptr->port_mutex);
4322 
4323 			return;
4324 		}
4325 
4326 		mutex_enter(&pptr->port_mutex);
4327 	}
4328 
4329 	if (pptr->port_id != port_sid) {
4330 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4331 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4332 		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4333 		    port_sid);
4334 		/*
4335 		 * The local port changed ID. It is the first time a port ID
4336 		 * is assigned or something drastic happened.  We might have
4337 		 * been unplugged and replugged on another loop or fabric port
4338 		 * or somebody grabbed the AL_PA we had or somebody rezoned
4339 		 * the fabric we were plugged into.
4340 		 */
4341 		pptr->port_id = port_sid;
4342 	}
4343 
4344 	switch (FC_PORT_STATE_MASK(port_state)) {
4345 	case FC_STATE_OFFLINE:
4346 	case FC_STATE_RESET_REQUESTED:
4347 		/*
4348 		 * link has gone from online to offline -- just update the
4349 		 * state of this port to BUSY and MARKed to go offline
4350 		 */
4351 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4352 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4353 		    "link went offline");
4354 		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4355 			/*
4356 			 * We were offline a while ago and this one
4357 			 * seems to indicate that the loop has gone
4358 			 * dead forever.
4359 			 */
4360 			pptr->port_tmp_cnt += dev_cnt;
4361 			pptr->port_state &= ~FCP_STATE_OFFLINE;
4362 			pptr->port_state |= FCP_STATE_INIT;
4363 			link_count = pptr->port_link_cnt;
4364 			fcp_handle_devices(pptr, devlist, dev_cnt,
4365 			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4366 		} else {
4367 			pptr->port_link_cnt++;
4368 			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4369 			fcp_update_state(pptr, (FCP_LUN_BUSY |
4370 			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4371 			if (pptr->port_mpxio) {
4372 				fcp_update_mpxio_path_verifybusy(pptr);
4373 			}
4374 			pptr->port_state |= FCP_STATE_OFFLINE;
4375 			pptr->port_state &=
4376 			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4377 			pptr->port_tmp_cnt = 0;
4378 		}
4379 		mutex_exit(&pptr->port_mutex);
4380 		break;
4381 
4382 	case FC_STATE_ONLINE:
4383 	case FC_STATE_LIP:
4384 	case FC_STATE_LIP_LBIT_SET:
4385 		/*
4386 		 * link has gone from offline to online
4387 		 */
4388 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4389 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4390 		    "link went online");
4391 
4392 		pptr->port_link_cnt++;
4393 
4394 		while (pptr->port_ipkt_cnt) {
4395 			mutex_exit(&pptr->port_mutex);
4396 			delay(drv_usectohz(1000000));
4397 			mutex_enter(&pptr->port_mutex);
4398 		}
4399 
4400 		pptr->port_topology = port_top;
4401 
4402 		/*
4403 		 * The state of the targets and luns accessible through this
4404 		 * port is updated.
4405 		 */
4406 		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4407 		    FCP_CAUSE_LINK_CHANGE);
4408 
4409 		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4410 		pptr->port_state |= FCP_STATE_ONLINING;
4411 		pptr->port_tmp_cnt = dev_cnt;
4412 		link_count = pptr->port_link_cnt;
4413 
4414 		pptr->port_deadline = fcp_watchdog_time +
4415 		    FCP_ICMD_DEADLINE;
4416 
4417 		if (!dev_cnt) {
4418 			/*
4419 			 * We go directly to the online state if no remote
4420 			 * ports were discovered.
4421 			 */
4422 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4423 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4424 			    "No remote ports discovered");
4425 
4426 			pptr->port_state &= ~FCP_STATE_ONLINING;
4427 			pptr->port_state |= FCP_STATE_ONLINE;
4428 		}
4429 
4430 		switch (port_top) {
4431 		case FC_TOP_FABRIC:
4432 		case FC_TOP_PUBLIC_LOOP:
4433 		case FC_TOP_PRIVATE_LOOP:
4434 		case FC_TOP_PT_PT:
4435 
4436 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4437 				fcp_retry_ns_registry(pptr, port_sid);
4438 			}
4439 
4440 			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4441 			    map_tag, FCP_CAUSE_LINK_CHANGE);
4442 			break;
4443 
4444 		default:
4445 			/*
4446 			 * We got here because we were provided with an unknown
4447 			 * topology.
4448 			 */
4449 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4450 				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4451 			}
4452 
4453 			pptr->port_tmp_cnt -= dev_cnt;
4454 			fcp_log(CE_WARN, pptr->port_dip,
4455 			    "!unknown/unsupported topology (0x%x)", port_top);
4456 			break;
4457 		}
4458 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4459 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4460 		    "Notify ssd of the reset to reinstate the reservations");
4461 
4462 		scsi_hba_reset_notify_callback(&pptr->port_mutex,
4463 		    &pptr->port_reset_notify_listf);
4464 
4465 		mutex_exit(&pptr->port_mutex);
4466 
4467 		break;
4468 
4469 	case FC_STATE_RESET:
4470 		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4471 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4472 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4473 		    "RESET state, waiting for Offline/Online state_cb");
4474 		mutex_exit(&pptr->port_mutex);
4475 		break;
4476 
4477 	case FC_STATE_DEVICE_CHANGE:
4478 		/*
4479 		 * We come here when an application has requested
4480 		 * Dynamic node creation/deletion in Fabric connectivity.
4481 		 */
4482 		if (pptr->port_state & (FCP_STATE_OFFLINE |
4483 		    FCP_STATE_INIT)) {
4484 			/*
4485 			 * This case can happen when the FCTL is in the
4486 			 * process of giving us on online and the host on
4487 			 * the other side issues a PLOGI/PLOGO. Ideally
4488 			 * the state changes should be serialized unless
4489 			 * they are opposite (online-offline).
4490 			 * The transport will give us a final state change
4491 			 * so we can ignore this for the time being.
4492 			 */
4493 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4494 			mutex_exit(&pptr->port_mutex);
4495 			break;
4496 		}
4497 
4498 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4499 			fcp_retry_ns_registry(pptr, port_sid);
4500 		}
4501 
4502 		/*
4503 		 * Extend the deadline under steady state conditions
4504 		 * to provide more time for the device-change-commands
4505 		 */
4506 		if (!pptr->port_ipkt_cnt) {
4507 			pptr->port_deadline = fcp_watchdog_time +
4508 			    FCP_ICMD_DEADLINE;
4509 		}
4510 
4511 		/*
4512 		 * There is another race condition here, where if we were
4513 		 * in ONLINEING state and a devices in the map logs out,
4514 		 * fp will give another state change as DEVICE_CHANGE
4515 		 * and OLD. This will result in that target being offlined.
4516 		 * The pd_handle is freed. If from the first statec callback
4517 		 * we were going to fire a PLOGI/PRLI, the system will
4518 		 * panic in fc_ulp_transport with invalid pd_handle.
4519 		 * The fix is to check for the link_cnt before issuing
4520 		 * any command down.
4521 		 */
4522 		fcp_update_targets(pptr, devlist, dev_cnt,
4523 		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4524 
4525 		link_count = pptr->port_link_cnt;
4526 
4527 		fcp_handle_devices(pptr, devlist, dev_cnt,
4528 		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4529 
4530 		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4531 
4532 		mutex_exit(&pptr->port_mutex);
4533 		break;
4534 
4535 	case FC_STATE_TARGET_PORT_RESET:
4536 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4537 			fcp_retry_ns_registry(pptr, port_sid);
4538 		}
4539 
4540 		/* Do nothing else */
4541 		mutex_exit(&pptr->port_mutex);
4542 		break;
4543 
4544 	default:
4545 		fcp_log(CE_WARN, pptr->port_dip,
4546 		    "!Invalid state change=0x%x", port_state);
4547 		mutex_exit(&pptr->port_mutex);
4548 		break;
4549 	}
4550 
4551 	if (map_tag) {
4552 		kmem_free(map_tag, map_len);
4553 	}
4554 }
4555 
4556 /*
4557  *     Function: fcp_handle_devices
4558  *
4559  *  Description: This function updates the devices currently known by
4560  *		 walking the list provided by the caller.  The list passed
4561  *		 by the caller is supposed to be the list of reachable
4562  *		 devices.
4563  *
4564  *     Argument: *pptr		Fcp port structure.
4565  *		 *devlist	Pointer to the first entry of a table
4566  *				containing the remote ports that can be
4567  *				reached.
4568  *		 dev_cnt	Number of entries pointed by devlist.
4569  *		 link_cnt	Link state count.
4570  *		 *map_tag	Array of fcp_map_tag_t structures.
4571  *		 cause		What caused this function to be called.
4572  *
4573  * Return Value: None
4574  *
4575  *	  Notes: The pptr->port_mutex must be held.
4576  */
4577 static void
4578 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4579     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4580 {
4581 	int			i;
4582 	int			check_finish_init = 0;
4583 	fc_portmap_t		*map_entry;
4584 	struct fcp_tgt	*ptgt = NULL;
4585 
4586 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4587 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
4588 	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4589 
4590 	if (dev_cnt) {
4591 		ASSERT(map_tag != NULL);
4592 	}
4593 
4594 	/*
4595 	 * The following code goes through the list of remote ports that are
4596 	 * accessible through this (pptr) local port (The list walked is the
4597 	 * one provided by the caller which is the list of the remote ports
4598 	 * currently reachable).  It checks if any of them was already
4599 	 * known by looking for the corresponding target structure based on
4600 	 * the world wide name.	 If a target is part of the list it is tagged
4601 	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4602 	 *
4603 	 * Old comment
4604 	 * -----------
4605 	 * Before we drop port mutex; we MUST get the tags updated; This
4606 	 * two step process is somewhat slow, but more reliable.
4607 	 */
4608 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4609 		map_entry = &(devlist[i]);
4610 
4611 		/*
4612 		 * get ptr to this map entry in our port's
4613 		 * list (if any)
4614 		 */
4615 		ptgt = fcp_lookup_target(pptr,
4616 		    (uchar_t *)&(map_entry->map_pwwn));
4617 
4618 		if (ptgt) {
4619 			map_tag[i] = ptgt->tgt_change_cnt;
4620 			if (cause == FCP_CAUSE_LINK_CHANGE) {
4621 				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4622 			}
4623 		}
4624 	}
4625 
4626 	/*
4627 	 * At this point we know which devices of the new list were already
4628 	 * known (The field tgt_aux_state of the target structure has been
4629 	 * set to FCP_TGT_TAGGED).
4630 	 *
4631 	 * The following code goes through the list of targets currently known
4632 	 * by the local port (the list is actually a hashing table).  If a
4633 	 * target is found and is not tagged, it means the target cannot
4634 	 * be reached anymore through the local port (pptr).  It is offlined.
4635 	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4636 	 */
4637 	for (i = 0; i < FCP_NUM_HASH; i++) {
4638 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4639 		    ptgt = ptgt->tgt_next) {
4640 			mutex_enter(&ptgt->tgt_mutex);
4641 			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4642 			    (cause == FCP_CAUSE_LINK_CHANGE) &&
4643 			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4644 				fcp_offline_target_now(pptr, ptgt,
4645 				    link_cnt, ptgt->tgt_change_cnt, 0);
4646 			}
4647 			mutex_exit(&ptgt->tgt_mutex);
4648 		}
4649 	}
4650 
4651 	/*
4652 	 * At this point, the devices that were known but cannot be reached
4653 	 * anymore, have most likely been offlined.
4654 	 *
4655 	 * The following section of code seems to go through the list of
4656 	 * remote ports that can now be reached.  For every single one it
4657 	 * checks if it is already known or if it is a new port.
4658 	 */
4659 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4660 
4661 		if (check_finish_init) {
4662 			ASSERT(i > 0);
4663 			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4664 			    map_tag[i - 1], cause);
4665 			check_finish_init = 0;
4666 		}
4667 
4668 		/* get a pointer to this map entry */
4669 		map_entry = &(devlist[i]);
4670 
4671 		/*
4672 		 * Check for the duplicate map entry flag. If we have marked
4673 		 * this entry as a duplicate we skip it since the correct
4674 		 * (perhaps even same) state change will be encountered
4675 		 * later in the list.
4676 		 */
4677 		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4678 			continue;
4679 		}
4680 
4681 		/* get ptr to this map entry in our port's list (if any) */
4682 		ptgt = fcp_lookup_target(pptr,
4683 		    (uchar_t *)&(map_entry->map_pwwn));
4684 
4685 		if (ptgt) {
4686 			/*
4687 			 * This device was already known.  The field
4688 			 * tgt_aux_state is reset (was probably set to
4689 			 * FCP_TGT_TAGGED previously in this routine).
4690 			 */
4691 			ptgt->tgt_aux_state = 0;
4692 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4693 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4694 			    "handle_devices: map did/state/type/flags = "
4695 			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4696 			    "tgt_state=%d",
4697 			    map_entry->map_did.port_id, map_entry->map_state,
4698 			    map_entry->map_type, map_entry->map_flags,
4699 			    ptgt->tgt_d_id, ptgt->tgt_state);
4700 		}
4701 
4702 		if (map_entry->map_type == PORT_DEVICE_OLD ||
4703 		    map_entry->map_type == PORT_DEVICE_NEW ||
4704 		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4705 		    map_entry->map_type == PORT_DEVICE_CHANGED) {
4706 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4707 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
4708 			    "map_type=%x, did = %x",
4709 			    map_entry->map_type,
4710 			    map_entry->map_did.port_id);
4711 		}
4712 
4713 		switch (map_entry->map_type) {
4714 		case PORT_DEVICE_NOCHANGE:
4715 		case PORT_DEVICE_USER_CREATE:
4716 		case PORT_DEVICE_USER_LOGIN:
4717 		case PORT_DEVICE_NEW:
4718 		case PORT_DEVICE_REPORTLUN_CHANGED:
4719 			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4720 
4721 			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4722 			    link_cnt, (ptgt) ? map_tag[i] : 0,
4723 			    cause) == TRUE) {
4724 
4725 				FCP_TGT_TRACE(ptgt, map_tag[i],
4726 				    FCP_TGT_TRACE_2);
4727 				check_finish_init++;
4728 			}
4729 			break;
4730 
4731 		case PORT_DEVICE_OLD:
4732 			if (ptgt != NULL) {
4733 				FCP_TGT_TRACE(ptgt, map_tag[i],
4734 				    FCP_TGT_TRACE_3);
4735 
4736 				mutex_enter(&ptgt->tgt_mutex);
4737 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4738 					/*
4739 					 * Must do an in-line wait for I/Os
4740 					 * to get drained
4741 					 */
4742 					mutex_exit(&ptgt->tgt_mutex);
4743 					mutex_exit(&pptr->port_mutex);
4744 
4745 					mutex_enter(&ptgt->tgt_mutex);
4746 					while (ptgt->tgt_ipkt_cnt ||
4747 					    fcp_outstanding_lun_cmds(ptgt)
4748 					    == FC_SUCCESS) {
4749 						mutex_exit(&ptgt->tgt_mutex);
4750 						delay(drv_usectohz(1000000));
4751 						mutex_enter(&ptgt->tgt_mutex);
4752 					}
4753 					mutex_exit(&ptgt->tgt_mutex);
4754 
4755 					mutex_enter(&pptr->port_mutex);
4756 					mutex_enter(&ptgt->tgt_mutex);
4757 
4758 					(void) fcp_offline_target(pptr, ptgt,
4759 					    link_cnt, map_tag[i], 0, 0);
4760 				}
4761 				mutex_exit(&ptgt->tgt_mutex);
4762 			}
4763 			check_finish_init++;
4764 			break;
4765 
4766 		case PORT_DEVICE_USER_DELETE:
4767 		case PORT_DEVICE_USER_LOGOUT:
4768 			if (ptgt != NULL) {
4769 				FCP_TGT_TRACE(ptgt, map_tag[i],
4770 				    FCP_TGT_TRACE_4);
4771 
4772 				mutex_enter(&ptgt->tgt_mutex);
4773 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4774 					(void) fcp_offline_target(pptr, ptgt,
4775 					    link_cnt, map_tag[i], 1, 0);
4776 				}
4777 				mutex_exit(&ptgt->tgt_mutex);
4778 			}
4779 			check_finish_init++;
4780 			break;
4781 
4782 		case PORT_DEVICE_CHANGED:
4783 			if (ptgt != NULL) {
4784 				FCP_TGT_TRACE(ptgt, map_tag[i],
4785 				    FCP_TGT_TRACE_5);
4786 
4787 				if (fcp_device_changed(pptr, ptgt,
4788 				    map_entry, link_cnt, map_tag[i],
4789 				    cause) == TRUE) {
4790 					check_finish_init++;
4791 				}
4792 			} else {
4793 				if (fcp_handle_mapflags(pptr, ptgt,
4794 				    map_entry, link_cnt, 0, cause) == TRUE) {
4795 					check_finish_init++;
4796 				}
4797 			}
4798 			break;
4799 
4800 		default:
4801 			fcp_log(CE_WARN, pptr->port_dip,
4802 			    "!Invalid map_type=0x%x", map_entry->map_type);
4803 			check_finish_init++;
4804 			break;
4805 		}
4806 	}
4807 
4808 	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4809 		ASSERT(i > 0);
4810 		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4811 		    map_tag[i-1], cause);
4812 	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4813 		fcp_offline_all(pptr, link_cnt, cause);
4814 	}
4815 }
4816 
4817 static int
4818 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4819 {
4820 	struct fcp_lun	*plun;
4821 	struct fcp_port *pptr;
4822 	int		 rscn_count;
4823 	int		 lun0_newalloc;
4824 	int		 ret  = TRUE;
4825 
4826 	ASSERT(ptgt);
4827 	pptr = ptgt->tgt_port;
4828 	lun0_newalloc = 0;
4829 	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4830 		/*
4831 		 * no LUN struct for LUN 0 yet exists,
4832 		 * so create one
4833 		 */
4834 		plun = fcp_alloc_lun(ptgt);
4835 		if (plun == NULL) {
4836 			fcp_log(CE_WARN, pptr->port_dip,
4837 			    "!Failed to allocate lun 0 for"
4838 			    " D_ID=%x", ptgt->tgt_d_id);
4839 			return (ret);
4840 		}
4841 		lun0_newalloc = 1;
4842 	}
4843 
4844 	mutex_enter(&ptgt->tgt_mutex);
4845 	/*
4846 	 * consider lun 0 as device not connected if it is
4847 	 * offlined or newly allocated
4848 	 */
4849 	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4850 		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4851 	}
4852 	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4853 	plun->lun_state &= ~FCP_LUN_OFFLINE;
4854 	ptgt->tgt_lun_cnt = 1;
4855 	ptgt->tgt_report_lun_cnt = 0;
4856 	mutex_exit(&ptgt->tgt_mutex);
4857 
4858 	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4859 	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4860 	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4861 	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4862 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4863 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4864 		    "to D_ID=%x", ptgt->tgt_d_id);
4865 	} else {
4866 		ret = FALSE;
4867 	}
4868 
4869 	return (ret);
4870 }
4871 
4872 /*
4873  *     Function: fcp_handle_mapflags
4874  *
4875  *  Description: This function creates a target structure if the ptgt passed
4876  *		 is NULL.  It also kicks off the PLOGI if we are not logged
4877  *		 into the target yet or the PRLI if we are logged into the
4878  *		 target already.  The rest of the treatment is done in the
4879  *		 callbacks of the PLOGI or PRLI.
4880  *
4881  *     Argument: *pptr		FCP Port structure.
4882  *		 *ptgt		Target structure.
4883  *		 *map_entry	Array of fc_portmap_t structures.
4884  *		 link_cnt	Link state count.
4885  *		 tgt_cnt	Target state count.
4886  *		 cause		What caused this function to be called.
4887  *
4888  * Return Value: TRUE	Failed
4889  *		 FALSE	Succeeded
4890  *
4891  *	  Notes: pptr->port_mutex must be owned.
4892  */
4893 static int
4894 fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
4895     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4896 {
4897 	int			lcount;
4898 	int			tcount;
4899 	int			ret = TRUE;
4900 	int			alloc;
4901 	struct fcp_ipkt	*icmd;
4902 	struct fcp_lun	*pseq_lun = NULL;
4903 	uchar_t			opcode;
4904 	int			valid_ptgt_was_passed = FALSE;
4905 
4906 	ASSERT(mutex_owned(&pptr->port_mutex));
4907 
4908 	/*
4909 	 * This case is possible where the FCTL has come up and done discovery
4910 	 * before FCP was loaded and attached. FCTL would have discovered the
4911 	 * devices and later the ULP came online. In this case ULP's would get
4912 	 * PORT_DEVICE_NOCHANGE but target would be NULL.
4913 	 */
4914 	if (ptgt == NULL) {
4915 		/* don't already have a target */
4916 		mutex_exit(&pptr->port_mutex);
4917 		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4918 		mutex_enter(&pptr->port_mutex);
4919 
4920 		if (ptgt == NULL) {
4921 			fcp_log(CE_WARN, pptr->port_dip,
4922 			    "!FC target allocation failed");
4923 			return (ret);
4924 		}
4925 		mutex_enter(&ptgt->tgt_mutex);
4926 		ptgt->tgt_statec_cause = cause;
4927 		ptgt->tgt_tmp_cnt = 1;
4928 		mutex_exit(&ptgt->tgt_mutex);
4929 	} else {
4930 		valid_ptgt_was_passed = TRUE;
4931 	}
4932 
4933 	/*
4934 	 * Copy in the target parameters
4935 	 */
4936 	mutex_enter(&ptgt->tgt_mutex);
4937 	ptgt->tgt_d_id = map_entry->map_did.port_id;
4938 	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4939 	ptgt->tgt_pd_handle = map_entry->map_pd;
4940 	ptgt->tgt_fca_dev = NULL;
4941 
4942 	/* Copy port and node WWNs */
4943 	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4944 	    FC_WWN_SIZE);
4945 	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4946 	    FC_WWN_SIZE);
4947 
4948 	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4949 	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4950 	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4951 	    valid_ptgt_was_passed) {
4952 		/*
4953 		 * determine if there are any tape LUNs on this target
4954 		 */
4955 		for (pseq_lun = ptgt->tgt_lun;
4956 		    pseq_lun != NULL;
4957 		    pseq_lun = pseq_lun->lun_next) {
4958 			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4959 			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4960 				fcp_update_tgt_state(ptgt, FCP_RESET,
4961 				    FCP_LUN_MARK);
4962 				mutex_exit(&ptgt->tgt_mutex);
4963 				return (ret);
4964 			}
4965 		}
4966 	}
4967 
4968 	/*
4969 	 * if UA'REPORT_LUN_CHANGED received,
4970 	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
4971 	 */
4972 	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
4973 		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
4974 		mutex_exit(&ptgt->tgt_mutex);
4975 		mutex_exit(&pptr->port_mutex);
4976 
4977 		ret = fcp_handle_reportlun_changed(ptgt, cause);
4978 
4979 		mutex_enter(&pptr->port_mutex);
4980 		return (ret);
4981 	}
4982 
4983 	/*
4984 	 * If ptgt was NULL when this function was entered, then tgt_node_state
4985 	 * was never specifically initialized but zeroed out which means
4986 	 * FCP_TGT_NODE_NONE.
4987 	 */
4988 	switch (ptgt->tgt_node_state) {
4989 	case FCP_TGT_NODE_NONE:
4990 	case FCP_TGT_NODE_ON_DEMAND:
4991 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
4992 		    !fcp_enable_auto_configuration &&
4993 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
4994 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
4995 		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
4996 		    fcp_enable_auto_configuration &&
4997 		    (ptgt->tgt_manual_config_only == 1) &&
4998 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
4999 			/*
5000 			 * If auto configuration is set and
5001 			 * the tgt_manual_config_only flag is set then
5002 			 * we only want the user to be able to change
5003 			 * the state through create_on_demand.
5004 			 */
5005 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5006 		} else {
5007 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5008 		}
5009 		break;
5010 
5011 	case FCP_TGT_NODE_PRESENT:
5012 		break;
5013 	}
5014 	/*
5015 	 * If we are booting from a fabric device, make sure we
5016 	 * mark the node state appropriately for this target to be
5017 	 * enumerated
5018 	 */
5019 	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5020 		if (bcmp((caddr_t)pptr->port_boot_wwn,
5021 		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5022 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
5023 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5024 		}
5025 	}
5026 	mutex_exit(&ptgt->tgt_mutex);
5027 
5028 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5029 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
5030 	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5031 	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5032 	    map_entry->map_rscn_info.ulp_rscn_count);
5033 
5034 	mutex_enter(&ptgt->tgt_mutex);
5035 
5036 	/*
5037 	 * Reset target OFFLINE state and mark the target BUSY
5038 	 */
5039 	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5040 	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5041 
5042 	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5043 	lcount = link_cnt;
5044 
5045 	mutex_exit(&ptgt->tgt_mutex);
5046 	mutex_exit(&pptr->port_mutex);
5047 
5048 	/*
5049 	 * if we are already logged in, then we do a PRLI, else
5050 	 * we do a PLOGI first (to get logged in)
5051 	 *
5052 	 * We will not check if we are the PLOGI initiator
5053 	 */
5054 	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5055 	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5056 
5057 	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5058 
5059 	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0, lcount, tcount,
5060 	    cause, map_entry->map_rscn_info.ulp_rscn_count);
5061 
5062 	if (icmd == NULL) {
5063 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5064 		/*
5065 		 * We've exited port_mutex before calling fcp_icmd_alloc,
5066 		 * we need to make sure we reacquire it before returning.
5067 		 */
5068 		mutex_enter(&pptr->port_mutex);
5069 		return (FALSE);
5070 	}
5071 
5072 	/* TRUE is only returned while target is intended skipped */
5073 	ret = FALSE;
5074 	/* discover info about this target */
5075 	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5076 	    lcount, tcount, cause)) == DDI_SUCCESS) {
5077 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5078 	} else {
5079 		fcp_icmd_free(pptr, icmd);
5080 		ret = TRUE;
5081 	}
5082 	mutex_enter(&pptr->port_mutex);
5083 
5084 	return (ret);
5085 }
5086 
5087 /*
5088  *     Function: fcp_send_els
5089  *
5090  *  Description: Sends an ELS to the target specified by the caller.  Supports
5091  *		 PLOGI and PRLI.
5092  *
5093  *     Argument: *pptr		Fcp port.
5094  *		 *ptgt		Target to send the ELS to.
5095  *		 *icmd		Internal packet
5096  *		 opcode		ELS opcode
5097  *		 lcount		Link state change counter
5098  *		 tcount		Target state change counter
5099  *		 cause		What caused the call
5100  *
5101  * Return Value: DDI_SUCCESS
5102  *		 Others
5103  */
5104 static int
5105 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5106     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5107 {
5108 	fc_packet_t		*fpkt;
5109 	fc_frame_hdr_t		*hp;
5110 	int			internal = 0;
5111 	int			alloc;
5112 	int			cmd_len;
5113 	int			resp_len;
5114 	int			res = DDI_FAILURE; /* default result */
5115 	int			rval = DDI_FAILURE;
5116 
5117 	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5118 	ASSERT(ptgt->tgt_port == pptr);
5119 
5120 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5121 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5122 	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5123 	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5124 
5125 	if (opcode == LA_ELS_PLOGI) {
5126 		cmd_len = sizeof (la_els_logi_t);
5127 		resp_len = sizeof (la_els_logi_t);
5128 	} else {
5129 		ASSERT(opcode == LA_ELS_PRLI);
5130 		cmd_len = sizeof (la_els_prli_t);
5131 		resp_len = sizeof (la_els_prli_t);
5132 	}
5133 
5134 	if (icmd == NULL) {
5135 		alloc = FCP_MAX(sizeof (la_els_logi_t),
5136 		    sizeof (la_els_prli_t));
5137 		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0,
5138 		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5139 		if (icmd == NULL) {
5140 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5141 			return (res);
5142 		}
5143 		internal++;
5144 	}
5145 	fpkt = icmd->ipkt_fpkt;
5146 
5147 	fpkt->pkt_cmdlen = cmd_len;
5148 	fpkt->pkt_rsplen = resp_len;
5149 	fpkt->pkt_datalen = 0;
5150 	icmd->ipkt_retries = 0;
5151 
5152 	/* fill in fpkt info */
5153 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5154 	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5155 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5156 
5157 	/* get ptr to frame hdr in fpkt */
5158 	hp = &fpkt->pkt_cmd_fhdr;
5159 
5160 	/*
5161 	 * fill in frame hdr
5162 	 */
5163 	hp->r_ctl = R_CTL_ELS_REQ;
5164 	hp->s_id = pptr->port_id;	/* source ID */
5165 	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
5166 	hp->type = FC_TYPE_EXTENDED_LS;
5167 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5168 	hp->seq_id = 0;
5169 	hp->rsvd = 0;
5170 	hp->df_ctl  = 0;
5171 	hp->seq_cnt = 0;
5172 	hp->ox_id = 0xffff;		/* i.e. none */
5173 	hp->rx_id = 0xffff;		/* i.e. none */
5174 	hp->ro = 0;
5175 
5176 	/*
5177 	 * at this point we have a filled in cmd pkt
5178 	 *
5179 	 * fill in the respective info, then use the transport to send
5180 	 * the packet
5181 	 *
5182 	 * for a PLOGI call fc_ulp_login(), and
5183 	 * for a PRLI call fc_ulp_issue_els()
5184 	 */
5185 	switch (opcode) {
5186 	case LA_ELS_PLOGI: {
5187 		struct la_els_logi logi;
5188 
5189 		bzero(&logi, sizeof (struct la_els_logi));
5190 
5191 		hp = &fpkt->pkt_cmd_fhdr;
5192 		hp->r_ctl = R_CTL_ELS_REQ;
5193 		logi.ls_code.ls_code = LA_ELS_PLOGI;
5194 		logi.ls_code.mbz = 0;
5195 
5196 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5197 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5198 
5199 		icmd->ipkt_opcode = LA_ELS_PLOGI;
5200 
5201 		mutex_enter(&pptr->port_mutex);
5202 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5203 
5204 			mutex_exit(&pptr->port_mutex);
5205 
5206 			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5207 			if (rval == FC_SUCCESS) {
5208 				res = DDI_SUCCESS;
5209 				break;
5210 			}
5211 
5212 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5213 
5214 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5215 			    rval, "PLOGI");
5216 		} else {
5217 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5218 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
5219 			    "fcp_send_els1: state change occured"
5220 			    " for D_ID=0x%x", ptgt->tgt_d_id);
5221 			mutex_exit(&pptr->port_mutex);
5222 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5223 		}
5224 		break;
5225 	}
5226 
5227 	case LA_ELS_PRLI: {
5228 		struct la_els_prli	prli;
5229 		struct fcp_prli		*fprli;
5230 
5231 		bzero(&prli, sizeof (struct la_els_prli));
5232 
5233 		hp = &fpkt->pkt_cmd_fhdr;
5234 		hp->r_ctl = R_CTL_ELS_REQ;
5235 
5236 		/* fill in PRLI cmd ELS fields */
5237 		prli.ls_code = LA_ELS_PRLI;
5238 		prli.page_length = 0x10;	/* huh? */
5239 		prli.payload_length = sizeof (struct la_els_prli);
5240 
5241 		icmd->ipkt_opcode = LA_ELS_PRLI;
5242 
5243 		/* get ptr to PRLI service params */
5244 		fprli = (struct fcp_prli *)prli.service_params;
5245 
5246 		/* fill in service params */
5247 		fprli->type = 0x08;
5248 		fprli->resvd1 = 0;
5249 		fprli->orig_process_assoc_valid = 0;
5250 		fprli->resp_process_assoc_valid = 0;
5251 		fprli->establish_image_pair = 1;
5252 		fprli->resvd2 = 0;
5253 		fprli->resvd3 = 0;
5254 		fprli->obsolete_1 = 0;
5255 		fprli->obsolete_2 = 0;
5256 		fprli->data_overlay_allowed = 0;
5257 		fprli->initiator_fn = 1;
5258 		fprli->confirmed_compl_allowed = 1;
5259 
5260 		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5261 			fprli->target_fn = 1;
5262 		} else {
5263 			fprli->target_fn = 0;
5264 		}
5265 
5266 		fprli->retry = 1;
5267 		fprli->read_xfer_rdy_disabled = 1;
5268 		fprli->write_xfer_rdy_disabled = 0;
5269 
5270 		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5271 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5272 
5273 		/* issue the PRLI request */
5274 
5275 		mutex_enter(&pptr->port_mutex);
5276 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5277 
5278 			mutex_exit(&pptr->port_mutex);
5279 
5280 			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5281 			if (rval == FC_SUCCESS) {
5282 				res = DDI_SUCCESS;
5283 				break;
5284 			}
5285 
5286 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5287 
5288 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5289 			    rval, "PRLI");
5290 		} else {
5291 			mutex_exit(&pptr->port_mutex);
5292 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5293 		}
5294 		break;
5295 	}
5296 
5297 	default:
5298 		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5299 		break;
5300 	}
5301 
5302 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5303 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5304 	    "fcp_send_els: returning %d", res);
5305 
5306 	if (res != DDI_SUCCESS) {
5307 		if (internal) {
5308 			fcp_icmd_free(pptr, icmd);
5309 		}
5310 	}
5311 
5312 	return (res);
5313 }
5314 
5315 
5316 /*
5317  * called internally update the state of all of the tgts and each LUN
5318  * for this port (i.e. each target  known to be attached to this port)
5319  * if they are not already offline
5320  *
5321  * must be called with the port mutex owned
5322  *
5323  * acquires and releases the target mutexes for each target attached
5324  * to this port
5325  */
5326 void
5327 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5328 {
5329 	int i;
5330 	struct fcp_tgt *ptgt;
5331 
5332 	ASSERT(mutex_owned(&pptr->port_mutex));
5333 
5334 	for (i = 0; i < FCP_NUM_HASH; i++) {
5335 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5336 		    ptgt = ptgt->tgt_next) {
5337 			mutex_enter(&ptgt->tgt_mutex);
5338 			fcp_update_tgt_state(ptgt, FCP_SET, state);
5339 			ptgt->tgt_change_cnt++;
5340 			ptgt->tgt_statec_cause = cause;
5341 			ptgt->tgt_tmp_cnt = 1;
5342 			ptgt->tgt_done = 0;
5343 			mutex_exit(&ptgt->tgt_mutex);
5344 		}
5345 	}
5346 }
5347 
5348 
5349 static void
5350 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5351 {
5352 	int i;
5353 	int ndevs;
5354 	struct fcp_tgt *ptgt;
5355 
5356 	ASSERT(mutex_owned(&pptr->port_mutex));
5357 
5358 	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5359 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5360 		    ptgt = ptgt->tgt_next) {
5361 			ndevs++;
5362 		}
5363 	}
5364 
5365 	if (ndevs == 0) {
5366 		return;
5367 	}
5368 	pptr->port_tmp_cnt = ndevs;
5369 
5370 	for (i = 0; i < FCP_NUM_HASH; i++) {
5371 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5372 		    ptgt = ptgt->tgt_next) {
5373 			(void) fcp_call_finish_init_held(pptr, ptgt,
5374 			    lcount, ptgt->tgt_change_cnt, cause);
5375 		}
5376 	}
5377 }
5378 
5379 /*
5380  *     Function: fcp_update_tgt_state
5381  *
5382  *  Description: This function updates the field tgt_state of a target.	 That
5383  *		 field is a bitmap and which bit can be set or reset
5384  *		 individually.	The action applied to the target state is also
5385  *		 applied to all the LUNs belonging to the target (provided the
5386  *		 LUN is not offline).  A side effect of applying the state
5387  *		 modification to the target and the LUNs is the field tgt_trace
5388  *		 of the target and lun_trace of the LUNs is set to zero.
5389  *
5390  *
5391  *     Argument: *ptgt	Target structure.
5392  *		 flag	Flag indication what action to apply (set/reset).
5393  *		 state	State bits to update.
5394  *
5395  * Return Value: None
5396  *
5397  *	Context: Interrupt, Kernel or User context.
5398  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5399  *		 calling this function.
5400  */
5401 void
5402 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5403 {
5404 	struct fcp_lun *plun;
5405 
5406 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5407 
5408 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5409 		/* The target is not offline. */
5410 		if (flag == FCP_SET) {
5411 			ptgt->tgt_state |= state;
5412 			ptgt->tgt_trace = 0;
5413 		} else {
5414 			ptgt->tgt_state &= ~state;
5415 		}
5416 
5417 		for (plun = ptgt->tgt_lun; plun != NULL;
5418 		    plun = plun->lun_next) {
5419 			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5420 				/* The LUN is not offline. */
5421 				if (flag == FCP_SET) {
5422 					plun->lun_state |= state;
5423 					plun->lun_trace = 0;
5424 				} else {
5425 					plun->lun_state &= ~state;
5426 				}
5427 			}
5428 		}
5429 	}
5430 }
5431 
5432 /*
5433  *     Function: fcp_update_tgt_state
5434  *
5435  *  Description: This function updates the field lun_state of a LUN.  That
5436  *		 field is a bitmap and which bit can be set or reset
5437  *		 individually.
5438  *
5439  *     Argument: *plun	LUN structure.
5440  *		 flag	Flag indication what action to apply (set/reset).
5441  *		 state	State bits to update.
5442  *
5443  * Return Value: None
5444  *
5445  *	Context: Interrupt, Kernel or User context.
5446  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5447  *		 calling this function.
5448  */
5449 void
5450 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5451 {
5452 	struct fcp_tgt	*ptgt = plun->lun_tgt;
5453 
5454 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5455 
5456 	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5457 		if (flag == FCP_SET) {
5458 			plun->lun_state |= state;
5459 		} else {
5460 			plun->lun_state &= ~state;
5461 		}
5462 	}
5463 }
5464 
5465 /*
5466  *     Function: fcp_get_port
5467  *
5468  *  Description: This function returns the fcp_port structure from the opaque
5469  *		 handle passed by the caller.  That opaque handle is the handle
5470  *		 used by fp/fctl to identify a particular local port.  That
5471  *		 handle has been stored in the corresponding fcp_port
5472  *		 structure.  This function is going to walk the global list of
5473  *		 fcp_port structures till one has a port_fp_handle that matches
5474  *		 the handle passed by the caller.  This function enters the
5475  *		 mutex fcp_global_mutex while walking the global list and then
5476  *		 releases it.
5477  *
5478  *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
5479  *				particular port.
5480  *
5481  * Return Value: NULL		Not found.
5482  *		 Not NULL	Pointer to the fcp_port structure.
5483  *
5484  *	Context: Interrupt, Kernel or User context.
5485  */
5486 static struct fcp_port *
5487 fcp_get_port(opaque_t port_handle)
5488 {
5489 	struct fcp_port *pptr;
5490 
5491 	ASSERT(port_handle != NULL);
5492 
5493 	mutex_enter(&fcp_global_mutex);
5494 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5495 		if (pptr->port_fp_handle == port_handle) {
5496 			break;
5497 		}
5498 	}
5499 	mutex_exit(&fcp_global_mutex);
5500 
5501 	return (pptr);
5502 }
5503 
5504 
5505 static void
5506 fcp_unsol_callback(fc_packet_t *fpkt)
5507 {
5508 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5509 	struct fcp_port *pptr = icmd->ipkt_port;
5510 
5511 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5512 		caddr_t state, reason, action, expln;
5513 
5514 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
5515 		    &action, &expln);
5516 
5517 		fcp_log(CE_WARN, pptr->port_dip,
5518 		    "!couldn't post response to unsolicited request: "
5519 		    " state=%s reason=%s rx_id=%x ox_id=%x",
5520 		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5521 		    fpkt->pkt_cmd_fhdr.rx_id);
5522 	}
5523 	fcp_icmd_free(pptr, icmd);
5524 }
5525 
5526 
5527 /*
5528  * Perform general purpose preparation of a response to an unsolicited request
5529  */
5530 static void
5531 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5532     uchar_t r_ctl, uchar_t type)
5533 {
5534 	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5535 	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5536 	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5537 	pkt->pkt_cmd_fhdr.type = type;
5538 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5539 	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5540 	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5541 	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5542 	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5543 	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5544 	pkt->pkt_cmd_fhdr.ro = 0;
5545 	pkt->pkt_cmd_fhdr.rsvd = 0;
5546 	pkt->pkt_comp = fcp_unsol_callback;
5547 	pkt->pkt_pd = NULL;
5548 }
5549 
5550 
5551 /*ARGSUSED*/
5552 static int
5553 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5554 {
5555 	fc_packet_t		*fpkt;
5556 	struct la_els_prli	prli;
5557 	struct fcp_prli		*fprli;
5558 	struct fcp_ipkt	*icmd;
5559 	struct la_els_prli	*from;
5560 	struct fcp_prli		*orig;
5561 	struct fcp_tgt	*ptgt;
5562 	int			tcount = 0;
5563 	int			lcount;
5564 
5565 	from = (struct la_els_prli *)buf->ub_buffer;
5566 	orig = (struct fcp_prli *)from->service_params;
5567 
5568 	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5569 	    NULL) {
5570 		mutex_enter(&ptgt->tgt_mutex);
5571 		tcount = ptgt->tgt_change_cnt;
5572 		mutex_exit(&ptgt->tgt_mutex);
5573 	}
5574 	mutex_enter(&pptr->port_mutex);
5575 	lcount = pptr->port_link_cnt;
5576 	mutex_exit(&pptr->port_mutex);
5577 
5578 	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5579 	    sizeof (la_els_prli_t), 0, 0, lcount, tcount, 0,
5580 	    FC_INVALID_RSCN_COUNT)) == NULL) {
5581 		return (FC_FAILURE);
5582 	}
5583 	fpkt = icmd->ipkt_fpkt;
5584 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5585 	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5586 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5587 	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5588 	fpkt->pkt_rsplen = 0;
5589 	fpkt->pkt_datalen = 0;
5590 
5591 	icmd->ipkt_opcode = LA_ELS_PRLI;
5592 
5593 	bzero(&prli, sizeof (struct la_els_prli));
5594 	fprli = (struct fcp_prli *)prli.service_params;
5595 	prli.ls_code = LA_ELS_ACC;
5596 	prli.page_length = 0x10;
5597 	prli.payload_length = sizeof (struct la_els_prli);
5598 
5599 	/* fill in service params */
5600 	fprli->type = 0x08;
5601 	fprli->resvd1 = 0;
5602 	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5603 	fprli->orig_process_associator = orig->orig_process_associator;
5604 	fprli->resp_process_assoc_valid = 0;
5605 	fprli->establish_image_pair = 1;
5606 	fprli->resvd2 = 0;
5607 	fprli->resvd3 = 0;
5608 	fprli->obsolete_1 = 0;
5609 	fprli->obsolete_2 = 0;
5610 	fprli->data_overlay_allowed = 0;
5611 	fprli->initiator_fn = 1;
5612 	fprli->confirmed_compl_allowed = 1;
5613 
5614 	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5615 		fprli->target_fn = 1;
5616 	} else {
5617 		fprli->target_fn = 0;
5618 	}
5619 
5620 	fprli->retry = 1;
5621 	fprli->read_xfer_rdy_disabled = 1;
5622 	fprli->write_xfer_rdy_disabled = 0;
5623 
5624 	/* save the unsol prli payload first */
5625 	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5626 	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5627 
5628 	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5629 	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5630 
5631 	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5632 
5633 	mutex_enter(&pptr->port_mutex);
5634 	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5635 		int rval;
5636 		mutex_exit(&pptr->port_mutex);
5637 
5638 		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5639 		    FC_SUCCESS) {
5640 			if (rval == FC_STATEC_BUSY || rval == FC_OFFLINE) {
5641 				fcp_queue_ipkt(pptr, fpkt);
5642 				return (FC_SUCCESS);
5643 			}
5644 			/* Let it timeout */
5645 			fcp_icmd_free(pptr, icmd);
5646 			return (FC_FAILURE);
5647 		}
5648 	} else {
5649 		mutex_exit(&pptr->port_mutex);
5650 		fcp_icmd_free(pptr, icmd);
5651 		return (FC_FAILURE);
5652 	}
5653 
5654 	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5655 
5656 	return (FC_SUCCESS);
5657 }
5658 
5659 /*
5660  *     Function: fcp_icmd_alloc
5661  *
5662  *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
5663  *		 field is initialized to fcp_icmd_callback.  Sometimes it is
5664  *		 modified by the caller (such as fcp_send_scsi).  The
5665  *		 structure is also tied to the state of the line and of the
5666  *		 target at a particular time.  That link is established by
5667  *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5668  *		 and tcount which came respectively from pptr->link_cnt and
5669  *		 ptgt->tgt_change_cnt.
5670  *
5671  *     Argument: *pptr		Fcp port.
5672  *		 *ptgt		Target (destination of the command).
5673  *		 cmd_len	Length of the command.
5674  *		 resp_len	Length of the expected response.
5675  *		 data_len	Length of the data.
5676  *		 nodma		Indicates weither the command and response.
5677  *				will be transfer through DMA or not.
5678  *		 lcount		Link state change counter.
5679  *		 tcount		Target state change counter.
5680  *		 cause		Reason that lead to this call.
5681  *
5682  * Return Value: NULL		Failed.
5683  *		 Not NULL	Internal packet address.
5684  */
5685 static struct fcp_ipkt *
5686 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5687     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5688     uint32_t rscn_count)
5689 {
5690 	int			dma_setup = 0;
5691 	fc_packet_t		*fpkt;
5692 	struct fcp_ipkt	*icmd = NULL;
5693 
5694 	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5695 	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5696 	    KM_NOSLEEP);
5697 	if (icmd == NULL) {
5698 		fcp_log(CE_WARN, pptr->port_dip,
5699 		    "!internal packet allocation failed");
5700 		return (NULL);
5701 	}
5702 
5703 	/*
5704 	 * initialize the allocated packet
5705 	 */
5706 	icmd->ipkt_nodma = nodma;
5707 	icmd->ipkt_next = icmd->ipkt_prev = NULL;
5708 	icmd->ipkt_lun = NULL;
5709 
5710 	icmd->ipkt_link_cnt = lcount;
5711 	icmd->ipkt_change_cnt = tcount;
5712 	icmd->ipkt_cause = cause;
5713 
5714 	mutex_enter(&pptr->port_mutex);
5715 	icmd->ipkt_port = pptr;
5716 	mutex_exit(&pptr->port_mutex);
5717 
5718 	/* keep track of amt of data to be sent in pkt */
5719 	icmd->ipkt_cmdlen = cmd_len;
5720 	icmd->ipkt_resplen = resp_len;
5721 	icmd->ipkt_datalen = data_len;
5722 
5723 	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5724 	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5725 
5726 	/* set pkt's private ptr to point to cmd pkt */
5727 	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5728 
5729 	/* set FCA private ptr to memory just beyond */
5730 	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5731 	    ((char *)icmd + sizeof (struct fcp_ipkt) +
5732 	    pptr->port_dmacookie_sz);
5733 
5734 	/* get ptr to fpkt substruct and fill it in */
5735 	fpkt = icmd->ipkt_fpkt;
5736 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5737 	    sizeof (struct fcp_ipkt));
5738 
5739 	if (ptgt != NULL) {
5740 		icmd->ipkt_tgt = ptgt;
5741 		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5742 	}
5743 
5744 	fpkt->pkt_comp = fcp_icmd_callback;
5745 	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5746 	fpkt->pkt_cmdlen = cmd_len;
5747 	fpkt->pkt_rsplen = resp_len;
5748 	fpkt->pkt_datalen = data_len;
5749 
5750 	/*
5751 	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5752 	 * rscn_count as fcp knows down to the transport. If a valid count was
5753 	 * passed into this function, we allocate memory to actually pass down
5754 	 * this info.
5755 	 *
5756 	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5757 	 * basically mean that fcp will not be able to help transport
5758 	 * distinguish if a new RSCN has come after fcp was last informed about
5759 	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5760 	 * 5068068 where the device might end up going offline in case of RSCN
5761 	 * storms.
5762 	 */
5763 	fpkt->pkt_ulp_rscn_infop = NULL;
5764 	if (rscn_count != FC_INVALID_RSCN_COUNT) {
5765 		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5766 		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5767 		if (fpkt->pkt_ulp_rscn_infop == NULL) {
5768 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5769 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5770 			    "Failed to alloc memory to pass rscn info");
5771 		}
5772 	}
5773 
5774 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5775 		fc_ulp_rscn_info_t	*rscnp;
5776 
5777 		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5778 		rscnp->ulp_rscn_count = rscn_count;
5779 	}
5780 
5781 	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5782 		goto fail;
5783 	}
5784 	dma_setup++;
5785 
5786 	/*
5787 	 * Must hold target mutex across setting of pkt_pd and call to
5788 	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5789 	 * away while we're not looking.
5790 	 */
5791 	if (ptgt != NULL) {
5792 		mutex_enter(&ptgt->tgt_mutex);
5793 		fpkt->pkt_pd = ptgt->tgt_pd_handle;
5794 
5795 		/* ask transport to do its initialization on this pkt */
5796 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5797 		    != FC_SUCCESS) {
5798 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5799 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5800 			    "fc_ulp_init_packet failed");
5801 			mutex_exit(&ptgt->tgt_mutex);
5802 			goto fail;
5803 		}
5804 		mutex_exit(&ptgt->tgt_mutex);
5805 	} else {
5806 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5807 		    != FC_SUCCESS) {
5808 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5809 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5810 			    "fc_ulp_init_packet failed");
5811 			goto fail;
5812 		}
5813 	}
5814 
5815 	mutex_enter(&pptr->port_mutex);
5816 	if (pptr->port_state & (FCP_STATE_DETACHING |
5817 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5818 		int rval;
5819 
5820 		mutex_exit(&pptr->port_mutex);
5821 
5822 		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5823 		ASSERT(rval == FC_SUCCESS);
5824 
5825 		goto fail;
5826 	}
5827 
5828 	if (ptgt != NULL) {
5829 		mutex_enter(&ptgt->tgt_mutex);
5830 		ptgt->tgt_ipkt_cnt++;
5831 		mutex_exit(&ptgt->tgt_mutex);
5832 	}
5833 
5834 	pptr->port_ipkt_cnt++;
5835 
5836 	mutex_exit(&pptr->port_mutex);
5837 
5838 	return (icmd);
5839 
5840 fail:
5841 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5842 		kmem_free(fpkt->pkt_ulp_rscn_infop,
5843 		    sizeof (fc_ulp_rscn_info_t));
5844 		fpkt->pkt_ulp_rscn_infop = NULL;
5845 	}
5846 
5847 	if (dma_setup) {
5848 		fcp_free_dma(pptr, icmd);
5849 	}
5850 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5851 	    (size_t)pptr->port_dmacookie_sz);
5852 
5853 	return (NULL);
5854 }
5855 
5856 /*
5857  *     Function: fcp_icmd_free
5858  *
5859  *  Description: Frees the internal command passed by the caller.
5860  *
5861  *     Argument: *pptr		Fcp port.
5862  *		 *icmd		Internal packet to free.
5863  *
5864  * Return Value: None
5865  */
5866 static void
5867 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5868 {
5869 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
5870 
5871 	/* Let the underlying layers do their cleanup. */
5872 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5873 	    icmd->ipkt_fpkt);
5874 
5875 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5876 		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5877 		    sizeof (fc_ulp_rscn_info_t));
5878 	}
5879 
5880 	fcp_free_dma(pptr, icmd);
5881 
5882 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5883 	    (size_t)pptr->port_dmacookie_sz);
5884 
5885 	mutex_enter(&pptr->port_mutex);
5886 
5887 	if (ptgt) {
5888 		mutex_enter(&ptgt->tgt_mutex);
5889 		ptgt->tgt_ipkt_cnt--;
5890 		mutex_exit(&ptgt->tgt_mutex);
5891 	}
5892 
5893 	pptr->port_ipkt_cnt--;
5894 	mutex_exit(&pptr->port_mutex);
5895 }
5896 
5897 /*
5898  *     Function: fcp_alloc_dma
5899  *
5900  *  Description: Allocated the DMA resources required for the internal
5901  *		 packet.
5902  *
5903  *     Argument: *pptr	FCP port.
5904  *		 *icmd	Internal FCP packet.
5905  *		 nodma	Indicates if the Cmd and Resp will be DMAed.
5906  *		 flags	Allocation flags (Sleep or NoSleep).
5907  *
5908  * Return Value: FC_SUCCESS
5909  *		 FC_NOMEM
5910  */
5911 static int
5912 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5913     int nodma, int flags)
5914 {
5915 	int		rval;
5916 	size_t		real_size;
5917 	uint_t		ccount;
5918 	int		bound = 0;
5919 	int		cmd_resp = 0;
5920 	fc_packet_t	*fpkt;
5921 	ddi_dma_cookie_t	pkt_data_cookie;
5922 	ddi_dma_cookie_t	*cp;
5923 	uint32_t		cnt;
5924 
5925 	fpkt = &icmd->ipkt_fc_packet;
5926 
5927 	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5928 	    fpkt->pkt_resp_dma == NULL);
5929 
5930 	icmd->ipkt_nodma = nodma;
5931 
5932 	if (nodma) {
5933 		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5934 		if (fpkt->pkt_cmd == NULL) {
5935 			goto fail;
5936 		}
5937 
5938 		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5939 		if (fpkt->pkt_resp == NULL) {
5940 			goto fail;
5941 		}
5942 	} else {
5943 		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5944 
5945 		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5946 		if (rval == FC_FAILURE) {
5947 			ASSERT(fpkt->pkt_cmd_dma == NULL &&
5948 			    fpkt->pkt_resp_dma == NULL);
5949 			goto fail;
5950 		}
5951 		cmd_resp++;
5952 	}
5953 
5954 	if (fpkt->pkt_datalen != 0) {
5955 		/*
5956 		 * set up DMA handle and memory for the data in this packet
5957 		 */
5958 		if (ddi_dma_alloc_handle(pptr->port_dip,
5959 		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
5960 		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
5961 			goto fail;
5962 		}
5963 
5964 		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
5965 		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
5966 		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
5967 		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
5968 			goto fail;
5969 		}
5970 
5971 		/* was DMA mem size gotten < size asked for/needed ?? */
5972 		if (real_size < fpkt->pkt_datalen) {
5973 			goto fail;
5974 		}
5975 
5976 		/* bind DMA address and handle together */
5977 		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
5978 		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
5979 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
5980 		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
5981 			goto fail;
5982 		}
5983 		bound++;
5984 
5985 		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
5986 			goto fail;
5987 		}
5988 
5989 		fpkt->pkt_data_cookie_cnt = ccount;
5990 
5991 		cp = fpkt->pkt_data_cookie;
5992 		*cp = pkt_data_cookie;
5993 		cp++;
5994 
5995 		for (cnt = 1; cnt < ccount; cnt++, cp++) {
5996 			ddi_dma_nextcookie(fpkt->pkt_data_dma,
5997 			    &pkt_data_cookie);
5998 			*cp = pkt_data_cookie;
5999 		}
6000 
6001 	}
6002 
6003 	return (FC_SUCCESS);
6004 
6005 fail:
6006 	if (bound) {
6007 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6008 	}
6009 
6010 	if (fpkt->pkt_data_dma) {
6011 		if (fpkt->pkt_data) {
6012 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6013 		}
6014 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6015 	}
6016 
6017 	if (nodma) {
6018 		if (fpkt->pkt_cmd) {
6019 			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6020 		}
6021 		if (fpkt->pkt_resp) {
6022 			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6023 		}
6024 	} else {
6025 		if (cmd_resp) {
6026 			fcp_free_cmd_resp(pptr, fpkt);
6027 		}
6028 	}
6029 
6030 	return (FC_NOMEM);
6031 }
6032 
6033 
6034 static void
6035 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6036 {
6037 	fc_packet_t *fpkt = icmd->ipkt_fpkt;
6038 
6039 	if (fpkt->pkt_data_dma) {
6040 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6041 		if (fpkt->pkt_data) {
6042 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6043 		}
6044 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6045 	}
6046 
6047 	if (icmd->ipkt_nodma) {
6048 		if (fpkt->pkt_cmd) {
6049 			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6050 		}
6051 		if (fpkt->pkt_resp) {
6052 			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6053 		}
6054 	} else {
6055 		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6056 
6057 		fcp_free_cmd_resp(pptr, fpkt);
6058 	}
6059 }
6060 
6061 /*
6062  *     Function: fcp_lookup_target
6063  *
6064  *  Description: Finds a target given a WWN.
6065  *
6066  *     Argument: *pptr	FCP port.
6067  *		 *wwn	World Wide Name of the device to look for.
6068  *
6069  * Return Value: NULL		No target found
6070  *		 Not NULL	Target structure
6071  *
6072  *	Context: Interrupt context.
6073  *		 The mutex pptr->port_mutex must be owned.
6074  */
6075 /* ARGSUSED */
6076 static struct fcp_tgt *
6077 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6078 {
6079 	int			hash;
6080 	struct fcp_tgt	*ptgt;
6081 
6082 	ASSERT(mutex_owned(&pptr->port_mutex));
6083 
6084 	hash = FCP_HASH(wwn);
6085 
6086 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6087 	    ptgt = ptgt->tgt_next) {
6088 		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6089 		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6090 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
6091 			break;
6092 		}
6093 	}
6094 
6095 	return (ptgt);
6096 }
6097 
6098 
6099 /*
6100  * Find target structure given a port identifier
6101  */
6102 static struct fcp_tgt *
6103 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6104 {
6105 	fc_portid_t		port_id;
6106 	la_wwn_t		pwwn;
6107 	struct fcp_tgt	*ptgt = NULL;
6108 
6109 	port_id.priv_lilp_posit = 0;
6110 	port_id.port_id = d_id;
6111 	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6112 	    &pwwn) == FC_SUCCESS) {
6113 		mutex_enter(&pptr->port_mutex);
6114 		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6115 		mutex_exit(&pptr->port_mutex);
6116 	}
6117 
6118 	return (ptgt);
6119 }
6120 
6121 
6122 /*
6123  * the packet completion callback routine for info cmd pkts
6124  *
6125  * this means fpkt pts to a response to either a PLOGI or a PRLI
6126  *
6127  * if there is an error an attempt is made to call a routine to resend
6128  * the command that failed
6129  */
6130 static void
6131 fcp_icmd_callback(fc_packet_t *fpkt)
6132 {
6133 	struct fcp_ipkt	*icmd;
6134 	struct fcp_port	*pptr;
6135 	struct fcp_tgt	*ptgt;
6136 	struct la_els_prli	*prli;
6137 	struct la_els_prli	prli_s;
6138 	struct fcp_prli		*fprli;
6139 	struct fcp_lun	*plun;
6140 	int		free_pkt = 1;
6141 	int		rval;
6142 	ls_code_t	resp;
6143 	uchar_t		prli_acc = 0;
6144 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
6145 	int		lun0_newalloc;
6146 
6147 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6148 
6149 	/* get ptrs to the port and target structs for the cmd */
6150 	pptr = icmd->ipkt_port;
6151 	ptgt = icmd->ipkt_tgt;
6152 
6153 	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6154 
6155 	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6156 		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6157 		    sizeof (prli_s));
6158 		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6159 	}
6160 
6161 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6162 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6163 	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
6164 	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6165 	    ptgt->tgt_d_id);
6166 
6167 	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6168 	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6169 
6170 		mutex_enter(&ptgt->tgt_mutex);
6171 		if (ptgt->tgt_pd_handle == NULL) {
6172 			/*
6173 			 * in a fabric environment the port device handles
6174 			 * get created only after successful LOGIN into the
6175 			 * transport, so the transport makes this port
6176 			 * device (pd) handle available in this packet, so
6177 			 * save it now
6178 			 */
6179 			ASSERT(fpkt->pkt_pd != NULL);
6180 			ptgt->tgt_pd_handle = fpkt->pkt_pd;
6181 		}
6182 		mutex_exit(&ptgt->tgt_mutex);
6183 
6184 		/* which ELS cmd is this response for ?? */
6185 		switch (icmd->ipkt_opcode) {
6186 		case LA_ELS_PLOGI:
6187 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6188 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6189 			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6190 			    ptgt->tgt_d_id,
6191 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6192 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6193 
6194 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6195 			    FCP_TGT_TRACE_15);
6196 
6197 			/* Note that we are not allocating a new icmd */
6198 			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6199 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6200 			    icmd->ipkt_cause) != DDI_SUCCESS) {
6201 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6202 				    FCP_TGT_TRACE_16);
6203 				goto fail;
6204 			}
6205 			break;
6206 
6207 		case LA_ELS_PRLI:
6208 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6209 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6210 			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6211 
6212 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6213 			    FCP_TGT_TRACE_17);
6214 
6215 			prli = &prli_s;
6216 
6217 			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6218 			    sizeof (prli_s));
6219 
6220 			fprli = (struct fcp_prli *)prli->service_params;
6221 
6222 			mutex_enter(&ptgt->tgt_mutex);
6223 			ptgt->tgt_icap = fprli->initiator_fn;
6224 			ptgt->tgt_tcap = fprli->target_fn;
6225 			mutex_exit(&ptgt->tgt_mutex);
6226 
6227 			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6228 				/*
6229 				 * this FCP device does not support target mode
6230 				 */
6231 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6232 				    FCP_TGT_TRACE_18);
6233 				goto fail;
6234 			}
6235 			if (fprli->retry == 1) {
6236 				fc_ulp_disable_relogin(pptr->port_fp_handle,
6237 				    &ptgt->tgt_port_wwn);
6238 			}
6239 
6240 			/* target is no longer offline */
6241 			mutex_enter(&pptr->port_mutex);
6242 			mutex_enter(&ptgt->tgt_mutex);
6243 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6244 				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6245 				    FCP_TGT_MARK);
6246 			} else {
6247 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6248 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6249 				    "fcp_icmd_callback,1: state change "
6250 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6251 				mutex_exit(&ptgt->tgt_mutex);
6252 				mutex_exit(&pptr->port_mutex);
6253 				goto fail;
6254 			}
6255 			mutex_exit(&ptgt->tgt_mutex);
6256 			mutex_exit(&pptr->port_mutex);
6257 
6258 			/*
6259 			 * lun 0 should always respond to inquiry, so
6260 			 * get the LUN struct for LUN 0
6261 			 *
6262 			 * Currently we deal with first level of addressing.
6263 			 * If / when we start supporting 0x device types
6264 			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6265 			 * this logic will need revisiting.
6266 			 */
6267 			lun0_newalloc = 0;
6268 			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6269 				/*
6270 				 * no LUN struct for LUN 0 yet exists,
6271 				 * so create one
6272 				 */
6273 				plun = fcp_alloc_lun(ptgt);
6274 				if (plun == NULL) {
6275 					fcp_log(CE_WARN, pptr->port_dip,
6276 					    "!Failed to allocate lun 0 for"
6277 					    " D_ID=%x", ptgt->tgt_d_id);
6278 					goto fail;
6279 				}
6280 				lun0_newalloc = 1;
6281 			}
6282 
6283 			/* fill in LUN info */
6284 			mutex_enter(&ptgt->tgt_mutex);
6285 			/*
6286 			 * consider lun 0 as device not connected if it is
6287 			 * offlined or newly allocated
6288 			 */
6289 			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6290 			    lun0_newalloc) {
6291 				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6292 			}
6293 			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6294 			plun->lun_state &= ~FCP_LUN_OFFLINE;
6295 			ptgt->tgt_lun_cnt = 1;
6296 			ptgt->tgt_report_lun_cnt = 0;
6297 			mutex_exit(&ptgt->tgt_mutex);
6298 
6299 			/* Retrieve the rscn count (if a valid one exists) */
6300 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6301 				rscn_count = ((fc_ulp_rscn_info_t *)
6302 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6303 				    ->ulp_rscn_count;
6304 			} else {
6305 				rscn_count = FC_INVALID_RSCN_COUNT;
6306 			}
6307 
6308 			/* send Report Lun request to target */
6309 			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6310 			    sizeof (struct fcp_reportlun_resp),
6311 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6312 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6313 				mutex_enter(&pptr->port_mutex);
6314 				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6315 					fcp_log(CE_WARN, pptr->port_dip,
6316 					    "!Failed to send REPORT LUN to"
6317 					    "  D_ID=%x", ptgt->tgt_d_id);
6318 				} else {
6319 					FCP_TRACE(fcp_logq,
6320 					    pptr->port_instbuf, fcp_trace,
6321 					    FCP_BUF_LEVEL_5, 0,
6322 					    "fcp_icmd_callback,2:state change"
6323 					    " occured for D_ID=0x%x",
6324 					    ptgt->tgt_d_id);
6325 				}
6326 				mutex_exit(&pptr->port_mutex);
6327 
6328 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6329 				    FCP_TGT_TRACE_19);
6330 
6331 				goto fail;
6332 			} else {
6333 				free_pkt = 0;
6334 				fcp_icmd_free(pptr, icmd);
6335 			}
6336 			break;
6337 
6338 		default:
6339 			fcp_log(CE_WARN, pptr->port_dip,
6340 			    "!fcp_icmd_callback Invalid opcode");
6341 			goto fail;
6342 		}
6343 
6344 		return;
6345 	}
6346 
6347 
6348 	/*
6349 	 * Other PLOGI failures are not retried as the
6350 	 * transport does it already
6351 	 */
6352 	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6353 		if (fcp_is_retryable(icmd) &&
6354 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6355 
6356 			if (FCP_MUST_RETRY(fpkt)) {
6357 				fcp_queue_ipkt(pptr, fpkt);
6358 				return;
6359 			}
6360 
6361 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6362 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6363 			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
6364 			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6365 			    fpkt->pkt_reason);
6366 
6367 			/*
6368 			 * Retry by recalling the routine that
6369 			 * originally queued this packet
6370 			 */
6371 			mutex_enter(&pptr->port_mutex);
6372 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6373 				caddr_t msg;
6374 
6375 				mutex_exit(&pptr->port_mutex);
6376 
6377 				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6378 
6379 				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6380 					fpkt->pkt_timeout +=
6381 					    FCP_TIMEOUT_DELTA;
6382 				}
6383 
6384 				rval = fc_ulp_issue_els(pptr->port_fp_handle,
6385 				    fpkt);
6386 				if (rval == FC_SUCCESS) {
6387 					return;
6388 				}
6389 
6390 				if (rval == FC_STATEC_BUSY ||
6391 				    rval == FC_OFFLINE) {
6392 					fcp_queue_ipkt(pptr, fpkt);
6393 					return;
6394 				}
6395 				(void) fc_ulp_error(rval, &msg);
6396 
6397 				fcp_log(CE_NOTE, pptr->port_dip,
6398 				    "!ELS 0x%x failed to d_id=0x%x;"
6399 				    " %s", icmd->ipkt_opcode,
6400 				    ptgt->tgt_d_id, msg);
6401 			} else {
6402 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6403 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6404 				    "fcp_icmd_callback,3: state change "
6405 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6406 				mutex_exit(&pptr->port_mutex);
6407 			}
6408 		}
6409 	} else {
6410 		if (fcp_is_retryable(icmd) &&
6411 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6412 			if (FCP_MUST_RETRY(fpkt)) {
6413 				fcp_queue_ipkt(pptr, fpkt);
6414 				return;
6415 			}
6416 		}
6417 		mutex_enter(&pptr->port_mutex);
6418 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6419 		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6420 			mutex_exit(&pptr->port_mutex);
6421 			fcp_print_error(fpkt);
6422 		} else {
6423 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6424 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6425 			    "fcp_icmd_callback,4: state change occured"
6426 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6427 			mutex_exit(&pptr->port_mutex);
6428 		}
6429 	}
6430 
6431 fail:
6432 	if (free_pkt) {
6433 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6434 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6435 		fcp_icmd_free(pptr, icmd);
6436 	}
6437 }
6438 
6439 
6440 /*
6441  * called internally to send an info cmd using the transport
6442  *
6443  * sends either an INQ or a REPORT_LUN
6444  *
6445  * when the packet is completed fcp_scsi_callback is called
6446  */
6447 static int
6448 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6449     int lcount, int tcount, int cause, uint32_t rscn_count)
6450 {
6451 	int			nodma;
6452 	struct fcp_ipkt		*icmd;
6453 	struct fcp_tgt		*ptgt;
6454 	struct fcp_port		*pptr;
6455 	fc_frame_hdr_t		*hp;
6456 	fc_packet_t		*fpkt;
6457 	struct fcp_cmd		fcp_cmd;
6458 	struct fcp_cmd		*fcmd;
6459 	union scsi_cdb		*scsi_cdb;
6460 
6461 	ASSERT(plun != NULL);
6462 
6463 	ptgt = plun->lun_tgt;
6464 	ASSERT(ptgt != NULL);
6465 
6466 	pptr = ptgt->tgt_port;
6467 	ASSERT(pptr != NULL);
6468 
6469 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6470 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6471 	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6472 
6473 	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6474 
6475 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6476 	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6477 	    rscn_count);
6478 
6479 	if (icmd == NULL) {
6480 		return (DDI_FAILURE);
6481 	}
6482 
6483 	fpkt = icmd->ipkt_fpkt;
6484 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6485 	icmd->ipkt_retries = 0;
6486 	icmd->ipkt_opcode = opcode;
6487 	icmd->ipkt_lun = plun;
6488 
6489 	if (nodma) {
6490 		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6491 	} else {
6492 		fcmd = &fcp_cmd;
6493 	}
6494 	bzero(fcmd, sizeof (struct fcp_cmd));
6495 
6496 	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6497 
6498 	hp = &fpkt->pkt_cmd_fhdr;
6499 
6500 	hp->s_id = pptr->port_id;
6501 	hp->d_id = ptgt->tgt_d_id;
6502 	hp->r_ctl = R_CTL_COMMAND;
6503 	hp->type = FC_TYPE_SCSI_FCP;
6504 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6505 	hp->rsvd = 0;
6506 	hp->seq_id = 0;
6507 	hp->seq_cnt = 0;
6508 	hp->ox_id = 0xffff;
6509 	hp->rx_id = 0xffff;
6510 	hp->ro = 0;
6511 
6512 	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6513 
6514 	/*
6515 	 * Request SCSI target for expedited processing
6516 	 */
6517 
6518 	/*
6519 	 * Set up for untagged queuing because we do not
6520 	 * know if the fibre device supports queuing.
6521 	 */
6522 	fcmd->fcp_cntl.cntl_reserved_0 = 0;
6523 	fcmd->fcp_cntl.cntl_reserved_1 = 0;
6524 	fcmd->fcp_cntl.cntl_reserved_2 = 0;
6525 	fcmd->fcp_cntl.cntl_reserved_3 = 0;
6526 	fcmd->fcp_cntl.cntl_reserved_4 = 0;
6527 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6528 	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6529 
6530 	switch (opcode) {
6531 	case SCMD_INQUIRY_PAGE83:
6532 		/*
6533 		 * Prepare to get the Inquiry VPD page 83 information
6534 		 */
6535 		fcmd->fcp_cntl.cntl_read_data = 1;
6536 		fcmd->fcp_cntl.cntl_write_data = 0;
6537 		fcmd->fcp_data_len = alloc_len;
6538 
6539 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6540 		fpkt->pkt_comp = fcp_scsi_callback;
6541 
6542 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6543 		scsi_cdb->g0_addr2 = 0x01;
6544 		scsi_cdb->g0_addr1 = 0x83;
6545 		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6546 		break;
6547 
6548 	case SCMD_INQUIRY:
6549 		fcmd->fcp_cntl.cntl_read_data = 1;
6550 		fcmd->fcp_cntl.cntl_write_data = 0;
6551 		fcmd->fcp_data_len = alloc_len;
6552 
6553 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6554 		fpkt->pkt_comp = fcp_scsi_callback;
6555 
6556 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6557 		scsi_cdb->g0_count0 = SUN_INQSIZE;
6558 		break;
6559 
6560 	case SCMD_REPORT_LUN: {
6561 		fc_portid_t	d_id;
6562 		opaque_t	fca_dev;
6563 
6564 		ASSERT(alloc_len >= 16);
6565 
6566 		d_id.priv_lilp_posit = 0;
6567 		d_id.port_id = ptgt->tgt_d_id;
6568 
6569 		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6570 
6571 		mutex_enter(&ptgt->tgt_mutex);
6572 		ptgt->tgt_fca_dev = fca_dev;
6573 		mutex_exit(&ptgt->tgt_mutex);
6574 
6575 		fcmd->fcp_cntl.cntl_read_data = 1;
6576 		fcmd->fcp_cntl.cntl_write_data = 0;
6577 		fcmd->fcp_data_len = alloc_len;
6578 
6579 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6580 		fpkt->pkt_comp = fcp_scsi_callback;
6581 
6582 		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6583 		scsi_cdb->scc5_count0 = alloc_len & 0xff;
6584 		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6585 		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6586 		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6587 		break;
6588 	}
6589 
6590 	default:
6591 		fcp_log(CE_WARN, pptr->port_dip,
6592 		    "!fcp_send_scsi Invalid opcode");
6593 		break;
6594 	}
6595 
6596 	if (!nodma) {
6597 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6598 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6599 	}
6600 
6601 	mutex_enter(&pptr->port_mutex);
6602 	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6603 
6604 		mutex_exit(&pptr->port_mutex);
6605 		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6606 		    FC_SUCCESS) {
6607 			fcp_icmd_free(pptr, icmd);
6608 			return (DDI_FAILURE);
6609 		}
6610 		return (DDI_SUCCESS);
6611 	} else {
6612 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6613 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6614 		    "fcp_send_scsi,1: state change occured"
6615 		    " for D_ID=0x%x", ptgt->tgt_d_id);
6616 		mutex_exit(&pptr->port_mutex);
6617 		fcp_icmd_free(pptr, icmd);
6618 		return (DDI_FAILURE);
6619 	}
6620 }
6621 
6622 
6623 /*
6624  * called by fcp_scsi_callback to check to handle the case where
6625  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6626  */
6627 static int
6628 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6629 {
6630 	uchar_t				rqlen;
6631 	int				rval = DDI_FAILURE;
6632 	struct scsi_extended_sense	sense_info, *sense;
6633 	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
6634 	    fpkt->pkt_ulp_private;
6635 	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
6636 	struct fcp_port		*pptr = ptgt->tgt_port;
6637 
6638 	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6639 
6640 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6641 		/*
6642 		 * SCSI-II Reserve Release support. Some older FC drives return
6643 		 * Reservation conflict for Report Luns command.
6644 		 */
6645 		if (icmd->ipkt_nodma) {
6646 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6647 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6648 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6649 		} else {
6650 			fcp_rsp_t	new_resp;
6651 
6652 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6653 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6654 
6655 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6656 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6657 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6658 
6659 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6660 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6661 		}
6662 
6663 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6664 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6665 
6666 		return (DDI_SUCCESS);
6667 	}
6668 
6669 	sense = &sense_info;
6670 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
6671 		/* no need to continue if sense length is not set */
6672 		return (rval);
6673 	}
6674 
6675 	/* casting 64-bit integer to 8-bit */
6676 	rqlen = (uchar_t)min(rsp->fcp_sense_len,
6677 	    sizeof (struct scsi_extended_sense));
6678 
6679 	if (rqlen < 14) {
6680 		/* no need to continue if request length isn't long enough */
6681 		return (rval);
6682 	}
6683 
6684 	if (icmd->ipkt_nodma) {
6685 		/*
6686 		 * We can safely use fcp_response_len here since the
6687 		 * only path that calls fcp_check_reportlun,
6688 		 * fcp_scsi_callback, has already called
6689 		 * fcp_validate_fcp_response.
6690 		 */
6691 		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6692 		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6693 	} else {
6694 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6695 		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6696 		    sizeof (struct scsi_extended_sense));
6697 	}
6698 
6699 	if (!FCP_SENSE_NO_LUN(sense)) {
6700 		mutex_enter(&ptgt->tgt_mutex);
6701 		/* clear the flag if any */
6702 		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6703 		mutex_exit(&ptgt->tgt_mutex);
6704 	}
6705 
6706 	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6707 	    (sense->es_add_code == 0x20)) {
6708 		if (icmd->ipkt_nodma) {
6709 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6710 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6711 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6712 		} else {
6713 			fcp_rsp_t	new_resp;
6714 
6715 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6716 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6717 
6718 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6719 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6720 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6721 
6722 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6723 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6724 		}
6725 
6726 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6727 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6728 
6729 		return (DDI_SUCCESS);
6730 	}
6731 
6732 	/*
6733 	 * This is for the STK library which returns a check condition,
6734 	 * to indicate device is not ready, manual assistance needed.
6735 	 * This is to a report lun command when the door is open.
6736 	 */
6737 	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6738 		if (icmd->ipkt_nodma) {
6739 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6740 			rsp->fcp_u.fcp_status.sense_len_set = 0;
6741 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6742 		} else {
6743 			fcp_rsp_t	new_resp;
6744 
6745 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6746 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6747 
6748 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6749 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6750 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6751 
6752 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6753 			    fpkt->pkt_resp_acc, sizeof (new_resp));
6754 		}
6755 
6756 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6757 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6758 
6759 		return (DDI_SUCCESS);
6760 	}
6761 
6762 	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6763 	    (FCP_SENSE_NO_LUN(sense))) {
6764 		mutex_enter(&ptgt->tgt_mutex);
6765 		if ((FCP_SENSE_NO_LUN(sense)) &&
6766 		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6767 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6768 			mutex_exit(&ptgt->tgt_mutex);
6769 			/*
6770 			 * reconfig was triggred by ILLEGAL REQUEST but
6771 			 * got ILLEGAL REQUEST again
6772 			 */
6773 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6774 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
6775 			    "!FCP: Unable to obtain Report Lun data"
6776 			    " target=%x", ptgt->tgt_d_id);
6777 		} else {
6778 			if (ptgt->tgt_tid == NULL) {
6779 				timeout_id_t	tid;
6780 				/*
6781 				 * REPORT LUN data has changed.	 Kick off
6782 				 * rediscovery
6783 				 */
6784 				tid = timeout(fcp_reconfigure_luns,
6785 				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6786 
6787 				ptgt->tgt_tid = tid;
6788 				ptgt->tgt_state |= FCP_TGT_BUSY;
6789 			}
6790 			if (FCP_SENSE_NO_LUN(sense)) {
6791 				ptgt->tgt_state |= FCP_TGT_ILLREQ;
6792 			}
6793 			mutex_exit(&ptgt->tgt_mutex);
6794 			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6795 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6796 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6797 				    "!FCP:Report Lun Has Changed"
6798 				    " target=%x", ptgt->tgt_d_id);
6799 			} else if (FCP_SENSE_NO_LUN(sense)) {
6800 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6801 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6802 				    "!FCP:LU Not Supported"
6803 				    " target=%x", ptgt->tgt_d_id);
6804 			}
6805 		}
6806 		rval = DDI_SUCCESS;
6807 	}
6808 
6809 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6810 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6811 	    "D_ID=%x, sense=%x, status=%x",
6812 	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6813 	    rsp->fcp_u.fcp_status.scsi_status);
6814 
6815 	return (rval);
6816 }
6817 
6818 /*
6819  *     Function: fcp_scsi_callback
6820  *
6821  *  Description: This is the callback routine set by fcp_send_scsi() after
6822  *		 it calls fcp_icmd_alloc().  The SCSI command completed here
6823  *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
6824  *		 INQUIRY_PAGE83.
6825  *
6826  *     Argument: *fpkt	 FC packet used to convey the command
6827  *
6828  * Return Value: None
6829  */
6830 static void
6831 fcp_scsi_callback(fc_packet_t *fpkt)
6832 {
6833 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
6834 	    fpkt->pkt_ulp_private;
6835 	struct fcp_rsp_info	fcp_rsp_err, *bep;
6836 	struct fcp_port	*pptr;
6837 	struct fcp_tgt	*ptgt;
6838 	struct fcp_lun	*plun;
6839 	struct fcp_rsp		response, *rsp;
6840 
6841 	if (icmd->ipkt_nodma) {
6842 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6843 	} else {
6844 		rsp = &response;
6845 		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6846 		    sizeof (struct fcp_rsp));
6847 	}
6848 
6849 	ptgt = icmd->ipkt_tgt;
6850 	pptr = ptgt->tgt_port;
6851 	plun = icmd->ipkt_lun;
6852 
6853 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6854 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6855 	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
6856 	    "status=%x, lun num=%x",
6857 	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6858 	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6859 
6860 	/*
6861 	 * Pre-init LUN GUID with NWWN if it is not a device that
6862 	 * supports multiple luns and we know it's not page83
6863 	 * compliant.  Although using a NWWN is not lun unique,
6864 	 * we will be fine since there is only one lun behind the taget
6865 	 * in this case.
6866 	 */
6867 	if ((plun->lun_guid_size == 0) &&
6868 	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6869 	    (fcp_symmetric_device_probe(plun) == 0)) {
6870 
6871 		char ascii_wwn[FC_WWN_SIZE*2+1];
6872 		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6873 		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6874 	}
6875 
6876 	/*
6877 	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6878 	 * when thay have more data than what is asked in CDB. An overrun
6879 	 * is really when FCP_DL is smaller than the data length in CDB.
6880 	 * In the case here we know that REPORT LUN command we formed within
6881 	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6882 	 * behavior. In reality this is FC_SUCCESS.
6883 	 */
6884 	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6885 	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6886 	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6887 		fpkt->pkt_state = FC_PKT_SUCCESS;
6888 	}
6889 
6890 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6891 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6892 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6893 		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6894 		    ptgt->tgt_d_id);
6895 
6896 		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6897 			/*
6898 			 * Inquiry VPD page command on A5K SES devices would
6899 			 * result in data CRC errors.
6900 			 */
6901 			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6902 				(void) fcp_handle_page83(fpkt, icmd, 1);
6903 				return;
6904 			}
6905 		}
6906 		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6907 		    FCP_MUST_RETRY(fpkt)) {
6908 			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6909 			fcp_retry_scsi_cmd(fpkt);
6910 			return;
6911 		}
6912 
6913 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6914 		    FCP_TGT_TRACE_20);
6915 
6916 		mutex_enter(&pptr->port_mutex);
6917 		mutex_enter(&ptgt->tgt_mutex);
6918 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6919 			mutex_exit(&ptgt->tgt_mutex);
6920 			mutex_exit(&pptr->port_mutex);
6921 			fcp_print_error(fpkt);
6922 		} else {
6923 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6924 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6925 			    "fcp_scsi_callback,1: state change occured"
6926 			    " for D_ID=0x%x", ptgt->tgt_d_id);
6927 			mutex_exit(&ptgt->tgt_mutex);
6928 			mutex_exit(&pptr->port_mutex);
6929 		}
6930 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6931 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6932 		fcp_icmd_free(pptr, icmd);
6933 		return;
6934 	}
6935 
6936 	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
6937 
6938 	mutex_enter(&pptr->port_mutex);
6939 	mutex_enter(&ptgt->tgt_mutex);
6940 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6941 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6942 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6943 		    "fcp_scsi_callback,2: state change occured"
6944 		    " for D_ID=0x%x", ptgt->tgt_d_id);
6945 		mutex_exit(&ptgt->tgt_mutex);
6946 		mutex_exit(&pptr->port_mutex);
6947 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6948 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6949 		fcp_icmd_free(pptr, icmd);
6950 		return;
6951 	}
6952 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
6953 
6954 	mutex_exit(&ptgt->tgt_mutex);
6955 	mutex_exit(&pptr->port_mutex);
6956 
6957 	if (icmd->ipkt_nodma) {
6958 		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
6959 		    sizeof (struct fcp_rsp));
6960 	} else {
6961 		bep = &fcp_rsp_err;
6962 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
6963 		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
6964 	}
6965 
6966 	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
6967 		fcp_retry_scsi_cmd(fpkt);
6968 		return;
6969 	}
6970 
6971 	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
6972 	    FCP_NO_FAILURE) {
6973 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6974 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6975 		    "rsp_code=0x%x, rsp_len_set=0x%x",
6976 		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
6977 		fcp_retry_scsi_cmd(fpkt);
6978 		return;
6979 	}
6980 
6981 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
6982 	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
6983 		fcp_queue_ipkt(pptr, fpkt);
6984 		return;
6985 	}
6986 
6987 	/*
6988 	 * Devices that do not support INQUIRY_PAGE83, return check condition
6989 	 * with illegal request as per SCSI spec.
6990 	 * Crossbridge is one such device and Daktari's SES node is another.
6991 	 * We want to ideally enumerate these devices as a non-mpxio devices.
6992 	 * SES nodes (Daktari only currently) are an exception to this.
6993 	 */
6994 	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6995 	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
6996 
6997 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6998 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
6999 		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7000 		    "check condition. May enumerate as non-mpxio device",
7001 		    ptgt->tgt_d_id, plun->lun_type);
7002 
7003 		/*
7004 		 * If we let Daktari's SES be enumerated as a non-mpxio
7005 		 * device, there will be a discrepency in that the other
7006 		 * internal FC disks will get enumerated as mpxio devices.
7007 		 * Applications like luxadm expect this to be consistent.
7008 		 *
7009 		 * So, we put in a hack here to check if this is an SES device
7010 		 * and handle it here.
7011 		 */
7012 		if (plun->lun_type == DTYPE_ESI) {
7013 			/*
7014 			 * Since, pkt_state is actually FC_PKT_SUCCESS
7015 			 * at this stage, we fake a failure here so that
7016 			 * fcp_handle_page83 will create a device path using
7017 			 * the WWN instead of the GUID which is not there anyway
7018 			 */
7019 			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7020 			(void) fcp_handle_page83(fpkt, icmd, 1);
7021 			return;
7022 		}
7023 
7024 		mutex_enter(&ptgt->tgt_mutex);
7025 		plun->lun_state &= ~(FCP_LUN_OFFLINE |
7026 		    FCP_LUN_MARK | FCP_LUN_BUSY);
7027 		mutex_exit(&ptgt->tgt_mutex);
7028 
7029 		(void) fcp_call_finish_init(pptr, ptgt,
7030 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7031 		    icmd->ipkt_cause);
7032 		fcp_icmd_free(pptr, icmd);
7033 		return;
7034 	}
7035 
7036 	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7037 		int rval = DDI_FAILURE;
7038 
7039 		/*
7040 		 * handle cases where report lun isn't supported
7041 		 * by faking up our own REPORT_LUN response or
7042 		 * UNIT ATTENTION
7043 		 */
7044 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7045 			rval = fcp_check_reportlun(rsp, fpkt);
7046 
7047 			/*
7048 			 * fcp_check_reportlun might have modified the
7049 			 * FCP response. Copy it in again to get an updated
7050 			 * FCP response
7051 			 */
7052 			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7053 				rsp = &response;
7054 
7055 				FCP_CP_IN(fpkt->pkt_resp, rsp,
7056 				    fpkt->pkt_resp_acc,
7057 				    sizeof (struct fcp_rsp));
7058 			}
7059 		}
7060 
7061 		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7062 			if (rval == DDI_SUCCESS) {
7063 				(void) fcp_call_finish_init(pptr, ptgt,
7064 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7065 				    icmd->ipkt_cause);
7066 				fcp_icmd_free(pptr, icmd);
7067 			} else {
7068 				fcp_retry_scsi_cmd(fpkt);
7069 			}
7070 
7071 			return;
7072 		}
7073 	} else {
7074 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7075 			mutex_enter(&ptgt->tgt_mutex);
7076 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7077 			mutex_exit(&ptgt->tgt_mutex);
7078 		}
7079 	}
7080 
7081 	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7082 
7083 	(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, DDI_DMA_SYNC_FORCPU);
7084 
7085 	switch (icmd->ipkt_opcode) {
7086 	case SCMD_INQUIRY:
7087 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7088 		fcp_handle_inquiry(fpkt, icmd);
7089 		break;
7090 
7091 	case SCMD_REPORT_LUN:
7092 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7093 		    FCP_TGT_TRACE_22);
7094 		fcp_handle_reportlun(fpkt, icmd);
7095 		break;
7096 
7097 	case SCMD_INQUIRY_PAGE83:
7098 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7099 		(void) fcp_handle_page83(fpkt, icmd, 0);
7100 		break;
7101 
7102 	default:
7103 		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7104 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7105 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7106 		fcp_icmd_free(pptr, icmd);
7107 		break;
7108 	}
7109 }
7110 
7111 
7112 static void
7113 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7114 {
7115 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
7116 	    fpkt->pkt_ulp_private;
7117 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
7118 	struct fcp_port	*pptr = ptgt->tgt_port;
7119 
7120 	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7121 	    fcp_is_retryable(icmd)) {
7122 		mutex_enter(&pptr->port_mutex);
7123 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7124 			mutex_exit(&pptr->port_mutex);
7125 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7126 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7127 			    "Retrying %s to %x; state=%x, reason=%x",
7128 			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7129 			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7130 			    fpkt->pkt_state, fpkt->pkt_reason);
7131 
7132 			fcp_queue_ipkt(pptr, fpkt);
7133 		} else {
7134 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7135 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7136 			    "fcp_retry_scsi_cmd,1: state change occured"
7137 			    " for D_ID=0x%x", ptgt->tgt_d_id);
7138 			mutex_exit(&pptr->port_mutex);
7139 			(void) fcp_call_finish_init(pptr, ptgt,
7140 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7141 			    icmd->ipkt_cause);
7142 			fcp_icmd_free(pptr, icmd);
7143 		}
7144 	} else {
7145 		fcp_print_error(fpkt);
7146 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7147 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7148 		fcp_icmd_free(pptr, icmd);
7149 	}
7150 }
7151 
7152 /*
7153  *     Function: fcp_handle_page83
7154  *
7155  *  Description: Treats the response to INQUIRY_PAGE83.
7156  *
7157  *     Argument: *fpkt	FC packet used to convey the command.
7158  *		 *icmd	Original fcp_ipkt structure.
7159  *		 ignore_page83_data
7160  *			if it's 1, that means it's a special devices's
7161  *			page83 response, it should be enumerated under mpxio
7162  *
7163  * Return Value: None
7164  */
7165 static void
7166 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7167     int ignore_page83_data)
7168 {
7169 	struct fcp_port	*pptr;
7170 	struct fcp_lun	*plun;
7171 	struct fcp_tgt	*ptgt;
7172 	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7173 	int			fail = 0;
7174 	ddi_devid_t		devid;
7175 	char			*guid = NULL;
7176 	int			ret;
7177 
7178 	ASSERT(icmd != NULL && fpkt != NULL);
7179 
7180 	pptr = icmd->ipkt_port;
7181 	ptgt = icmd->ipkt_tgt;
7182 	plun = icmd->ipkt_lun;
7183 
7184 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7185 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7186 
7187 		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7188 		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
7189 
7190 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7191 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7192 		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7193 		    "dtype=0x%x, lun num=%x",
7194 		    pptr->port_instance, ptgt->tgt_d_id,
7195 		    dev_id_page[0], plun->lun_num);
7196 
7197 		ret = ddi_devid_scsi_encode(
7198 		    DEVID_SCSI_ENCODE_VERSION_LATEST,
7199 		    NULL,		/* driver name */
7200 		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
7201 		    sizeof (plun->lun_inq), /* size of standard inquiry */
7202 		    NULL,		/* page 80 data */
7203 		    0,		/* page 80 len */
7204 		    dev_id_page,	/* page 83 data */
7205 		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7206 		    &devid);
7207 
7208 		if (ret == DDI_SUCCESS) {
7209 
7210 			guid = ddi_devid_to_guid(devid);
7211 
7212 			if (guid) {
7213 				/*
7214 				 * Check our current guid.  If it's non null
7215 				 * and it has changed, we need to copy it into
7216 				 * lun_old_guid since we might still need it.
7217 				 */
7218 				if (plun->lun_guid &&
7219 				    strcmp(guid, plun->lun_guid)) {
7220 					unsigned int len;
7221 
7222 					/*
7223 					 * If the guid of the LUN changes,
7224 					 * reconfiguration should be triggered
7225 					 * to reflect the changes.
7226 					 * i.e. we should offline the LUN with
7227 					 * the old guid, and online the LUN with
7228 					 * the new guid.
7229 					 */
7230 					plun->lun_state |= FCP_LUN_CHANGED;
7231 
7232 					if (plun->lun_old_guid) {
7233 						kmem_free(plun->lun_old_guid,
7234 						    plun->lun_old_guid_size);
7235 					}
7236 
7237 					len = plun->lun_guid_size;
7238 					plun->lun_old_guid_size = len;
7239 
7240 					plun->lun_old_guid = kmem_zalloc(len,
7241 					    KM_NOSLEEP);
7242 
7243 					if (plun->lun_old_guid) {
7244 						/*
7245 						 * The alloc was successful then
7246 						 * let's do the copy.
7247 						 */
7248 						bcopy(plun->lun_guid,
7249 						    plun->lun_old_guid, len);
7250 					} else {
7251 						fail = 1;
7252 						plun->lun_old_guid_size = 0;
7253 					}
7254 				}
7255 				if (!fail) {
7256 					if (fcp_copy_guid_2_lun_block(
7257 					    plun, guid)) {
7258 						fail = 1;
7259 					}
7260 				}
7261 				ddi_devid_free_guid(guid);
7262 
7263 			} else {
7264 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7265 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
7266 				    "fcp_handle_page83: unable to create "
7267 				    "GUID");
7268 
7269 				/* couldn't create good guid from devid */
7270 				fail = 1;
7271 			}
7272 			ddi_devid_free(devid);
7273 
7274 		} else if (ret == DDI_NOT_WELL_FORMED) {
7275 			/* NULL filled data for page 83 */
7276 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7277 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7278 			    "fcp_handle_page83: retry GUID");
7279 
7280 			icmd->ipkt_retries = 0;
7281 			fcp_retry_scsi_cmd(fpkt);
7282 			return;
7283 		} else {
7284 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7285 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7286 			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7287 			    ret);
7288 			/*
7289 			 * Since the page83 validation
7290 			 * introduced late, we are being
7291 			 * tolerant to the existing devices
7292 			 * that already found to be working
7293 			 * under mpxio, like A5200's SES device,
7294 			 * its page83 response will not be standard-compliant,
7295 			 * but we still want it to be enumerated under mpxio.
7296 			 */
7297 			if (fcp_symmetric_device_probe(plun) != 0) {
7298 				fail = 1;
7299 			}
7300 		}
7301 
7302 	} else {
7303 		/* bad packet state */
7304 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7305 
7306 		/*
7307 		 * For some special devices (A5K SES and Daktari's SES devices),
7308 		 * they should be enumerated under mpxio
7309 		 * or "luxadm dis" will fail
7310 		 */
7311 		if (ignore_page83_data) {
7312 			fail = 0;
7313 		} else {
7314 			fail = 1;
7315 		}
7316 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7317 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7318 		    "!Devid page cmd failed. "
7319 		    "fpkt_state: %x fpkt_reason: %x",
7320 		    "ignore_page83: %d",
7321 		    fpkt->pkt_state, fpkt->pkt_reason,
7322 		    ignore_page83_data);
7323 	}
7324 
7325 	mutex_enter(&pptr->port_mutex);
7326 	mutex_enter(&plun->lun_mutex);
7327 	/*
7328 	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7329 	 * mismatch between lun_cip and lun_mpxio.
7330 	 */
7331 	if (plun->lun_cip == NULL) {
7332 		/*
7333 		 * If we don't have a guid for this lun it's because we were
7334 		 * unable to glean one from the page 83 response.  Set the
7335 		 * control flag to 0 here to make sure that we don't attempt to
7336 		 * enumerate it under mpxio.
7337 		 */
7338 		if (fail || pptr->port_mpxio == 0) {
7339 			plun->lun_mpxio = 0;
7340 		} else {
7341 			plun->lun_mpxio = 1;
7342 		}
7343 	}
7344 	mutex_exit(&plun->lun_mutex);
7345 	mutex_exit(&pptr->port_mutex);
7346 
7347 	mutex_enter(&ptgt->tgt_mutex);
7348 	plun->lun_state &=
7349 	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7350 	mutex_exit(&ptgt->tgt_mutex);
7351 
7352 	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7353 	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7354 
7355 	fcp_icmd_free(pptr, icmd);
7356 }
7357 
7358 /*
7359  *     Function: fcp_handle_inquiry
7360  *
7361  *  Description: Called by fcp_scsi_callback to handle the response to an
7362  *		 INQUIRY request.
7363  *
7364  *     Argument: *fpkt	FC packet used to convey the command.
7365  *		 *icmd	Original fcp_ipkt structure.
7366  *
7367  * Return Value: None
7368  */
7369 static void
7370 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7371 {
7372 	struct fcp_port	*pptr;
7373 	struct fcp_lun	*plun;
7374 	struct fcp_tgt	*ptgt;
7375 	uchar_t		dtype;
7376 	uchar_t		pqual;
7377 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
7378 
7379 	ASSERT(icmd != NULL && fpkt != NULL);
7380 
7381 	pptr = icmd->ipkt_port;
7382 	ptgt = icmd->ipkt_tgt;
7383 	plun = icmd->ipkt_lun;
7384 
7385 	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7386 	    sizeof (struct scsi_inquiry));
7387 
7388 	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7389 	pqual = plun->lun_inq.inq_dtype >> 5;
7390 
7391 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7392 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7393 	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7394 	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7395 	    plun->lun_num, dtype, pqual);
7396 
7397 	if (pqual != 0) {
7398 		/*
7399 		 * Non-zero peripheral qualifier
7400 		 */
7401 		fcp_log(CE_CONT, pptr->port_dip,
7402 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7403 		    "Device type=0x%x Peripheral qual=0x%x\n",
7404 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7405 
7406 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7407 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7408 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7409 		    "Device type=0x%x Peripheral qual=0x%x\n",
7410 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7411 
7412 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7413 
7414 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7415 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7416 		fcp_icmd_free(pptr, icmd);
7417 		return;
7418 	}
7419 
7420 	/*
7421 	 * If the device is already initialized, check the dtype
7422 	 * for a change. If it has changed then update the flags
7423 	 * so the create_luns will offline the old device and
7424 	 * create the new device. Refer to bug: 4764752
7425 	 */
7426 	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7427 		plun->lun_state |= FCP_LUN_CHANGED;
7428 	}
7429 	plun->lun_type = plun->lun_inq.inq_dtype;
7430 
7431 	/*
7432 	 * This code is setting/initializing the throttling in the FCA
7433 	 * driver.
7434 	 */
7435 	mutex_enter(&pptr->port_mutex);
7436 	if (!pptr->port_notify) {
7437 		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7438 			uint32_t cmd = 0;
7439 			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7440 			    ((cmd & 0xFFFFFF00 >> 8) |
7441 			    FCP_SVE_THROTTLE << 8));
7442 			pptr->port_notify = 1;
7443 			mutex_exit(&pptr->port_mutex);
7444 			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7445 			mutex_enter(&pptr->port_mutex);
7446 		}
7447 	}
7448 
7449 	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7450 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7451 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7452 		    "fcp_handle_inquiry,1:state change occured"
7453 		    " for D_ID=0x%x", ptgt->tgt_d_id);
7454 		mutex_exit(&pptr->port_mutex);
7455 
7456 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7457 		(void) fcp_call_finish_init(pptr, ptgt,
7458 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7459 		    icmd->ipkt_cause);
7460 		fcp_icmd_free(pptr, icmd);
7461 		return;
7462 	}
7463 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7464 	mutex_exit(&pptr->port_mutex);
7465 
7466 	/* Retrieve the rscn count (if a valid one exists) */
7467 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7468 		rscn_count = ((fc_ulp_rscn_info_t *)
7469 		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7470 	} else {
7471 		rscn_count = FC_INVALID_RSCN_COUNT;
7472 	}
7473 
7474 	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7475 	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
7476 	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7477 	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7478 		fcp_log(CE_WARN, NULL, "!failed to send page 83");
7479 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7480 		(void) fcp_call_finish_init(pptr, ptgt,
7481 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7482 		    icmd->ipkt_cause);
7483 	}
7484 
7485 	/*
7486 	 * Read Inquiry VPD Page 0x83 to uniquely
7487 	 * identify this logical unit.
7488 	 */
7489 	fcp_icmd_free(pptr, icmd);
7490 }
7491 
7492 /*
7493  *     Function: fcp_handle_reportlun
7494  *
7495  *  Description: Called by fcp_scsi_callback to handle the response to a
7496  *		 REPORT_LUN request.
7497  *
7498  *     Argument: *fpkt	FC packet used to convey the command.
7499  *		 *icmd	Original fcp_ipkt structure.
7500  *
7501  * Return Value: None
7502  */
7503 static void
7504 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7505 {
7506 	int				i;
7507 	int				nluns_claimed;
7508 	int				nluns_bufmax;
7509 	int				len;
7510 	uint16_t			lun_num;
7511 	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
7512 	struct fcp_port			*pptr;
7513 	struct fcp_tgt			*ptgt;
7514 	struct fcp_lun			*plun;
7515 	struct fcp_reportlun_resp	*report_lun;
7516 
7517 	pptr = icmd->ipkt_port;
7518 	ptgt = icmd->ipkt_tgt;
7519 	len = fpkt->pkt_datalen;
7520 
7521 	if ((len < FCP_LUN_HEADER) ||
7522 	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7523 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7524 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7525 		fcp_icmd_free(pptr, icmd);
7526 		return;
7527 	}
7528 
7529 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7530 	    fpkt->pkt_datalen);
7531 
7532 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7533 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7534 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7535 	    pptr->port_instance, ptgt->tgt_d_id);
7536 
7537 	/*
7538 	 * Get the number of luns (which is supplied as LUNS * 8) the
7539 	 * device claims it has.
7540 	 */
7541 	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7542 
7543 	/*
7544 	 * Get the maximum number of luns the buffer submitted can hold.
7545 	 */
7546 	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7547 
7548 	/*
7549 	 * Due to limitations of certain hardware, we support only 16 bit LUNs
7550 	 */
7551 	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7552 		kmem_free(report_lun, len);
7553 
7554 		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7555 		    " 0x%x number of LUNs for target=%x", nluns_claimed,
7556 		    ptgt->tgt_d_id);
7557 
7558 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7559 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7560 		fcp_icmd_free(pptr, icmd);
7561 		return;
7562 	}
7563 
7564 	/*
7565 	 * If there are more LUNs than we have allocated memory for,
7566 	 * allocate more space and send down yet another report lun if
7567 	 * the maximum number of attempts hasn't been reached.
7568 	 */
7569 	mutex_enter(&ptgt->tgt_mutex);
7570 
7571 	if ((nluns_claimed > nluns_bufmax) &&
7572 	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7573 
7574 		struct fcp_lun *plun;
7575 
7576 		ptgt->tgt_report_lun_cnt++;
7577 		plun = ptgt->tgt_lun;
7578 		ASSERT(plun != NULL);
7579 		mutex_exit(&ptgt->tgt_mutex);
7580 
7581 		kmem_free(report_lun, len);
7582 
7583 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7584 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7585 		    "!Dynamically discovered %d LUNs for D_ID=%x",
7586 		    nluns_claimed, ptgt->tgt_d_id);
7587 
7588 		/* Retrieve the rscn count (if a valid one exists) */
7589 		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7590 			rscn_count = ((fc_ulp_rscn_info_t *)
7591 			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7592 			    ulp_rscn_count;
7593 		} else {
7594 			rscn_count = FC_INVALID_RSCN_COUNT;
7595 		}
7596 
7597 		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7598 		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7599 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7600 		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7601 			(void) fcp_call_finish_init(pptr, ptgt,
7602 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7603 			    icmd->ipkt_cause);
7604 		}
7605 
7606 		fcp_icmd_free(pptr, icmd);
7607 		return;
7608 	}
7609 
7610 	if (nluns_claimed > nluns_bufmax) {
7611 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7612 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7613 		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7614 		    "	 Number of LUNs lost=%x",
7615 		    ptgt->tgt_port_wwn.raw_wwn[0],
7616 		    ptgt->tgt_port_wwn.raw_wwn[1],
7617 		    ptgt->tgt_port_wwn.raw_wwn[2],
7618 		    ptgt->tgt_port_wwn.raw_wwn[3],
7619 		    ptgt->tgt_port_wwn.raw_wwn[4],
7620 		    ptgt->tgt_port_wwn.raw_wwn[5],
7621 		    ptgt->tgt_port_wwn.raw_wwn[6],
7622 		    ptgt->tgt_port_wwn.raw_wwn[7],
7623 		    nluns_claimed - nluns_bufmax);
7624 
7625 		nluns_claimed = nluns_bufmax;
7626 	}
7627 	ptgt->tgt_lun_cnt = nluns_claimed;
7628 
7629 	/*
7630 	 * Identify missing LUNs and print warning messages
7631 	 */
7632 	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7633 		int offline;
7634 		int exists = 0;
7635 
7636 		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7637 
7638 		for (i = 0; i < nluns_claimed && exists == 0; i++) {
7639 			uchar_t		*lun_string;
7640 
7641 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7642 
7643 			switch (lun_string[0] & 0xC0) {
7644 			case FCP_LUN_ADDRESSING:
7645 			case FCP_PD_ADDRESSING:
7646 			case FCP_VOLUME_ADDRESSING:
7647 				lun_num = ((lun_string[0] & 0x3F) << 8) |
7648 				    lun_string[1];
7649 				if (plun->lun_num == lun_num) {
7650 					exists++;
7651 					break;
7652 				}
7653 				break;
7654 
7655 			default:
7656 				break;
7657 			}
7658 		}
7659 
7660 		if (!exists && !offline) {
7661 			mutex_exit(&ptgt->tgt_mutex);
7662 
7663 			mutex_enter(&pptr->port_mutex);
7664 			mutex_enter(&ptgt->tgt_mutex);
7665 			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7666 				/*
7667 				 * set disappear flag when device was connected
7668 				 */
7669 				if (!(plun->lun_state &
7670 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7671 					plun->lun_state |= FCP_LUN_DISAPPEARED;
7672 				}
7673 				mutex_exit(&ptgt->tgt_mutex);
7674 				mutex_exit(&pptr->port_mutex);
7675 				if (!(plun->lun_state &
7676 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7677 					fcp_log(CE_NOTE, pptr->port_dip,
7678 					    "!Lun=%x for target=%x disappeared",
7679 					    plun->lun_num, ptgt->tgt_d_id);
7680 				}
7681 				mutex_enter(&ptgt->tgt_mutex);
7682 			} else {
7683 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7684 				    fcp_trace, FCP_BUF_LEVEL_5, 0,
7685 				    "fcp_handle_reportlun,1: state change"
7686 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
7687 				mutex_exit(&ptgt->tgt_mutex);
7688 				mutex_exit(&pptr->port_mutex);
7689 				kmem_free(report_lun, len);
7690 				(void) fcp_call_finish_init(pptr, ptgt,
7691 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7692 				    icmd->ipkt_cause);
7693 				fcp_icmd_free(pptr, icmd);
7694 				return;
7695 			}
7696 		} else if (exists) {
7697 			/*
7698 			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7699 			 * actually exists in REPORT_LUN response
7700 			 */
7701 			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7702 				plun->lun_state &=
7703 				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
7704 			}
7705 			if (offline || plun->lun_num == 0) {
7706 				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7707 					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7708 					mutex_exit(&ptgt->tgt_mutex);
7709 					fcp_log(CE_NOTE, pptr->port_dip,
7710 					    "!Lun=%x for target=%x reappeared",
7711 					    plun->lun_num, ptgt->tgt_d_id);
7712 					mutex_enter(&ptgt->tgt_mutex);
7713 				}
7714 			}
7715 		}
7716 	}
7717 
7718 	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7719 	mutex_exit(&ptgt->tgt_mutex);
7720 
7721 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7722 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7723 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7724 	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7725 
7726 	/* scan each lun */
7727 	for (i = 0; i < nluns_claimed; i++) {
7728 		uchar_t	*lun_string;
7729 
7730 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7731 
7732 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7733 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7734 		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7735 		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7736 		    lun_string[0]);
7737 
7738 		switch (lun_string[0] & 0xC0) {
7739 		case FCP_LUN_ADDRESSING:
7740 		case FCP_PD_ADDRESSING:
7741 		case FCP_VOLUME_ADDRESSING:
7742 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7743 
7744 			/* We will skip masked LUNs because of the blacklist. */
7745 			if (fcp_lun_blacklist != NULL) {
7746 				mutex_enter(&ptgt->tgt_mutex);
7747 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
7748 				    lun_num) == TRUE) {
7749 					ptgt->tgt_lun_cnt--;
7750 					mutex_exit(&ptgt->tgt_mutex);
7751 					break;
7752 				}
7753 				mutex_exit(&ptgt->tgt_mutex);
7754 			}
7755 
7756 			/* see if this LUN is already allocated */
7757 			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7758 				plun = fcp_alloc_lun(ptgt);
7759 				if (plun == NULL) {
7760 					fcp_log(CE_NOTE, pptr->port_dip,
7761 					    "!Lun allocation failed"
7762 					    " target=%x lun=%x",
7763 					    ptgt->tgt_d_id, lun_num);
7764 					break;
7765 				}
7766 			}
7767 
7768 			mutex_enter(&plun->lun_tgt->tgt_mutex);
7769 			/* convert to LUN */
7770 			plun->lun_addr.ent_addr_0 =
7771 			    BE_16(*(uint16_t *)&(lun_string[0]));
7772 			plun->lun_addr.ent_addr_1 =
7773 			    BE_16(*(uint16_t *)&(lun_string[2]));
7774 			plun->lun_addr.ent_addr_2 =
7775 			    BE_16(*(uint16_t *)&(lun_string[4]));
7776 			plun->lun_addr.ent_addr_3 =
7777 			    BE_16(*(uint16_t *)&(lun_string[6]));
7778 
7779 			plun->lun_num = lun_num;
7780 			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7781 			plun->lun_state &= ~FCP_LUN_OFFLINE;
7782 			mutex_exit(&plun->lun_tgt->tgt_mutex);
7783 
7784 			/* Retrieve the rscn count (if a valid one exists) */
7785 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7786 				rscn_count = ((fc_ulp_rscn_info_t *)
7787 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7788 				    ulp_rscn_count;
7789 			} else {
7790 				rscn_count = FC_INVALID_RSCN_COUNT;
7791 			}
7792 
7793 			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7794 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7795 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7796 				mutex_enter(&pptr->port_mutex);
7797 				mutex_enter(&plun->lun_tgt->tgt_mutex);
7798 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7799 					fcp_log(CE_NOTE, pptr->port_dip,
7800 					    "!failed to send INQUIRY"
7801 					    " target=%x lun=%x",
7802 					    ptgt->tgt_d_id, plun->lun_num);
7803 				} else {
7804 					FCP_TRACE(fcp_logq,
7805 					    pptr->port_instbuf, fcp_trace,
7806 					    FCP_BUF_LEVEL_5, 0,
7807 					    "fcp_handle_reportlun,2: state"
7808 					    " change occured for D_ID=0x%x",
7809 					    ptgt->tgt_d_id);
7810 				}
7811 				mutex_exit(&plun->lun_tgt->tgt_mutex);
7812 				mutex_exit(&pptr->port_mutex);
7813 			} else {
7814 				continue;
7815 			}
7816 			break;
7817 
7818 		default:
7819 			fcp_log(CE_WARN, NULL,
7820 			    "!Unsupported LUN Addressing method %x "
7821 			    "in response to REPORT_LUN", lun_string[0]);
7822 			break;
7823 		}
7824 
7825 		/*
7826 		 * each time through this loop we should decrement
7827 		 * the tmp_cnt by one -- since we go through this loop
7828 		 * one time for each LUN, the tmp_cnt should never be <=0
7829 		 */
7830 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7831 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7832 	}
7833 
7834 	if (i == 0) {
7835 		fcp_log(CE_WARN, pptr->port_dip,
7836 		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7837 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7838 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7839 	}
7840 
7841 	kmem_free(report_lun, len);
7842 	fcp_icmd_free(pptr, icmd);
7843 }
7844 
7845 
7846 /*
7847  * called internally to return a LUN given a target and a LUN number
7848  */
7849 static struct fcp_lun *
7850 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7851 {
7852 	struct fcp_lun	*plun;
7853 
7854 	mutex_enter(&ptgt->tgt_mutex);
7855 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7856 		if (plun->lun_num == lun_num) {
7857 			mutex_exit(&ptgt->tgt_mutex);
7858 			return (plun);
7859 		}
7860 	}
7861 	mutex_exit(&ptgt->tgt_mutex);
7862 
7863 	return (NULL);
7864 }
7865 
7866 
7867 /*
7868  * handle finishing one target for fcp_finish_init
7869  *
7870  * return true (non-zero) if we want finish_init to continue with the
7871  * next target
7872  *
7873  * called with the port mutex held
7874  */
7875 /*ARGSUSED*/
7876 static int
7877 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7878     int link_cnt, int tgt_cnt, int cause)
7879 {
7880 	int	rval = 1;
7881 	ASSERT(pptr != NULL);
7882 	ASSERT(ptgt != NULL);
7883 
7884 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7885 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7886 	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7887 	    ptgt->tgt_state);
7888 
7889 	ASSERT(mutex_owned(&pptr->port_mutex));
7890 
7891 	if ((pptr->port_link_cnt != link_cnt) ||
7892 	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7893 		/*
7894 		 * oh oh -- another link reset or target change
7895 		 * must have occurred while we are in here
7896 		 */
7897 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7898 
7899 		return (0);
7900 	} else {
7901 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7902 	}
7903 
7904 	mutex_enter(&ptgt->tgt_mutex);
7905 
7906 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7907 		/*
7908 		 * tgt is not offline -- is it marked (i.e. needs
7909 		 * to be offlined) ??
7910 		 */
7911 		if (ptgt->tgt_state & FCP_TGT_MARK) {
7912 			/*
7913 			 * this target not offline *and*
7914 			 * marked
7915 			 */
7916 			ptgt->tgt_state &= ~FCP_TGT_MARK;
7917 			rval = fcp_offline_target(pptr, ptgt, link_cnt,
7918 			    tgt_cnt, 0, 0);
7919 		} else {
7920 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
7921 
7922 			/* create the LUNs */
7923 			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7924 				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7925 				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7926 				    cause);
7927 				ptgt->tgt_device_created = 1;
7928 			} else {
7929 				fcp_update_tgt_state(ptgt, FCP_RESET,
7930 				    FCP_LUN_BUSY);
7931 			}
7932 		}
7933 	}
7934 
7935 	mutex_exit(&ptgt->tgt_mutex);
7936 
7937 	return (rval);
7938 }
7939 
7940 
7941 /*
7942  * this routine is called to finish port initialization
7943  *
7944  * Each port has a "temp" counter -- when a state change happens (e.g.
7945  * port online), the temp count is set to the number of devices in the map.
7946  * Then, as each device gets "discovered", the temp counter is decremented
7947  * by one.  When this count reaches zero we know that all of the devices
7948  * in the map have been discovered (or an error has occurred), so we can
7949  * then finish initialization -- which is done by this routine (well, this
7950  * and fcp-finish_tgt())
7951  *
7952  * acquires and releases the global mutex
7953  *
7954  * called with the port mutex owned
7955  */
7956 static void
7957 fcp_finish_init(struct fcp_port *pptr)
7958 {
7959 #ifdef	DEBUG
7960 	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
7961 	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
7962 	    FCP_STACK_DEPTH);
7963 #endif /* DEBUG */
7964 
7965 	ASSERT(mutex_owned(&pptr->port_mutex));
7966 
7967 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7968 	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
7969 	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
7970 
7971 	if ((pptr->port_state & FCP_STATE_ONLINING) &&
7972 	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
7973 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
7974 		pptr->port_state &= ~FCP_STATE_ONLINING;
7975 		pptr->port_state |= FCP_STATE_ONLINE;
7976 	}
7977 
7978 	/* Wake up threads waiting on config done */
7979 	cv_broadcast(&pptr->port_config_cv);
7980 }
7981 
7982 
7983 /*
7984  * called from fcp_finish_init to create the LUNs for a target
7985  *
7986  * called with the port mutex owned
7987  */
7988 static void
7989 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
7990 {
7991 	struct fcp_lun	*plun;
7992 	struct fcp_port	*pptr;
7993 	child_info_t		*cip = NULL;
7994 
7995 	ASSERT(ptgt != NULL);
7996 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
7997 
7998 	pptr = ptgt->tgt_port;
7999 
8000 	ASSERT(pptr != NULL);
8001 
8002 	/* scan all LUNs for this target */
8003 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8004 		if (plun->lun_state & FCP_LUN_OFFLINE) {
8005 			continue;
8006 		}
8007 
8008 		if (plun->lun_state & FCP_LUN_MARK) {
8009 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8010 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8011 			    "fcp_create_luns: offlining marked LUN!");
8012 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8013 			continue;
8014 		}
8015 
8016 		plun->lun_state &= ~FCP_LUN_BUSY;
8017 
8018 		/*
8019 		 * There are conditions in which FCP_LUN_INIT flag is cleared
8020 		 * but we have a valid plun->lun_cip. To cover this case also
8021 		 * CLEAR_BUSY whenever we have a valid lun_cip.
8022 		 */
8023 		if (plun->lun_mpxio && plun->lun_cip &&
8024 		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8025 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8026 		    0, 0))) {
8027 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8028 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8029 			    "fcp_create_luns: enable lun %p failed!",
8030 			    plun);
8031 		}
8032 
8033 		if (plun->lun_state & FCP_LUN_INIT &&
8034 		    !(plun->lun_state & FCP_LUN_CHANGED)) {
8035 			continue;
8036 		}
8037 
8038 		if (cause == FCP_CAUSE_USER_CREATE) {
8039 			continue;
8040 		}
8041 
8042 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
8043 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
8044 		    "create_luns: passing ONLINE elem to HP thread");
8045 
8046 		/*
8047 		 * If lun has changed, prepare for offlining the old path.
8048 		 * Do not offline the old path right now, since it may be
8049 		 * still opened.
8050 		 */
8051 		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8052 			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8053 		}
8054 
8055 		/* pass an ONLINE element to the hotplug thread */
8056 		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8057 		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8058 
8059 			/*
8060 			 * We can not synchronous attach (i.e pass
8061 			 * NDI_ONLINE_ATTACH) here as we might be
8062 			 * coming from an interrupt or callback
8063 			 * thread.
8064 			 */
8065 			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8066 			    link_cnt, tgt_cnt, 0, 0)) {
8067 				fcp_log(CE_CONT, pptr->port_dip,
8068 				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8069 				    plun->lun_tgt->tgt_d_id, plun->lun_num);
8070 			}
8071 		}
8072 	}
8073 }
8074 
8075 
8076 /*
8077  * function to online/offline devices
8078  */
8079 static int
8080 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8081     int online, int lcount, int tcount, int flags)
8082 {
8083 	int			rval = NDI_FAILURE;
8084 	int			circ;
8085 	child_info_t		*ccip;
8086 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
8087 	int			is_mpxio = pptr->port_mpxio;
8088 	dev_info_t		*cdip, *pdip;
8089 	char			*devname;
8090 
8091 	if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8092 		/*
8093 		 * When this event gets serviced, lun_cip and lun_mpxio
8094 		 * has changed, so it should be invalidated now.
8095 		 */
8096 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8097 		    FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8098 		    "plun: %p, cip: %p, what:%d", plun, cip, online);
8099 		return (rval);
8100 	}
8101 
8102 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8103 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
8104 	    "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8105 	    "flags=%x mpxio=%x\n",
8106 	    plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8107 	    plun->lun_mpxio);
8108 
8109 	/*
8110 	 * lun_mpxio needs checking here because we can end up in a race
8111 	 * condition where this task has been dispatched while lun_mpxio is
8112 	 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8113 	 * enable MPXIO for the LUN, but was unable to, and hence cleared
8114 	 * the flag. We rely on the serialization of the tasks here. We return
8115 	 * NDI_SUCCESS so any callers continue without reporting spurious
8116 	 * errors, and the still think we're an MPXIO LUN.
8117 	 */
8118 
8119 	if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8120 	    online == FCP_MPXIO_PATH_SET_BUSY) {
8121 		if (plun->lun_mpxio) {
8122 			rval = fcp_update_mpxio_path(plun, cip, online);
8123 		} else {
8124 			rval = NDI_SUCCESS;
8125 		}
8126 		return (rval);
8127 	}
8128 
8129 	/*
8130 	 * Explicit devfs_clean() due to ndi_devi_offline() not
8131 	 * executing devfs_clean() if parent lock is held.
8132 	 */
8133 	ASSERT(!servicing_interrupt());
8134 	if (online == FCP_OFFLINE) {
8135 		if (plun->lun_mpxio == 0) {
8136 			if (plun->lun_cip == cip) {
8137 				cdip = DIP(plun->lun_cip);
8138 			} else {
8139 				cdip = DIP(cip);
8140 			}
8141 		} else if ((plun->lun_cip == cip) && plun->lun_cip) {
8142 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8143 		} else if ((plun->lun_cip != cip) && cip) {
8144 			/*
8145 			 * This means a DTYPE/GUID change, we shall get the
8146 			 * dip of the old cip instead of the current lun_cip.
8147 			 */
8148 			cdip = mdi_pi_get_client(PIP(cip));
8149 		}
8150 		if (cdip) {
8151 			if (i_ddi_devi_attached(cdip)) {
8152 				pdip = ddi_get_parent(cdip);
8153 				devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8154 				ndi_devi_enter(pdip, &circ);
8155 				(void) ddi_deviname(cdip, devname);
8156 				ndi_devi_exit(pdip, circ);
8157 				/*
8158 				 * Release parent lock before calling
8159 				 * devfs_clean().
8160 				 */
8161 				rval = devfs_clean(pdip, devname + 1,
8162 				    DV_CLEAN_FORCE);
8163 				kmem_free(devname, MAXNAMELEN + 1);
8164 				/*
8165 				 * Return if devfs_clean() fails for
8166 				 * non-MPXIO case.
8167 				 * For MPXIO case, another path could be
8168 				 * offlined.
8169 				 */
8170 				if (rval && plun->lun_mpxio == 0) {
8171 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8172 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8173 					    "fcp_trigger_lun: devfs_clean "
8174 					    "failed rval=%x  dip=%p",
8175 					    rval, pdip);
8176 					return (NDI_FAILURE);
8177 				}
8178 			}
8179 		}
8180 	}
8181 
8182 	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8183 		return (NDI_FAILURE);
8184 	}
8185 
8186 	if (is_mpxio) {
8187 		mdi_devi_enter(pptr->port_dip, &circ);
8188 	} else {
8189 		ndi_devi_enter(pptr->port_dip, &circ);
8190 	}
8191 
8192 	mutex_enter(&pptr->port_mutex);
8193 	mutex_enter(&plun->lun_mutex);
8194 
8195 	if (online == FCP_ONLINE) {
8196 		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8197 		if (ccip == NULL) {
8198 			goto fail;
8199 		}
8200 	} else {
8201 		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8202 			goto fail;
8203 		}
8204 		ccip = cip;
8205 	}
8206 
8207 	if (online == FCP_ONLINE) {
8208 		rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8209 		    &circ);
8210 		fc_ulp_log_device_event(pptr->port_fp_handle,
8211 		    FC_ULP_DEVICE_ONLINE);
8212 	} else {
8213 		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8214 		    &circ);
8215 		fc_ulp_log_device_event(pptr->port_fp_handle,
8216 		    FC_ULP_DEVICE_OFFLINE);
8217 	}
8218 
8219 fail:	mutex_exit(&plun->lun_mutex);
8220 	mutex_exit(&pptr->port_mutex);
8221 
8222 	if (is_mpxio) {
8223 		mdi_devi_exit(pptr->port_dip, circ);
8224 	} else {
8225 		ndi_devi_exit(pptr->port_dip, circ);
8226 	}
8227 
8228 	fc_ulp_idle_port(pptr->port_fp_handle);
8229 
8230 	return (rval);
8231 }
8232 
8233 
8234 /*
8235  * take a target offline by taking all of its LUNs offline
8236  */
8237 /*ARGSUSED*/
8238 static int
8239 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8240     int link_cnt, int tgt_cnt, int nowait, int flags)
8241 {
8242 	struct fcp_tgt_elem	*elem;
8243 
8244 	ASSERT(mutex_owned(&pptr->port_mutex));
8245 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8246 
8247 	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8248 
8249 	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8250 	    ptgt->tgt_change_cnt)) {
8251 		mutex_exit(&ptgt->tgt_mutex);
8252 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8253 		mutex_enter(&ptgt->tgt_mutex);
8254 
8255 		return (0);
8256 	}
8257 
8258 	ptgt->tgt_pd_handle = NULL;
8259 	mutex_exit(&ptgt->tgt_mutex);
8260 	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8261 	mutex_enter(&ptgt->tgt_mutex);
8262 
8263 	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8264 
8265 	if (ptgt->tgt_tcap &&
8266 	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8267 		elem->flags = flags;
8268 		elem->time = fcp_watchdog_time;
8269 		if (nowait == 0) {
8270 			elem->time += fcp_offline_delay;
8271 		}
8272 		elem->ptgt = ptgt;
8273 		elem->link_cnt = link_cnt;
8274 		elem->tgt_cnt = tgt_cnt;
8275 		elem->next = pptr->port_offline_tgts;
8276 		pptr->port_offline_tgts = elem;
8277 	} else {
8278 		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8279 	}
8280 
8281 	return (1);
8282 }
8283 
8284 
8285 static void
8286 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8287     int link_cnt, int tgt_cnt, int flags)
8288 {
8289 	ASSERT(mutex_owned(&pptr->port_mutex));
8290 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8291 
8292 	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8293 	ptgt->tgt_state = FCP_TGT_OFFLINE;
8294 	ptgt->tgt_pd_handle = NULL;
8295 	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8296 }
8297 
8298 
8299 static void
8300 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8301     int flags)
8302 {
8303 	struct	fcp_lun	*plun;
8304 
8305 	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8306 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8307 
8308 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8309 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8310 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8311 		}
8312 	}
8313 }
8314 
8315 
8316 /*
8317  * take a LUN offline
8318  *
8319  * enters and leaves with the target mutex held, releasing it in the process
8320  *
8321  * allocates memory in non-sleep mode
8322  */
8323 static void
8324 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8325     int nowait, int flags)
8326 {
8327 	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8328 	struct fcp_lun_elem	*elem;
8329 
8330 	ASSERT(plun != NULL);
8331 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8332 
8333 	if (nowait) {
8334 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8335 		return;
8336 	}
8337 
8338 	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8339 		elem->flags = flags;
8340 		elem->time = fcp_watchdog_time;
8341 		if (nowait == 0) {
8342 			elem->time += fcp_offline_delay;
8343 		}
8344 		elem->plun = plun;
8345 		elem->link_cnt = link_cnt;
8346 		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8347 		elem->next = pptr->port_offline_luns;
8348 		pptr->port_offline_luns = elem;
8349 	} else {
8350 		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8351 	}
8352 }
8353 
8354 
8355 static void
8356 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8357 {
8358 	struct fcp_pkt	*head = NULL;
8359 
8360 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8361 
8362 	mutex_exit(&LUN_TGT->tgt_mutex);
8363 
8364 	head = fcp_scan_commands(plun);
8365 	if (head != NULL) {
8366 		fcp_abort_commands(head, LUN_PORT);
8367 	}
8368 
8369 	mutex_enter(&LUN_TGT->tgt_mutex);
8370 
8371 	if (plun->lun_cip && plun->lun_mpxio) {
8372 		/*
8373 		 * Intimate MPxIO lun busy is cleared
8374 		 */
8375 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8376 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8377 		    0, 0)) {
8378 			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8379 			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8380 			    LUN_TGT->tgt_d_id, plun->lun_num);
8381 		}
8382 		/*
8383 		 * Intimate MPxIO that the lun is now marked for offline
8384 		 */
8385 		mutex_exit(&LUN_TGT->tgt_mutex);
8386 		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8387 		mutex_enter(&LUN_TGT->tgt_mutex);
8388 	}
8389 }
8390 
8391 static void
8392 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8393     int flags)
8394 {
8395 	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8396 
8397 	mutex_exit(&LUN_TGT->tgt_mutex);
8398 	fcp_update_offline_flags(plun);
8399 	mutex_enter(&LUN_TGT->tgt_mutex);
8400 
8401 	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8402 
8403 	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8404 	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8405 	    "offline_lun: passing OFFLINE elem to HP thread");
8406 
8407 	if (plun->lun_cip) {
8408 		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8409 		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8410 		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8411 		    LUN_TGT->tgt_trace);
8412 
8413 		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8414 		    link_cnt, tgt_cnt, flags, 0)) {
8415 			fcp_log(CE_CONT, LUN_PORT->port_dip,
8416 			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8417 			    LUN_TGT->tgt_d_id, plun->lun_num);
8418 		}
8419 	}
8420 }
8421 
8422 static void
8423 fcp_scan_offline_luns(struct fcp_port *pptr)
8424 {
8425 	struct fcp_lun_elem	*elem;
8426 	struct fcp_lun_elem	*prev;
8427 	struct fcp_lun_elem	*next;
8428 
8429 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8430 
8431 	prev = NULL;
8432 	elem = pptr->port_offline_luns;
8433 	while (elem) {
8434 		next = elem->next;
8435 		if (elem->time <= fcp_watchdog_time) {
8436 			int			changed = 1;
8437 			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8438 
8439 			mutex_enter(&ptgt->tgt_mutex);
8440 			if (pptr->port_link_cnt == elem->link_cnt &&
8441 			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8442 				changed = 0;
8443 			}
8444 
8445 			if (!changed &&
8446 			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8447 				fcp_offline_lun_now(elem->plun,
8448 				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8449 			}
8450 			mutex_exit(&ptgt->tgt_mutex);
8451 
8452 			kmem_free(elem, sizeof (*elem));
8453 
8454 			if (prev) {
8455 				prev->next = next;
8456 			} else {
8457 				pptr->port_offline_luns = next;
8458 			}
8459 		} else {
8460 			prev = elem;
8461 		}
8462 		elem = next;
8463 	}
8464 }
8465 
8466 
8467 static void
8468 fcp_scan_offline_tgts(struct fcp_port *pptr)
8469 {
8470 	struct fcp_tgt_elem	*elem;
8471 	struct fcp_tgt_elem	*prev;
8472 	struct fcp_tgt_elem	*next;
8473 
8474 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8475 
8476 	prev = NULL;
8477 	elem = pptr->port_offline_tgts;
8478 	while (elem) {
8479 		next = elem->next;
8480 		if (elem->time <= fcp_watchdog_time) {
8481 			int			changed = 1;
8482 			struct fcp_tgt	*ptgt = elem->ptgt;
8483 
8484 			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8485 				changed = 0;
8486 			}
8487 
8488 			mutex_enter(&ptgt->tgt_mutex);
8489 			if (!changed && !(ptgt->tgt_state &
8490 			    FCP_TGT_OFFLINE)) {
8491 				fcp_offline_target_now(pptr,
8492 				    ptgt, elem->link_cnt, elem->tgt_cnt,
8493 				    elem->flags);
8494 			}
8495 			mutex_exit(&ptgt->tgt_mutex);
8496 
8497 			kmem_free(elem, sizeof (*elem));
8498 
8499 			if (prev) {
8500 				prev->next = next;
8501 			} else {
8502 				pptr->port_offline_tgts = next;
8503 			}
8504 		} else {
8505 			prev = elem;
8506 		}
8507 		elem = next;
8508 	}
8509 }
8510 
8511 
8512 static void
8513 fcp_update_offline_flags(struct fcp_lun *plun)
8514 {
8515 	struct fcp_port	*pptr = LUN_PORT;
8516 	ASSERT(plun != NULL);
8517 
8518 	mutex_enter(&LUN_TGT->tgt_mutex);
8519 	plun->lun_state |= FCP_LUN_OFFLINE;
8520 	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8521 
8522 	mutex_enter(&plun->lun_mutex);
8523 	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8524 		dev_info_t *cdip = NULL;
8525 
8526 		mutex_exit(&LUN_TGT->tgt_mutex);
8527 
8528 		if (plun->lun_mpxio == 0) {
8529 			cdip = DIP(plun->lun_cip);
8530 		} else if (plun->lun_cip) {
8531 			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8532 		}
8533 
8534 		mutex_exit(&plun->lun_mutex);
8535 		if (cdip) {
8536 			(void) ndi_event_retrieve_cookie(
8537 			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8538 			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8539 			(void) ndi_event_run_callbacks(
8540 			    pptr->port_ndi_event_hdl, cdip,
8541 			    fcp_remove_eid, NULL);
8542 		}
8543 	} else {
8544 		mutex_exit(&plun->lun_mutex);
8545 		mutex_exit(&LUN_TGT->tgt_mutex);
8546 	}
8547 }
8548 
8549 
8550 /*
8551  * Scan all of the command pkts for this port, moving pkts that
8552  * match our LUN onto our own list (headed by "head")
8553  */
8554 static struct fcp_pkt *
8555 fcp_scan_commands(struct fcp_lun *plun)
8556 {
8557 	struct fcp_port	*pptr = LUN_PORT;
8558 
8559 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8560 	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8561 	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8562 
8563 	struct fcp_pkt	*head = NULL;	/* head of our list */
8564 	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8565 
8566 	int			cmds_found = 0;
8567 
8568 	mutex_enter(&pptr->port_pkt_mutex);
8569 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8570 		struct fcp_lun *tlun =
8571 		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8572 
8573 		ncmd = cmd->cmd_next;	/* set next command */
8574 
8575 		/*
8576 		 * if this pkt is for a different LUN  or the
8577 		 * command is sent down, skip it.
8578 		 */
8579 		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8580 		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8581 			pcmd = cmd;
8582 			continue;
8583 		}
8584 		cmds_found++;
8585 		if (pcmd != NULL) {
8586 			ASSERT(pptr->port_pkt_head != cmd);
8587 			pcmd->cmd_next = cmd->cmd_next;
8588 		} else {
8589 			ASSERT(cmd == pptr->port_pkt_head);
8590 			pptr->port_pkt_head = cmd->cmd_next;
8591 		}
8592 
8593 		if (cmd == pptr->port_pkt_tail) {
8594 			pptr->port_pkt_tail = pcmd;
8595 			if (pcmd) {
8596 				pcmd->cmd_next = NULL;
8597 			}
8598 		}
8599 
8600 		if (head == NULL) {
8601 			head = tail = cmd;
8602 		} else {
8603 			ASSERT(tail != NULL);
8604 
8605 			tail->cmd_next = cmd;
8606 			tail = cmd;
8607 		}
8608 		cmd->cmd_next = NULL;
8609 	}
8610 	mutex_exit(&pptr->port_pkt_mutex);
8611 
8612 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8613 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8614 	    "scan commands: %d cmd(s) found", cmds_found);
8615 
8616 	return (head);
8617 }
8618 
8619 
8620 /*
8621  * Abort all the commands in the command queue
8622  */
8623 static void
8624 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8625 {
8626 	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8627 	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8628 
8629 	ASSERT(mutex_owned(&pptr->port_mutex));
8630 
8631 	/* scan through the pkts and invalid them */
8632 	for (cmd = head; cmd != NULL; cmd = ncmd) {
8633 		struct scsi_pkt *pkt = cmd->cmd_pkt;
8634 
8635 		ncmd = cmd->cmd_next;
8636 		ASSERT(pkt != NULL);
8637 
8638 		/*
8639 		 * The lun is going to be marked offline. Indicate
8640 		 * the target driver not to requeue or retry this command
8641 		 * as the device is going to be offlined pretty soon.
8642 		 */
8643 		pkt->pkt_reason = CMD_DEV_GONE;
8644 		pkt->pkt_statistics = 0;
8645 		pkt->pkt_state = 0;
8646 
8647 		/* reset cmd flags/state */
8648 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8649 		cmd->cmd_state = FCP_PKT_IDLE;
8650 
8651 		/*
8652 		 * ensure we have a packet completion routine,
8653 		 * then call it.
8654 		 */
8655 		ASSERT(pkt->pkt_comp != NULL);
8656 
8657 		mutex_exit(&pptr->port_mutex);
8658 		fcp_post_callback(cmd);
8659 		mutex_enter(&pptr->port_mutex);
8660 	}
8661 }
8662 
8663 
8664 /*
8665  * the pkt_comp callback for command packets
8666  */
8667 static void
8668 fcp_cmd_callback(fc_packet_t *fpkt)
8669 {
8670 	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8671 	struct scsi_pkt *pkt = cmd->cmd_pkt;
8672 	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8673 
8674 	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8675 
8676 	if (cmd->cmd_state == FCP_PKT_IDLE) {
8677 		cmn_err(CE_PANIC, "Packet already completed %p",
8678 		    (void *)cmd);
8679 	}
8680 
8681 	/*
8682 	 * Watch thread should be freeing the packet, ignore the pkt.
8683 	 */
8684 	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8685 		fcp_log(CE_CONT, pptr->port_dip,
8686 		    "!FCP: Pkt completed while aborting\n");
8687 		return;
8688 	}
8689 	cmd->cmd_state = FCP_PKT_IDLE;
8690 
8691 	fcp_complete_pkt(fpkt);
8692 
8693 #ifdef	DEBUG
8694 	mutex_enter(&pptr->port_pkt_mutex);
8695 	pptr->port_npkts--;
8696 	mutex_exit(&pptr->port_pkt_mutex);
8697 #endif /* DEBUG */
8698 
8699 	fcp_post_callback(cmd);
8700 }
8701 
8702 
8703 static void
8704 fcp_complete_pkt(fc_packet_t *fpkt)
8705 {
8706 	int			error = 0;
8707 	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8708 	    fpkt->pkt_ulp_private;
8709 	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8710 	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8711 	struct fcp_lun	*plun;
8712 	struct fcp_tgt	*ptgt;
8713 	struct fcp_rsp		*rsp;
8714 	struct scsi_address	save;
8715 
8716 #ifdef	DEBUG
8717 	save = pkt->pkt_address;
8718 #endif /* DEBUG */
8719 
8720 	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8721 
8722 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8723 		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8724 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8725 			    sizeof (struct fcp_rsp));
8726 		}
8727 
8728 		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8729 		    STATE_SENT_CMD | STATE_GOT_STATUS;
8730 
8731 		pkt->pkt_resid = 0;
8732 
8733 		if (cmd->cmd_pkt->pkt_numcookies) {
8734 			pkt->pkt_state |= STATE_XFERRED_DATA;
8735 			if (fpkt->pkt_data_resid) {
8736 				error++;
8737 			}
8738 		}
8739 
8740 		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8741 		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8742 			/*
8743 			 * The next two checks make sure that if there
8744 			 * is no sense data or a valid response and
8745 			 * the command came back with check condition,
8746 			 * the command should be retried.
8747 			 */
8748 			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8749 			    !rsp->fcp_u.fcp_status.sense_len_set) {
8750 				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8751 				pkt->pkt_resid = cmd->cmd_dmacount;
8752 			}
8753 		}
8754 
8755 		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8756 			return;
8757 		}
8758 
8759 		plun = ADDR2LUN(&pkt->pkt_address);
8760 		ptgt = plun->lun_tgt;
8761 		ASSERT(ptgt != NULL);
8762 
8763 		/*
8764 		 * Update the transfer resid, if appropriate
8765 		 */
8766 		if (rsp->fcp_u.fcp_status.resid_over ||
8767 		    rsp->fcp_u.fcp_status.resid_under) {
8768 			pkt->pkt_resid = rsp->fcp_resid;
8769 		}
8770 
8771 		/*
8772 		 * First see if we got a FCP protocol error.
8773 		 */
8774 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8775 			struct fcp_rsp_info	*bep;
8776 			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8777 			    sizeof (struct fcp_rsp));
8778 
8779 			if (fcp_validate_fcp_response(rsp, pptr) !=
8780 			    FC_SUCCESS) {
8781 				pkt->pkt_reason = CMD_CMPLT;
8782 				*(pkt->pkt_scbp) = STATUS_CHECK;
8783 
8784 				fcp_log(CE_WARN, pptr->port_dip,
8785 				    "!SCSI command to d_id=0x%x lun=0x%x"
8786 				    " failed, Bad FCP response values:"
8787 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8788 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8789 				    ptgt->tgt_d_id, plun->lun_num,
8790 				    rsp->reserved_0, rsp->reserved_1,
8791 				    rsp->fcp_u.fcp_status.reserved_0,
8792 				    rsp->fcp_u.fcp_status.reserved_1,
8793 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8794 
8795 				return;
8796 			}
8797 
8798 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8799 				FCP_CP_IN(fpkt->pkt_resp +
8800 				    sizeof (struct fcp_rsp), bep,
8801 				    fpkt->pkt_resp_acc,
8802 				    sizeof (struct fcp_rsp_info));
8803 			}
8804 
8805 			if (bep->rsp_code != FCP_NO_FAILURE) {
8806 				child_info_t	*cip;
8807 
8808 				pkt->pkt_reason = CMD_TRAN_ERR;
8809 
8810 				mutex_enter(&plun->lun_mutex);
8811 				cip = plun->lun_cip;
8812 				mutex_exit(&plun->lun_mutex);
8813 
8814 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8815 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8816 				    "FCP response error on cmd=%p"
8817 				    " target=0x%x, cip=%p", cmd,
8818 				    ptgt->tgt_d_id, cip);
8819 			}
8820 		}
8821 
8822 		/*
8823 		 * See if we got a SCSI error with sense data
8824 		 */
8825 		if (rsp->fcp_u.fcp_status.sense_len_set) {
8826 			uchar_t				rqlen;
8827 			caddr_t				sense_from;
8828 			child_info_t			*cip;
8829 			timeout_id_t			tid;
8830 			struct scsi_arq_status		*arq;
8831 			struct scsi_extended_sense	*sense_to;
8832 
8833 			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8834 			sense_to = &arq->sts_sensedata;
8835 
8836 			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8837 			    sizeof (struct scsi_extended_sense));
8838 
8839 			sense_from = (caddr_t)fpkt->pkt_resp +
8840 			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8841 
8842 			if (fcp_validate_fcp_response(rsp, pptr) !=
8843 			    FC_SUCCESS) {
8844 				pkt->pkt_reason = CMD_CMPLT;
8845 				*(pkt->pkt_scbp) = STATUS_CHECK;
8846 
8847 				fcp_log(CE_WARN, pptr->port_dip,
8848 				    "!SCSI command to d_id=0x%x lun=0x%x"
8849 				    " failed, Bad FCP response values:"
8850 				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8851 				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8852 				    ptgt->tgt_d_id, plun->lun_num,
8853 				    rsp->reserved_0, rsp->reserved_1,
8854 				    rsp->fcp_u.fcp_status.reserved_0,
8855 				    rsp->fcp_u.fcp_status.reserved_1,
8856 				    rsp->fcp_response_len, rsp->fcp_sense_len);
8857 
8858 				return;
8859 			}
8860 
8861 			/*
8862 			 * copy in sense information
8863 			 */
8864 			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8865 				FCP_CP_IN(sense_from, sense_to,
8866 				    fpkt->pkt_resp_acc, rqlen);
8867 			} else {
8868 				bcopy(sense_from, sense_to, rqlen);
8869 			}
8870 
8871 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8872 			    (FCP_SENSE_NO_LUN(sense_to))) {
8873 				mutex_enter(&ptgt->tgt_mutex);
8874 				if (ptgt->tgt_tid == NULL) {
8875 					/*
8876 					 * Kick off rediscovery
8877 					 */
8878 					tid = timeout(fcp_reconfigure_luns,
8879 					    (caddr_t)ptgt, drv_usectohz(1));
8880 
8881 					ptgt->tgt_tid = tid;
8882 					ptgt->tgt_state |= FCP_TGT_BUSY;
8883 				}
8884 				mutex_exit(&ptgt->tgt_mutex);
8885 				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8886 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8887 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8888 					    "!FCP: Report Lun Has Changed"
8889 					    " target=%x", ptgt->tgt_d_id);
8890 				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8891 					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8892 					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8893 					    "!FCP: LU Not Supported"
8894 					    " target=%x", ptgt->tgt_d_id);
8895 				}
8896 			}
8897 			ASSERT(pkt->pkt_scbp != NULL);
8898 
8899 			pkt->pkt_state |= STATE_ARQ_DONE;
8900 
8901 			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8902 
8903 			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8904 			arq->sts_rqpkt_reason = 0;
8905 			arq->sts_rqpkt_statistics = 0;
8906 
8907 			arq->sts_rqpkt_state = STATE_GOT_BUS |
8908 			    STATE_GOT_TARGET | STATE_SENT_CMD |
8909 			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8910 			    STATE_XFERRED_DATA;
8911 
8912 			mutex_enter(&plun->lun_mutex);
8913 			cip = plun->lun_cip;
8914 			mutex_exit(&plun->lun_mutex);
8915 
8916 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8917 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
8918 			    "SCSI Check condition on cmd=%p target=0x%x"
8919 			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
8920 			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
8921 			    cmd->cmd_fcp_cmd.fcp_cdb[0],
8922 			    rsp->fcp_u.fcp_status.scsi_status,
8923 			    sense_to->es_key, sense_to->es_add_code,
8924 			    sense_to->es_qual_code);
8925 		}
8926 	} else {
8927 		plun = ADDR2LUN(&pkt->pkt_address);
8928 		ptgt = plun->lun_tgt;
8929 		ASSERT(ptgt != NULL);
8930 
8931 		/*
8932 		 * Work harder to translate errors into target driver
8933 		 * understandable ones. Note with despair that the target
8934 		 * drivers don't decode pkt_state and pkt_reason exhaustively
8935 		 * They resort to using the big hammer most often, which
8936 		 * may not get fixed in the life time of this driver.
8937 		 */
8938 		pkt->pkt_state = 0;
8939 		pkt->pkt_statistics = 0;
8940 
8941 		switch (fpkt->pkt_state) {
8942 		case FC_PKT_TRAN_ERROR:
8943 			switch (fpkt->pkt_reason) {
8944 			case FC_REASON_OVERRUN:
8945 				pkt->pkt_reason = CMD_CMD_OVR;
8946 				pkt->pkt_statistics |= STAT_ABORTED;
8947 				break;
8948 
8949 			case FC_REASON_XCHG_BSY: {
8950 				caddr_t ptr;
8951 
8952 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
8953 
8954 				ptr = (caddr_t)pkt->pkt_scbp;
8955 				if (ptr) {
8956 					*ptr = STATUS_BUSY;
8957 				}
8958 				break;
8959 			}
8960 
8961 			case FC_REASON_ABORTED:
8962 				pkt->pkt_reason = CMD_TRAN_ERR;
8963 				pkt->pkt_statistics |= STAT_ABORTED;
8964 				break;
8965 
8966 			case FC_REASON_ABORT_FAILED:
8967 				pkt->pkt_reason = CMD_ABORT_FAIL;
8968 				break;
8969 
8970 			case FC_REASON_NO_SEQ_INIT:
8971 			case FC_REASON_CRC_ERROR:
8972 				pkt->pkt_reason = CMD_TRAN_ERR;
8973 				pkt->pkt_statistics |= STAT_ABORTED;
8974 				break;
8975 			default:
8976 				pkt->pkt_reason = CMD_TRAN_ERR;
8977 				break;
8978 			}
8979 			break;
8980 
8981 		case FC_PKT_PORT_OFFLINE: {
8982 			dev_info_t	*cdip = NULL;
8983 			caddr_t		ptr;
8984 
8985 			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
8986 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8987 				    fcp_trace, FCP_BUF_LEVEL_8, 0,
8988 				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
8989 				    ptgt->tgt_d_id);
8990 			}
8991 
8992 			mutex_enter(&plun->lun_mutex);
8993 			if (plun->lun_mpxio == 0) {
8994 				cdip = DIP(plun->lun_cip);
8995 			} else if (plun->lun_cip) {
8996 				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8997 			}
8998 
8999 			mutex_exit(&plun->lun_mutex);
9000 
9001 			if (cdip) {
9002 				(void) ndi_event_retrieve_cookie(
9003 				    pptr->port_ndi_event_hdl, cdip,
9004 				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9005 				    NDI_EVENT_NOPASS);
9006 				(void) ndi_event_run_callbacks(
9007 				    pptr->port_ndi_event_hdl, cdip,
9008 				    fcp_remove_eid, NULL);
9009 			}
9010 
9011 			/*
9012 			 * If the link goes off-line for a lip,
9013 			 * this will cause a error to the ST SG
9014 			 * SGEN drivers. By setting BUSY we will
9015 			 * give the drivers the chance to retry
9016 			 * before it blows of the job. ST will
9017 			 * remember how many times it has retried.
9018 			 */
9019 
9020 			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9021 			    (plun->lun_type == DTYPE_CHANGER)) {
9022 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9023 				ptr = (caddr_t)pkt->pkt_scbp;
9024 				if (ptr) {
9025 					*ptr = STATUS_BUSY;
9026 				}
9027 			} else {
9028 				pkt->pkt_reason = CMD_TRAN_ERR;
9029 				pkt->pkt_statistics |= STAT_BUS_RESET;
9030 			}
9031 			break;
9032 		}
9033 
9034 		case FC_PKT_TRAN_BSY:
9035 			/*
9036 			 * Use the ssd Qfull handling here.
9037 			 */
9038 			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9039 			pkt->pkt_state = STATE_GOT_BUS;
9040 			break;
9041 
9042 		case FC_PKT_TIMEOUT:
9043 			pkt->pkt_reason = CMD_TIMEOUT;
9044 			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9045 				pkt->pkt_statistics |= STAT_TIMEOUT;
9046 			} else {
9047 				pkt->pkt_statistics |= STAT_ABORTED;
9048 			}
9049 			break;
9050 
9051 		case FC_PKT_LOCAL_RJT:
9052 			switch (fpkt->pkt_reason) {
9053 			case FC_REASON_OFFLINE: {
9054 				dev_info_t	*cdip = NULL;
9055 
9056 				mutex_enter(&plun->lun_mutex);
9057 				if (plun->lun_mpxio == 0) {
9058 					cdip = DIP(plun->lun_cip);
9059 				} else if (plun->lun_cip) {
9060 					cdip = mdi_pi_get_client(
9061 					    PIP(plun->lun_cip));
9062 				}
9063 				mutex_exit(&plun->lun_mutex);
9064 
9065 				if (cdip) {
9066 					(void) ndi_event_retrieve_cookie(
9067 					    pptr->port_ndi_event_hdl, cdip,
9068 					    FCAL_REMOVE_EVENT,
9069 					    &fcp_remove_eid,
9070 					    NDI_EVENT_NOPASS);
9071 					(void) ndi_event_run_callbacks(
9072 					    pptr->port_ndi_event_hdl,
9073 					    cdip, fcp_remove_eid, NULL);
9074 				}
9075 
9076 				pkt->pkt_reason = CMD_TRAN_ERR;
9077 				pkt->pkt_statistics |= STAT_BUS_RESET;
9078 
9079 				break;
9080 			}
9081 
9082 			case FC_REASON_NOMEM:
9083 			case FC_REASON_QFULL: {
9084 				caddr_t ptr;
9085 
9086 				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9087 				ptr = (caddr_t)pkt->pkt_scbp;
9088 				if (ptr) {
9089 					*ptr = STATUS_BUSY;
9090 				}
9091 				break;
9092 			}
9093 
9094 			case FC_REASON_DMA_ERROR:
9095 				pkt->pkt_reason = CMD_DMA_DERR;
9096 				pkt->pkt_statistics |= STAT_ABORTED;
9097 				break;
9098 
9099 			case FC_REASON_CRC_ERROR:
9100 			case FC_REASON_UNDERRUN: {
9101 				uchar_t		status;
9102 				/*
9103 				 * Work around for Bugid: 4240945.
9104 				 * IB on A5k doesn't set the Underrun bit
9105 				 * in the fcp status, when it is transferring
9106 				 * less than requested amount of data. Work
9107 				 * around the ses problem to keep luxadm
9108 				 * happy till ibfirmware is fixed.
9109 				 */
9110 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9111 					FCP_CP_IN(fpkt->pkt_resp, rsp,
9112 					    fpkt->pkt_resp_acc,
9113 					    sizeof (struct fcp_rsp));
9114 				}
9115 				status = rsp->fcp_u.fcp_status.scsi_status;
9116 				if (((plun->lun_type & DTYPE_MASK) ==
9117 				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9118 					pkt->pkt_reason = CMD_CMPLT;
9119 					*pkt->pkt_scbp = status;
9120 					pkt->pkt_resid = 0;
9121 				} else {
9122 					pkt->pkt_reason = CMD_TRAN_ERR;
9123 					pkt->pkt_statistics |= STAT_ABORTED;
9124 				}
9125 				break;
9126 			}
9127 
9128 			case FC_REASON_NO_CONNECTION:
9129 			case FC_REASON_UNSUPPORTED:
9130 			case FC_REASON_ILLEGAL_REQ:
9131 			case FC_REASON_BAD_SID:
9132 			case FC_REASON_DIAG_BUSY:
9133 			case FC_REASON_FCAL_OPN_FAIL:
9134 			case FC_REASON_BAD_XID:
9135 			default:
9136 				pkt->pkt_reason = CMD_TRAN_ERR;
9137 				pkt->pkt_statistics |= STAT_ABORTED;
9138 				break;
9139 
9140 			}
9141 			break;
9142 
9143 		case FC_PKT_NPORT_RJT:
9144 		case FC_PKT_FABRIC_RJT:
9145 		case FC_PKT_NPORT_BSY:
9146 		case FC_PKT_FABRIC_BSY:
9147 		default:
9148 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9149 			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9150 			    "FC Status 0x%x, reason 0x%x",
9151 			    fpkt->pkt_state, fpkt->pkt_reason);
9152 			pkt->pkt_reason = CMD_TRAN_ERR;
9153 			pkt->pkt_statistics |= STAT_ABORTED;
9154 			break;
9155 		}
9156 
9157 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9158 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9159 		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9160 		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9161 		    fpkt->pkt_reason);
9162 	}
9163 
9164 	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9165 }
9166 
9167 
9168 static int
9169 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9170 {
9171 	if (rsp->reserved_0 || rsp->reserved_1 ||
9172 	    rsp->fcp_u.fcp_status.reserved_0 ||
9173 	    rsp->fcp_u.fcp_status.reserved_1) {
9174 		/*
9175 		 * These reserved fields should ideally be zero. FCP-2 does say
9176 		 * that the recipient need not check for reserved fields to be
9177 		 * zero. If they are not zero, we will not make a fuss about it
9178 		 * - just log it (in debug to both trace buffer and messages
9179 		 * file and to trace buffer only in non-debug) and move on.
9180 		 *
9181 		 * Non-zero reserved fields were seen with minnows.
9182 		 *
9183 		 * qlc takes care of some of this but we cannot assume that all
9184 		 * FCAs will do so.
9185 		 */
9186 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9187 		    FCP_BUF_LEVEL_5, 0,
9188 		    "Got fcp response packet with non-zero reserved fields "
9189 		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9190 		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9191 		    rsp->reserved_0, rsp->reserved_1,
9192 		    rsp->fcp_u.fcp_status.reserved_0,
9193 		    rsp->fcp_u.fcp_status.reserved_1);
9194 	}
9195 
9196 	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9197 	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9198 		return (FC_FAILURE);
9199 	}
9200 
9201 	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9202 	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9203 	    sizeof (struct fcp_rsp))) {
9204 		return (FC_FAILURE);
9205 	}
9206 
9207 	return (FC_SUCCESS);
9208 }
9209 
9210 
9211 /*
9212  * This is called when there is a change the in device state. The case we're
9213  * handling here is, if the d_id s does not match, offline this tgt and online
9214  * a new tgt with the new d_id.	 called from fcp_handle_devices with
9215  * port_mutex held.
9216  */
9217 static int
9218 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9219     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9220 {
9221 	ASSERT(mutex_owned(&pptr->port_mutex));
9222 
9223 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9224 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9225 	    "Starting fcp_device_changed...");
9226 
9227 	/*
9228 	 * The two cases where the port_device_changed is called is
9229 	 * either it changes it's d_id or it's hard address.
9230 	 */
9231 	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9232 	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9233 	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9234 
9235 		/* offline this target */
9236 		mutex_enter(&ptgt->tgt_mutex);
9237 		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9238 			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9239 			    0, 1, NDI_DEVI_REMOVE);
9240 		}
9241 		mutex_exit(&ptgt->tgt_mutex);
9242 
9243 		fcp_log(CE_NOTE, pptr->port_dip,
9244 		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9245 		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9246 		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9247 		    map_entry->map_hard_addr.hard_addr);
9248 	}
9249 
9250 	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9251 	    link_cnt, tgt_cnt, cause));
9252 }
9253 
9254 /*
9255  *     Function: fcp_alloc_lun
9256  *
9257  *  Description: Creates a new lun structure and adds it to the list
9258  *		 of luns of the target.
9259  *
9260  *     Argument: ptgt		Target the lun will belong to.
9261  *
9262  * Return Value: NULL		Failed
9263  *		 Not NULL	Succeeded
9264  *
9265  *	Context: Kernel context
9266  */
9267 static struct fcp_lun *
9268 fcp_alloc_lun(struct fcp_tgt *ptgt)
9269 {
9270 	struct fcp_lun *plun;
9271 
9272 	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9273 	if (plun != NULL) {
9274 		/*
9275 		 * Initialize the mutex before putting in the target list
9276 		 * especially before releasing the target mutex.
9277 		 */
9278 		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9279 		plun->lun_tgt = ptgt;
9280 
9281 		mutex_enter(&ptgt->tgt_mutex);
9282 		plun->lun_next = ptgt->tgt_lun;
9283 		ptgt->tgt_lun = plun;
9284 		plun->lun_old_guid = NULL;
9285 		plun->lun_old_guid_size = 0;
9286 		mutex_exit(&ptgt->tgt_mutex);
9287 	}
9288 
9289 	return (plun);
9290 }
9291 
9292 /*
9293  *     Function: fcp_dealloc_lun
9294  *
9295  *  Description: Frees the LUN structure passed by the caller.
9296  *
9297  *     Argument: plun		LUN structure to free.
9298  *
9299  * Return Value: None
9300  *
9301  *	Context: Kernel context.
9302  */
9303 static void
9304 fcp_dealloc_lun(struct fcp_lun *plun)
9305 {
9306 	mutex_enter(&plun->lun_mutex);
9307 	if (plun->lun_cip) {
9308 		fcp_remove_child(plun);
9309 	}
9310 	mutex_exit(&plun->lun_mutex);
9311 
9312 	mutex_destroy(&plun->lun_mutex);
9313 	if (plun->lun_guid) {
9314 		kmem_free(plun->lun_guid, plun->lun_guid_size);
9315 	}
9316 	if (plun->lun_old_guid) {
9317 		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9318 	}
9319 	kmem_free(plun, sizeof (*plun));
9320 }
9321 
9322 /*
9323  *     Function: fcp_alloc_tgt
9324  *
9325  *  Description: Creates a new target structure and adds it to the port
9326  *		 hash list.
9327  *
9328  *     Argument: pptr		fcp port structure
9329  *		 *map_entry	entry describing the target to create
9330  *		 link_cnt	Link state change counter
9331  *
9332  * Return Value: NULL		Failed
9333  *		 Not NULL	Succeeded
9334  *
9335  *	Context: Kernel context.
9336  */
9337 static struct fcp_tgt *
9338 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9339 {
9340 	int			hash;
9341 	uchar_t			*wwn;
9342 	struct fcp_tgt	*ptgt;
9343 
9344 	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9345 	if (ptgt != NULL) {
9346 		mutex_enter(&pptr->port_mutex);
9347 		if (link_cnt != pptr->port_link_cnt) {
9348 			/*
9349 			 * oh oh -- another link reset
9350 			 * in progress -- give up
9351 			 */
9352 			mutex_exit(&pptr->port_mutex);
9353 			kmem_free(ptgt, sizeof (*ptgt));
9354 			ptgt = NULL;
9355 		} else {
9356 			/*
9357 			 * initialize the mutex before putting in the port
9358 			 * wwn list, especially before releasing the port
9359 			 * mutex.
9360 			 */
9361 			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9362 
9363 			/* add new target entry to the port's hash list */
9364 			wwn = (uchar_t *)&map_entry->map_pwwn;
9365 			hash = FCP_HASH(wwn);
9366 
9367 			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9368 			pptr->port_tgt_hash_table[hash] = ptgt;
9369 
9370 			/* save cross-ptr */
9371 			ptgt->tgt_port = pptr;
9372 
9373 			ptgt->tgt_change_cnt = 1;
9374 
9375 			/* initialize the target manual_config_only flag */
9376 			if (fcp_enable_auto_configuration) {
9377 				ptgt->tgt_manual_config_only = 0;
9378 			} else {
9379 				ptgt->tgt_manual_config_only = 1;
9380 			}
9381 
9382 			mutex_exit(&pptr->port_mutex);
9383 		}
9384 	}
9385 
9386 	return (ptgt);
9387 }
9388 
9389 /*
9390  *     Function: fcp_dealloc_tgt
9391  *
9392  *  Description: Frees the target structure passed by the caller.
9393  *
9394  *     Argument: ptgt		Target structure to free.
9395  *
9396  * Return Value: None
9397  *
9398  *	Context: Kernel context.
9399  */
9400 static void
9401 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9402 {
9403 	mutex_destroy(&ptgt->tgt_mutex);
9404 	kmem_free(ptgt, sizeof (*ptgt));
9405 }
9406 
9407 
9408 /*
9409  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9410  *
9411  *	Device discovery commands will not be retried for-ever as
9412  *	this will have repercussions on other devices that need to
9413  *	be submitted to the hotplug thread. After a quick glance
9414  *	at the SCSI-3 spec, it was found that the spec doesn't
9415  *	mandate a forever retry, rather recommends a delayed retry.
9416  *
9417  *	Since Photon IB is single threaded, STATUS_BUSY is common
9418  *	in a 4+initiator environment. Make sure the total time
9419  *	spent on retries (including command timeout) does not
9420  *	60 seconds
9421  */
9422 static void
9423 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9424 {
9425 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9426 	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9427 
9428 	mutex_enter(&pptr->port_mutex);
9429 	mutex_enter(&ptgt->tgt_mutex);
9430 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9431 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9432 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9433 		    "fcp_queue_ipkt,1:state change occured"
9434 		    " for D_ID=0x%x", ptgt->tgt_d_id);
9435 		mutex_exit(&ptgt->tgt_mutex);
9436 		mutex_exit(&pptr->port_mutex);
9437 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9438 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9439 		fcp_icmd_free(pptr, icmd);
9440 		return;
9441 	}
9442 	mutex_exit(&ptgt->tgt_mutex);
9443 
9444 	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9445 
9446 	if (pptr->port_ipkt_list != NULL) {
9447 		/* add pkt to front of doubly-linked list */
9448 		pptr->port_ipkt_list->ipkt_prev = icmd;
9449 		icmd->ipkt_next = pptr->port_ipkt_list;
9450 		pptr->port_ipkt_list = icmd;
9451 		icmd->ipkt_prev = NULL;
9452 	} else {
9453 		/* this is the first/only pkt on the list */
9454 		pptr->port_ipkt_list = icmd;
9455 		icmd->ipkt_next = NULL;
9456 		icmd->ipkt_prev = NULL;
9457 	}
9458 	mutex_exit(&pptr->port_mutex);
9459 }
9460 
9461 /*
9462  *     Function: fcp_transport
9463  *
9464  *  Description: This function submits the Fibre Channel packet to the transort
9465  *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9466  *		 fails the submission, the treatment depends on the value of
9467  *		 the variable internal.
9468  *
9469  *     Argument: port_handle	fp/fctl port handle.
9470  *		 *fpkt		Packet to submit to the transport layer.
9471  *		 internal	Not zero when it's an internal packet.
9472  *
9473  * Return Value: FC_TRAN_BUSY
9474  *		 FC_STATEC_BUSY
9475  *		 FC_OFFLINE
9476  *		 FC_LOGINREQ
9477  *		 FC_DEVICE_BUSY
9478  *		 FC_SUCCESS
9479  */
9480 static int
9481 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9482 {
9483 	int	rval;
9484 
9485 	rval = fc_ulp_transport(port_handle, fpkt);
9486 	if (rval == FC_SUCCESS) {
9487 		return (rval);
9488 	}
9489 
9490 	/*
9491 	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9492 	 * a command, if the underlying modules see that there is a state
9493 	 * change, or if a port is OFFLINE, that means, that state change
9494 	 * hasn't reached FCP yet, so re-queue the command for deferred
9495 	 * submission.
9496 	 */
9497 	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9498 	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9499 	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9500 		/*
9501 		 * Defer packet re-submission. Life hang is possible on
9502 		 * internal commands if the port driver sends FC_STATEC_BUSY
9503 		 * for ever, but that shouldn't happen in a good environment.
9504 		 * Limiting re-transport for internal commands is probably a
9505 		 * good idea..
9506 		 * A race condition can happen when a port sees barrage of
9507 		 * link transitions offline to online. If the FCTL has
9508 		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9509 		 * internal commands should be queued to do the discovery.
9510 		 * The race condition is when an online comes and FCP starts
9511 		 * its internal discovery and the link goes offline. It is
9512 		 * possible that the statec_callback has not reached FCP
9513 		 * and FCP is carrying on with its internal discovery.
9514 		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9515 		 * that the link has gone offline. At this point FCP should
9516 		 * drop all the internal commands and wait for the
9517 		 * statec_callback. It will be facilitated by incrementing
9518 		 * port_link_cnt.
9519 		 *
9520 		 * For external commands, the (FC)pkt_timeout is decremented
9521 		 * by the QUEUE Delay added by our driver, Care is taken to
9522 		 * ensure that it doesn't become zero (zero means no timeout)
9523 		 * If the time expires right inside driver queue itself,
9524 		 * the watch thread will return it to the original caller
9525 		 * indicating that the command has timed-out.
9526 		 */
9527 		if (internal) {
9528 			char			*op;
9529 			struct fcp_ipkt	*icmd;
9530 
9531 			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9532 			switch (icmd->ipkt_opcode) {
9533 			case SCMD_REPORT_LUN:
9534 				op = "REPORT LUN";
9535 				break;
9536 
9537 			case SCMD_INQUIRY:
9538 				op = "INQUIRY";
9539 				break;
9540 
9541 			case SCMD_INQUIRY_PAGE83:
9542 				op = "INQUIRY-83";
9543 				break;
9544 
9545 			default:
9546 				op = "Internal SCSI COMMAND";
9547 				break;
9548 			}
9549 
9550 			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9551 			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9552 				rval = FC_SUCCESS;
9553 			}
9554 		} else {
9555 			struct fcp_pkt *cmd;
9556 			struct fcp_port *pptr;
9557 
9558 			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9559 			cmd->cmd_state = FCP_PKT_IDLE;
9560 			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9561 
9562 			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9563 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9564 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9565 				    "fcp_transport: xport busy for pkt %p",
9566 				    cmd->cmd_pkt);
9567 				rval = FC_TRAN_BUSY;
9568 			} else {
9569 				fcp_queue_pkt(pptr, cmd);
9570 				rval = FC_SUCCESS;
9571 			}
9572 		}
9573 	}
9574 
9575 	return (rval);
9576 }
9577 
9578 /*VARARGS3*/
9579 static void
9580 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9581 {
9582 	char		buf[256];
9583 	va_list		ap;
9584 
9585 	if (dip == NULL) {
9586 		dip = fcp_global_dip;
9587 	}
9588 
9589 	va_start(ap, fmt);
9590 	(void) vsprintf(buf, fmt, ap);
9591 	va_end(ap);
9592 
9593 	scsi_log(dip, "fcp", level, buf);
9594 }
9595 
9596 /*
9597  * This function retries NS registry of FC4 type.
9598  * It assumes that fcp_mutex is held.
9599  * The function does nothing if topology is not fabric
9600  * So, the topology has to be set before this function can be called
9601  */
9602 static void
9603 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9604 {
9605 	int	rval;
9606 
9607 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9608 
9609 	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9610 	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9611 	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9612 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9613 			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9614 		}
9615 		return;
9616 	}
9617 	mutex_exit(&pptr->port_mutex);
9618 	rval = fcp_do_ns_registry(pptr, s_id);
9619 	mutex_enter(&pptr->port_mutex);
9620 
9621 	if (rval == 0) {
9622 		/* Registry successful. Reset flag */
9623 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9624 	}
9625 }
9626 
9627 /*
9628  * This function registers the ULP with the switch by calling transport i/f
9629  */
9630 static int
9631 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9632 {
9633 	fc_ns_cmd_t		ns_cmd;
9634 	ns_rfc_type_t		rfc;
9635 	uint32_t		types[8];
9636 
9637 	/*
9638 	 * Prepare the Name server structure to
9639 	 * register with the transport in case of
9640 	 * Fabric configuration.
9641 	 */
9642 	bzero(&rfc, sizeof (rfc));
9643 	bzero(types, sizeof (types));
9644 
9645 	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9646 	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9647 
9648 	rfc.rfc_port_id.port_id = s_id;
9649 	bcopy(types, rfc.rfc_types, sizeof (types));
9650 
9651 	ns_cmd.ns_flags = 0;
9652 	ns_cmd.ns_cmd = NS_RFT_ID;
9653 	ns_cmd.ns_req_len = sizeof (rfc);
9654 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9655 	ns_cmd.ns_resp_len = 0;
9656 	ns_cmd.ns_resp_payload = NULL;
9657 
9658 	/*
9659 	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9660 	 */
9661 	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9662 		fcp_log(CE_WARN, pptr->port_dip,
9663 		    "!ns_registry: failed name server registration");
9664 		return (1);
9665 	}
9666 
9667 	return (0);
9668 }
9669 
9670 /*
9671  *     Function: fcp_handle_port_attach
9672  *
9673  *  Description: This function is called from fcp_port_attach() to attach a
9674  *		 new port. This routine does the following:
9675  *
9676  *		1) Allocates an fcp_port structure and initializes it.
9677  *		2) Tries to register the new FC-4 (FCP) capablity with the name
9678  *		   server.
9679  *		3) Kicks off the enumeration of the targets/luns visible
9680  *		   through this new port.  That is done by calling
9681  *		   fcp_statec_callback() if the port is online.
9682  *
9683  *     Argument: ulph		fp/fctl port handle.
9684  *		 *pinfo		Port information.
9685  *		 s_id		Port ID.
9686  *		 instance	Device instance number for the local port
9687  *				(returned by ddi_get_instance()).
9688  *
9689  * Return Value: DDI_SUCCESS
9690  *		 DDI_FAILURE
9691  *
9692  *	Context: User and Kernel context.
9693  */
9694 /*ARGSUSED*/
9695 int
9696 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9697     uint32_t s_id, int instance)
9698 {
9699 	int			res = DDI_FAILURE;
9700 	scsi_hba_tran_t		*tran;
9701 	int			mutex_initted = FALSE;
9702 	int			hba_attached = FALSE;
9703 	int			soft_state_linked = FALSE;
9704 	int			event_bind = FALSE;
9705 	struct fcp_port		*pptr;
9706 	fc_portmap_t		*tmp_list = NULL;
9707 	uint32_t		max_cnt, alloc_cnt;
9708 	uchar_t			*boot_wwn = NULL;
9709 	uint_t			nbytes;
9710 	int			manual_cfg;
9711 
9712 	/*
9713 	 * this port instance attaching for the first time (or after
9714 	 * being detached before)
9715 	 */
9716 	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9717 	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9718 
9719 	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9720 		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9721 		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9722 		    instance);
9723 		return (res);
9724 	}
9725 
9726 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9727 		/* this shouldn't happen */
9728 		ddi_soft_state_free(fcp_softstate, instance);
9729 		cmn_err(CE_WARN, "fcp: bad soft state");
9730 		return (res);
9731 	}
9732 
9733 	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9734 
9735 	/*
9736 	 * Make a copy of ulp_port_info as fctl allocates
9737 	 * a temp struct.
9738 	 */
9739 	(void) fcp_cp_pinfo(pptr, pinfo);
9740 
9741 	/*
9742 	 * Check for manual_configuration_only property.
9743 	 * Enable manual configurtion if the property is
9744 	 * set to 1, otherwise disable manual configuration.
9745 	 */
9746 	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9747 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9748 	    MANUAL_CFG_ONLY,
9749 	    -1)) != -1) {
9750 		if (manual_cfg == 1) {
9751 			char	*pathname;
9752 			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9753 			(void) ddi_pathname(pptr->port_dip, pathname);
9754 			cmn_err(CE_NOTE,
9755 			    "%s (%s%d) %s is enabled via %s.conf.",
9756 			    pathname,
9757 			    ddi_driver_name(pptr->port_dip),
9758 			    ddi_get_instance(pptr->port_dip),
9759 			    MANUAL_CFG_ONLY,
9760 			    ddi_driver_name(pptr->port_dip));
9761 			fcp_enable_auto_configuration = 0;
9762 			kmem_free(pathname, MAXPATHLEN);
9763 		}
9764 	}
9765 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt))
9766 	pptr->port_link_cnt = 1;
9767 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt))
9768 	pptr->port_id = s_id;
9769 	pptr->port_instance = instance;
9770 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state))
9771 	pptr->port_state = FCP_STATE_INIT;
9772 	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state))
9773 
9774 	pptr->port_dmacookie_sz = (pptr->port_data_dma_attr.dma_attr_sgllen *
9775 	    sizeof (ddi_dma_cookie_t));
9776 
9777 	/*
9778 	 * The two mutexes of fcp_port are initialized.	 The variable
9779 	 * mutex_initted is incremented to remember that fact.	That variable
9780 	 * is checked when the routine fails and the mutexes have to be
9781 	 * destroyed.
9782 	 */
9783 	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9784 	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9785 	mutex_initted++;
9786 
9787 	/*
9788 	 * The SCSI tran structure is allocate and initialized now.
9789 	 */
9790 	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9791 		fcp_log(CE_WARN, pptr->port_dip,
9792 		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9793 		goto fail;
9794 	}
9795 
9796 	/* link in the transport structure then fill it in */
9797 	pptr->port_tran = tran;
9798 	tran->tran_hba_private		= pptr;
9799 	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9800 	tran->tran_tgt_probe		= NULL;
9801 	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9802 	tran->tran_start		= fcp_scsi_start;
9803 	tran->tran_reset		= fcp_scsi_reset;
9804 	tran->tran_abort		= fcp_scsi_abort;
9805 	tran->tran_getcap		= fcp_scsi_getcap;
9806 	tran->tran_setcap		= fcp_scsi_setcap;
9807 	tran->tran_init_pkt		= NULL;
9808 	tran->tran_destroy_pkt		= NULL;
9809 	tran->tran_dmafree		= NULL;
9810 	tran->tran_sync_pkt		= NULL;
9811 	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9812 	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9813 	tran->tran_get_name		= fcp_scsi_get_name;
9814 	tran->tran_clear_aca		= NULL;
9815 	tran->tran_clear_task_set	= NULL;
9816 	tran->tran_terminate_task	= NULL;
9817 	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9818 	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9819 	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9820 	tran->tran_post_event		= fcp_scsi_bus_post_event;
9821 	tran->tran_quiesce		= NULL;
9822 	tran->tran_unquiesce		= NULL;
9823 	tran->tran_bus_reset		= NULL;
9824 	tran->tran_bus_config		= fcp_scsi_bus_config;
9825 	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9826 	tran->tran_bus_power		= NULL;
9827 	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9828 
9829 	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9830 	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9831 	tran->tran_setup_pkt		= fcp_pkt_setup;
9832 	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9833 	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9834 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9835 
9836 	/*
9837 	 * Allocate an ndi event handle
9838 	 */
9839 	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9840 	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9841 
9842 	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9843 	    sizeof (fcp_ndi_event_defs));
9844 
9845 	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9846 	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9847 
9848 	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9849 	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9850 	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9851 
9852 	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9853 	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9854 	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9855 		goto fail;
9856 	}
9857 	event_bind++;	/* Checked in fail case */
9858 
9859 	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9860 	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9861 	    != DDI_SUCCESS) {
9862 		fcp_log(CE_WARN, pptr->port_dip,
9863 		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9864 		goto fail;
9865 	}
9866 	hba_attached++;	/* Checked in fail case */
9867 
9868 	pptr->port_mpxio = 0;
9869 	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9870 	    MDI_SUCCESS) {
9871 		pptr->port_mpxio++;
9872 	}
9873 
9874 	/*
9875 	 * The following code is putting the new port structure in the global
9876 	 * list of ports and, if it is the first port to attach, it start the
9877 	 * fcp_watchdog_tick.
9878 	 *
9879 	 * Why put this new port in the global before we are done attaching it?
9880 	 * We are actually making the structure globally known before we are
9881 	 * done attaching it.  The reason for that is: because of the code that
9882 	 * follows.  At this point the resources to handle the port are
9883 	 * allocated.  This function is now going to do the following:
9884 	 *
9885 	 *   1) It is going to try to register with the name server advertizing
9886 	 *	the new FCP capability of the port.
9887 	 *   2) It is going to play the role of the fp/fctl layer by building
9888 	 *	a list of worlwide names reachable through this port and call
9889 	 *	itself on fcp_statec_callback().  That requires the port to
9890 	 *	be part of the global list.
9891 	 */
9892 	mutex_enter(&fcp_global_mutex);
9893 	if (fcp_port_head == NULL) {
9894 		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
9895 	}
9896 	pptr->port_next = fcp_port_head;
9897 	fcp_port_head = pptr;
9898 	soft_state_linked++;
9899 
9900 	if (fcp_watchdog_init++ == 0) {
9901 		fcp_watchdog_tick = fcp_watchdog_timeout *
9902 		    drv_usectohz(1000000);
9903 		fcp_watchdog_id = timeout(fcp_watch, NULL,
9904 		    fcp_watchdog_tick);
9905 	}
9906 	mutex_exit(&fcp_global_mutex);
9907 
9908 	/*
9909 	 * Here an attempt is made to register with the name server, the new
9910 	 * FCP capability.  That is done using an RTF_ID to the name server.
9911 	 * It is done synchronously.  The function fcp_do_ns_registry()
9912 	 * doesn't return till the name server responded.
9913 	 * On failures, just ignore it for now and it will get retried during
9914 	 * state change callbacks. We'll set a flag to show this failure
9915 	 */
9916 	if (fcp_do_ns_registry(pptr, s_id)) {
9917 		mutex_enter(&pptr->port_mutex);
9918 		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
9919 		mutex_exit(&pptr->port_mutex);
9920 	} else {
9921 		mutex_enter(&pptr->port_mutex);
9922 		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9923 		mutex_exit(&pptr->port_mutex);
9924 	}
9925 
9926 	/*
9927 	 * Lookup for boot WWN property
9928 	 */
9929 	if (modrootloaded != 1) {
9930 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
9931 		    ddi_get_parent(pinfo->port_dip),
9932 		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
9933 		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
9934 		    (nbytes == FC_WWN_SIZE)) {
9935 			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
9936 		}
9937 		if (boot_wwn) {
9938 			ddi_prop_free(boot_wwn);
9939 		}
9940 	}
9941 
9942 	/*
9943 	 * Handle various topologies and link states.
9944 	 */
9945 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
9946 	case FC_STATE_OFFLINE:
9947 
9948 		/*
9949 		 * we're attaching a port where the link is offline
9950 		 *
9951 		 * Wait for ONLINE, at which time a state
9952 		 * change will cause a statec_callback
9953 		 *
9954 		 * in the mean time, do not do anything
9955 		 */
9956 		res = DDI_SUCCESS;
9957 		pptr->port_state |= FCP_STATE_OFFLINE;
9958 		break;
9959 
9960 	case FC_STATE_ONLINE: {
9961 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
9962 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
9963 			res = DDI_SUCCESS;
9964 			break;
9965 		}
9966 		/*
9967 		 * discover devices and create nodes (a private
9968 		 * loop or point-to-point)
9969 		 */
9970 		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
9971 
9972 		/*
9973 		 * At this point we are going to build a list of all the ports
9974 		 * that	can be reached through this local port.	 It looks like
9975 		 * we cannot handle more than FCP_MAX_DEVICES per local port
9976 		 * (128).
9977 		 */
9978 		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
9979 		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
9980 		    KM_NOSLEEP)) == NULL) {
9981 			fcp_log(CE_WARN, pptr->port_dip,
9982 			    "!fcp%d: failed to allocate portmap",
9983 			    instance);
9984 			goto fail;
9985 		}
9986 
9987 		/*
9988 		 * fc_ulp_getportmap() is going to provide us with the list of
9989 		 * remote ports in the buffer we just allocated.  The way the
9990 		 * list is going to be retrieved depends on the topology.
9991 		 * However, if we are connected to a Fabric, a name server
9992 		 * request may be sent to get the list of FCP capable ports.
9993 		 * It should be noted that is the case the request is
9994 		 * synchronous.	 This means we are stuck here till the name
9995 		 * server replies.  A lot of things can change during that time
9996 		 * and including, may be, being called on
9997 		 * fcp_statec_callback() for different reasons. I'm not sure
9998 		 * the code can handle that.
9999 		 */
10000 		max_cnt = FCP_MAX_DEVICES;
10001 		alloc_cnt = FCP_MAX_DEVICES;
10002 		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10003 		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10004 		    FC_SUCCESS) {
10005 			caddr_t msg;
10006 
10007 			(void) fc_ulp_error(res, &msg);
10008 
10009 			/*
10010 			 * this	 just means the transport is
10011 			 * busy perhaps building a portmap so,
10012 			 * for now, succeed this port attach
10013 			 * when the transport has a new map,
10014 			 * it'll send us a state change then
10015 			 */
10016 			fcp_log(CE_WARN, pptr->port_dip,
10017 			    "!failed to get port map : %s", msg);
10018 
10019 			res = DDI_SUCCESS;
10020 			break;	/* go return result */
10021 		}
10022 		if (max_cnt > alloc_cnt) {
10023 			alloc_cnt = max_cnt;
10024 		}
10025 
10026 		/*
10027 		 * We are now going to call fcp_statec_callback() ourselves.
10028 		 * By issuing this call we are trying to kick off the enumera-
10029 		 * tion process.
10030 		 */
10031 		/*
10032 		 * let the state change callback do the SCSI device
10033 		 * discovery and create the devinfos
10034 		 */
10035 		fcp_statec_callback(ulph, pptr->port_fp_handle,
10036 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10037 		    max_cnt, pptr->port_id);
10038 
10039 		res = DDI_SUCCESS;
10040 		break;
10041 	}
10042 
10043 	default:
10044 		/* unknown port state */
10045 		fcp_log(CE_WARN, pptr->port_dip,
10046 		    "!fcp%d: invalid port state at attach=0x%x",
10047 		    instance, pptr->port_phys_state);
10048 
10049 		mutex_enter(&pptr->port_mutex);
10050 		pptr->port_phys_state = FCP_STATE_OFFLINE;
10051 		mutex_exit(&pptr->port_mutex);
10052 
10053 		res = DDI_SUCCESS;
10054 		break;
10055 	}
10056 
10057 	/* free temp list if used */
10058 	if (tmp_list != NULL) {
10059 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10060 	}
10061 
10062 	/* note the attach time */
10063 	pptr->port_attach_time = lbolt64;
10064 
10065 	/* all done */
10066 	return (res);
10067 
10068 	/* a failure we have to clean up after */
10069 fail:
10070 	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10071 
10072 	if (soft_state_linked) {
10073 		/* remove this fcp_port from the linked list */
10074 		(void) fcp_soft_state_unlink(pptr);
10075 	}
10076 
10077 	/* unbind and free event set */
10078 	if (pptr->port_ndi_event_hdl) {
10079 		if (event_bind) {
10080 			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10081 			    &pptr->port_ndi_events, NDI_SLEEP);
10082 		}
10083 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10084 	}
10085 
10086 	if (pptr->port_ndi_event_defs) {
10087 		(void) kmem_free(pptr->port_ndi_event_defs,
10088 		    sizeof (fcp_ndi_event_defs));
10089 	}
10090 
10091 	/*
10092 	 * Clean up mpxio stuff
10093 	 */
10094 	if (pptr->port_mpxio) {
10095 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10096 		pptr->port_mpxio--;
10097 	}
10098 
10099 	/* undo SCSI HBA setup */
10100 	if (hba_attached) {
10101 		(void) scsi_hba_detach(pptr->port_dip);
10102 	}
10103 	if (pptr->port_tran != NULL) {
10104 		scsi_hba_tran_free(pptr->port_tran);
10105 	}
10106 
10107 	mutex_enter(&fcp_global_mutex);
10108 
10109 	/*
10110 	 * We check soft_state_linked, because it is incremented right before
10111 	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10112 	 * soft_state_linked is still FALSE, we do not want to decrement
10113 	 * fcp_watchdog_init or possibly call untimeout.
10114 	 */
10115 
10116 	if (soft_state_linked) {
10117 		if (--fcp_watchdog_init == 0) {
10118 			timeout_id_t	tid = fcp_watchdog_id;
10119 
10120 			mutex_exit(&fcp_global_mutex);
10121 			(void) untimeout(tid);
10122 		} else {
10123 			mutex_exit(&fcp_global_mutex);
10124 		}
10125 	} else {
10126 		mutex_exit(&fcp_global_mutex);
10127 	}
10128 
10129 	if (mutex_initted) {
10130 		mutex_destroy(&pptr->port_mutex);
10131 		mutex_destroy(&pptr->port_pkt_mutex);
10132 	}
10133 
10134 	if (tmp_list != NULL) {
10135 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10136 	}
10137 
10138 	/* this makes pptr invalid */
10139 	ddi_soft_state_free(fcp_softstate, instance);
10140 
10141 	return (DDI_FAILURE);
10142 }
10143 
10144 
10145 static int
10146 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10147 {
10148 	int count = 0;
10149 
10150 	mutex_enter(&pptr->port_mutex);
10151 
10152 	/*
10153 	 * if the port is powered down or suspended, nothing else
10154 	 * to do; just return.
10155 	 */
10156 	if (flag != FCP_STATE_DETACHING) {
10157 		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10158 		    FCP_STATE_SUSPENDED)) {
10159 			pptr->port_state |= flag;
10160 			mutex_exit(&pptr->port_mutex);
10161 			return (FC_SUCCESS);
10162 		}
10163 	}
10164 
10165 	if (pptr->port_state & FCP_STATE_IN_MDI) {
10166 		mutex_exit(&pptr->port_mutex);
10167 		return (FC_FAILURE);
10168 	}
10169 
10170 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10171 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10172 	    "fcp_handle_port_detach: port is detaching");
10173 
10174 	pptr->port_state |= flag;
10175 
10176 	/*
10177 	 * Wait for any ongoing reconfig/ipkt to complete, that
10178 	 * ensures the freeing to targets/luns is safe.
10179 	 * No more ref to this port should happen from statec/ioctl
10180 	 * after that as it was removed from the global port list.
10181 	 */
10182 	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10183 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10184 		/*
10185 		 * Let's give sufficient time for reconfig/ipkt
10186 		 * to complete.
10187 		 */
10188 		if (count++ >= FCP_ICMD_DEADLINE) {
10189 			break;
10190 		}
10191 		mutex_exit(&pptr->port_mutex);
10192 		delay(drv_usectohz(1000000));
10193 		mutex_enter(&pptr->port_mutex);
10194 	}
10195 
10196 	/*
10197 	 * if the driver is still busy then fail to
10198 	 * suspend/power down.
10199 	 */
10200 	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10201 	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10202 		pptr->port_state &= ~flag;
10203 		mutex_exit(&pptr->port_mutex);
10204 		return (FC_FAILURE);
10205 	}
10206 
10207 	if (flag == FCP_STATE_DETACHING) {
10208 		pptr = fcp_soft_state_unlink(pptr);
10209 		ASSERT(pptr != NULL);
10210 	}
10211 
10212 	pptr->port_link_cnt++;
10213 	pptr->port_state |= FCP_STATE_OFFLINE;
10214 	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10215 
10216 	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10217 	    FCP_CAUSE_LINK_DOWN);
10218 	mutex_exit(&pptr->port_mutex);
10219 
10220 	/* kill watch dog timer if we're the last */
10221 	mutex_enter(&fcp_global_mutex);
10222 	if (--fcp_watchdog_init == 0) {
10223 		timeout_id_t	tid = fcp_watchdog_id;
10224 		mutex_exit(&fcp_global_mutex);
10225 		(void) untimeout(tid);
10226 	} else {
10227 		mutex_exit(&fcp_global_mutex);
10228 	}
10229 
10230 	/* clean up the port structures */
10231 	if (flag == FCP_STATE_DETACHING) {
10232 		fcp_cleanup_port(pptr, instance);
10233 	}
10234 
10235 	return (FC_SUCCESS);
10236 }
10237 
10238 
10239 static void
10240 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10241 {
10242 	ASSERT(pptr != NULL);
10243 
10244 	/* unbind and free event set */
10245 	if (pptr->port_ndi_event_hdl) {
10246 		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10247 		    &pptr->port_ndi_events, NDI_SLEEP);
10248 		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10249 	}
10250 
10251 	if (pptr->port_ndi_event_defs) {
10252 		(void) kmem_free(pptr->port_ndi_event_defs,
10253 		    sizeof (fcp_ndi_event_defs));
10254 	}
10255 
10256 	/* free the lun/target structures and devinfos */
10257 	fcp_free_targets(pptr);
10258 
10259 	/*
10260 	 * Clean up mpxio stuff
10261 	 */
10262 	if (pptr->port_mpxio) {
10263 		(void) mdi_phci_unregister(pptr->port_dip, 0);
10264 		pptr->port_mpxio--;
10265 	}
10266 
10267 	/* clean up SCSA stuff */
10268 	(void) scsi_hba_detach(pptr->port_dip);
10269 	if (pptr->port_tran != NULL) {
10270 		scsi_hba_tran_free(pptr->port_tran);
10271 	}
10272 
10273 #ifdef	KSTATS_CODE
10274 	/* clean up kstats */
10275 	if (pptr->fcp_ksp != NULL) {
10276 		kstat_delete(pptr->fcp_ksp);
10277 	}
10278 #endif
10279 
10280 	/* clean up soft state mutexes/condition variables */
10281 	mutex_destroy(&pptr->port_mutex);
10282 	mutex_destroy(&pptr->port_pkt_mutex);
10283 
10284 	/* all done with soft state */
10285 	ddi_soft_state_free(fcp_softstate, instance);
10286 }
10287 
10288 /*
10289  *     Function: fcp_kmem_cache_constructor
10290  *
10291  *  Description: This function allocates and initializes the resources required
10292  *		 to build a scsi_pkt structure the target driver.  The result
10293  *		 of the allocation and initialization will be cached in the
10294  *		 memory cache.	As DMA resources may be allocated here, that
10295  *		 means DMA resources will be tied up in the cache manager.
10296  *		 This is a tradeoff that has been made for performance reasons.
10297  *
10298  *     Argument: *buf		Memory to preinitialize.
10299  *		 *arg		FCP port structure (fcp_port).
10300  *		 kmflags	Value passed to kmem_cache_alloc() and
10301  *				propagated to the constructor.
10302  *
10303  * Return Value: 0	Allocation/Initialization was successful.
10304  *		 -1	Allocation or Initialization failed.
10305  *
10306  *
10307  * If the returned value is 0, the buffer is initialized like this:
10308  *
10309  *		    +================================+
10310  *	     +----> |	      struct scsi_pkt	     |
10311  *	     |	    |				     |
10312  *	     | +--- | pkt_ha_private		     |
10313  *	     | |    |				     |
10314  *	     | |    +================================+
10315  *	     | |
10316  *	     | |    +================================+
10317  *	     | +--> |	    struct fcp_pkt	     | <---------+
10318  *	     |	    |				     |		 |
10319  *	     +----- | cmd_pkt			     |		 |
10320  *		    |			  cmd_fp_pkt | ---+	 |
10321  *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10322  *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10323  *	  |    |    |--------------------------------|	  |	 |
10324  *	  |    |    |	      struct fc_packet	     | <--+	 |
10325  *	  |    |    |				     |		 |
10326  *	  |    |    |		     pkt_ulp_private | ----------+
10327  *	  |    |    |		     pkt_fca_private | -----+
10328  *	  |    |    |		     pkt_data_cookie | ---+ |
10329  *	  |    |    | pkt_cmdlen		     |	  | |
10330  *	  |    |(a) | pkt_rsplen		     |	  | |
10331  *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10332  *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10333  *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10334  *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10335  *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10336  *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10337  *		    +================================+	  | |  |   |   |    |
10338  *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10339  *		    |				     |	    |  |   |   |    |
10340  *		    +================================+	    |  |   |   |    |
10341  *		    |	      fca_private	     | <----+  |   |   |    |
10342  *		    |				     |	       |   |   |    |
10343  *		    +================================+	       |   |   |    |
10344  *							       |   |   |    |
10345  *							       |   |   |    |
10346  *		    +================================+	 (d)   |   |   |    |
10347  *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10348  *		    |				     |		   |   |    |
10349  *		    +================================+		   |   |    |
10350  *								   |   |    |
10351  *		    +================================+	 (d)	   |   |    |
10352  *		    |		fcp_resp	     | <-----------+   |    |
10353  *		    |	(DMA resources associated)   |		       |    |
10354  *		    +================================+		       |    |
10355  *								       |    |
10356  *								       |    |
10357  *								       |    |
10358  *		    +================================+	 (c)	       |    |
10359  *		    |	     fcp_cmd cookies	     | <---------------+    |
10360  *		    |				     |			    |
10361  *		    +================================+			    |
10362  *									    |
10363  *		    +================================+	 (c)		    |
10364  *		    |		 fcp_cmd	     | <--------------------+
10365  *		    |	(DMA resources associated)   |
10366  *		    +================================+
10367  *
10368  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10369  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10370  * (c) Only if DMA is used for the FCP_CMD buffer.
10371  * (d) Only if DMA is used for the FCP_RESP buffer
10372  */
10373 static int
10374 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10375     int kmflags)
10376 {
10377 	struct fcp_pkt	*cmd;
10378 	struct fcp_port	*pptr;
10379 	fc_packet_t	*fpkt;
10380 
10381 	pptr = (struct fcp_port *)tran->tran_hba_private;
10382 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10383 	bzero(cmd, tran->tran_hba_len);
10384 
10385 	cmd->cmd_pkt = pkt;
10386 	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10387 	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10388 	cmd->cmd_fp_pkt = fpkt;
10389 
10390 	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10391 	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10392 	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10393 	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10394 
10395 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10396 	    sizeof (struct fcp_pkt));
10397 
10398 	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10399 	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10400 
10401 	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10402 		/*
10403 		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10404 		 * fcp_resp.  The transfer of information will be done by
10405 		 * bcopy.
10406 		 * The naming of the flags (that is actually a value) is
10407 		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10408 		 * DMA" but instead "NO DMA".
10409 		 */
10410 		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10411 		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10412 		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10413 	} else {
10414 		/*
10415 		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10416 		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10417 		 * interfaces.
10418 		 */
10419 		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10420 			return (-1);
10421 		}
10422 	}
10423 
10424 	return (0);
10425 }
10426 
10427 /*
10428  *     Function: fcp_kmem_cache_destructor
10429  *
10430  *  Description: Called by the destructor of the cache managed by SCSA.
10431  *		 All the resources pre-allocated in fcp_pkt_constructor
10432  *		 and the data also pre-initialized in fcp_pkt_constructor
10433  *		 are freed and uninitialized here.
10434  *
10435  *     Argument: *buf		Memory to uninitialize.
10436  *		 *arg		FCP port structure (fcp_port).
10437  *
10438  * Return Value: None
10439  *
10440  *	Context: kernel
10441  */
10442 static void
10443 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10444 {
10445 	struct fcp_pkt	*cmd;
10446 	struct fcp_port	*pptr;
10447 
10448 	pptr = (struct fcp_port *)(tran->tran_hba_private);
10449 	cmd = pkt->pkt_ha_private;
10450 
10451 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10452 		/*
10453 		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10454 		 * buffer and DMA resources allocated to do so are released.
10455 		 */
10456 		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10457 	}
10458 }
10459 
10460 /*
10461  *     Function: fcp_alloc_cmd_resp
10462  *
10463  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10464  *		 will be DMAed by the HBA.  The buffer is allocated applying
10465  *		 the DMA requirements for the HBA.  The buffers allocated will
10466  *		 also be bound.	 DMA resources are allocated in the process.
10467  *		 They will be released by fcp_free_cmd_resp().
10468  *
10469  *     Argument: *pptr	FCP port.
10470  *		 *fpkt	fc packet for which the cmd and resp packet should be
10471  *			allocated.
10472  *		 flags	Allocation flags.
10473  *
10474  * Return Value: FC_FAILURE
10475  *		 FC_SUCCESS
10476  *
10477  *	Context: User or Kernel context only if flags == KM_SLEEP.
10478  *		 Interrupt context if the KM_SLEEP is not specified.
10479  */
10480 static int
10481 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10482 {
10483 	int			rval;
10484 	int			cmd_len;
10485 	int			resp_len;
10486 	ulong_t			real_len;
10487 	int			(*cb) (caddr_t);
10488 	ddi_dma_cookie_t	pkt_cookie;
10489 	ddi_dma_cookie_t	*cp;
10490 	uint32_t		cnt;
10491 
10492 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10493 
10494 	cmd_len = fpkt->pkt_cmdlen;
10495 	resp_len = fpkt->pkt_rsplen;
10496 
10497 	ASSERT(fpkt->pkt_cmd_dma == NULL);
10498 
10499 	/* Allocation of a DMA handle used in subsequent calls. */
10500 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10501 	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10502 		return (FC_FAILURE);
10503 	}
10504 
10505 	/* A buffer is allocated that satisfies the DMA requirements. */
10506 	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10507 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10508 	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10509 
10510 	if (rval != DDI_SUCCESS) {
10511 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10512 		return (FC_FAILURE);
10513 	}
10514 
10515 	if (real_len < cmd_len) {
10516 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10517 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10518 		return (FC_FAILURE);
10519 	}
10520 
10521 	/* The buffer allocated is DMA bound. */
10522 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10523 	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10524 	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10525 
10526 	if (rval != DDI_DMA_MAPPED) {
10527 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10528 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10529 		return (FC_FAILURE);
10530 	}
10531 
10532 	if (fpkt->pkt_cmd_cookie_cnt >
10533 	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10534 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10535 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10536 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10537 		return (FC_FAILURE);
10538 	}
10539 
10540 	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10541 
10542 	/*
10543 	 * The buffer where the scatter/gather list is going to be built is
10544 	 * allocated.
10545 	 */
10546 	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10547 	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10548 	    KM_NOSLEEP);
10549 
10550 	if (cp == NULL) {
10551 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10552 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10553 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10554 		return (FC_FAILURE);
10555 	}
10556 
10557 	/*
10558 	 * The scatter/gather list for the buffer we just allocated is built
10559 	 * here.
10560 	 */
10561 	*cp = pkt_cookie;
10562 	cp++;
10563 
10564 	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10565 		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10566 		    &pkt_cookie);
10567 		*cp = pkt_cookie;
10568 	}
10569 
10570 	ASSERT(fpkt->pkt_resp_dma == NULL);
10571 	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10572 	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10573 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10574 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10575 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10576 		return (FC_FAILURE);
10577 	}
10578 
10579 	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10580 	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10581 	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10582 	    &fpkt->pkt_resp_acc);
10583 
10584 	if (rval != DDI_SUCCESS) {
10585 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10586 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10587 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10588 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10589 		kmem_free(fpkt->pkt_cmd_cookie,
10590 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10591 		return (FC_FAILURE);
10592 	}
10593 
10594 	if (real_len < resp_len) {
10595 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10596 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10597 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10598 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10599 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10600 		kmem_free(fpkt->pkt_cmd_cookie,
10601 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10602 		return (FC_FAILURE);
10603 	}
10604 
10605 	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10606 	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10607 	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10608 
10609 	if (rval != DDI_DMA_MAPPED) {
10610 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10611 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10612 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10613 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10614 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10615 		kmem_free(fpkt->pkt_cmd_cookie,
10616 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10617 		return (FC_FAILURE);
10618 	}
10619 
10620 	if (fpkt->pkt_resp_cookie_cnt >
10621 	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10622 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10623 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10624 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10625 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10626 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10627 		kmem_free(fpkt->pkt_cmd_cookie,
10628 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10629 		return (FC_FAILURE);
10630 	}
10631 
10632 	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10633 
10634 	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10635 	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10636 	    KM_NOSLEEP);
10637 
10638 	if (cp == NULL) {
10639 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10640 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10641 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10642 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10643 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10644 		kmem_free(fpkt->pkt_cmd_cookie,
10645 		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10646 		return (FC_FAILURE);
10647 	}
10648 
10649 	*cp = pkt_cookie;
10650 	cp++;
10651 
10652 	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10653 		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10654 		    &pkt_cookie);
10655 		*cp = pkt_cookie;
10656 	}
10657 
10658 	return (FC_SUCCESS);
10659 }
10660 
10661 /*
10662  *     Function: fcp_free_cmd_resp
10663  *
10664  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10665  *		 allocated by fcp_alloc_cmd_resp() and all the resources
10666  *		 associated with them.	That includes the DMA resources and the
10667  *		 buffer allocated for the cookies of each one of them.
10668  *
10669  *     Argument: *pptr		FCP port context.
10670  *		 *fpkt		fc packet containing the cmd and resp packet
10671  *				to be released.
10672  *
10673  * Return Value: None
10674  *
10675  *	Context: Interrupt, User and Kernel context.
10676  */
10677 /* ARGSUSED */
10678 static void
10679 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10680 {
10681 	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10682 
10683 	if (fpkt->pkt_resp_dma) {
10684 		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10685 		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10686 		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10687 	}
10688 
10689 	if (fpkt->pkt_resp_cookie) {
10690 		kmem_free(fpkt->pkt_resp_cookie,
10691 		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10692 		fpkt->pkt_resp_cookie = NULL;
10693 	}
10694 
10695 	if (fpkt->pkt_cmd_dma) {
10696 		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10697 		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10698 		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10699 	}
10700 
10701 	if (fpkt->pkt_cmd_cookie) {
10702 		kmem_free(fpkt->pkt_cmd_cookie,
10703 		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10704 		fpkt->pkt_cmd_cookie = NULL;
10705 	}
10706 }
10707 
10708 
10709 /*
10710  * called by the transport to do our own target initialization
10711  *
10712  * can acquire and release the global mutex
10713  */
10714 /* ARGSUSED */
10715 static int
10716 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10717     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10718 {
10719 	uchar_t			*bytes;
10720 	uint_t			nbytes;
10721 	uint16_t		lun_num;
10722 	struct fcp_tgt	*ptgt;
10723 	struct fcp_lun	*plun;
10724 	struct fcp_port	*pptr = (struct fcp_port *)
10725 	    hba_tran->tran_hba_private;
10726 
10727 	ASSERT(pptr != NULL);
10728 
10729 	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10730 	    FCP_BUF_LEVEL_8, 0,
10731 	    "fcp_phys_tgt_init: called for %s (instance %d)",
10732 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10733 
10734 	/* get our port WWN property */
10735 	bytes = NULL;
10736 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10737 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10738 	    (nbytes != FC_WWN_SIZE)) {
10739 		/* no port WWN property */
10740 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10741 		    FCP_BUF_LEVEL_8, 0,
10742 		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10743 		    " for %s (instance %d): bytes=%p nbytes=%x",
10744 		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10745 		    nbytes);
10746 
10747 		if (bytes != NULL) {
10748 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10749 		}
10750 
10751 		return (DDI_NOT_WELL_FORMED);
10752 	}
10753 	ASSERT(bytes != NULL);
10754 
10755 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10756 	    LUN_PROP, 0xFFFF);
10757 	if (lun_num == 0xFFFF) {
10758 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10759 		    FCP_BUF_LEVEL_8, 0,
10760 		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10761 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10762 		    ddi_get_instance(tgt_dip));
10763 
10764 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10765 		return (DDI_NOT_WELL_FORMED);
10766 	}
10767 
10768 	mutex_enter(&pptr->port_mutex);
10769 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10770 		mutex_exit(&pptr->port_mutex);
10771 		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10772 		    FCP_BUF_LEVEL_8, 0,
10773 		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10774 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10775 		    ddi_get_instance(tgt_dip));
10776 
10777 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10778 		return (DDI_FAILURE);
10779 	}
10780 
10781 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10782 	    FC_WWN_SIZE) == 0);
10783 	ASSERT(plun->lun_num == lun_num);
10784 
10785 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10786 
10787 	ptgt = plun->lun_tgt;
10788 
10789 	mutex_enter(&ptgt->tgt_mutex);
10790 	plun->lun_tgt_count++;
10791 	scsi_device_hba_private_set(sd, plun);
10792 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10793 	plun->lun_sd = sd;
10794 	mutex_exit(&ptgt->tgt_mutex);
10795 	mutex_exit(&pptr->port_mutex);
10796 
10797 	return (DDI_SUCCESS);
10798 }
10799 
10800 /*ARGSUSED*/
10801 static int
10802 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10803     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10804 {
10805 	uchar_t			*bytes;
10806 	uint_t			nbytes;
10807 	uint16_t		lun_num;
10808 	struct fcp_tgt	*ptgt;
10809 	struct fcp_lun	*plun;
10810 	struct fcp_port	*pptr = (struct fcp_port *)
10811 	    hba_tran->tran_hba_private;
10812 	child_info_t		*cip;
10813 
10814 	ASSERT(pptr != NULL);
10815 
10816 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10817 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10818 	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10819 	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10820 	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10821 
10822 	cip = (child_info_t *)sd->sd_pathinfo;
10823 	if (cip == NULL) {
10824 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10825 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10826 		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10827 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10828 		    ddi_get_instance(tgt_dip));
10829 
10830 		return (DDI_NOT_WELL_FORMED);
10831 	}
10832 
10833 	/* get our port WWN property */
10834 	bytes = NULL;
10835 	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10836 	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10837 	    (nbytes != FC_WWN_SIZE)) {
10838 		if (bytes) {
10839 			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10840 		}
10841 		return (DDI_NOT_WELL_FORMED);
10842 	}
10843 
10844 	ASSERT(bytes != NULL);
10845 
10846 	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10847 	    LUN_PROP, 0xFFFF);
10848 	if (lun_num == 0xFFFF) {
10849 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10850 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10851 		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10852 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10853 		    ddi_get_instance(tgt_dip));
10854 
10855 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10856 		return (DDI_NOT_WELL_FORMED);
10857 	}
10858 
10859 	mutex_enter(&pptr->port_mutex);
10860 	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10861 		mutex_exit(&pptr->port_mutex);
10862 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10863 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10864 		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10865 		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10866 		    ddi_get_instance(tgt_dip));
10867 
10868 		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10869 		return (DDI_FAILURE);
10870 	}
10871 
10872 	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10873 	    FC_WWN_SIZE) == 0);
10874 	ASSERT(plun->lun_num == lun_num);
10875 
10876 	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10877 
10878 	ptgt = plun->lun_tgt;
10879 
10880 	mutex_enter(&ptgt->tgt_mutex);
10881 	plun->lun_tgt_count++;
10882 	scsi_device_hba_private_set(sd, plun);
10883 	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10884 	plun->lun_sd = sd;
10885 	mutex_exit(&ptgt->tgt_mutex);
10886 	mutex_exit(&pptr->port_mutex);
10887 
10888 	return (DDI_SUCCESS);
10889 }
10890 
10891 
10892 /*
10893  * called by the transport to do our own target initialization
10894  *
10895  * can acquire and release the global mutex
10896  */
10897 /* ARGSUSED */
10898 static int
10899 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10900     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10901 {
10902 	struct fcp_port	*pptr = (struct fcp_port *)
10903 	    hba_tran->tran_hba_private;
10904 	int			rval;
10905 
10906 	ASSERT(pptr != NULL);
10907 
10908 	/*
10909 	 * Child node is getting initialized.  Look at the mpxio component
10910 	 * type on the child device to see if this device is mpxio managed
10911 	 * or not.
10912 	 */
10913 	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
10914 		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
10915 	} else {
10916 		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
10917 	}
10918 
10919 	return (rval);
10920 }
10921 
10922 
10923 /* ARGSUSED */
10924 static void
10925 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10926     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10927 {
10928 	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
10929 	struct fcp_tgt	*ptgt;
10930 
10931 	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
10932 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10933 	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
10934 	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
10935 	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10936 
10937 	if (plun == NULL) {
10938 		return;
10939 	}
10940 	ptgt = plun->lun_tgt;
10941 
10942 	ASSERT(ptgt != NULL);
10943 
10944 	mutex_enter(&ptgt->tgt_mutex);
10945 	ASSERT(plun->lun_tgt_count > 0);
10946 
10947 	if (--plun->lun_tgt_count == 0) {
10948 		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
10949 	}
10950 	plun->lun_sd = NULL;
10951 	mutex_exit(&ptgt->tgt_mutex);
10952 }
10953 
10954 /*
10955  *     Function: fcp_scsi_start
10956  *
10957  *  Description: This function is called by the target driver to request a
10958  *		 command to be sent.
10959  *
10960  *     Argument: *ap		SCSI address of the device.
10961  *		 *pkt		SCSI packet containing the cmd to send.
10962  *
10963  * Return Value: TRAN_ACCEPT
10964  *		 TRAN_BUSY
10965  *		 TRAN_BADPKT
10966  *		 TRAN_FATAL_ERROR
10967  */
10968 static int
10969 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
10970 {
10971 	struct fcp_port	*pptr = ADDR2FCP(ap);
10972 	struct fcp_lun	*plun = ADDR2LUN(ap);
10973 	struct fcp_pkt	*cmd = PKT2CMD(pkt);
10974 	struct fcp_tgt	*ptgt = plun->lun_tgt;
10975 	int			rval;
10976 
10977 	/* ensure command isn't already issued */
10978 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
10979 
10980 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10981 	    fcp_trace, FCP_BUF_LEVEL_9, 0,
10982 	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
10983 
10984 	/*
10985 	 * It is strange that we enter the fcp_port mutex and the target
10986 	 * mutex to check the lun state (which has a mutex of its own).
10987 	 */
10988 	mutex_enter(&pptr->port_mutex);
10989 	mutex_enter(&ptgt->tgt_mutex);
10990 
10991 	/*
10992 	 * If the device is offline and is not in the process of coming
10993 	 * online, fail the request.
10994 	 */
10995 
10996 	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
10997 	    !(plun->lun_state & FCP_LUN_ONLINING)) {
10998 		mutex_exit(&ptgt->tgt_mutex);
10999 		mutex_exit(&pptr->port_mutex);
11000 
11001 		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11002 			pkt->pkt_reason = CMD_DEV_GONE;
11003 		}
11004 
11005 		return (TRAN_FATAL_ERROR);
11006 	}
11007 	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11008 
11009 	/*
11010 	 * If we are suspended, kernel is trying to dump, so don't
11011 	 * block, fail or defer requests - send them down right away.
11012 	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11013 	 * assume we have been suspended.  There is hardware such as
11014 	 * the v880 that doesn't do PM.	 Thus, the check for
11015 	 * ddi_in_panic.
11016 	 *
11017 	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11018 	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11019 	 * either the device will have gone away or changed and we can fail
11020 	 * the request, or we can proceed if the device didn't change.
11021 	 *
11022 	 * If the pd in the target or the packet is NULL it's probably
11023 	 * because the device has gone away, we allow the request to be
11024 	 * put on the internal queue here in case the device comes back within
11025 	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11026 	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11027 	 * could be NULL because the device was disappearing during or since
11028 	 * packet initialization.
11029 	 */
11030 
11031 	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11032 	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11033 	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11034 	    (ptgt->tgt_pd_handle == NULL) ||
11035 	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11036 		/*
11037 		 * If ((LUN is busy AND
11038 		 *	LUN not suspended AND
11039 		 *	The system is not in panic state) OR
11040 		 *	(The port is coming up))
11041 		 *
11042 		 * We check to see if the any of the flags FLAG_NOINTR or
11043 		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11044 		 * returned will be TRAN_BUSY.	If not, the request is queued.
11045 		 */
11046 		mutex_exit(&ptgt->tgt_mutex);
11047 		mutex_exit(&pptr->port_mutex);
11048 
11049 		/* see if using interrupts is allowed (so queueing'll work) */
11050 		if (pkt->pkt_flags & FLAG_NOINTR) {
11051 			pkt->pkt_resid = 0;
11052 			return (TRAN_BUSY);
11053 		}
11054 		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11055 			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11056 			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11057 			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11058 			return (TRAN_BUSY);
11059 		}
11060 #ifdef	DEBUG
11061 		mutex_enter(&pptr->port_pkt_mutex);
11062 		pptr->port_npkts++;
11063 		mutex_exit(&pptr->port_pkt_mutex);
11064 #endif /* DEBUG */
11065 
11066 		/* got queue up the pkt for later */
11067 		fcp_queue_pkt(pptr, cmd);
11068 		return (TRAN_ACCEPT);
11069 	}
11070 	cmd->cmd_state = FCP_PKT_ISSUED;
11071 
11072 	mutex_exit(&ptgt->tgt_mutex);
11073 	mutex_exit(&pptr->port_mutex);
11074 
11075 	/*
11076 	 * Now that we released the mutexes, what was protected by them can
11077 	 * change.
11078 	 */
11079 
11080 	/*
11081 	 * If there is a reconfiguration in progress, wait for it to complete.
11082 	 */
11083 	fcp_reconfig_wait(pptr);
11084 
11085 	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11086 	    pkt->pkt_time : 0;
11087 
11088 	/* prepare the packet */
11089 
11090 	fcp_prepare_pkt(pptr, cmd, plun);
11091 
11092 	if (cmd->cmd_pkt->pkt_time) {
11093 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11094 	} else {
11095 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11096 	}
11097 
11098 	/*
11099 	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11100 	 * have to do polled I/O
11101 	 */
11102 	if (pkt->pkt_flags & FLAG_NOINTR) {
11103 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11104 		return (fcp_dopoll(pptr, cmd));
11105 	}
11106 
11107 #ifdef	DEBUG
11108 	mutex_enter(&pptr->port_pkt_mutex);
11109 	pptr->port_npkts++;
11110 	mutex_exit(&pptr->port_pkt_mutex);
11111 #endif /* DEBUG */
11112 
11113 	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11114 	if (rval == FC_SUCCESS) {
11115 		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11116 		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11117 		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11118 		return (TRAN_ACCEPT);
11119 	}
11120 
11121 	cmd->cmd_state = FCP_PKT_IDLE;
11122 
11123 #ifdef	DEBUG
11124 	mutex_enter(&pptr->port_pkt_mutex);
11125 	pptr->port_npkts--;
11126 	mutex_exit(&pptr->port_pkt_mutex);
11127 #endif /* DEBUG */
11128 
11129 	/*
11130 	 * For lack of clearer definitions, choose
11131 	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11132 	 */
11133 
11134 	if (rval == FC_TRAN_BUSY) {
11135 		pkt->pkt_resid = 0;
11136 		rval = TRAN_BUSY;
11137 	} else {
11138 		mutex_enter(&ptgt->tgt_mutex);
11139 		if (plun->lun_state & FCP_LUN_OFFLINE) {
11140 			child_info_t	*cip;
11141 
11142 			mutex_enter(&plun->lun_mutex);
11143 			cip = plun->lun_cip;
11144 			mutex_exit(&plun->lun_mutex);
11145 
11146 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11147 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11148 			    "fcp_transport failed 2 for %x: %x; dip=%p",
11149 			    plun->lun_tgt->tgt_d_id, rval, cip);
11150 
11151 			rval = TRAN_FATAL_ERROR;
11152 		} else {
11153 			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11154 				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11155 				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11156 				    "fcp_scsi_start: FC_BUSY for pkt %p",
11157 				    pkt);
11158 				rval = TRAN_BUSY;
11159 			} else {
11160 				rval = TRAN_ACCEPT;
11161 				fcp_queue_pkt(pptr, cmd);
11162 			}
11163 		}
11164 		mutex_exit(&ptgt->tgt_mutex);
11165 	}
11166 
11167 	return (rval);
11168 }
11169 
11170 /*
11171  * called by the transport to abort a packet
11172  */
11173 /*ARGSUSED*/
11174 static int
11175 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11176 {
11177 	int tgt_cnt;
11178 	struct fcp_port		*pptr = ADDR2FCP(ap);
11179 	struct fcp_lun	*plun = ADDR2LUN(ap);
11180 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11181 
11182 	if (pkt == NULL) {
11183 		if (ptgt) {
11184 			mutex_enter(&ptgt->tgt_mutex);
11185 			tgt_cnt = ptgt->tgt_change_cnt;
11186 			mutex_exit(&ptgt->tgt_mutex);
11187 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11188 			return (TRUE);
11189 		}
11190 	}
11191 	return (FALSE);
11192 }
11193 
11194 
11195 /*
11196  * Perform reset
11197  */
11198 int
11199 fcp_scsi_reset(struct scsi_address *ap, int level)
11200 {
11201 	int			rval = 0;
11202 	struct fcp_port		*pptr = ADDR2FCP(ap);
11203 	struct fcp_lun	*plun = ADDR2LUN(ap);
11204 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11205 
11206 	if (level == RESET_ALL) {
11207 		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11208 			rval = 1;
11209 		}
11210 	} else if (level == RESET_TARGET || level == RESET_LUN) {
11211 		/*
11212 		 * If we are in the middle of discovery, return
11213 		 * SUCCESS as this target will be rediscovered
11214 		 * anyway
11215 		 */
11216 		mutex_enter(&ptgt->tgt_mutex);
11217 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11218 			mutex_exit(&ptgt->tgt_mutex);
11219 			return (1);
11220 		}
11221 		mutex_exit(&ptgt->tgt_mutex);
11222 
11223 		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11224 			rval = 1;
11225 		}
11226 	}
11227 	return (rval);
11228 }
11229 
11230 
11231 /*
11232  * called by the framework to get a SCSI capability
11233  */
11234 static int
11235 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11236 {
11237 	return (fcp_commoncap(ap, cap, 0, whom, 0));
11238 }
11239 
11240 
11241 /*
11242  * called by the framework to set a SCSI capability
11243  */
11244 static int
11245 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11246 {
11247 	return (fcp_commoncap(ap, cap, value, whom, 1));
11248 }
11249 
11250 /*
11251  *     Function: fcp_pkt_setup
11252  *
11253  *  Description: This function sets up the scsi_pkt structure passed by the
11254  *		 caller. This function assumes fcp_pkt_constructor has been
11255  *		 called previously for the packet passed by the caller.	 If
11256  *		 successful this call will have the following results:
11257  *
11258  *		   - The resources needed that will be constant through out
11259  *		     the whole transaction are allocated.
11260  *		   - The fields that will be constant through out the whole
11261  *		     transaction are initialized.
11262  *		   - The scsi packet will be linked to the LUN structure
11263  *		     addressed by the transaction.
11264  *
11265  *     Argument:
11266  *		 *pkt		Pointer to a scsi_pkt structure.
11267  *		 callback
11268  *		 arg
11269  *
11270  * Return Value: 0	Success
11271  *		 !0	Failure
11272  *
11273  *	Context: Kernel context or interrupt context
11274  */
11275 /* ARGSUSED */
11276 static int
11277 fcp_pkt_setup(struct scsi_pkt *pkt,
11278     int (*callback)(caddr_t arg),
11279     caddr_t arg)
11280 {
11281 	struct fcp_pkt	*cmd;
11282 	struct fcp_port	*pptr;
11283 	struct fcp_lun	*plun;
11284 	struct fcp_tgt	*ptgt;
11285 	int		kf;
11286 	fc_packet_t	*fpkt;
11287 	fc_frame_hdr_t	*hp;
11288 
11289 	pptr = ADDR2FCP(&pkt->pkt_address);
11290 	plun = ADDR2LUN(&pkt->pkt_address);
11291 	ptgt = plun->lun_tgt;
11292 
11293 	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11294 	fpkt = cmd->cmd_fp_pkt;
11295 
11296 	/*
11297 	 * this request is for dma allocation only
11298 	 */
11299 	/*
11300 	 * First step of fcp_scsi_init_pkt: pkt allocation
11301 	 * We determine if the caller is willing to wait for the
11302 	 * resources.
11303 	 */
11304 	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11305 
11306 	/*
11307 	 * Selective zeroing of the pkt.
11308 	 */
11309 	cmd->cmd_back = NULL;
11310 	cmd->cmd_next = NULL;
11311 
11312 	/*
11313 	 * Zero out fcp command
11314 	 */
11315 	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11316 
11317 	cmd->cmd_state = FCP_PKT_IDLE;
11318 
11319 	fpkt = cmd->cmd_fp_pkt;
11320 	fpkt->pkt_data_acc = NULL;
11321 
11322 	/*
11323 	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11324 	 * could be destroyed.	We need fail pkt_setup.
11325 	 */
11326 	if (pptr->port_state & FCP_STATE_OFFLINE) {
11327 		return (-1);
11328 	}
11329 
11330 	mutex_enter(&ptgt->tgt_mutex);
11331 	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11332 
11333 	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11334 	    != FC_SUCCESS) {
11335 		mutex_exit(&ptgt->tgt_mutex);
11336 		return (-1);
11337 	}
11338 
11339 	mutex_exit(&ptgt->tgt_mutex);
11340 
11341 	/* Fill in the Fabric Channel Header */
11342 	hp = &fpkt->pkt_cmd_fhdr;
11343 	hp->r_ctl = R_CTL_COMMAND;
11344 	hp->rsvd = 0;
11345 	hp->type = FC_TYPE_SCSI_FCP;
11346 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11347 	hp->seq_id = 0;
11348 	hp->df_ctl  = 0;
11349 	hp->seq_cnt = 0;
11350 	hp->ox_id = 0xffff;
11351 	hp->rx_id = 0xffff;
11352 	hp->ro = 0;
11353 
11354 	/*
11355 	 * A doubly linked list (cmd_forw, cmd_back) is built
11356 	 * out of every allocated packet on a per-lun basis
11357 	 *
11358 	 * The packets are maintained in the list so as to satisfy
11359 	 * scsi_abort() requests. At present (which is unlikely to
11360 	 * change in the future) nobody performs a real scsi_abort
11361 	 * in the SCSI target drivers (as they don't keep the packets
11362 	 * after doing scsi_transport - so they don't know how to
11363 	 * abort a packet other than sending a NULL to abort all
11364 	 * outstanding packets)
11365 	 */
11366 	mutex_enter(&plun->lun_mutex);
11367 	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11368 		plun->lun_pkt_head->cmd_back = cmd;
11369 	} else {
11370 		plun->lun_pkt_tail = cmd;
11371 	}
11372 	plun->lun_pkt_head = cmd;
11373 	mutex_exit(&plun->lun_mutex);
11374 	return (0);
11375 }
11376 
11377 /*
11378  *     Function: fcp_pkt_teardown
11379  *
11380  *  Description: This function releases a scsi_pkt structure and all the
11381  *		 resources attached to it.
11382  *
11383  *     Argument: *pkt		Pointer to a scsi_pkt structure.
11384  *
11385  * Return Value: None
11386  *
11387  *	Context: User, Kernel or Interrupt context.
11388  */
11389 static void
11390 fcp_pkt_teardown(struct scsi_pkt *pkt)
11391 {
11392 	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11393 	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11394 	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11395 
11396 	/*
11397 	 * Remove the packet from the per-lun list
11398 	 */
11399 	mutex_enter(&plun->lun_mutex);
11400 	if (cmd->cmd_back) {
11401 		ASSERT(cmd != plun->lun_pkt_head);
11402 		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11403 	} else {
11404 		ASSERT(cmd == plun->lun_pkt_head);
11405 		plun->lun_pkt_head = cmd->cmd_forw;
11406 	}
11407 
11408 	if (cmd->cmd_forw) {
11409 		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11410 	} else {
11411 		ASSERT(cmd == plun->lun_pkt_tail);
11412 		plun->lun_pkt_tail = cmd->cmd_back;
11413 	}
11414 
11415 	mutex_exit(&plun->lun_mutex);
11416 
11417 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11418 }
11419 
11420 /*
11421  * Routine for reset notification setup, to register or cancel.
11422  * This function is called by SCSA
11423  */
11424 /*ARGSUSED*/
11425 static int
11426 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11427     void (*callback)(caddr_t), caddr_t arg)
11428 {
11429 	struct fcp_port *pptr = ADDR2FCP(ap);
11430 
11431 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11432 	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11433 }
11434 
11435 
11436 static int
11437 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11438     ddi_eventcookie_t *event_cookiep)
11439 {
11440 	struct fcp_port *pptr = fcp_dip2port(dip);
11441 
11442 	if (pptr == NULL) {
11443 		return (DDI_FAILURE);
11444 	}
11445 
11446 	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11447 	    event_cookiep, NDI_EVENT_NOPASS));
11448 }
11449 
11450 
11451 static int
11452 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11453     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11454     ddi_callback_id_t *cb_id)
11455 {
11456 	struct fcp_port *pptr = fcp_dip2port(dip);
11457 
11458 	if (pptr == NULL) {
11459 		return (DDI_FAILURE);
11460 	}
11461 
11462 	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11463 	    eventid, callback, arg, NDI_SLEEP, cb_id));
11464 }
11465 
11466 
11467 static int
11468 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11469 {
11470 
11471 	struct fcp_port *pptr = fcp_dip2port(dip);
11472 
11473 	if (pptr == NULL) {
11474 		return (DDI_FAILURE);
11475 	}
11476 	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11477 }
11478 
11479 
11480 /*
11481  * called by the transport to post an event
11482  */
11483 static int
11484 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11485     ddi_eventcookie_t eventid, void *impldata)
11486 {
11487 	struct fcp_port *pptr = fcp_dip2port(dip);
11488 
11489 	if (pptr == NULL) {
11490 		return (DDI_FAILURE);
11491 	}
11492 
11493 	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11494 	    eventid, impldata));
11495 }
11496 
11497 
11498 /*
11499  * A target in in many cases in Fibre Channel has a one to one relation
11500  * with a port identifier (which is also known as D_ID and also as AL_PA
11501  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11502  * will most likely result in resetting all LUNs (which means a reset will
11503  * occur on all the SCSI devices connected at the other end of the bridge)
11504  * That is the latest favorite topic for discussion, for, one can debate as
11505  * hot as one likes and come up with arguably a best solution to one's
11506  * satisfaction
11507  *
11508  * To stay on track and not digress much, here are the problems stated
11509  * briefly:
11510  *
11511  *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11512  *	target drivers use RESET_TARGET even if their instance is on a
11513  *	LUN. Doesn't that sound a bit broken ?
11514  *
11515  *	FCP SCSI (the current spec) only defines RESET TARGET in the
11516  *	control fields of an FCP_CMND structure. It should have been
11517  *	fixed right there, giving flexibility to the initiators to
11518  *	minimize havoc that could be caused by resetting a target.
11519  */
11520 static int
11521 fcp_reset_target(struct scsi_address *ap, int level)
11522 {
11523 	int			rval = FC_FAILURE;
11524 	char			lun_id[25];
11525 	struct fcp_port		*pptr = ADDR2FCP(ap);
11526 	struct fcp_lun	*plun = ADDR2LUN(ap);
11527 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11528 	struct scsi_pkt		*pkt;
11529 	struct fcp_pkt	*cmd;
11530 	struct fcp_rsp		*rsp;
11531 	uint32_t		tgt_cnt;
11532 	struct fcp_rsp_info	*rsp_info;
11533 	struct fcp_reset_elem	*p;
11534 	int			bval;
11535 
11536 	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11537 	    KM_NOSLEEP)) == NULL) {
11538 		return (rval);
11539 	}
11540 
11541 	mutex_enter(&ptgt->tgt_mutex);
11542 	if (level == RESET_TARGET) {
11543 		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11544 			mutex_exit(&ptgt->tgt_mutex);
11545 			kmem_free(p, sizeof (struct fcp_reset_elem));
11546 			return (rval);
11547 		}
11548 		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11549 		(void) strcpy(lun_id, " ");
11550 	} else {
11551 		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11552 			mutex_exit(&ptgt->tgt_mutex);
11553 			kmem_free(p, sizeof (struct fcp_reset_elem));
11554 			return (rval);
11555 		}
11556 		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11557 
11558 		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11559 	}
11560 	tgt_cnt = ptgt->tgt_change_cnt;
11561 
11562 	mutex_exit(&ptgt->tgt_mutex);
11563 
11564 	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11565 	    0, 0, NULL, 0)) == NULL) {
11566 		kmem_free(p, sizeof (struct fcp_reset_elem));
11567 		mutex_enter(&ptgt->tgt_mutex);
11568 		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11569 		mutex_exit(&ptgt->tgt_mutex);
11570 		return (rval);
11571 	}
11572 	pkt->pkt_time = FCP_POLL_TIMEOUT;
11573 
11574 	/* fill in cmd part of packet */
11575 	cmd = PKT2CMD(pkt);
11576 	if (level == RESET_TARGET) {
11577 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11578 	} else {
11579 		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11580 	}
11581 	cmd->cmd_fp_pkt->pkt_comp = NULL;
11582 	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11583 
11584 	/* prepare a packet for transport */
11585 	fcp_prepare_pkt(pptr, cmd, plun);
11586 
11587 	if (cmd->cmd_pkt->pkt_time) {
11588 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11589 	} else {
11590 		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11591 	}
11592 
11593 	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11594 	bval = fcp_dopoll(pptr, cmd);
11595 	fc_ulp_idle_port(pptr->port_fp_handle);
11596 
11597 	/* submit the packet */
11598 	if (bval == TRAN_ACCEPT) {
11599 		int error = 3;
11600 
11601 		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11602 		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11603 		    sizeof (struct fcp_rsp));
11604 
11605 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11606 			if (fcp_validate_fcp_response(rsp, pptr) ==
11607 			    FC_SUCCESS) {
11608 				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11609 					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11610 					    sizeof (struct fcp_rsp), rsp_info,
11611 					    cmd->cmd_fp_pkt->pkt_resp_acc,
11612 					    sizeof (struct fcp_rsp_info));
11613 				}
11614 				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11615 					rval = FC_SUCCESS;
11616 					error = 0;
11617 				} else {
11618 					error = 1;
11619 				}
11620 			} else {
11621 				error = 2;
11622 			}
11623 		}
11624 
11625 		switch (error) {
11626 		case 0:
11627 			fcp_log(CE_WARN, pptr->port_dip,
11628 			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11629 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11630 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11631 			break;
11632 
11633 		case 1:
11634 			fcp_log(CE_WARN, pptr->port_dip,
11635 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11636 			    " response code=%x",
11637 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11638 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11639 			    rsp_info->rsp_code);
11640 			break;
11641 
11642 		case 2:
11643 			fcp_log(CE_WARN, pptr->port_dip,
11644 			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11645 			    " Bad FCP response values: rsvd1=%x,"
11646 			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11647 			    " rsplen=%x, senselen=%x",
11648 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11649 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11650 			    rsp->reserved_0, rsp->reserved_1,
11651 			    rsp->fcp_u.fcp_status.reserved_0,
11652 			    rsp->fcp_u.fcp_status.reserved_1,
11653 			    rsp->fcp_response_len, rsp->fcp_sense_len);
11654 			break;
11655 
11656 		default:
11657 			fcp_log(CE_WARN, pptr->port_dip,
11658 			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11659 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11660 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11661 			break;
11662 		}
11663 	}
11664 	scsi_destroy_pkt(pkt);
11665 
11666 	if (rval == FC_FAILURE) {
11667 		mutex_enter(&ptgt->tgt_mutex);
11668 		if (level == RESET_TARGET) {
11669 			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11670 		} else {
11671 			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11672 		}
11673 		mutex_exit(&ptgt->tgt_mutex);
11674 		kmem_free(p, sizeof (struct fcp_reset_elem));
11675 		return (rval);
11676 	}
11677 
11678 	mutex_enter(&pptr->port_mutex);
11679 	if (level == RESET_TARGET) {
11680 		p->tgt = ptgt;
11681 		p->lun = NULL;
11682 	} else {
11683 		p->tgt = NULL;
11684 		p->lun = plun;
11685 	}
11686 	p->tgt = ptgt;
11687 	p->tgt_cnt = tgt_cnt;
11688 	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11689 	p->next = pptr->port_reset_list;
11690 	pptr->port_reset_list = p;
11691 
11692 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11693 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11694 	    "Notify ssd of the reset to reinstate the reservations");
11695 
11696 	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11697 	    &pptr->port_reset_notify_listf);
11698 
11699 	mutex_exit(&pptr->port_mutex);
11700 
11701 	return (rval);
11702 }
11703 
11704 
11705 /*
11706  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11707  * SCSI capabilities
11708  */
11709 /* ARGSUSED */
11710 static int
11711 fcp_commoncap(struct scsi_address *ap, char *cap,
11712     int val, int tgtonly, int doset)
11713 {
11714 	struct fcp_port		*pptr = ADDR2FCP(ap);
11715 	struct fcp_lun	*plun = ADDR2LUN(ap);
11716 	struct fcp_tgt	*ptgt = plun->lun_tgt;
11717 	int			cidx;
11718 	int			rval = FALSE;
11719 
11720 	if (cap == (char *)0) {
11721 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11722 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11723 		    "fcp_commoncap: invalid arg");
11724 		return (rval);
11725 	}
11726 
11727 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11728 		return (UNDEFINED);
11729 	}
11730 
11731 	/*
11732 	 * Process setcap request.
11733 	 */
11734 	if (doset) {
11735 		/*
11736 		 * At present, we can only set binary (0/1) values
11737 		 */
11738 		switch (cidx) {
11739 		case SCSI_CAP_ARQ:
11740 			if (val == 0) {
11741 				rval = FALSE;
11742 			} else {
11743 				rval = TRUE;
11744 			}
11745 			break;
11746 
11747 		case SCSI_CAP_LUN_RESET:
11748 			if (val) {
11749 				plun->lun_cap |= FCP_LUN_CAP_RESET;
11750 			} else {
11751 				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11752 			}
11753 			rval = TRUE;
11754 			break;
11755 
11756 		case SCSI_CAP_SECTOR_SIZE:
11757 			rval = TRUE;
11758 			break;
11759 		default:
11760 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11761 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11762 			    "fcp_setcap: unsupported %d", cidx);
11763 			rval = UNDEFINED;
11764 			break;
11765 		}
11766 
11767 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11768 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11769 		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11770 		    "0x%x/0x%x/0x%x/%d",
11771 		    cap, val, tgtonly, doset, rval);
11772 
11773 	} else {
11774 		/*
11775 		 * Process getcap request.
11776 		 */
11777 		switch (cidx) {
11778 		case SCSI_CAP_DMA_MAX:
11779 			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11780 
11781 			/*
11782 			 * Need to make an adjustment qlc is uint_t 64
11783 			 * st is int, so we will make the adjustment here
11784 			 * being as nobody wants to touch this.
11785 			 * It still leaves the max single block length
11786 			 * of 2 gig. This should last .
11787 			 */
11788 
11789 			if (rval == -1) {
11790 				rval = MAX_INT_DMA;
11791 			}
11792 
11793 			break;
11794 
11795 		case SCSI_CAP_INITIATOR_ID:
11796 			rval = pptr->port_id;
11797 			break;
11798 
11799 		case SCSI_CAP_ARQ:
11800 		case SCSI_CAP_RESET_NOTIFICATION:
11801 		case SCSI_CAP_TAGGED_QING:
11802 			rval = TRUE;
11803 			break;
11804 
11805 		case SCSI_CAP_SCSI_VERSION:
11806 			rval = 3;
11807 			break;
11808 
11809 		case SCSI_CAP_INTERCONNECT_TYPE:
11810 			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11811 			    (ptgt->tgt_hard_addr == 0)) {
11812 				rval = INTERCONNECT_FABRIC;
11813 			} else {
11814 				rval = INTERCONNECT_FIBRE;
11815 			}
11816 			break;
11817 
11818 		case SCSI_CAP_LUN_RESET:
11819 			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11820 			    TRUE : FALSE;
11821 			break;
11822 
11823 		default:
11824 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11825 			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11826 			    "fcp_getcap: unsupported %d", cidx);
11827 			rval = UNDEFINED;
11828 			break;
11829 		}
11830 
11831 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11832 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11833 		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11834 		    "0x%x/0x%x/0x%x/%d",
11835 		    cap, val, tgtonly, doset, rval);
11836 	}
11837 
11838 	return (rval);
11839 }
11840 
11841 /*
11842  * called by the transport to get the port-wwn and lun
11843  * properties of this device, and to create a "name" based on them
11844  *
11845  * these properties don't exist on sun4m
11846  *
11847  * return 1 for success else return 0
11848  */
11849 /* ARGSUSED */
11850 static int
11851 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11852 {
11853 	int			i;
11854 	int			*lun;
11855 	int			numChars;
11856 	uint_t			nlun;
11857 	uint_t			count;
11858 	uint_t			nbytes;
11859 	uchar_t			*bytes;
11860 	uint16_t		lun_num;
11861 	uint32_t		tgt_id;
11862 	char			**conf_wwn;
11863 	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11864 	uchar_t			barray[FC_WWN_SIZE];
11865 	dev_info_t		*tgt_dip;
11866 	struct fcp_tgt	*ptgt;
11867 	struct fcp_port	*pptr;
11868 	struct fcp_lun	*plun;
11869 
11870 	ASSERT(sd != NULL);
11871 	ASSERT(name != NULL);
11872 
11873 	tgt_dip = sd->sd_dev;
11874 	pptr = ddi_get_soft_state(fcp_softstate,
11875 	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11876 	if (pptr == NULL) {
11877 		return (0);
11878 	}
11879 
11880 	ASSERT(tgt_dip != NULL);
11881 
11882 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11883 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11884 	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11885 		name[0] = '\0';
11886 		return (0);
11887 	}
11888 
11889 	if (nlun == 0) {
11890 		ddi_prop_free(lun);
11891 		return (0);
11892 	}
11893 
11894 	lun_num = lun[0];
11895 	ddi_prop_free(lun);
11896 
11897 	/*
11898 	 * Lookup for .conf WWN property
11899 	 */
11900 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
11901 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
11902 	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
11903 		ASSERT(count >= 1);
11904 
11905 		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
11906 		ddi_prop_free(conf_wwn);
11907 		mutex_enter(&pptr->port_mutex);
11908 		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
11909 			mutex_exit(&pptr->port_mutex);
11910 			return (0);
11911 		}
11912 		ptgt = plun->lun_tgt;
11913 		mutex_exit(&pptr->port_mutex);
11914 
11915 		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
11916 		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
11917 
11918 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
11919 		    ptgt->tgt_hard_addr != 0) {
11920 			tgt_id = (uint32_t)fcp_alpa_to_switch[
11921 			    ptgt->tgt_hard_addr];
11922 		} else {
11923 			tgt_id = ptgt->tgt_d_id;
11924 		}
11925 
11926 		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
11927 		    TARGET_PROP, tgt_id);
11928 	}
11929 
11930 	/* get the our port-wwn property */
11931 	bytes = NULL;
11932 	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
11933 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
11934 	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
11935 		if (bytes != NULL) {
11936 			ddi_prop_free(bytes);
11937 		}
11938 		return (0);
11939 	}
11940 
11941 	for (i = 0; i < FC_WWN_SIZE; i++) {
11942 		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
11943 	}
11944 
11945 	/* Stick in the address of the form "wWWN,LUN" */
11946 	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
11947 
11948 	ASSERT(numChars < len);
11949 	if (numChars >= len) {
11950 		fcp_log(CE_WARN, pptr->port_dip,
11951 		    "!fcp_scsi_get_name: "
11952 		    "name parameter length too small, it needs to be %d",
11953 		    numChars+1);
11954 	}
11955 
11956 	ddi_prop_free(bytes);
11957 
11958 	return (1);
11959 }
11960 
11961 
11962 /*
11963  * called by the transport to get the SCSI target id value, returning
11964  * it in "name"
11965  *
11966  * this isn't needed/used on sun4m
11967  *
11968  * return 1 for success else return 0
11969  */
11970 /* ARGSUSED */
11971 static int
11972 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
11973 {
11974 	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
11975 	struct fcp_tgt	*ptgt;
11976 	int    numChars;
11977 
11978 	if (plun == NULL) {
11979 		return (0);
11980 	}
11981 
11982 	if ((ptgt = plun->lun_tgt) == NULL) {
11983 		return (0);
11984 	}
11985 
11986 	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
11987 
11988 	ASSERT(numChars < len);
11989 	if (numChars >= len) {
11990 		fcp_log(CE_WARN, NULL,
11991 		    "!fcp_scsi_get_bus_addr: "
11992 		    "name parameter length too small, it needs to be %d",
11993 		    numChars+1);
11994 	}
11995 
11996 	return (1);
11997 }
11998 
11999 
12000 /*
12001  * called internally to reset the link where the specified port lives
12002  */
12003 static int
12004 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12005 {
12006 	la_wwn_t		wwn;
12007 	struct fcp_lun	*plun;
12008 	struct fcp_tgt	*ptgt;
12009 
12010 	/* disable restart of lip if we're suspended */
12011 	mutex_enter(&pptr->port_mutex);
12012 
12013 	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12014 	    FCP_STATE_POWER_DOWN)) {
12015 		mutex_exit(&pptr->port_mutex);
12016 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12017 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12018 		    "fcp_linkreset, fcp%d: link reset "
12019 		    "disabled due to DDI_SUSPEND",
12020 		    ddi_get_instance(pptr->port_dip));
12021 		return (FC_FAILURE);
12022 	}
12023 
12024 	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12025 		mutex_exit(&pptr->port_mutex);
12026 		return (FC_SUCCESS);
12027 	}
12028 
12029 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12030 	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12031 
12032 	/*
12033 	 * If ap == NULL assume local link reset.
12034 	 */
12035 	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12036 		plun = ADDR2LUN(ap);
12037 		ptgt = plun->lun_tgt;
12038 		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12039 	} else {
12040 		bzero((caddr_t)&wwn, sizeof (wwn));
12041 	}
12042 	mutex_exit(&pptr->port_mutex);
12043 
12044 	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12045 }
12046 
12047 
12048 /*
12049  * called from fcp_port_attach() to resume a port
12050  * return DDI_* success/failure status
12051  * acquires and releases the global mutex
12052  * acquires and releases the port mutex
12053  */
12054 /*ARGSUSED*/
12055 
12056 static int
12057 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12058     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12059 {
12060 	int			res = DDI_FAILURE; /* default result */
12061 	struct fcp_port	*pptr;		/* port state ptr */
12062 	uint32_t		alloc_cnt;
12063 	uint32_t		max_cnt;
12064 	fc_portmap_t		*tmp_list = NULL;
12065 
12066 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12067 	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12068 	    instance);
12069 
12070 	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12071 		cmn_err(CE_WARN, "fcp: bad soft state");
12072 		return (res);
12073 	}
12074 
12075 	mutex_enter(&pptr->port_mutex);
12076 	switch (cmd) {
12077 	case FC_CMD_RESUME:
12078 		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12079 		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12080 		break;
12081 
12082 	case FC_CMD_POWER_UP:
12083 		/*
12084 		 * If the port is DDI_SUSPENded, defer rediscovery
12085 		 * until DDI_RESUME occurs
12086 		 */
12087 		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12088 			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12089 			mutex_exit(&pptr->port_mutex);
12090 			return (DDI_SUCCESS);
12091 		}
12092 		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12093 	}
12094 	pptr->port_id = s_id;
12095 	pptr->port_state = FCP_STATE_INIT;
12096 	mutex_exit(&pptr->port_mutex);
12097 
12098 	/*
12099 	 * Make a copy of ulp_port_info as fctl allocates
12100 	 * a temp struct.
12101 	 */
12102 	(void) fcp_cp_pinfo(pptr, pinfo);
12103 
12104 	mutex_enter(&fcp_global_mutex);
12105 	if (fcp_watchdog_init++ == 0) {
12106 		fcp_watchdog_tick = fcp_watchdog_timeout *
12107 		    drv_usectohz(1000000);
12108 		fcp_watchdog_id = timeout(fcp_watch,
12109 		    NULL, fcp_watchdog_tick);
12110 	}
12111 	mutex_exit(&fcp_global_mutex);
12112 
12113 	/*
12114 	 * Handle various topologies and link states.
12115 	 */
12116 	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12117 	case FC_STATE_OFFLINE:
12118 		/*
12119 		 * Wait for ONLINE, at which time a state
12120 		 * change will cause a statec_callback
12121 		 */
12122 		res = DDI_SUCCESS;
12123 		break;
12124 
12125 	case FC_STATE_ONLINE:
12126 
12127 		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12128 			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12129 			res = DDI_SUCCESS;
12130 			break;
12131 		}
12132 
12133 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12134 		    !fcp_enable_auto_configuration) {
12135 			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12136 			if (tmp_list == NULL) {
12137 				if (!alloc_cnt) {
12138 					res = DDI_SUCCESS;
12139 				}
12140 				break;
12141 			}
12142 			max_cnt = alloc_cnt;
12143 		} else {
12144 			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12145 
12146 			alloc_cnt = FCP_MAX_DEVICES;
12147 
12148 			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12149 			    (sizeof (fc_portmap_t)) * alloc_cnt,
12150 			    KM_NOSLEEP)) == NULL) {
12151 				fcp_log(CE_WARN, pptr->port_dip,
12152 				    "!fcp%d: failed to allocate portmap",
12153 				    instance);
12154 				break;
12155 			}
12156 
12157 			max_cnt = alloc_cnt;
12158 			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12159 			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12160 			    FC_SUCCESS) {
12161 				caddr_t msg;
12162 
12163 				(void) fc_ulp_error(res, &msg);
12164 
12165 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12166 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12167 				    "resume failed getportmap: reason=0x%x",
12168 				    res);
12169 
12170 				fcp_log(CE_WARN, pptr->port_dip,
12171 				    "!failed to get port map : %s", msg);
12172 				break;
12173 			}
12174 			if (max_cnt > alloc_cnt) {
12175 				alloc_cnt = max_cnt;
12176 			}
12177 		}
12178 
12179 		/*
12180 		 * do the SCSI device discovery and create
12181 		 * the devinfos
12182 		 */
12183 		fcp_statec_callback(ulph, pptr->port_fp_handle,
12184 		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12185 		    max_cnt, pptr->port_id);
12186 
12187 		res = DDI_SUCCESS;
12188 		break;
12189 
12190 	default:
12191 		fcp_log(CE_WARN, pptr->port_dip,
12192 		    "!fcp%d: invalid port state at attach=0x%x",
12193 		    instance, pptr->port_phys_state);
12194 
12195 		mutex_enter(&pptr->port_mutex);
12196 		pptr->port_phys_state = FCP_STATE_OFFLINE;
12197 		mutex_exit(&pptr->port_mutex);
12198 		res = DDI_SUCCESS;
12199 
12200 		break;
12201 	}
12202 
12203 	if (tmp_list != NULL) {
12204 		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12205 	}
12206 
12207 	return (res);
12208 }
12209 
12210 
12211 static void
12212 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12213 {
12214 	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12215 	pptr->port_dip = pinfo->port_dip;
12216 	pptr->port_fp_handle = pinfo->port_handle;
12217 	pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12218 	pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12219 	pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12220 	pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12221 	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12222 	pptr->port_max_exch = pinfo->port_fca_max_exch;
12223 	pptr->port_phys_state = pinfo->port_state;
12224 	pptr->port_topology = pinfo->port_flags;
12225 	pptr->port_reset_action = pinfo->port_reset_action;
12226 	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12227 	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12228 	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12229 	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12230 
12231 	/* Clear FMA caps to avoid fm-capability ereport */
12232 	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12233 		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12234 	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12235 		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12236 	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12237 		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12238 }
12239 
12240 /*
12241  * If the elements wait field is set to 1 then
12242  * another thread is waiting for the operation to complete. Once
12243  * it is complete, the waiting thread is signaled and the element is
12244  * freed by the waiting thread. If the elements wait field is set to 0
12245  * the element is freed.
12246  */
12247 static void
12248 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12249 {
12250 	ASSERT(elem != NULL);
12251 	mutex_enter(&elem->mutex);
12252 	elem->result = result;
12253 	if (elem->wait) {
12254 		elem->wait = 0;
12255 		cv_signal(&elem->cv);
12256 		mutex_exit(&elem->mutex);
12257 	} else {
12258 		mutex_exit(&elem->mutex);
12259 		cv_destroy(&elem->cv);
12260 		mutex_destroy(&elem->mutex);
12261 		kmem_free(elem, sizeof (struct fcp_hp_elem));
12262 	}
12263 }
12264 
12265 /*
12266  * This function is invoked from the taskq thread to allocate
12267  * devinfo nodes and to online/offline them.
12268  */
12269 static void
12270 fcp_hp_task(void *arg)
12271 {
12272 	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12273 	struct fcp_lun	*plun = elem->lun;
12274 	struct fcp_port		*pptr = elem->port;
12275 	int			result;
12276 
12277 	ASSERT(elem->what == FCP_ONLINE ||
12278 	    elem->what == FCP_OFFLINE ||
12279 	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12280 	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12281 
12282 	mutex_enter(&pptr->port_mutex);
12283 	mutex_enter(&plun->lun_mutex);
12284 	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12285 	    plun->lun_event_count != elem->event_cnt) ||
12286 	    pptr->port_state & (FCP_STATE_SUSPENDED |
12287 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12288 		mutex_exit(&plun->lun_mutex);
12289 		mutex_exit(&pptr->port_mutex);
12290 		fcp_process_elem(elem, NDI_FAILURE);
12291 		return;
12292 	}
12293 	mutex_exit(&plun->lun_mutex);
12294 	mutex_exit(&pptr->port_mutex);
12295 
12296 	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12297 	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12298 	fcp_process_elem(elem, result);
12299 }
12300 
12301 
12302 static child_info_t *
12303 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12304     int tcount)
12305 {
12306 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12307 
12308 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12309 		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12310 
12311 		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12312 		/*
12313 		 * Child has not been created yet. Create the child device
12314 		 * based on the per-Lun flags.
12315 		 */
12316 		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12317 			plun->lun_cip =
12318 			    CIP(fcp_create_dip(plun, lcount, tcount));
12319 			plun->lun_mpxio = 0;
12320 		} else {
12321 			plun->lun_cip =
12322 			    CIP(fcp_create_pip(plun, lcount, tcount));
12323 			plun->lun_mpxio = 1;
12324 		}
12325 	} else {
12326 		plun->lun_cip = cip;
12327 	}
12328 
12329 	return (plun->lun_cip);
12330 }
12331 
12332 
12333 static int
12334 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12335 {
12336 	int		rval = FC_FAILURE;
12337 	dev_info_t	*pdip;
12338 	struct dev_info	*dip;
12339 	int		circular;
12340 
12341 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12342 
12343 	pdip = plun->lun_tgt->tgt_port->port_dip;
12344 
12345 	if (plun->lun_cip == NULL) {
12346 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12347 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12348 		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12349 		    "plun: %p lun state: %x num: %d target state: %x",
12350 		    plun, plun->lun_state, plun->lun_num,
12351 		    plun->lun_tgt->tgt_port->port_state);
12352 		return (rval);
12353 	}
12354 	ndi_devi_enter(pdip, &circular);
12355 	dip = DEVI(pdip)->devi_child;
12356 	while (dip) {
12357 		if (dip == DEVI(cdip)) {
12358 			rval = FC_SUCCESS;
12359 			break;
12360 		}
12361 		dip = dip->devi_sibling;
12362 	}
12363 	ndi_devi_exit(pdip, circular);
12364 	return (rval);
12365 }
12366 
12367 static int
12368 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12369 {
12370 	int		rval = FC_FAILURE;
12371 
12372 	ASSERT(plun != NULL);
12373 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12374 
12375 	if (plun->lun_mpxio == 0) {
12376 		rval = fcp_is_dip_present(plun, DIP(cip));
12377 	} else {
12378 		rval = fcp_is_pip_present(plun, PIP(cip));
12379 	}
12380 
12381 	return (rval);
12382 }
12383 
12384 /*
12385  *     Function: fcp_create_dip
12386  *
12387  *  Description: Creates a dev_info_t structure for the LUN specified by the
12388  *		 caller.
12389  *
12390  *     Argument: plun		Lun structure
12391  *		 link_cnt	Link state count.
12392  *		 tgt_cnt	Target state change count.
12393  *
12394  * Return Value: NULL if it failed
12395  *		 dev_info_t structure address if it succeeded
12396  *
12397  *	Context: Kernel context
12398  */
12399 static dev_info_t *
12400 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12401 {
12402 	int			failure = 0;
12403 	uint32_t		tgt_id;
12404 	uint64_t		sam_lun;
12405 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12406 	struct fcp_port	*pptr = ptgt->tgt_port;
12407 	dev_info_t		*pdip = pptr->port_dip;
12408 	dev_info_t		*cdip = NULL;
12409 	dev_info_t		*old_dip = DIP(plun->lun_cip);
12410 	char			*nname = NULL;
12411 	char			**compatible = NULL;
12412 	int			ncompatible;
12413 	char			*scsi_binding_set;
12414 	char			t_pwwn[17];
12415 
12416 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12417 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12418 
12419 	/* get the 'scsi-binding-set' property */
12420 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12421 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12422 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12423 		scsi_binding_set = NULL;
12424 	}
12425 
12426 	/* determine the node name and compatible */
12427 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12428 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12429 	if (scsi_binding_set) {
12430 		ddi_prop_free(scsi_binding_set);
12431 	}
12432 
12433 	if (nname == NULL) {
12434 #ifdef	DEBUG
12435 		cmn_err(CE_WARN, "%s%d: no driver for "
12436 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12437 		    "	 compatible: %s",
12438 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12439 		    ptgt->tgt_port_wwn.raw_wwn[0],
12440 		    ptgt->tgt_port_wwn.raw_wwn[1],
12441 		    ptgt->tgt_port_wwn.raw_wwn[2],
12442 		    ptgt->tgt_port_wwn.raw_wwn[3],
12443 		    ptgt->tgt_port_wwn.raw_wwn[4],
12444 		    ptgt->tgt_port_wwn.raw_wwn[5],
12445 		    ptgt->tgt_port_wwn.raw_wwn[6],
12446 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12447 		    *compatible);
12448 #endif	/* DEBUG */
12449 		failure++;
12450 		goto end_of_fcp_create_dip;
12451 	}
12452 
12453 	cdip = fcp_find_existing_dip(plun, pdip, nname);
12454 
12455 	/*
12456 	 * if the old_dip does not match the cdip, that means there is
12457 	 * some property change. since we'll be using the cdip, we need
12458 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12459 	 * then the dtype for the device has been updated. Offline the
12460 	 * the old device and create a new device with the new device type
12461 	 * Refer to bug: 4764752
12462 	 */
12463 	if (old_dip && (cdip != old_dip ||
12464 	    plun->lun_state & FCP_LUN_CHANGED)) {
12465 		plun->lun_state &= ~(FCP_LUN_INIT);
12466 		mutex_exit(&plun->lun_mutex);
12467 		mutex_exit(&pptr->port_mutex);
12468 
12469 		mutex_enter(&ptgt->tgt_mutex);
12470 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12471 		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12472 		mutex_exit(&ptgt->tgt_mutex);
12473 
12474 #ifdef DEBUG
12475 		if (cdip != NULL) {
12476 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12477 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12478 			    "Old dip=%p; New dip=%p don't match", old_dip,
12479 			    cdip);
12480 		} else {
12481 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12482 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12483 			    "Old dip=%p; New dip=NULL don't match", old_dip);
12484 		}
12485 #endif
12486 
12487 		mutex_enter(&pptr->port_mutex);
12488 		mutex_enter(&plun->lun_mutex);
12489 	}
12490 
12491 	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12492 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12493 		if (ndi_devi_alloc(pptr->port_dip, nname,
12494 		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12495 			failure++;
12496 			goto end_of_fcp_create_dip;
12497 		}
12498 	}
12499 
12500 	/*
12501 	 * Previously all the properties for the devinfo were destroyed here
12502 	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12503 	 * the devid property (and other properties established by the target
12504 	 * driver or framework) which the code does not always recreate, this
12505 	 * call was removed.
12506 	 * This opens a theoretical possibility that we may return with a
12507 	 * stale devid on the node if the scsi entity behind the fibre channel
12508 	 * lun has changed.
12509 	 */
12510 
12511 	/* decorate the node with compatible */
12512 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12513 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12514 		failure++;
12515 		goto end_of_fcp_create_dip;
12516 	}
12517 
12518 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12519 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12520 		failure++;
12521 		goto end_of_fcp_create_dip;
12522 	}
12523 
12524 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12525 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12526 		failure++;
12527 		goto end_of_fcp_create_dip;
12528 	}
12529 
12530 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12531 	t_pwwn[16] = '\0';
12532 	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12533 	    != DDI_PROP_SUCCESS) {
12534 		failure++;
12535 		goto end_of_fcp_create_dip;
12536 	}
12537 
12538 	/*
12539 	 * If there is no hard address - We might have to deal with
12540 	 * that by using WWN - Having said that it is important to
12541 	 * recognize this problem early so ssd can be informed of
12542 	 * the right interconnect type.
12543 	 */
12544 	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12545 		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12546 	} else {
12547 		tgt_id = ptgt->tgt_d_id;
12548 	}
12549 
12550 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12551 	    tgt_id) != DDI_PROP_SUCCESS) {
12552 		failure++;
12553 		goto end_of_fcp_create_dip;
12554 	}
12555 
12556 	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12557 	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12558 		failure++;
12559 		goto end_of_fcp_create_dip;
12560 	}
12561 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12562 	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12563 	    sam_lun) != DDI_PROP_SUCCESS) {
12564 		failure++;
12565 		goto end_of_fcp_create_dip;
12566 	}
12567 
12568 end_of_fcp_create_dip:
12569 	scsi_hba_nodename_compatible_free(nname, compatible);
12570 
12571 	if (cdip != NULL && failure) {
12572 		(void) ndi_prop_remove_all(cdip);
12573 		(void) ndi_devi_free(cdip);
12574 		cdip = NULL;
12575 	}
12576 
12577 	return (cdip);
12578 }
12579 
12580 /*
12581  *     Function: fcp_create_pip
12582  *
12583  *  Description: Creates a Path Id for the LUN specified by the caller.
12584  *
12585  *     Argument: plun		Lun structure
12586  *		 link_cnt	Link state count.
12587  *		 tgt_cnt	Target state count.
12588  *
12589  * Return Value: NULL if it failed
12590  *		 mdi_pathinfo_t structure address if it succeeded
12591  *
12592  *	Context: Kernel context
12593  */
12594 static mdi_pathinfo_t *
12595 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12596 {
12597 	int			i;
12598 	char			buf[MAXNAMELEN];
12599 	char			uaddr[MAXNAMELEN];
12600 	int			failure = 0;
12601 	uint32_t		tgt_id;
12602 	uint64_t		sam_lun;
12603 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12604 	struct fcp_port	*pptr = ptgt->tgt_port;
12605 	dev_info_t		*pdip = pptr->port_dip;
12606 	mdi_pathinfo_t		*pip = NULL;
12607 	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12608 	char			*nname = NULL;
12609 	char			**compatible = NULL;
12610 	int			ncompatible;
12611 	char			*scsi_binding_set;
12612 	char			t_pwwn[17];
12613 
12614 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12615 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12616 
12617 	scsi_binding_set = "vhci";
12618 
12619 	/* determine the node name and compatible */
12620 	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12621 	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12622 
12623 	if (nname == NULL) {
12624 #ifdef	DEBUG
12625 		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12626 		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12627 		    "	 compatible: %s",
12628 		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12629 		    ptgt->tgt_port_wwn.raw_wwn[0],
12630 		    ptgt->tgt_port_wwn.raw_wwn[1],
12631 		    ptgt->tgt_port_wwn.raw_wwn[2],
12632 		    ptgt->tgt_port_wwn.raw_wwn[3],
12633 		    ptgt->tgt_port_wwn.raw_wwn[4],
12634 		    ptgt->tgt_port_wwn.raw_wwn[5],
12635 		    ptgt->tgt_port_wwn.raw_wwn[6],
12636 		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12637 		    *compatible);
12638 #endif	/* DEBUG */
12639 		failure++;
12640 		goto end_of_fcp_create_pip;
12641 	}
12642 
12643 	pip = fcp_find_existing_pip(plun, pdip);
12644 
12645 	/*
12646 	 * if the old_dip does not match the cdip, that means there is
12647 	 * some property change. since we'll be using the cdip, we need
12648 	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12649 	 * then the dtype for the device has been updated. Offline the
12650 	 * the old device and create a new device with the new device type
12651 	 * Refer to bug: 4764752
12652 	 */
12653 	if (old_pip && (pip != old_pip ||
12654 	    plun->lun_state & FCP_LUN_CHANGED)) {
12655 		plun->lun_state &= ~(FCP_LUN_INIT);
12656 		mutex_exit(&plun->lun_mutex);
12657 		mutex_exit(&pptr->port_mutex);
12658 
12659 		mutex_enter(&ptgt->tgt_mutex);
12660 		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12661 		    FCP_OFFLINE, lcount, tcount,
12662 		    NDI_DEVI_REMOVE, 0);
12663 		mutex_exit(&ptgt->tgt_mutex);
12664 
12665 		if (pip != NULL) {
12666 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12667 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12668 			    "Old pip=%p; New pip=%p don't match",
12669 			    old_pip, pip);
12670 		} else {
12671 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12672 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12673 			    "Old pip=%p; New pip=NULL don't match",
12674 			    old_pip);
12675 		}
12676 
12677 		mutex_enter(&pptr->port_mutex);
12678 		mutex_enter(&plun->lun_mutex);
12679 	}
12680 
12681 	/*
12682 	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12683 	 * lun_guid_size which is dependent on the target, I don't
12684 	 * believe the same trancation happens here UNLESS the standards
12685 	 * change the FC_WWN_SIZE value to something larger than
12686 	 * MAXNAMELEN(currently 255 bytes).
12687 	 */
12688 
12689 	for (i = 0; i < FC_WWN_SIZE; i++) {
12690 		(void) sprintf(&buf[i << 1], "%02x",
12691 		    ptgt->tgt_port_wwn.raw_wwn[i]);
12692 	}
12693 
12694 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12695 	    buf, plun->lun_num);
12696 
12697 	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12698 		/*
12699 		 * Release the locks before calling into
12700 		 * mdi_pi_alloc_compatible() since this can result in a
12701 		 * callback into fcp which can result in a deadlock
12702 		 * (see bug # 4870272).
12703 		 *
12704 		 * Basically, what we are trying to avoid is the scenario where
12705 		 * one thread does ndi_devi_enter() and tries to grab
12706 		 * fcp_mutex and another does it the other way round.
12707 		 *
12708 		 * But before we do that, make sure that nobody releases the
12709 		 * port in the meantime. We can do this by setting a flag.
12710 		 */
12711 		plun->lun_state &= ~(FCP_LUN_CHANGED);
12712 		pptr->port_state |= FCP_STATE_IN_MDI;
12713 		mutex_exit(&plun->lun_mutex);
12714 		mutex_exit(&pptr->port_mutex);
12715 		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12716 		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12717 			fcp_log(CE_WARN, pptr->port_dip,
12718 			    "!path alloc failed:0x%x", plun);
12719 			mutex_enter(&pptr->port_mutex);
12720 			mutex_enter(&plun->lun_mutex);
12721 			pptr->port_state &= ~FCP_STATE_IN_MDI;
12722 			failure++;
12723 			goto end_of_fcp_create_pip;
12724 		}
12725 		mutex_enter(&pptr->port_mutex);
12726 		mutex_enter(&plun->lun_mutex);
12727 		pptr->port_state &= ~FCP_STATE_IN_MDI;
12728 	} else {
12729 		(void) mdi_prop_remove(pip, NULL);
12730 	}
12731 
12732 	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12733 
12734 	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12735 	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12736 	    != DDI_PROP_SUCCESS) {
12737 		failure++;
12738 		goto end_of_fcp_create_pip;
12739 	}
12740 
12741 	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12742 	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12743 	    != DDI_PROP_SUCCESS) {
12744 		failure++;
12745 		goto end_of_fcp_create_pip;
12746 	}
12747 
12748 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12749 	t_pwwn[16] = '\0';
12750 	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12751 	    != DDI_PROP_SUCCESS) {
12752 		failure++;
12753 		goto end_of_fcp_create_pip;
12754 	}
12755 
12756 	/*
12757 	 * If there is no hard address - We might have to deal with
12758 	 * that by using WWN - Having said that it is important to
12759 	 * recognize this problem early so ssd can be informed of
12760 	 * the right interconnect type.
12761 	 */
12762 	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12763 	    ptgt->tgt_hard_addr != 0) {
12764 		tgt_id = (uint32_t)
12765 		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12766 	} else {
12767 		tgt_id = ptgt->tgt_d_id;
12768 	}
12769 
12770 	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12771 	    != DDI_PROP_SUCCESS) {
12772 		failure++;
12773 		goto end_of_fcp_create_pip;
12774 	}
12775 
12776 	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12777 	    != DDI_PROP_SUCCESS) {
12778 		failure++;
12779 		goto end_of_fcp_create_pip;
12780 	}
12781 	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12782 	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12783 	    != DDI_PROP_SUCCESS) {
12784 		failure++;
12785 		goto end_of_fcp_create_pip;
12786 	}
12787 
12788 end_of_fcp_create_pip:
12789 	scsi_hba_nodename_compatible_free(nname, compatible);
12790 
12791 	if (pip != NULL && failure) {
12792 		(void) mdi_prop_remove(pip, NULL);
12793 		mutex_exit(&plun->lun_mutex);
12794 		mutex_exit(&pptr->port_mutex);
12795 		(void) mdi_pi_free(pip, 0);
12796 		mutex_enter(&pptr->port_mutex);
12797 		mutex_enter(&plun->lun_mutex);
12798 		pip = NULL;
12799 	}
12800 
12801 	return (pip);
12802 }
12803 
12804 static dev_info_t *
12805 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12806 {
12807 	uint_t			nbytes;
12808 	uchar_t			*bytes;
12809 	uint_t			nwords;
12810 	uint32_t		tgt_id;
12811 	int			*words;
12812 	dev_info_t		*cdip;
12813 	dev_info_t		*ndip;
12814 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12815 	struct fcp_port	*pptr = ptgt->tgt_port;
12816 	int			circular;
12817 
12818 	ndi_devi_enter(pdip, &circular);
12819 
12820 	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12821 	while ((cdip = ndip) != NULL) {
12822 		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12823 
12824 		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12825 			continue;
12826 		}
12827 
12828 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12829 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12830 		    &nbytes) != DDI_PROP_SUCCESS) {
12831 			continue;
12832 		}
12833 
12834 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12835 			if (bytes != NULL) {
12836 				ddi_prop_free(bytes);
12837 			}
12838 			continue;
12839 		}
12840 		ASSERT(bytes != NULL);
12841 
12842 		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12843 			ddi_prop_free(bytes);
12844 			continue;
12845 		}
12846 
12847 		ddi_prop_free(bytes);
12848 
12849 		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12850 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12851 		    &nbytes) != DDI_PROP_SUCCESS) {
12852 			continue;
12853 		}
12854 
12855 		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12856 			if (bytes != NULL) {
12857 				ddi_prop_free(bytes);
12858 			}
12859 			continue;
12860 		}
12861 		ASSERT(bytes != NULL);
12862 
12863 		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12864 			ddi_prop_free(bytes);
12865 			continue;
12866 		}
12867 
12868 		ddi_prop_free(bytes);
12869 
12870 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12871 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12872 		    &nwords) != DDI_PROP_SUCCESS) {
12873 			continue;
12874 		}
12875 
12876 		if (nwords != 1 || words == NULL) {
12877 			if (words != NULL) {
12878 				ddi_prop_free(words);
12879 			}
12880 			continue;
12881 		}
12882 		ASSERT(words != NULL);
12883 
12884 		/*
12885 		 * If there is no hard address - We might have to deal with
12886 		 * that by using WWN - Having said that it is important to
12887 		 * recognize this problem early so ssd can be informed of
12888 		 * the right interconnect type.
12889 		 */
12890 		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12891 		    ptgt->tgt_hard_addr != 0) {
12892 			tgt_id =
12893 			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12894 		} else {
12895 			tgt_id = ptgt->tgt_d_id;
12896 		}
12897 
12898 		if (tgt_id != (uint32_t)*words) {
12899 			ddi_prop_free(words);
12900 			continue;
12901 		}
12902 		ddi_prop_free(words);
12903 
12904 		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12905 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
12906 		    &nwords) != DDI_PROP_SUCCESS) {
12907 			continue;
12908 		}
12909 
12910 		if (nwords != 1 || words == NULL) {
12911 			if (words != NULL) {
12912 				ddi_prop_free(words);
12913 			}
12914 			continue;
12915 		}
12916 		ASSERT(words != NULL);
12917 
12918 		if (plun->lun_num == (uint16_t)*words) {
12919 			ddi_prop_free(words);
12920 			break;
12921 		}
12922 		ddi_prop_free(words);
12923 	}
12924 	ndi_devi_exit(pdip, circular);
12925 
12926 	return (cdip);
12927 }
12928 
12929 
12930 static int
12931 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
12932 {
12933 	dev_info_t	*pdip;
12934 	char		buf[MAXNAMELEN];
12935 	char		uaddr[MAXNAMELEN];
12936 	int		rval = FC_FAILURE;
12937 
12938 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12939 
12940 	pdip = plun->lun_tgt->tgt_port->port_dip;
12941 
12942 	/*
12943 	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
12944 	 * non-NULL even when the LUN is not there as in the case when a LUN is
12945 	 * configured and then deleted on the device end (for T3/T4 case). In
12946 	 * such cases, pip will be NULL.
12947 	 *
12948 	 * If the device generates an RSCN, it will end up getting offlined when
12949 	 * it disappeared and a new LUN will get created when it is rediscovered
12950 	 * on the device. If we check for lun_cip here, the LUN will not end
12951 	 * up getting onlined since this function will end up returning a
12952 	 * FC_SUCCESS.
12953 	 *
12954 	 * The behavior is different on other devices. For instance, on a HDS,
12955 	 * there was no RSCN generated by the device but the next I/O generated
12956 	 * a check condition and rediscovery got triggered that way. So, in
12957 	 * such cases, this path will not be exercised
12958 	 */
12959 	if (pip == NULL) {
12960 		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12961 		    fcp_trace, FCP_BUF_LEVEL_4, 0,
12962 		    "fcp_is_pip_present: plun->lun_cip is NULL: "
12963 		    "plun: %p lun state: %x num: %d target state: %x",
12964 		    plun, plun->lun_state, plun->lun_num,
12965 		    plun->lun_tgt->tgt_port->port_state);
12966 		return (rval);
12967 	}
12968 
12969 	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
12970 
12971 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
12972 
12973 	if (plun->lun_old_guid) {
12974 		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
12975 			rval = FC_SUCCESS;
12976 		}
12977 	} else {
12978 		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
12979 			rval = FC_SUCCESS;
12980 		}
12981 	}
12982 	return (rval);
12983 }
12984 
12985 static mdi_pathinfo_t *
12986 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
12987 {
12988 	char			buf[MAXNAMELEN];
12989 	char			uaddr[MAXNAMELEN];
12990 	mdi_pathinfo_t		*pip;
12991 	struct fcp_tgt	*ptgt = plun->lun_tgt;
12992 	struct fcp_port	*pptr = ptgt->tgt_port;
12993 
12994 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12995 
12996 	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
12997 	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
12998 
12999 	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13000 
13001 	return (pip);
13002 }
13003 
13004 
13005 static int
13006 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13007     int tcount, int flags, int *circ)
13008 {
13009 	int			rval;
13010 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13011 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13012 	dev_info_t		*cdip = NULL;
13013 
13014 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13015 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13016 
13017 	if (plun->lun_cip == NULL) {
13018 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13019 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13020 		    "fcp_online_child: plun->lun_cip is NULL: "
13021 		    "plun: %p state: %x num: %d target state: %x",
13022 		    plun, plun->lun_state, plun->lun_num,
13023 		    plun->lun_tgt->tgt_port->port_state);
13024 		return (NDI_FAILURE);
13025 	}
13026 again:
13027 	if (plun->lun_mpxio == 0) {
13028 		cdip = DIP(cip);
13029 		mutex_exit(&plun->lun_mutex);
13030 		mutex_exit(&pptr->port_mutex);
13031 
13032 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13033 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13034 		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13035 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13036 
13037 		/*
13038 		 * We could check for FCP_LUN_INIT here but chances
13039 		 * of getting here when it's already in FCP_LUN_INIT
13040 		 * is rare and a duplicate ndi_devi_online wouldn't
13041 		 * hurt either (as the node would already have been
13042 		 * in CF2)
13043 		 */
13044 		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13045 			rval = ndi_devi_bind_driver(cdip, flags);
13046 		} else {
13047 			rval = ndi_devi_online(cdip, flags);
13048 		}
13049 		/*
13050 		 * We log the message into trace buffer if the device
13051 		 * is "ses" and into syslog for any other device
13052 		 * type. This is to prevent the ndi_devi_online failure
13053 		 * message that appears for V880/A5K ses devices.
13054 		 */
13055 		if (rval == NDI_SUCCESS) {
13056 			mutex_enter(&ptgt->tgt_mutex);
13057 			plun->lun_state |= FCP_LUN_INIT;
13058 			mutex_exit(&ptgt->tgt_mutex);
13059 		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13060 			fcp_log(CE_NOTE, pptr->port_dip,
13061 			    "!ndi_devi_online:"
13062 			    " failed for %s: target=%x lun=%x %x",
13063 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13064 			    plun->lun_num, rval);
13065 		} else {
13066 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13067 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13068 			    " !ndi_devi_online:"
13069 			    " failed for %s: target=%x lun=%x %x",
13070 			    ddi_get_name(cdip), ptgt->tgt_d_id,
13071 			    plun->lun_num, rval);
13072 		}
13073 	} else {
13074 		cdip = mdi_pi_get_client(PIP(cip));
13075 		mutex_exit(&plun->lun_mutex);
13076 		mutex_exit(&pptr->port_mutex);
13077 
13078 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13079 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13080 		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13081 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13082 
13083 		/*
13084 		 * Hold path and exit phci to avoid deadlock with power
13085 		 * management code during mdi_pi_online.
13086 		 */
13087 		mdi_hold_path(PIP(cip));
13088 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13089 
13090 		rval = mdi_pi_online(PIP(cip), flags);
13091 
13092 		mdi_devi_enter_phci(pptr->port_dip, circ);
13093 		mdi_rele_path(PIP(cip));
13094 
13095 		if (rval == MDI_SUCCESS) {
13096 			mutex_enter(&ptgt->tgt_mutex);
13097 			plun->lun_state |= FCP_LUN_INIT;
13098 			mutex_exit(&ptgt->tgt_mutex);
13099 
13100 			/*
13101 			 * Clear MPxIO path permanent disable in case
13102 			 * fcp hotplug dropped the offline event.
13103 			 */
13104 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13105 
13106 		} else if (rval == MDI_NOT_SUPPORTED) {
13107 			child_info_t	*old_cip = cip;
13108 
13109 			/*
13110 			 * MPxIO does not support this device yet.
13111 			 * Enumerate in legacy mode.
13112 			 */
13113 			mutex_enter(&pptr->port_mutex);
13114 			mutex_enter(&plun->lun_mutex);
13115 			plun->lun_mpxio = 0;
13116 			plun->lun_cip = NULL;
13117 			cdip = fcp_create_dip(plun, lcount, tcount);
13118 			plun->lun_cip = cip = CIP(cdip);
13119 			if (cip == NULL) {
13120 				fcp_log(CE_WARN, pptr->port_dip,
13121 				    "!fcp_online_child: "
13122 				    "Create devinfo failed for LU=%p", plun);
13123 				mutex_exit(&plun->lun_mutex);
13124 
13125 				mutex_enter(&ptgt->tgt_mutex);
13126 				plun->lun_state |= FCP_LUN_OFFLINE;
13127 				mutex_exit(&ptgt->tgt_mutex);
13128 
13129 				mutex_exit(&pptr->port_mutex);
13130 
13131 				/*
13132 				 * free the mdi_pathinfo node
13133 				 */
13134 				(void) mdi_pi_free(PIP(old_cip), 0);
13135 			} else {
13136 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13137 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13138 				    "fcp_online_child: creating devinfo "
13139 				    "node 0x%p for plun 0x%p",
13140 				    cip, plun);
13141 				mutex_exit(&plun->lun_mutex);
13142 				mutex_exit(&pptr->port_mutex);
13143 				/*
13144 				 * free the mdi_pathinfo node
13145 				 */
13146 				(void) mdi_pi_free(PIP(old_cip), 0);
13147 				mutex_enter(&pptr->port_mutex);
13148 				mutex_enter(&plun->lun_mutex);
13149 				goto again;
13150 			}
13151 		} else {
13152 			if (cdip) {
13153 				fcp_log(CE_NOTE, pptr->port_dip,
13154 				    "!fcp_online_child: mdi_pi_online:"
13155 				    " failed for %s: target=%x lun=%x %x",
13156 				    ddi_get_name(cdip), ptgt->tgt_d_id,
13157 				    plun->lun_num, rval);
13158 			}
13159 		}
13160 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13161 	}
13162 
13163 	if (rval == NDI_SUCCESS) {
13164 		if (cdip) {
13165 			(void) ndi_event_retrieve_cookie(
13166 			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13167 			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13168 			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13169 			    cdip, fcp_insert_eid, NULL);
13170 		}
13171 	}
13172 	mutex_enter(&pptr->port_mutex);
13173 	mutex_enter(&plun->lun_mutex);
13174 	return (rval);
13175 }
13176 
13177 /* ARGSUSED */
13178 static int
13179 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13180     int tcount, int flags, int *circ)
13181 {
13182 	int rval;
13183 	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13184 	struct fcp_tgt	*ptgt = plun->lun_tgt;
13185 	dev_info_t		*cdip;
13186 
13187 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13188 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13189 
13190 	if (plun->lun_cip == NULL) {
13191 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13192 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13193 		    "fcp_offline_child: plun->lun_cip is NULL: "
13194 		    "plun: %p lun state: %x num: %d target state: %x",
13195 		    plun, plun->lun_state, plun->lun_num,
13196 		    plun->lun_tgt->tgt_port->port_state);
13197 		return (NDI_FAILURE);
13198 	}
13199 
13200 	if (plun->lun_mpxio == 0) {
13201 		cdip = DIP(cip);
13202 		mutex_exit(&plun->lun_mutex);
13203 		mutex_exit(&pptr->port_mutex);
13204 		rval = ndi_devi_offline(DIP(cip), flags);
13205 		if (rval != NDI_SUCCESS) {
13206 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13207 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13208 			    "fcp_offline_child: ndi_devi_offline failed "
13209 			    "rval=%x cip=%p", rval, cip);
13210 		}
13211 	} else {
13212 		cdip = mdi_pi_get_client(PIP(cip));
13213 		mutex_exit(&plun->lun_mutex);
13214 		mutex_exit(&pptr->port_mutex);
13215 
13216 		/*
13217 		 * Exit phci to avoid deadlock with power management code
13218 		 * during mdi_pi_offline
13219 		 */
13220 		mdi_hold_path(PIP(cip));
13221 		mdi_devi_exit_phci(pptr->port_dip, *circ);
13222 
13223 		rval = mdi_pi_offline(PIP(cip), flags);
13224 
13225 		mdi_devi_enter_phci(pptr->port_dip, circ);
13226 		mdi_rele_path(PIP(cip));
13227 
13228 		if (rval == MDI_SUCCESS) {
13229 			/*
13230 			 * Clear MPxIO path permanent disable as the path is
13231 			 * already offlined.
13232 			 */
13233 			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13234 
13235 			if (flags & NDI_DEVI_REMOVE) {
13236 				(void) mdi_pi_free(PIP(cip), 0);
13237 			}
13238 		} else {
13239 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13240 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13241 			    "fcp_offline_child: mdi_pi_offline failed "
13242 			    "rval=%x cip=%p", rval, cip);
13243 		}
13244 		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13245 	}
13246 
13247 	mutex_enter(&ptgt->tgt_mutex);
13248 	plun->lun_state &= ~FCP_LUN_INIT;
13249 	mutex_exit(&ptgt->tgt_mutex);
13250 
13251 	mutex_enter(&pptr->port_mutex);
13252 	mutex_enter(&plun->lun_mutex);
13253 
13254 	if (rval == NDI_SUCCESS) {
13255 		cdip = NULL;
13256 		if (flags & NDI_DEVI_REMOVE) {
13257 			/*
13258 			 * If the guid of the LUN changes, lun_cip will not
13259 			 * equal to cip, and after offlining the LUN with the
13260 			 * old guid, we should keep lun_cip since it's the cip
13261 			 * of the LUN with the new guid.
13262 			 * Otherwise remove our reference to child node.
13263 			 */
13264 			if (plun->lun_cip == cip) {
13265 				plun->lun_cip = NULL;
13266 			}
13267 			if (plun->lun_old_guid) {
13268 				kmem_free(plun->lun_old_guid,
13269 				    plun->lun_old_guid_size);
13270 				plun->lun_old_guid = NULL;
13271 				plun->lun_old_guid_size = 0;
13272 			}
13273 		}
13274 	}
13275 
13276 	if (cdip) {
13277 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13278 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13279 		    " target=%x lun=%x", "ndi_offline",
13280 		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13281 	}
13282 
13283 	return (rval);
13284 }
13285 
13286 static void
13287 fcp_remove_child(struct fcp_lun *plun)
13288 {
13289 	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13290 
13291 	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13292 		if (plun->lun_mpxio == 0) {
13293 			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13294 			(void) ndi_devi_free(DIP(plun->lun_cip));
13295 		} else {
13296 			mutex_exit(&plun->lun_mutex);
13297 			mutex_exit(&plun->lun_tgt->tgt_mutex);
13298 			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13299 			FCP_TRACE(fcp_logq,
13300 			    plun->lun_tgt->tgt_port->port_instbuf,
13301 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13302 			    "lun=%p pip freed %p", plun, plun->lun_cip);
13303 			(void) mdi_prop_remove(PIP(plun->lun_cip), NULL);
13304 			(void) mdi_pi_free(PIP(plun->lun_cip), 0);
13305 			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13306 			mutex_enter(&plun->lun_tgt->tgt_mutex);
13307 			mutex_enter(&plun->lun_mutex);
13308 		}
13309 	}
13310 
13311 	plun->lun_cip = NULL;
13312 }
13313 
13314 /*
13315  * called when a timeout occurs
13316  *
13317  * can be scheduled during an attach or resume (if not already running)
13318  *
13319  * one timeout is set up for all ports
13320  *
13321  * acquires and releases the global mutex
13322  */
13323 /*ARGSUSED*/
13324 static void
13325 fcp_watch(void *arg)
13326 {
13327 	struct fcp_port	*pptr;
13328 	struct fcp_ipkt	*icmd;
13329 	struct fcp_ipkt	*nicmd;
13330 	struct fcp_pkt	*cmd;
13331 	struct fcp_pkt	*ncmd;
13332 	struct fcp_pkt	*tail;
13333 	struct fcp_pkt	*pcmd;
13334 	struct fcp_pkt	*save_head;
13335 	struct fcp_port	*save_port;
13336 
13337 	/* increment global watchdog time */
13338 	fcp_watchdog_time += fcp_watchdog_timeout;
13339 
13340 	mutex_enter(&fcp_global_mutex);
13341 
13342 	/* scan each port in our list */
13343 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13344 		save_port = fcp_port_head;
13345 		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13346 		mutex_exit(&fcp_global_mutex);
13347 
13348 		mutex_enter(&pptr->port_mutex);
13349 		if (pptr->port_ipkt_list == NULL &&
13350 		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13351 		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13352 			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13353 			mutex_exit(&pptr->port_mutex);
13354 			mutex_enter(&fcp_global_mutex);
13355 			goto end_of_watchdog;
13356 		}
13357 
13358 		/*
13359 		 * We check if a list of targets need to be offlined.
13360 		 */
13361 		if (pptr->port_offline_tgts) {
13362 			fcp_scan_offline_tgts(pptr);
13363 		}
13364 
13365 		/*
13366 		 * We check if a list of luns need to be offlined.
13367 		 */
13368 		if (pptr->port_offline_luns) {
13369 			fcp_scan_offline_luns(pptr);
13370 		}
13371 
13372 		/*
13373 		 * We check if a list of targets or luns need to be reset.
13374 		 */
13375 		if (pptr->port_reset_list) {
13376 			fcp_check_reset_delay(pptr);
13377 		}
13378 
13379 		mutex_exit(&pptr->port_mutex);
13380 
13381 		/*
13382 		 * This is where the pending commands (pkt) are checked for
13383 		 * timeout.
13384 		 */
13385 		mutex_enter(&pptr->port_pkt_mutex);
13386 		tail = pptr->port_pkt_tail;
13387 
13388 		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13389 		    cmd != NULL; cmd = ncmd) {
13390 			ncmd = cmd->cmd_next;
13391 			/*
13392 			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13393 			 * must be set.
13394 			 */
13395 			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13396 			/*
13397 			 * FCP_INVALID_TIMEOUT will be set for those
13398 			 * command that need to be failed. Mostly those
13399 			 * cmds that could not be queued down for the
13400 			 * "timeout" value. cmd->cmd_timeout is used
13401 			 * to try and requeue the command regularly.
13402 			 */
13403 			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13404 				/*
13405 				 * This command hasn't timed out yet.  Let's
13406 				 * go to the next one.
13407 				 */
13408 				pcmd = cmd;
13409 				goto end_of_loop;
13410 			}
13411 
13412 			if (cmd == pptr->port_pkt_head) {
13413 				ASSERT(pcmd == NULL);
13414 				pptr->port_pkt_head = cmd->cmd_next;
13415 			} else {
13416 				ASSERT(pcmd != NULL);
13417 				pcmd->cmd_next = cmd->cmd_next;
13418 			}
13419 
13420 			if (cmd == pptr->port_pkt_tail) {
13421 				ASSERT(cmd->cmd_next == NULL);
13422 				pptr->port_pkt_tail = pcmd;
13423 				if (pcmd) {
13424 					pcmd->cmd_next = NULL;
13425 				}
13426 			}
13427 			cmd->cmd_next = NULL;
13428 
13429 			/*
13430 			 * save the current head before dropping the
13431 			 * mutex - If the head doesn't remain the
13432 			 * same after re acquiring the mutex, just
13433 			 * bail out and revisit on next tick.
13434 			 *
13435 			 * PS: The tail pointer can change as the commands
13436 			 * get requeued after failure to retransport
13437 			 */
13438 			save_head = pptr->port_pkt_head;
13439 			mutex_exit(&pptr->port_pkt_mutex);
13440 
13441 			if (cmd->cmd_fp_pkt->pkt_timeout ==
13442 			    FCP_INVALID_TIMEOUT) {
13443 				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13444 				struct fcp_lun	*plun;
13445 				struct fcp_tgt	*ptgt;
13446 
13447 				plun = ADDR2LUN(&pkt->pkt_address);
13448 				ptgt = plun->lun_tgt;
13449 
13450 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13451 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13452 				    "SCSI cmd 0x%x to D_ID=%x timed out",
13453 				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13454 
13455 				cmd->cmd_state == FCP_PKT_ABORTING ?
13456 				    fcp_fail_cmd(cmd, CMD_RESET,
13457 				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13458 				    CMD_TIMEOUT, STAT_ABORTED);
13459 			} else {
13460 				fcp_retransport_cmd(pptr, cmd);
13461 			}
13462 			mutex_enter(&pptr->port_pkt_mutex);
13463 			if (save_head && save_head != pptr->port_pkt_head) {
13464 				/*
13465 				 * Looks like linked list got changed (mostly
13466 				 * happens when an an OFFLINE LUN code starts
13467 				 * returning overflow queue commands in
13468 				 * parallel. So bail out and revisit during
13469 				 * next tick
13470 				 */
13471 				break;
13472 			}
13473 		end_of_loop:
13474 			/*
13475 			 * Scan only upto the previously known tail pointer
13476 			 * to avoid excessive processing - lots of new packets
13477 			 * could have been added to the tail or the old ones
13478 			 * re-queued.
13479 			 */
13480 			if (cmd == tail) {
13481 				break;
13482 			}
13483 		}
13484 		mutex_exit(&pptr->port_pkt_mutex);
13485 
13486 		mutex_enter(&pptr->port_mutex);
13487 		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13488 			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13489 
13490 			nicmd = icmd->ipkt_next;
13491 			if ((icmd->ipkt_restart != 0) &&
13492 			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13493 				/* packet has not timed out */
13494 				continue;
13495 			}
13496 
13497 			/* time for packet re-transport */
13498 			if (icmd == pptr->port_ipkt_list) {
13499 				pptr->port_ipkt_list = icmd->ipkt_next;
13500 				if (pptr->port_ipkt_list) {
13501 					pptr->port_ipkt_list->ipkt_prev =
13502 					    NULL;
13503 				}
13504 			} else {
13505 				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13506 				if (icmd->ipkt_next) {
13507 					icmd->ipkt_next->ipkt_prev =
13508 					    icmd->ipkt_prev;
13509 				}
13510 			}
13511 			icmd->ipkt_next = NULL;
13512 			icmd->ipkt_prev = NULL;
13513 			mutex_exit(&pptr->port_mutex);
13514 
13515 			if (fcp_is_retryable(icmd)) {
13516 				fc_ulp_rscn_info_t *rscnp =
13517 				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13518 				    pkt_ulp_rscn_infop;
13519 
13520 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13521 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13522 				    "%x to D_ID=%x Retrying..",
13523 				    icmd->ipkt_opcode,
13524 				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13525 
13526 				/*
13527 				 * Update the RSCN count in the packet
13528 				 * before resending.
13529 				 */
13530 
13531 				if (rscnp != NULL) {
13532 					rscnp->ulp_rscn_count =
13533 					    fc_ulp_get_rscn_count(pptr->
13534 					    port_fp_handle);
13535 				}
13536 
13537 				mutex_enter(&pptr->port_mutex);
13538 				mutex_enter(&ptgt->tgt_mutex);
13539 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13540 					mutex_exit(&ptgt->tgt_mutex);
13541 					mutex_exit(&pptr->port_mutex);
13542 					switch (icmd->ipkt_opcode) {
13543 						int rval;
13544 					case LA_ELS_PLOGI:
13545 						if ((rval = fc_ulp_login(
13546 						    pptr->port_fp_handle,
13547 						    &icmd->ipkt_fpkt, 1)) ==
13548 						    FC_SUCCESS) {
13549 							mutex_enter(
13550 							    &pptr->port_mutex);
13551 							continue;
13552 						}
13553 						if (fcp_handle_ipkt_errors(
13554 						    pptr, ptgt, icmd, rval,
13555 						    "PLOGI") == DDI_SUCCESS) {
13556 							mutex_enter(
13557 							    &pptr->port_mutex);
13558 							continue;
13559 						}
13560 						break;
13561 
13562 					case LA_ELS_PRLI:
13563 						if ((rval = fc_ulp_issue_els(
13564 						    pptr->port_fp_handle,
13565 						    icmd->ipkt_fpkt)) ==
13566 						    FC_SUCCESS) {
13567 							mutex_enter(
13568 							    &pptr->port_mutex);
13569 							continue;
13570 						}
13571 						if (fcp_handle_ipkt_errors(
13572 						    pptr, ptgt, icmd, rval,
13573 						    "PRLI") == DDI_SUCCESS) {
13574 							mutex_enter(
13575 							    &pptr->port_mutex);
13576 							continue;
13577 						}
13578 						break;
13579 
13580 					default:
13581 						if ((rval = fcp_transport(
13582 						    pptr->port_fp_handle,
13583 						    icmd->ipkt_fpkt, 1)) ==
13584 						    FC_SUCCESS) {
13585 							mutex_enter(
13586 							    &pptr->port_mutex);
13587 							continue;
13588 						}
13589 						if (fcp_handle_ipkt_errors(
13590 						    pptr, ptgt, icmd, rval,
13591 						    "PRLI") == DDI_SUCCESS) {
13592 							mutex_enter(
13593 							    &pptr->port_mutex);
13594 							continue;
13595 						}
13596 						break;
13597 					}
13598 				} else {
13599 					mutex_exit(&ptgt->tgt_mutex);
13600 					mutex_exit(&pptr->port_mutex);
13601 				}
13602 			} else {
13603 				fcp_print_error(icmd->ipkt_fpkt);
13604 			}
13605 
13606 			(void) fcp_call_finish_init(pptr, ptgt,
13607 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13608 			    icmd->ipkt_cause);
13609 			fcp_icmd_free(pptr, icmd);
13610 			mutex_enter(&pptr->port_mutex);
13611 		}
13612 
13613 		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13614 		mutex_exit(&pptr->port_mutex);
13615 		mutex_enter(&fcp_global_mutex);
13616 
13617 	end_of_watchdog:
13618 		/*
13619 		 * Bail out early before getting into trouble
13620 		 */
13621 		if (save_port != fcp_port_head) {
13622 			break;
13623 		}
13624 	}
13625 
13626 	if (fcp_watchdog_init > 0) {
13627 		/* reschedule timeout to go again */
13628 		fcp_watchdog_id =
13629 		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13630 	}
13631 	mutex_exit(&fcp_global_mutex);
13632 }
13633 
13634 
13635 static void
13636 fcp_check_reset_delay(struct fcp_port *pptr)
13637 {
13638 	uint32_t		tgt_cnt;
13639 	int			level;
13640 	struct fcp_tgt	*ptgt;
13641 	struct fcp_lun	*plun;
13642 	struct fcp_reset_elem *cur = NULL;
13643 	struct fcp_reset_elem *next = NULL;
13644 	struct fcp_reset_elem *prev = NULL;
13645 
13646 	ASSERT(mutex_owned(&pptr->port_mutex));
13647 
13648 	next = pptr->port_reset_list;
13649 	while ((cur = next) != NULL) {
13650 		next = cur->next;
13651 
13652 		if (cur->timeout < fcp_watchdog_time) {
13653 			prev = cur;
13654 			continue;
13655 		}
13656 
13657 		ptgt = cur->tgt;
13658 		plun = cur->lun;
13659 		tgt_cnt = cur->tgt_cnt;
13660 
13661 		if (ptgt) {
13662 			level = RESET_TARGET;
13663 		} else {
13664 			ASSERT(plun != NULL);
13665 			level = RESET_LUN;
13666 			ptgt = plun->lun_tgt;
13667 		}
13668 		if (prev) {
13669 			prev->next = next;
13670 		} else {
13671 			/*
13672 			 * Because we drop port mutex while doing aborts for
13673 			 * packets, we can't rely on reset_list pointing to
13674 			 * our head
13675 			 */
13676 			if (cur == pptr->port_reset_list) {
13677 				pptr->port_reset_list = next;
13678 			} else {
13679 				struct fcp_reset_elem *which;
13680 
13681 				which = pptr->port_reset_list;
13682 				while (which && which->next != cur) {
13683 					which = which->next;
13684 				}
13685 				ASSERT(which != NULL);
13686 
13687 				which->next = next;
13688 				prev = which;
13689 			}
13690 		}
13691 
13692 		kmem_free(cur, sizeof (*cur));
13693 
13694 		if (tgt_cnt == ptgt->tgt_change_cnt) {
13695 			mutex_enter(&ptgt->tgt_mutex);
13696 			if (level == RESET_TARGET) {
13697 				fcp_update_tgt_state(ptgt,
13698 				    FCP_RESET, FCP_LUN_BUSY);
13699 			} else {
13700 				fcp_update_lun_state(plun,
13701 				    FCP_RESET, FCP_LUN_BUSY);
13702 			}
13703 			mutex_exit(&ptgt->tgt_mutex);
13704 
13705 			mutex_exit(&pptr->port_mutex);
13706 			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13707 			mutex_enter(&pptr->port_mutex);
13708 		}
13709 	}
13710 }
13711 
13712 
13713 static void
13714 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13715     struct fcp_lun *rlun, int tgt_cnt)
13716 {
13717 	int			rval;
13718 	struct fcp_lun	*tlun, *nlun;
13719 	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13720 	    *cmd = NULL, *head = NULL,
13721 	    *tail = NULL;
13722 
13723 	mutex_enter(&pptr->port_pkt_mutex);
13724 	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13725 		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13726 		struct fcp_tgt *ptgt = plun->lun_tgt;
13727 
13728 		ncmd = cmd->cmd_next;
13729 
13730 		if (ptgt != ttgt && plun != rlun) {
13731 			pcmd = cmd;
13732 			continue;
13733 		}
13734 
13735 		if (pcmd != NULL) {
13736 			ASSERT(pptr->port_pkt_head != cmd);
13737 			pcmd->cmd_next = ncmd;
13738 		} else {
13739 			ASSERT(cmd == pptr->port_pkt_head);
13740 			pptr->port_pkt_head = ncmd;
13741 		}
13742 		if (pptr->port_pkt_tail == cmd) {
13743 			ASSERT(cmd->cmd_next == NULL);
13744 			pptr->port_pkt_tail = pcmd;
13745 			if (pcmd != NULL) {
13746 				pcmd->cmd_next = NULL;
13747 			}
13748 		}
13749 
13750 		if (head == NULL) {
13751 			head = tail = cmd;
13752 		} else {
13753 			ASSERT(tail != NULL);
13754 			tail->cmd_next = cmd;
13755 			tail = cmd;
13756 		}
13757 		cmd->cmd_next = NULL;
13758 	}
13759 	mutex_exit(&pptr->port_pkt_mutex);
13760 
13761 	for (cmd = head; cmd != NULL; cmd = ncmd) {
13762 		struct scsi_pkt *pkt = cmd->cmd_pkt;
13763 
13764 		ncmd = cmd->cmd_next;
13765 		ASSERT(pkt != NULL);
13766 
13767 		mutex_enter(&pptr->port_mutex);
13768 		if (ttgt->tgt_change_cnt == tgt_cnt) {
13769 			mutex_exit(&pptr->port_mutex);
13770 			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13771 			pkt->pkt_reason = CMD_RESET;
13772 			pkt->pkt_statistics |= STAT_DEV_RESET;
13773 			cmd->cmd_state = FCP_PKT_IDLE;
13774 			fcp_post_callback(cmd);
13775 		} else {
13776 			mutex_exit(&pptr->port_mutex);
13777 		}
13778 	}
13779 
13780 	/*
13781 	 * If the FCA will return all the commands in its queue then our
13782 	 * work is easy, just return.
13783 	 */
13784 
13785 	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13786 		return;
13787 	}
13788 
13789 	/*
13790 	 * For RESET_LUN get hold of target pointer
13791 	 */
13792 	if (ttgt == NULL) {
13793 		ASSERT(rlun != NULL);
13794 
13795 		ttgt = rlun->lun_tgt;
13796 
13797 		ASSERT(ttgt != NULL);
13798 	}
13799 
13800 	/*
13801 	 * There are some severe race conditions here.
13802 	 * While we are trying to abort the pkt, it might be completing
13803 	 * so mark it aborted and if the abort does not succeed then
13804 	 * handle it in the watch thread.
13805 	 */
13806 	mutex_enter(&ttgt->tgt_mutex);
13807 	nlun = ttgt->tgt_lun;
13808 	mutex_exit(&ttgt->tgt_mutex);
13809 	while ((tlun = nlun) != NULL) {
13810 		int restart = 0;
13811 		if (rlun && rlun != tlun) {
13812 			mutex_enter(&ttgt->tgt_mutex);
13813 			nlun = tlun->lun_next;
13814 			mutex_exit(&ttgt->tgt_mutex);
13815 			continue;
13816 		}
13817 		mutex_enter(&tlun->lun_mutex);
13818 		cmd = tlun->lun_pkt_head;
13819 		while (cmd != NULL) {
13820 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13821 				struct scsi_pkt *pkt;
13822 
13823 				restart = 1;
13824 				cmd->cmd_state = FCP_PKT_ABORTING;
13825 				mutex_exit(&tlun->lun_mutex);
13826 				rval = fc_ulp_abort(pptr->port_fp_handle,
13827 				    cmd->cmd_fp_pkt, KM_SLEEP);
13828 				if (rval == FC_SUCCESS) {
13829 					pkt = cmd->cmd_pkt;
13830 					pkt->pkt_reason = CMD_RESET;
13831 					pkt->pkt_statistics |= STAT_DEV_RESET;
13832 					cmd->cmd_state = FCP_PKT_IDLE;
13833 					fcp_post_callback(cmd);
13834 				} else {
13835 					caddr_t msg;
13836 
13837 					(void) fc_ulp_error(rval, &msg);
13838 
13839 					/*
13840 					 * This part is tricky. The abort
13841 					 * failed and now the command could
13842 					 * be completing.  The cmd_state ==
13843 					 * FCP_PKT_ABORTING should save
13844 					 * us in fcp_cmd_callback. If we
13845 					 * are already aborting ignore the
13846 					 * command in fcp_cmd_callback.
13847 					 * Here we leave this packet for 20
13848 					 * sec to be aborted in the
13849 					 * fcp_watch thread.
13850 					 */
13851 					fcp_log(CE_WARN, pptr->port_dip,
13852 					    "!Abort failed after reset %s",
13853 					    msg);
13854 
13855 					cmd->cmd_timeout =
13856 					    fcp_watchdog_time +
13857 					    cmd->cmd_pkt->pkt_time +
13858 					    FCP_FAILED_DELAY;
13859 
13860 					cmd->cmd_fp_pkt->pkt_timeout =
13861 					    FCP_INVALID_TIMEOUT;
13862 					/*
13863 					 * This is a hack, cmd is put in the
13864 					 * overflow queue so that it can be
13865 					 * timed out finally
13866 					 */
13867 					cmd->cmd_flags |= CFLAG_IN_QUEUE;
13868 
13869 					mutex_enter(&pptr->port_pkt_mutex);
13870 					if (pptr->port_pkt_head) {
13871 						ASSERT(pptr->port_pkt_tail
13872 						    != NULL);
13873 						pptr->port_pkt_tail->cmd_next
13874 						    = cmd;
13875 						pptr->port_pkt_tail = cmd;
13876 					} else {
13877 						ASSERT(pptr->port_pkt_tail
13878 						    == NULL);
13879 						pptr->port_pkt_head =
13880 						    pptr->port_pkt_tail
13881 						    = cmd;
13882 					}
13883 					cmd->cmd_next = NULL;
13884 					mutex_exit(&pptr->port_pkt_mutex);
13885 				}
13886 				mutex_enter(&tlun->lun_mutex);
13887 				cmd = tlun->lun_pkt_head;
13888 			} else {
13889 				cmd = cmd->cmd_forw;
13890 			}
13891 		}
13892 		mutex_exit(&tlun->lun_mutex);
13893 
13894 		mutex_enter(&ttgt->tgt_mutex);
13895 		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
13896 		mutex_exit(&ttgt->tgt_mutex);
13897 
13898 		mutex_enter(&pptr->port_mutex);
13899 		if (tgt_cnt != ttgt->tgt_change_cnt) {
13900 			mutex_exit(&pptr->port_mutex);
13901 			return;
13902 		} else {
13903 			mutex_exit(&pptr->port_mutex);
13904 		}
13905 	}
13906 }
13907 
13908 
13909 /*
13910  * unlink the soft state, returning the soft state found (if any)
13911  *
13912  * acquires and releases the global mutex
13913  */
13914 struct fcp_port *
13915 fcp_soft_state_unlink(struct fcp_port *pptr)
13916 {
13917 	struct fcp_port	*hptr;		/* ptr index */
13918 	struct fcp_port	*tptr;		/* prev hptr */
13919 
13920 	mutex_enter(&fcp_global_mutex);
13921 	for (hptr = fcp_port_head, tptr = NULL;
13922 	    hptr != NULL;
13923 	    tptr = hptr, hptr = hptr->port_next) {
13924 		if (hptr == pptr) {
13925 			/* we found a match -- remove this item */
13926 			if (tptr == NULL) {
13927 				/* we're at the head of the list */
13928 				fcp_port_head = hptr->port_next;
13929 			} else {
13930 				tptr->port_next = hptr->port_next;
13931 			}
13932 			break;			/* success */
13933 		}
13934 	}
13935 	if (fcp_port_head == NULL) {
13936 		fcp_cleanup_blacklist(&fcp_lun_blacklist);
13937 	}
13938 	mutex_exit(&fcp_global_mutex);
13939 	return (hptr);
13940 }
13941 
13942 
13943 /*
13944  * called by fcp_scsi_hba_tgt_init to find a LUN given a
13945  * WWN and a LUN number
13946  */
13947 /* ARGSUSED */
13948 static struct fcp_lun *
13949 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
13950 {
13951 	int hash;
13952 	struct fcp_tgt *ptgt;
13953 	struct fcp_lun *plun;
13954 
13955 	ASSERT(mutex_owned(&pptr->port_mutex));
13956 
13957 	hash = FCP_HASH(wwn);
13958 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
13959 	    ptgt = ptgt->tgt_next) {
13960 		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
13961 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
13962 			mutex_enter(&ptgt->tgt_mutex);
13963 			for (plun = ptgt->tgt_lun;
13964 			    plun != NULL;
13965 			    plun = plun->lun_next) {
13966 				if (plun->lun_num == lun) {
13967 					mutex_exit(&ptgt->tgt_mutex);
13968 					return (plun);
13969 				}
13970 			}
13971 			mutex_exit(&ptgt->tgt_mutex);
13972 			return (NULL);
13973 		}
13974 	}
13975 	return (NULL);
13976 }
13977 
13978 /*
13979  *     Function: fcp_prepare_pkt
13980  *
13981  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
13982  *		 for fcp_start(). It binds the data or partially maps it.
13983  *		 Builds the FCP header and starts the initialization of the
13984  *		 Fibre Channel header.
13985  *
13986  *     Argument: *pptr		FCP port.
13987  *		 *cmd		FCP packet.
13988  *		 *plun		LUN the command will be sent to.
13989  *
13990  *	Context: User, Kernel and Interrupt context.
13991  */
13992 static void
13993 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
13994     struct fcp_lun *plun)
13995 {
13996 	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
13997 	struct fcp_tgt		*ptgt = plun->lun_tgt;
13998 	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
13999 
14000 	ASSERT(cmd->cmd_pkt->pkt_comp ||
14001 	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14002 
14003 	if (cmd->cmd_pkt->pkt_numcookies) {
14004 		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14005 			fcmd->fcp_cntl.cntl_read_data = 1;
14006 			fcmd->fcp_cntl.cntl_write_data = 0;
14007 			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14008 		} else {
14009 			fcmd->fcp_cntl.cntl_read_data = 0;
14010 			fcmd->fcp_cntl.cntl_write_data = 1;
14011 			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14012 		}
14013 
14014 		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14015 
14016 		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14017 		ASSERT(fpkt->pkt_data_cookie_cnt <=
14018 		    pptr->port_data_dma_attr.dma_attr_sgllen);
14019 
14020 		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14021 
14022 		/* FCA needs pkt_datalen to be set */
14023 		fpkt->pkt_datalen = cmd->cmd_dmacount;
14024 		fcmd->fcp_data_len = cmd->cmd_dmacount;
14025 	} else {
14026 		fcmd->fcp_cntl.cntl_read_data = 0;
14027 		fcmd->fcp_cntl.cntl_write_data = 0;
14028 		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14029 		fpkt->pkt_datalen = 0;
14030 		fcmd->fcp_data_len = 0;
14031 	}
14032 
14033 	/* set up the Tagged Queuing type */
14034 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14035 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14036 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14037 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14038 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14039 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14040 	} else {
14041 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14042 	}
14043 
14044 	fcmd->fcp_ent_addr = plun->lun_addr;
14045 
14046 	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14047 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14048 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14049 	} else {
14050 		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14051 	}
14052 
14053 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14054 	cmd->cmd_pkt->pkt_state = 0;
14055 	cmd->cmd_pkt->pkt_statistics = 0;
14056 	cmd->cmd_pkt->pkt_resid = 0;
14057 
14058 	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14059 
14060 	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14061 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14062 		fpkt->pkt_comp = NULL;
14063 	} else {
14064 		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14065 		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14066 			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14067 		}
14068 		fpkt->pkt_comp = fcp_cmd_callback;
14069 	}
14070 
14071 	mutex_enter(&pptr->port_mutex);
14072 	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14073 		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14074 	}
14075 	mutex_exit(&pptr->port_mutex);
14076 
14077 	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14078 	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14079 
14080 	/*
14081 	 * Save a few kernel cycles here
14082 	 */
14083 #ifndef	__lock_lint
14084 	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14085 #endif /* __lock_lint */
14086 }
14087 
14088 static void
14089 fcp_post_callback(struct fcp_pkt *cmd)
14090 {
14091 	scsi_hba_pkt_comp(cmd->cmd_pkt);
14092 }
14093 
14094 
14095 /*
14096  * called to do polled I/O by fcp_start()
14097  *
14098  * return a transport status value, i.e. TRAN_ACCECPT for success
14099  */
14100 static int
14101 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14102 {
14103 	int	rval;
14104 
14105 #ifdef	DEBUG
14106 	mutex_enter(&pptr->port_pkt_mutex);
14107 	pptr->port_npkts++;
14108 	mutex_exit(&pptr->port_pkt_mutex);
14109 #endif /* DEBUG */
14110 
14111 	if (cmd->cmd_fp_pkt->pkt_timeout) {
14112 		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14113 	} else {
14114 		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14115 	}
14116 
14117 	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14118 
14119 	cmd->cmd_state = FCP_PKT_ISSUED;
14120 
14121 	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14122 
14123 #ifdef	DEBUG
14124 	mutex_enter(&pptr->port_pkt_mutex);
14125 	pptr->port_npkts--;
14126 	mutex_exit(&pptr->port_pkt_mutex);
14127 #endif /* DEBUG */
14128 
14129 	cmd->cmd_state = FCP_PKT_IDLE;
14130 
14131 	switch (rval) {
14132 	case FC_SUCCESS:
14133 		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14134 			fcp_complete_pkt(cmd->cmd_fp_pkt);
14135 			rval = TRAN_ACCEPT;
14136 		} else {
14137 			rval = TRAN_FATAL_ERROR;
14138 		}
14139 		break;
14140 
14141 	case FC_TRAN_BUSY:
14142 		rval = TRAN_BUSY;
14143 		cmd->cmd_pkt->pkt_resid = 0;
14144 		break;
14145 
14146 	case FC_BADPACKET:
14147 		rval = TRAN_BADPKT;
14148 		break;
14149 
14150 	default:
14151 		rval = TRAN_FATAL_ERROR;
14152 		break;
14153 	}
14154 
14155 	return (rval);
14156 }
14157 
14158 
14159 /*
14160  * called by some of the following transport-called routines to convert
14161  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14162  */
14163 static struct fcp_port *
14164 fcp_dip2port(dev_info_t *dip)
14165 {
14166 	int	instance;
14167 
14168 	instance = ddi_get_instance(dip);
14169 	return (ddi_get_soft_state(fcp_softstate, instance));
14170 }
14171 
14172 
14173 /*
14174  * called internally to return a LUN given a dip
14175  */
14176 struct fcp_lun *
14177 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14178 {
14179 	struct fcp_tgt *ptgt;
14180 	struct fcp_lun *plun;
14181 	int i;
14182 
14183 
14184 	ASSERT(mutex_owned(&pptr->port_mutex));
14185 
14186 	for (i = 0; i < FCP_NUM_HASH; i++) {
14187 		for (ptgt = pptr->port_tgt_hash_table[i];
14188 		    ptgt != NULL;
14189 		    ptgt = ptgt->tgt_next) {
14190 			mutex_enter(&ptgt->tgt_mutex);
14191 			for (plun = ptgt->tgt_lun; plun != NULL;
14192 			    plun = plun->lun_next) {
14193 				mutex_enter(&plun->lun_mutex);
14194 				if (plun->lun_cip == cip) {
14195 					mutex_exit(&plun->lun_mutex);
14196 					mutex_exit(&ptgt->tgt_mutex);
14197 					return (plun); /* match found */
14198 				}
14199 				mutex_exit(&plun->lun_mutex);
14200 			}
14201 			mutex_exit(&ptgt->tgt_mutex);
14202 		}
14203 	}
14204 	return (NULL);				/* no LUN found */
14205 }
14206 
14207 /*
14208  * pass an element to the hotplug list, kick the hotplug thread
14209  * and wait for the element to get processed by the hotplug thread.
14210  * on return the element is freed.
14211  *
14212  * return zero success and non-zero on failure
14213  *
14214  * acquires/releases the target mutex
14215  *
14216  */
14217 static int
14218 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14219     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14220 {
14221 	struct fcp_hp_elem	*elem;
14222 	int			rval;
14223 
14224 	mutex_enter(&plun->lun_tgt->tgt_mutex);
14225 	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14226 	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14227 		mutex_exit(&plun->lun_tgt->tgt_mutex);
14228 		fcp_log(CE_CONT, pptr->port_dip,
14229 		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14230 		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14231 		return (NDI_FAILURE);
14232 	}
14233 	mutex_exit(&plun->lun_tgt->tgt_mutex);
14234 	mutex_enter(&elem->mutex);
14235 	if (elem->wait) {
14236 		while (elem->wait) {
14237 			cv_wait(&elem->cv, &elem->mutex);
14238 		}
14239 	}
14240 	rval = (elem->result);
14241 	mutex_exit(&elem->mutex);
14242 	mutex_destroy(&elem->mutex);
14243 	cv_destroy(&elem->cv);
14244 	kmem_free(elem, sizeof (struct fcp_hp_elem));
14245 	return (rval);
14246 }
14247 
14248 /*
14249  * pass an element to the hotplug list, and then
14250  * kick the hotplug thread
14251  *
14252  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14253  *
14254  * acquires/releases the hotplug mutex
14255  *
14256  * called with the target mutex owned
14257  *
14258  * memory acquired in NOSLEEP mode
14259  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14260  *	 for the hp daemon to process the request and is responsible for
14261  *	 freeing the element
14262  */
14263 static struct fcp_hp_elem *
14264 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14265     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14266 {
14267 	struct fcp_hp_elem	*elem;
14268 	dev_info_t *pdip;
14269 
14270 	ASSERT(pptr != NULL);
14271 	ASSERT(plun != NULL);
14272 	ASSERT(plun->lun_tgt != NULL);
14273 	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14274 
14275 	/* create space for a hotplug element */
14276 	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14277 	    == NULL) {
14278 		fcp_log(CE_WARN, NULL,
14279 		    "!can't allocate memory for hotplug element");
14280 		return (NULL);
14281 	}
14282 
14283 	/* fill in hotplug element */
14284 	elem->port = pptr;
14285 	elem->lun = plun;
14286 	elem->cip = cip;
14287 	elem->old_lun_mpxio = plun->lun_mpxio;
14288 	elem->what = what;
14289 	elem->flags = flags;
14290 	elem->link_cnt = link_cnt;
14291 	elem->tgt_cnt = tgt_cnt;
14292 	elem->wait = wait;
14293 	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14294 	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14295 
14296 	/* schedule the hotplug task */
14297 	pdip = pptr->port_dip;
14298 	mutex_enter(&plun->lun_mutex);
14299 	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14300 		plun->lun_event_count++;
14301 		elem->event_cnt = plun->lun_event_count;
14302 	}
14303 	mutex_exit(&plun->lun_mutex);
14304 	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14305 	    (void *)elem, KM_NOSLEEP) == NULL) {
14306 		mutex_enter(&plun->lun_mutex);
14307 		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14308 			plun->lun_event_count--;
14309 		}
14310 		mutex_exit(&plun->lun_mutex);
14311 		kmem_free(elem, sizeof (*elem));
14312 		return (0);
14313 	}
14314 
14315 	return (elem);
14316 }
14317 
14318 
14319 static void
14320 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14321 {
14322 	int			rval;
14323 	struct scsi_address	*ap;
14324 	struct fcp_lun	*plun;
14325 	struct fcp_tgt	*ptgt;
14326 	fc_packet_t	*fpkt;
14327 
14328 	ap = &cmd->cmd_pkt->pkt_address;
14329 	plun = ADDR2LUN(ap);
14330 	ptgt = plun->lun_tgt;
14331 
14332 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14333 
14334 	cmd->cmd_state = FCP_PKT_IDLE;
14335 
14336 	mutex_enter(&pptr->port_mutex);
14337 	mutex_enter(&ptgt->tgt_mutex);
14338 	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14339 	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14340 		fc_ulp_rscn_info_t *rscnp;
14341 
14342 		cmd->cmd_state = FCP_PKT_ISSUED;
14343 
14344 		/*
14345 		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14346 		 * originally NULL, hence we try to set it to the pd pointed
14347 		 * to by the SCSI device we're trying to get to.
14348 		 */
14349 
14350 		fpkt = cmd->cmd_fp_pkt;
14351 		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14352 			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14353 			/*
14354 			 * We need to notify the transport that we now have a
14355 			 * reference to the remote port handle.
14356 			 */
14357 			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14358 		}
14359 
14360 		mutex_exit(&ptgt->tgt_mutex);
14361 		mutex_exit(&pptr->port_mutex);
14362 
14363 		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14364 
14365 		/* prepare the packet */
14366 
14367 		fcp_prepare_pkt(pptr, cmd, plun);
14368 
14369 		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14370 		    pkt_ulp_rscn_infop;
14371 
14372 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14373 		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14374 
14375 		if (rscnp != NULL) {
14376 			rscnp->ulp_rscn_count =
14377 			    fc_ulp_get_rscn_count(pptr->
14378 			    port_fp_handle);
14379 		}
14380 
14381 		rval = fcp_transport(pptr->port_fp_handle,
14382 		    cmd->cmd_fp_pkt, 0);
14383 
14384 		if (rval == FC_SUCCESS) {
14385 			return;
14386 		}
14387 		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14388 	} else {
14389 		mutex_exit(&ptgt->tgt_mutex);
14390 		mutex_exit(&pptr->port_mutex);
14391 	}
14392 
14393 	fcp_queue_pkt(pptr, cmd);
14394 }
14395 
14396 
14397 static void
14398 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14399 {
14400 	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14401 
14402 	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14403 	cmd->cmd_state = FCP_PKT_IDLE;
14404 
14405 	cmd->cmd_pkt->pkt_reason = reason;
14406 	cmd->cmd_pkt->pkt_state = 0;
14407 	cmd->cmd_pkt->pkt_statistics = statistics;
14408 
14409 	fcp_post_callback(cmd);
14410 }
14411 
14412 /*
14413  *     Function: fcp_queue_pkt
14414  *
14415  *  Description: This function queues the packet passed by the caller into
14416  *		 the list of packets of the FCP port.
14417  *
14418  *     Argument: *pptr		FCP port.
14419  *		 *cmd		FCP packet to queue.
14420  *
14421  * Return Value: None
14422  *
14423  *	Context: User, Kernel and Interrupt context.
14424  */
14425 static void
14426 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14427 {
14428 	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14429 
14430 	mutex_enter(&pptr->port_pkt_mutex);
14431 	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14432 	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14433 	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14434 
14435 	/*
14436 	 * zero pkt_time means hang around for ever
14437 	 */
14438 	if (cmd->cmd_pkt->pkt_time) {
14439 		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14440 			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14441 		} else {
14442 			/*
14443 			 * Indicate the watch thread to fail the
14444 			 * command by setting it to highest value
14445 			 */
14446 			cmd->cmd_timeout = fcp_watchdog_time;
14447 			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14448 		}
14449 	}
14450 
14451 	if (pptr->port_pkt_head) {
14452 		ASSERT(pptr->port_pkt_tail != NULL);
14453 
14454 		pptr->port_pkt_tail->cmd_next = cmd;
14455 		pptr->port_pkt_tail = cmd;
14456 	} else {
14457 		ASSERT(pptr->port_pkt_tail == NULL);
14458 
14459 		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14460 	}
14461 	cmd->cmd_next = NULL;
14462 	mutex_exit(&pptr->port_pkt_mutex);
14463 }
14464 
14465 /*
14466  *     Function: fcp_update_targets
14467  *
14468  *  Description: This function applies the specified change of state to all
14469  *		 the targets listed.  The operation applied is 'set'.
14470  *
14471  *     Argument: *pptr		FCP port.
14472  *		 *dev_list	Array of fc_portmap_t structures.
14473  *		 count		Length of dev_list.
14474  *		 state		State bits to update.
14475  *		 cause		Reason for the update.
14476  *
14477  * Return Value: None
14478  *
14479  *	Context: User, Kernel and Interrupt context.
14480  *		 The mutex pptr->port_mutex must be held.
14481  */
14482 static void
14483 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14484     uint32_t count, uint32_t state, int cause)
14485 {
14486 	fc_portmap_t		*map_entry;
14487 	struct fcp_tgt	*ptgt;
14488 
14489 	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14490 
14491 	while (count--) {
14492 		map_entry = &(dev_list[count]);
14493 		ptgt = fcp_lookup_target(pptr,
14494 		    (uchar_t *)&(map_entry->map_pwwn));
14495 		if (ptgt == NULL) {
14496 			continue;
14497 		}
14498 
14499 		mutex_enter(&ptgt->tgt_mutex);
14500 		ptgt->tgt_trace = 0;
14501 		ptgt->tgt_change_cnt++;
14502 		ptgt->tgt_statec_cause = cause;
14503 		ptgt->tgt_tmp_cnt = 1;
14504 		fcp_update_tgt_state(ptgt, FCP_SET, state);
14505 		mutex_exit(&ptgt->tgt_mutex);
14506 	}
14507 }
14508 
14509 static int
14510 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14511     int lcount, int tcount, int cause)
14512 {
14513 	int rval;
14514 
14515 	mutex_enter(&pptr->port_mutex);
14516 	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14517 	mutex_exit(&pptr->port_mutex);
14518 
14519 	return (rval);
14520 }
14521 
14522 
14523 static int
14524 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14525     int lcount, int tcount, int cause)
14526 {
14527 	int	finish_init = 0;
14528 	int	finish_tgt = 0;
14529 	int	do_finish_init = 0;
14530 	int	rval = FCP_NO_CHANGE;
14531 
14532 	if (cause == FCP_CAUSE_LINK_CHANGE ||
14533 	    cause == FCP_CAUSE_LINK_DOWN) {
14534 		do_finish_init = 1;
14535 	}
14536 
14537 	if (ptgt != NULL) {
14538 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14539 		    FCP_BUF_LEVEL_2, 0,
14540 		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14541 		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14542 		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14543 		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14544 		    ptgt->tgt_d_id, ptgt->tgt_done);
14545 
14546 		mutex_enter(&ptgt->tgt_mutex);
14547 
14548 		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14549 			rval = FCP_DEV_CHANGE;
14550 			if (do_finish_init && ptgt->tgt_done == 0) {
14551 				ptgt->tgt_done++;
14552 				finish_init = 1;
14553 			}
14554 		} else {
14555 			if (--ptgt->tgt_tmp_cnt <= 0) {
14556 				ptgt->tgt_tmp_cnt = 0;
14557 				finish_tgt = 1;
14558 
14559 				if (do_finish_init) {
14560 					finish_init = 1;
14561 				}
14562 			}
14563 		}
14564 		mutex_exit(&ptgt->tgt_mutex);
14565 	} else {
14566 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14567 		    FCP_BUF_LEVEL_2, 0,
14568 		    "Call Finish Init for NO target");
14569 
14570 		if (do_finish_init) {
14571 			finish_init = 1;
14572 		}
14573 	}
14574 
14575 	if (finish_tgt) {
14576 		ASSERT(ptgt != NULL);
14577 
14578 		mutex_enter(&ptgt->tgt_mutex);
14579 #ifdef	DEBUG
14580 		bzero(ptgt->tgt_tmp_cnt_stack,
14581 		    sizeof (ptgt->tgt_tmp_cnt_stack));
14582 
14583 		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14584 		    FCP_STACK_DEPTH);
14585 #endif /* DEBUG */
14586 		mutex_exit(&ptgt->tgt_mutex);
14587 
14588 		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14589 	}
14590 
14591 	if (finish_init && lcount == pptr->port_link_cnt) {
14592 		ASSERT(pptr->port_tmp_cnt > 0);
14593 		if (--pptr->port_tmp_cnt == 0) {
14594 			fcp_finish_init(pptr);
14595 		}
14596 	} else if (lcount != pptr->port_link_cnt) {
14597 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14598 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14599 		    "fcp_call_finish_init_held,1: state change occured"
14600 		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14601 	}
14602 
14603 	return (rval);
14604 }
14605 
14606 static void
14607 fcp_reconfigure_luns(void * tgt_handle)
14608 {
14609 	uint32_t		dev_cnt;
14610 	fc_portmap_t		*devlist;
14611 	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14612 	struct fcp_port		*pptr = ptgt->tgt_port;
14613 
14614 	/*
14615 	 * If the timer that fires this off got canceled too late, the
14616 	 * target could have been destroyed.
14617 	 */
14618 
14619 	if (ptgt->tgt_tid == NULL) {
14620 		return;
14621 	}
14622 
14623 	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14624 	if (devlist == NULL) {
14625 		fcp_log(CE_WARN, pptr->port_dip,
14626 		    "!fcp%d: failed to allocate for portmap",
14627 		    pptr->port_instance);
14628 		return;
14629 	}
14630 
14631 	dev_cnt = 1;
14632 	devlist->map_pd = ptgt->tgt_pd_handle;
14633 	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14634 	devlist->map_did.port_id = ptgt->tgt_d_id;
14635 
14636 	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14637 	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14638 
14639 	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14640 	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14641 	devlist->map_flags = 0;
14642 
14643 	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14644 	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14645 
14646 	/*
14647 	 * Clear the tgt_tid after no more references to
14648 	 * the fcp_tgt
14649 	 */
14650 	mutex_enter(&ptgt->tgt_mutex);
14651 	ptgt->tgt_tid = NULL;
14652 	mutex_exit(&ptgt->tgt_mutex);
14653 
14654 	kmem_free(devlist, sizeof (*devlist));
14655 }
14656 
14657 
14658 static void
14659 fcp_free_targets(struct fcp_port *pptr)
14660 {
14661 	int			i;
14662 	struct fcp_tgt	*ptgt;
14663 
14664 	mutex_enter(&pptr->port_mutex);
14665 	for (i = 0; i < FCP_NUM_HASH; i++) {
14666 		ptgt = pptr->port_tgt_hash_table[i];
14667 		while (ptgt != NULL) {
14668 			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14669 
14670 			fcp_free_target(ptgt);
14671 			ptgt = next_tgt;
14672 		}
14673 	}
14674 	mutex_exit(&pptr->port_mutex);
14675 }
14676 
14677 
14678 static void
14679 fcp_free_target(struct fcp_tgt *ptgt)
14680 {
14681 	struct fcp_lun	*plun;
14682 	timeout_id_t		tid;
14683 
14684 	mutex_enter(&ptgt->tgt_mutex);
14685 	tid = ptgt->tgt_tid;
14686 
14687 	/*
14688 	 * Cancel any pending timeouts for this target.
14689 	 */
14690 
14691 	if (tid != NULL) {
14692 		/*
14693 		 * Set tgt_tid to NULL first to avoid a race in the callback.
14694 		 * If tgt_tid is NULL, the callback will simply return.
14695 		 */
14696 		ptgt->tgt_tid = NULL;
14697 		mutex_exit(&ptgt->tgt_mutex);
14698 		(void) untimeout(tid);
14699 		mutex_enter(&ptgt->tgt_mutex);
14700 	}
14701 
14702 	plun = ptgt->tgt_lun;
14703 	while (plun != NULL) {
14704 		struct fcp_lun *next_lun = plun->lun_next;
14705 
14706 		fcp_dealloc_lun(plun);
14707 		plun = next_lun;
14708 	}
14709 
14710 	mutex_exit(&ptgt->tgt_mutex);
14711 	fcp_dealloc_tgt(ptgt);
14712 }
14713 
14714 /*
14715  *     Function: fcp_is_retryable
14716  *
14717  *  Description: Indicates if the internal packet is retryable.
14718  *
14719  *     Argument: *icmd		FCP internal packet.
14720  *
14721  * Return Value: 0	Not retryable
14722  *		 1	Retryable
14723  *
14724  *	Context: User, Kernel and Interrupt context
14725  */
14726 static int
14727 fcp_is_retryable(struct fcp_ipkt *icmd)
14728 {
14729 	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14730 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14731 		return (0);
14732 	}
14733 
14734 	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14735 	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14736 }
14737 
14738 /*
14739  *     Function: fcp_create_on_demand
14740  *
14741  *     Argument: *pptr		FCP port.
14742  *		 *pwwn		Port WWN.
14743  *
14744  * Return Value: 0	Success
14745  *		 EIO
14746  *		 ENOMEM
14747  *		 EBUSY
14748  *		 EINVAL
14749  *
14750  *	Context: User and Kernel context
14751  */
14752 static int
14753 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14754 {
14755 	int			wait_ms;
14756 	int			tcount;
14757 	int			lcount;
14758 	int			ret;
14759 	int			error;
14760 	int			rval = EIO;
14761 	int			ntries;
14762 	fc_portmap_t		*devlist;
14763 	opaque_t		pd;
14764 	struct fcp_lun		*plun;
14765 	struct fcp_tgt		*ptgt;
14766 	int			old_manual = 0;
14767 
14768 	/* Allocates the fc_portmap_t structure. */
14769 	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14770 
14771 	/*
14772 	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14773 	 * in the commented statement below:
14774 	 *
14775 	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14776 	 *
14777 	 * Below, the deadline for the discovery process is set.
14778 	 */
14779 	mutex_enter(&pptr->port_mutex);
14780 	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14781 	mutex_exit(&pptr->port_mutex);
14782 
14783 	/*
14784 	 * We try to find the remote port based on the WWN provided by the
14785 	 * caller.  We actually ask fp/fctl if it has it.
14786 	 */
14787 	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14788 	    (la_wwn_t *)pwwn, &error, 1);
14789 
14790 	if (pd == NULL) {
14791 		kmem_free(devlist, sizeof (*devlist));
14792 		return (rval);
14793 	}
14794 
14795 	/*
14796 	 * The remote port was found.  We ask fp/fctl to update our
14797 	 * fc_portmap_t structure.
14798 	 */
14799 	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14800 	    (la_wwn_t *)pwwn, devlist);
14801 	if (ret != FC_SUCCESS) {
14802 		kmem_free(devlist, sizeof (*devlist));
14803 		return (rval);
14804 	}
14805 
14806 	/*
14807 	 * The map flag field is set to indicates that the creation is being
14808 	 * done at the user request (Ioclt probably luxadm or cfgadm).
14809 	 */
14810 	devlist->map_type = PORT_DEVICE_USER_CREATE;
14811 
14812 	mutex_enter(&pptr->port_mutex);
14813 
14814 	/*
14815 	 * We check to see if fcp already has a target that describes the
14816 	 * device being created.  If not it is created.
14817 	 */
14818 	ptgt = fcp_lookup_target(pptr, pwwn);
14819 	if (ptgt == NULL) {
14820 		lcount = pptr->port_link_cnt;
14821 		mutex_exit(&pptr->port_mutex);
14822 
14823 		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14824 		if (ptgt == NULL) {
14825 			fcp_log(CE_WARN, pptr->port_dip,
14826 			    "!FC target allocation failed");
14827 			return (ENOMEM);
14828 		}
14829 
14830 		mutex_enter(&pptr->port_mutex);
14831 	}
14832 
14833 	mutex_enter(&ptgt->tgt_mutex);
14834 	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
14835 	ptgt->tgt_tmp_cnt = 1;
14836 	ptgt->tgt_device_created = 0;
14837 	/*
14838 	 * If fabric and auto config is set but the target was
14839 	 * manually unconfigured then reset to the manual_config_only to
14840 	 * 0 so the device will get configured.
14841 	 */
14842 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14843 	    fcp_enable_auto_configuration &&
14844 	    ptgt->tgt_manual_config_only == 1) {
14845 		old_manual = 1;
14846 		ptgt->tgt_manual_config_only = 0;
14847 	}
14848 	mutex_exit(&ptgt->tgt_mutex);
14849 
14850 	fcp_update_targets(pptr, devlist, 1,
14851 	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
14852 
14853 	lcount = pptr->port_link_cnt;
14854 	tcount = ptgt->tgt_change_cnt;
14855 
14856 	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
14857 	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
14858 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14859 		    fcp_enable_auto_configuration && old_manual) {
14860 			mutex_enter(&ptgt->tgt_mutex);
14861 			ptgt->tgt_manual_config_only = 1;
14862 			mutex_exit(&ptgt->tgt_mutex);
14863 		}
14864 
14865 		if (pptr->port_link_cnt != lcount ||
14866 		    ptgt->tgt_change_cnt != tcount) {
14867 			rval = EBUSY;
14868 		}
14869 		mutex_exit(&pptr->port_mutex);
14870 
14871 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14872 		    FCP_BUF_LEVEL_3, 0,
14873 		    "fcp_create_on_demand: mapflags ptgt=%x, "
14874 		    "lcount=%x::port_link_cnt=%x, "
14875 		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
14876 		    ptgt, lcount, pptr->port_link_cnt,
14877 		    tcount, ptgt->tgt_change_cnt, rval);
14878 		return (rval);
14879 	}
14880 
14881 	/*
14882 	 * Due to lack of synchronization mechanisms, we perform
14883 	 * periodic monitoring of our request; Because requests
14884 	 * get dropped when another one supercedes (either because
14885 	 * of a link change or a target change), it is difficult to
14886 	 * provide a clean synchronization mechanism (such as a
14887 	 * semaphore or a conditional variable) without exhaustively
14888 	 * rewriting the mainline discovery code of this driver.
14889 	 */
14890 	wait_ms = 500;
14891 
14892 	ntries = fcp_max_target_retries;
14893 
14894 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14895 	    FCP_BUF_LEVEL_3, 0,
14896 	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
14897 	    "lcount=%x::port_link_cnt=%x, "
14898 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
14899 	    "tgt_tmp_cnt =%x",
14900 	    ntries, ptgt, lcount, pptr->port_link_cnt,
14901 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
14902 	    ptgt->tgt_tmp_cnt);
14903 
14904 	mutex_enter(&ptgt->tgt_mutex);
14905 	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
14906 	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
14907 		mutex_exit(&ptgt->tgt_mutex);
14908 		mutex_exit(&pptr->port_mutex);
14909 
14910 		delay(drv_usectohz(wait_ms * 1000));
14911 
14912 		mutex_enter(&pptr->port_mutex);
14913 		mutex_enter(&ptgt->tgt_mutex);
14914 	}
14915 
14916 
14917 	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
14918 		rval = EBUSY;
14919 	} else {
14920 		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
14921 		    FCP_TGT_NODE_PRESENT) {
14922 			rval = 0;
14923 		}
14924 	}
14925 
14926 	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14927 	    FCP_BUF_LEVEL_3, 0,
14928 	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
14929 	    "lcount=%x::port_link_cnt=%x, "
14930 	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
14931 	    "tgt_tmp_cnt =%x",
14932 	    ntries, ptgt, lcount, pptr->port_link_cnt,
14933 	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
14934 	    ptgt->tgt_tmp_cnt);
14935 
14936 	if (rval) {
14937 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14938 		    fcp_enable_auto_configuration && old_manual) {
14939 			ptgt->tgt_manual_config_only = 1;
14940 		}
14941 		mutex_exit(&ptgt->tgt_mutex);
14942 		mutex_exit(&pptr->port_mutex);
14943 		kmem_free(devlist, sizeof (*devlist));
14944 
14945 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14946 		    FCP_BUF_LEVEL_3, 0,
14947 		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
14948 		    "lcount=%x::port_link_cnt=%x, "
14949 		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
14950 		    "tgt_device_created=%x, tgt D_ID=%x",
14951 		    ntries, ptgt, lcount, pptr->port_link_cnt,
14952 		    tcount, ptgt->tgt_change_cnt, rval,
14953 		    ptgt->tgt_device_created, ptgt->tgt_d_id);
14954 		return (rval);
14955 	}
14956 
14957 	if ((plun = ptgt->tgt_lun) != NULL) {
14958 		tcount = plun->lun_tgt->tgt_change_cnt;
14959 	} else {
14960 		rval = EINVAL;
14961 	}
14962 	lcount = pptr->port_link_cnt;
14963 
14964 	/*
14965 	 * Configuring the target with no LUNs will fail. We
14966 	 * should reset the node state so that it is not
14967 	 * automatically configured when the LUNs are added
14968 	 * to this target.
14969 	 */
14970 	if (ptgt->tgt_lun_cnt == 0) {
14971 		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
14972 	}
14973 	mutex_exit(&ptgt->tgt_mutex);
14974 	mutex_exit(&pptr->port_mutex);
14975 
14976 	while (plun) {
14977 		child_info_t	*cip;
14978 
14979 		mutex_enter(&plun->lun_mutex);
14980 		cip = plun->lun_cip;
14981 		mutex_exit(&plun->lun_mutex);
14982 
14983 		mutex_enter(&ptgt->tgt_mutex);
14984 		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
14985 			mutex_exit(&ptgt->tgt_mutex);
14986 
14987 			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
14988 			    FCP_ONLINE, lcount, tcount,
14989 			    NDI_ONLINE_ATTACH);
14990 			if (rval != NDI_SUCCESS) {
14991 				FCP_TRACE(fcp_logq,
14992 				    pptr->port_instbuf, fcp_trace,
14993 				    FCP_BUF_LEVEL_3, 0,
14994 				    "fcp_create_on_demand: "
14995 				    "pass_to_hp_and_wait failed "
14996 				    "rval=%x", rval);
14997 				rval = EIO;
14998 			} else {
14999 				mutex_enter(&LUN_TGT->tgt_mutex);
15000 				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15001 				    FCP_LUN_BUSY);
15002 				mutex_exit(&LUN_TGT->tgt_mutex);
15003 			}
15004 			mutex_enter(&ptgt->tgt_mutex);
15005 		}
15006 
15007 		plun = plun->lun_next;
15008 		mutex_exit(&ptgt->tgt_mutex);
15009 	}
15010 
15011 	kmem_free(devlist, sizeof (*devlist));
15012 
15013 	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15014 	    fcp_enable_auto_configuration && old_manual) {
15015 		mutex_enter(&ptgt->tgt_mutex);
15016 		/* if successful then set manual to 0 */
15017 		if (rval == 0) {
15018 			ptgt->tgt_manual_config_only = 0;
15019 		} else {
15020 			/* reset to 1 so the user has to do the config */
15021 			ptgt->tgt_manual_config_only = 1;
15022 		}
15023 		mutex_exit(&ptgt->tgt_mutex);
15024 	}
15025 
15026 	return (rval);
15027 }
15028 
15029 
15030 static void
15031 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15032 {
15033 	int		count;
15034 	uchar_t		byte;
15035 
15036 	count = 0;
15037 	while (*string) {
15038 		byte = FCP_ATOB(*string); string++;
15039 		byte = byte << 4 | FCP_ATOB(*string); string++;
15040 		bytes[count++] = byte;
15041 
15042 		if (count >= byte_len) {
15043 			break;
15044 		}
15045 	}
15046 }
15047 
15048 static void
15049 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15050 {
15051 	int		i;
15052 
15053 	for (i = 0; i < FC_WWN_SIZE; i++) {
15054 		(void) sprintf(string + (i * 2),
15055 		    "%02x", wwn[i]);
15056 	}
15057 
15058 }
15059 
15060 static void
15061 fcp_print_error(fc_packet_t *fpkt)
15062 {
15063 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15064 	    fpkt->pkt_ulp_private;
15065 	struct fcp_port	*pptr;
15066 	struct fcp_tgt	*ptgt;
15067 	struct fcp_lun	*plun;
15068 	caddr_t			buf;
15069 	int			scsi_cmd = 0;
15070 
15071 	ptgt = icmd->ipkt_tgt;
15072 	plun = icmd->ipkt_lun;
15073 	pptr = ptgt->tgt_port;
15074 
15075 	buf = kmem_zalloc(256, KM_NOSLEEP);
15076 	if (buf == NULL) {
15077 		return;
15078 	}
15079 
15080 	switch (icmd->ipkt_opcode) {
15081 	case SCMD_REPORT_LUN:
15082 		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15083 		    " lun=0x%%x failed");
15084 		scsi_cmd++;
15085 		break;
15086 
15087 	case SCMD_INQUIRY_PAGE83:
15088 		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15089 		    " lun=0x%%x failed");
15090 		scsi_cmd++;
15091 		break;
15092 
15093 	case SCMD_INQUIRY:
15094 		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15095 		    " lun=0x%%x failed");
15096 		scsi_cmd++;
15097 		break;
15098 
15099 	case LA_ELS_PLOGI:
15100 		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15101 		break;
15102 
15103 	case LA_ELS_PRLI:
15104 		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15105 		break;
15106 	}
15107 
15108 	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15109 		struct fcp_rsp		response, *rsp;
15110 		uchar_t			asc, ascq;
15111 		caddr_t			sense_key = NULL;
15112 		struct fcp_rsp_info	fcp_rsp_err, *bep;
15113 
15114 		if (icmd->ipkt_nodma) {
15115 			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15116 			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15117 			    sizeof (struct fcp_rsp));
15118 		} else {
15119 			rsp = &response;
15120 			bep = &fcp_rsp_err;
15121 
15122 			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15123 			    sizeof (struct fcp_rsp));
15124 
15125 			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15126 			    bep, fpkt->pkt_resp_acc,
15127 			    sizeof (struct fcp_rsp_info));
15128 		}
15129 
15130 
15131 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15132 			(void) sprintf(buf + strlen(buf),
15133 			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15134 			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15135 			    " senselen=%%x. Giving up");
15136 
15137 			fcp_log(CE_WARN, pptr->port_dip, buf,
15138 			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15139 			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15140 			    rsp->fcp_u.fcp_status.reserved_1,
15141 			    rsp->fcp_response_len, rsp->fcp_sense_len);
15142 
15143 			kmem_free(buf, 256);
15144 			return;
15145 		}
15146 
15147 		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15148 		    bep->rsp_code != FCP_NO_FAILURE) {
15149 			(void) sprintf(buf + strlen(buf),
15150 			    " FCP Response code = 0x%x", bep->rsp_code);
15151 		}
15152 
15153 		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15154 			struct scsi_extended_sense sense_info, *sense_ptr;
15155 
15156 			if (icmd->ipkt_nodma) {
15157 				sense_ptr = (struct scsi_extended_sense *)
15158 				    ((caddr_t)fpkt->pkt_resp +
15159 				    sizeof (struct fcp_rsp) +
15160 				    rsp->fcp_response_len);
15161 			} else {
15162 				sense_ptr = &sense_info;
15163 
15164 				FCP_CP_IN(fpkt->pkt_resp +
15165 				    sizeof (struct fcp_rsp) +
15166 				    rsp->fcp_response_len, &sense_info,
15167 				    fpkt->pkt_resp_acc,
15168 				    sizeof (struct scsi_extended_sense));
15169 			}
15170 
15171 			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15172 			    NUM_IMPL_SENSE_KEYS) {
15173 				sense_key = sense_keys[sense_ptr->es_key];
15174 			} else {
15175 				sense_key = "Undefined";
15176 			}
15177 
15178 			asc = sense_ptr->es_add_code;
15179 			ascq = sense_ptr->es_qual_code;
15180 
15181 			(void) sprintf(buf + strlen(buf),
15182 			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15183 			    " Giving up");
15184 
15185 			fcp_log(CE_WARN, pptr->port_dip, buf,
15186 			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15187 			    asc, ascq);
15188 		} else {
15189 			(void) sprintf(buf + strlen(buf),
15190 			    " : SCSI status=%%x. Giving up");
15191 
15192 			fcp_log(CE_WARN, pptr->port_dip, buf,
15193 			    ptgt->tgt_d_id, plun->lun_num,
15194 			    rsp->fcp_u.fcp_status.scsi_status);
15195 		}
15196 	} else {
15197 		caddr_t state, reason, action, expln;
15198 
15199 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15200 		    &action, &expln);
15201 
15202 		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15203 		    " Reason:%%s. Giving up");
15204 
15205 		if (scsi_cmd) {
15206 			fcp_log(CE_WARN, pptr->port_dip, buf,
15207 			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15208 		} else {
15209 			fcp_log(CE_WARN, pptr->port_dip, buf,
15210 			    ptgt->tgt_d_id, state, reason);
15211 		}
15212 	}
15213 
15214 	kmem_free(buf, 256);
15215 }
15216 
15217 
15218 static int
15219 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15220     struct fcp_ipkt *icmd, int rval, caddr_t op)
15221 {
15222 	int	ret = DDI_FAILURE;
15223 	char	*error;
15224 
15225 	switch (rval) {
15226 	case FC_DEVICE_BUSY_NEW_RSCN:
15227 		/*
15228 		 * This means that there was a new RSCN that the transport
15229 		 * knows about (which the ULP *may* know about too) but the
15230 		 * pkt that was sent down was related to an older RSCN. So, we
15231 		 * are just going to reset the retry count and deadline and
15232 		 * continue to retry. The idea is that transport is currently
15233 		 * working on the new RSCN and will soon let the ULPs know
15234 		 * about it and when it does the existing logic will kick in
15235 		 * where it will change the tcount to indicate that something
15236 		 * changed on the target. So, rediscovery will start and there
15237 		 * will not be an infinite retry.
15238 		 *
15239 		 * For a full flow of how the RSCN info is transferred back and
15240 		 * forth, see fp.c
15241 		 */
15242 		icmd->ipkt_retries = 0;
15243 		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15244 		    FCP_ICMD_DEADLINE;
15245 
15246 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15247 		    FCP_BUF_LEVEL_3, 0,
15248 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15249 		    rval, ptgt->tgt_d_id);
15250 		/* FALLTHROUGH */
15251 
15252 	case FC_STATEC_BUSY:
15253 	case FC_DEVICE_BUSY:
15254 	case FC_PBUSY:
15255 	case FC_FBUSY:
15256 	case FC_TRAN_BUSY:
15257 	case FC_OFFLINE:
15258 		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15259 		    FCP_BUF_LEVEL_3, 0,
15260 		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15261 		    rval, ptgt->tgt_d_id);
15262 		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15263 		    fcp_is_retryable(icmd)) {
15264 			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15265 			ret = DDI_SUCCESS;
15266 		}
15267 		break;
15268 
15269 	case FC_LOGINREQ:
15270 		/*
15271 		 * FC_LOGINREQ used to be handled just like all the cases
15272 		 * above. It has been changed to handled a PRLI that fails
15273 		 * with FC_LOGINREQ different than other ipkts that fail
15274 		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15275 		 * a simple matter to turn it into a PLOGI instead, so that's
15276 		 * exactly what we do here.
15277 		 */
15278 		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15279 			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15280 			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15281 			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15282 		} else {
15283 			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15284 			    FCP_BUF_LEVEL_3, 0,
15285 			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15286 			    rval, ptgt->tgt_d_id);
15287 			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15288 			    fcp_is_retryable(icmd)) {
15289 				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15290 				ret = DDI_SUCCESS;
15291 			}
15292 		}
15293 		break;
15294 
15295 	default:
15296 		mutex_enter(&pptr->port_mutex);
15297 		mutex_enter(&ptgt->tgt_mutex);
15298 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15299 			mutex_exit(&ptgt->tgt_mutex);
15300 			mutex_exit(&pptr->port_mutex);
15301 
15302 			(void) fc_ulp_error(rval, &error);
15303 			fcp_log(CE_WARN, pptr->port_dip,
15304 			    "!Failed to send %s to D_ID=%x error=%s",
15305 			    op, ptgt->tgt_d_id, error);
15306 		} else {
15307 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15308 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15309 			    "fcp_handle_ipkt_errors,1: state change occured"
15310 			    " for D_ID=0x%x", ptgt->tgt_d_id);
15311 			mutex_exit(&ptgt->tgt_mutex);
15312 			mutex_exit(&pptr->port_mutex);
15313 		}
15314 		break;
15315 	}
15316 
15317 	return (ret);
15318 }
15319 
15320 
15321 /*
15322  * Check of outstanding commands on any LUN for this target
15323  */
15324 static int
15325 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15326 {
15327 	struct	fcp_lun	*plun;
15328 	struct	fcp_pkt	*cmd;
15329 
15330 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15331 		mutex_enter(&plun->lun_mutex);
15332 		for (cmd = plun->lun_pkt_head; cmd != NULL;
15333 		    cmd = cmd->cmd_forw) {
15334 			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15335 				mutex_exit(&plun->lun_mutex);
15336 				return (FC_SUCCESS);
15337 			}
15338 		}
15339 		mutex_exit(&plun->lun_mutex);
15340 	}
15341 
15342 	return (FC_FAILURE);
15343 }
15344 
15345 static fc_portmap_t *
15346 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15347 {
15348 	int			i;
15349 	fc_portmap_t		*devlist;
15350 	fc_portmap_t		*devptr = NULL;
15351 	struct fcp_tgt	*ptgt;
15352 
15353 	mutex_enter(&pptr->port_mutex);
15354 	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15355 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15356 		    ptgt = ptgt->tgt_next) {
15357 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15358 				++*dev_cnt;
15359 			}
15360 		}
15361 	}
15362 
15363 	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15364 	    KM_NOSLEEP);
15365 	if (devlist == NULL) {
15366 		mutex_exit(&pptr->port_mutex);
15367 		fcp_log(CE_WARN, pptr->port_dip,
15368 		    "!fcp%d: failed to allocate for portmap for construct map",
15369 		    pptr->port_instance);
15370 		return (devptr);
15371 	}
15372 
15373 	for (i = 0; i < FCP_NUM_HASH; i++) {
15374 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15375 		    ptgt = ptgt->tgt_next) {
15376 			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15377 				int ret;
15378 
15379 				ret = fc_ulp_pwwn_to_portmap(
15380 				    pptr->port_fp_handle,
15381 				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15382 				    devlist);
15383 
15384 				if (ret == FC_SUCCESS) {
15385 					devlist++;
15386 					continue;
15387 				}
15388 
15389 				devlist->map_pd = NULL;
15390 				devlist->map_did.port_id = ptgt->tgt_d_id;
15391 				devlist->map_hard_addr.hard_addr =
15392 				    ptgt->tgt_hard_addr;
15393 
15394 				devlist->map_state = PORT_DEVICE_INVALID;
15395 				devlist->map_type = PORT_DEVICE_OLD;
15396 
15397 				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15398 				    &devlist->map_nwwn, FC_WWN_SIZE);
15399 
15400 				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15401 				    &devlist->map_pwwn, FC_WWN_SIZE);
15402 
15403 				devlist++;
15404 			}
15405 		}
15406 	}
15407 
15408 	mutex_exit(&pptr->port_mutex);
15409 
15410 	return (devptr);
15411 }
15412 /*
15413  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15414  */
15415 static void
15416 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15417 {
15418 	int i;
15419 	struct fcp_tgt	*ptgt;
15420 	struct fcp_lun	*plun;
15421 
15422 	for (i = 0; i < FCP_NUM_HASH; i++) {
15423 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15424 		    ptgt = ptgt->tgt_next) {
15425 			mutex_enter(&ptgt->tgt_mutex);
15426 			for (plun = ptgt->tgt_lun; plun != NULL;
15427 			    plun = plun->lun_next) {
15428 				if (plun->lun_mpxio &&
15429 				    plun->lun_state & FCP_LUN_BUSY) {
15430 					if (!fcp_pass_to_hp(pptr, plun,
15431 					    plun->lun_cip,
15432 					    FCP_MPXIO_PATH_SET_BUSY,
15433 					    pptr->port_link_cnt,
15434 					    ptgt->tgt_change_cnt, 0, 0)) {
15435 						FCP_TRACE(fcp_logq,
15436 						    pptr->port_instbuf,
15437 						    fcp_trace,
15438 						    FCP_BUF_LEVEL_2, 0,
15439 						    "path_verifybusy: "
15440 						    "disable lun %p failed!",
15441 						    plun);
15442 					}
15443 				}
15444 			}
15445 			mutex_exit(&ptgt->tgt_mutex);
15446 		}
15447 	}
15448 }
15449 
15450 static int
15451 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15452 {
15453 	dev_info_t		*cdip = NULL;
15454 	dev_info_t		*pdip = NULL;
15455 
15456 	ASSERT(plun);
15457 
15458 	mutex_enter(&plun->lun_mutex);
15459 	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15460 		mutex_exit(&plun->lun_mutex);
15461 		return (NDI_FAILURE);
15462 	}
15463 	mutex_exit(&plun->lun_mutex);
15464 	cdip = mdi_pi_get_client(PIP(cip));
15465 	pdip = mdi_pi_get_phci(PIP(cip));
15466 
15467 	ASSERT(cdip != NULL);
15468 	ASSERT(pdip != NULL);
15469 
15470 	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15471 		/* LUN ready for IO */
15472 		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15473 	} else {
15474 		/* LUN busy to accept IO */
15475 		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15476 	}
15477 	return (NDI_SUCCESS);
15478 }
15479 
15480 /*
15481  * Caller must free the returned string of MAXPATHLEN len
15482  * If the device is offline (-1 instance number) NULL
15483  * will be returned.
15484  */
15485 static char *
15486 fcp_get_lun_path(struct fcp_lun *plun) {
15487 	dev_info_t	*dip = NULL;
15488 	char	*path = NULL;
15489 	if (plun == NULL) {
15490 		return (NULL);
15491 	}
15492 	if (plun->lun_mpxio == 0) {
15493 		dip = DIP(plun->lun_cip);
15494 	} else {
15495 		dip = mdi_pi_get_client(PIP(plun->lun_cip));
15496 	}
15497 	if (dip == NULL) {
15498 		return (NULL);
15499 	}
15500 	if (ddi_get_instance(dip) < 0) {
15501 		return (NULL);
15502 	}
15503 	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15504 	if (path == NULL) {
15505 		return (NULL);
15506 	}
15507 
15508 	(void) ddi_pathname(dip, path);
15509 	/*
15510 	 * In reality, the user wants a fully valid path (one they can open)
15511 	 * but this string is lacking the mount point, and the minor node.
15512 	 * It would be nice if we could "figure these out" somehow
15513 	 * and fill them in.  Otherwise, the userland code has to understand
15514 	 * driver specific details of which minor node is the "best" or
15515 	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15516 	 * which tape doesn't rewind)
15517 	 */
15518 	return (path);
15519 }
15520 
15521 static int
15522 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15523     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15524 {
15525 	int64_t reset_delay;
15526 	int rval, retry = 0;
15527 	struct fcp_port *pptr = fcp_dip2port(parent);
15528 
15529 	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15530 	    (lbolt64 - pptr->port_attach_time);
15531 	if (reset_delay < 0) {
15532 		reset_delay = 0;
15533 	}
15534 
15535 	if (fcp_bus_config_debug) {
15536 		flag |= NDI_DEVI_DEBUG;
15537 	}
15538 
15539 	switch (op) {
15540 	case BUS_CONFIG_ONE:
15541 		/*
15542 		 * Retry the command since we need to ensure
15543 		 * the fabric devices are available for root
15544 		 */
15545 		while (retry++ < fcp_max_bus_config_retries) {
15546 			rval =	(ndi_busop_bus_config(parent,
15547 			    flag | NDI_MDI_FALLBACK, op,
15548 			    arg, childp, (clock_t)reset_delay));
15549 			if (rval == 0) {
15550 				return (rval);
15551 			}
15552 		}
15553 
15554 		/*
15555 		 * drain taskq to make sure nodes are created and then
15556 		 * try again.
15557 		 */
15558 		taskq_wait(DEVI(parent)->devi_taskq);
15559 		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15560 		    op, arg, childp, 0));
15561 
15562 	case BUS_CONFIG_DRIVER:
15563 	case BUS_CONFIG_ALL: {
15564 		/*
15565 		 * delay till all devices report in (port_tmp_cnt == 0)
15566 		 * or FCP_INIT_WAIT_TIMEOUT
15567 		 */
15568 		mutex_enter(&pptr->port_mutex);
15569 		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15570 			(void) cv_timedwait(&pptr->port_config_cv,
15571 			    &pptr->port_mutex,
15572 			    ddi_get_lbolt() + (clock_t)reset_delay);
15573 			reset_delay =
15574 			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15575 			    (lbolt64 - pptr->port_attach_time);
15576 		}
15577 		mutex_exit(&pptr->port_mutex);
15578 		/* drain taskq to make sure nodes are created */
15579 		taskq_wait(DEVI(parent)->devi_taskq);
15580 		return (ndi_busop_bus_config(parent, flag, op,
15581 		    arg, childp, 0));
15582 	}
15583 
15584 	default:
15585 		return (NDI_FAILURE);
15586 	}
15587 	/*NOTREACHED*/
15588 }
15589 
15590 static int
15591 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15592     ddi_bus_config_op_t op, void *arg)
15593 {
15594 	if (fcp_bus_config_debug) {
15595 		flag |= NDI_DEVI_DEBUG;
15596 	}
15597 
15598 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15599 }
15600 
15601 
15602 /*
15603  * Routine to copy GUID into the lun structure.
15604  * returns 0 if copy was successful and 1 if encountered a
15605  * failure and did not copy the guid.
15606  */
15607 static int
15608 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15609 {
15610 
15611 	int retval = 0;
15612 
15613 	/* add one for the null terminator */
15614 	const unsigned int len = strlen(guidp) + 1;
15615 
15616 	if ((guidp == NULL) || (plun == NULL)) {
15617 		return (1);
15618 	}
15619 
15620 	/*
15621 	 * if the plun->lun_guid already has been allocated,
15622 	 * then check the size. if the size is exact, reuse
15623 	 * it....if not free it an allocate the required size.
15624 	 * The reallocation should NOT typically happen
15625 	 * unless the GUIDs reported changes between passes.
15626 	 * We free up and alloc again even if the
15627 	 * size was more than required. This is due to the
15628 	 * fact that the field lun_guid_size - serves
15629 	 * dual role of indicating the size of the wwn
15630 	 * size and ALSO the allocation size.
15631 	 */
15632 	if (plun->lun_guid) {
15633 		if (plun->lun_guid_size != len) {
15634 			/*
15635 			 * free the allocated memory and
15636 			 * initialize the field
15637 			 * lun_guid_size to 0.
15638 			 */
15639 			kmem_free(plun->lun_guid, plun->lun_guid_size);
15640 			plun->lun_guid = NULL;
15641 			plun->lun_guid_size = 0;
15642 		}
15643 	}
15644 	/*
15645 	 * alloc only if not already done.
15646 	 */
15647 	if (plun->lun_guid == NULL) {
15648 		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15649 		if (plun->lun_guid == NULL) {
15650 			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15651 			    "Unable to allocate"
15652 			    "Memory for GUID!!! size %d", len);
15653 			retval = 1;
15654 		} else {
15655 			plun->lun_guid_size = len;
15656 		}
15657 	}
15658 	if (plun->lun_guid) {
15659 		/*
15660 		 * now copy the GUID
15661 		 */
15662 		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15663 	}
15664 	return (retval);
15665 }
15666 
15667 /*
15668  * fcp_reconfig_wait
15669  *
15670  * Wait for a rediscovery/reconfiguration to complete before continuing.
15671  */
15672 
15673 static void
15674 fcp_reconfig_wait(struct fcp_port *pptr)
15675 {
15676 	clock_t		reconfig_start, wait_timeout;
15677 
15678 	/*
15679 	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15680 	 * reconfiguration in progress.
15681 	 */
15682 
15683 	mutex_enter(&pptr->port_mutex);
15684 	if (pptr->port_tmp_cnt == 0) {
15685 		mutex_exit(&pptr->port_mutex);
15686 		return;
15687 	}
15688 	mutex_exit(&pptr->port_mutex);
15689 
15690 	/*
15691 	 * If we cause a reconfig by raising power, delay until all devices
15692 	 * report in (port_tmp_cnt returns to 0)
15693 	 */
15694 
15695 	reconfig_start = ddi_get_lbolt();
15696 	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15697 
15698 	mutex_enter(&pptr->port_mutex);
15699 
15700 	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15701 	    pptr->port_tmp_cnt) {
15702 
15703 		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15704 		    reconfig_start + wait_timeout);
15705 	}
15706 
15707 	mutex_exit(&pptr->port_mutex);
15708 
15709 	/*
15710 	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15711 	 * we want may still be ok.  If not, it will error out later
15712 	 */
15713 }
15714 
15715 /*
15716  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15717  * We rely on the fcp_global_mutex to provide protection against changes to
15718  * the fcp_lun_blacklist.
15719  *
15720  * You can describe a list of target port WWNs and LUN numbers which will
15721  * not be configured. LUN numbers will be interpreted as decimal. White
15722  * spaces and ',' can be used in the list of LUN numbers.
15723  *
15724  * To prevent LUNs 1 and 2 from being configured for target
15725  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15726  *
15727  * pwwn-lun-blacklist=
15728  * "510000f010fd92a1,1,2",
15729  * "510000e012079df1,1,2";
15730  */
15731 static void
15732 fcp_read_blacklist(dev_info_t *dip,
15733     struct fcp_black_list_entry **pplun_blacklist) {
15734 	char **prop_array	= NULL;
15735 	char *curr_pwwn		= NULL;
15736 	char *curr_lun		= NULL;
15737 	uint32_t prop_item	= 0;
15738 	int idx			= 0;
15739 	int len			= 0;
15740 
15741 	ASSERT(mutex_owned(&fcp_global_mutex));
15742 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15743 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15744 	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15745 		return;
15746 	}
15747 
15748 	for (idx = 0; idx < prop_item; idx++) {
15749 
15750 		curr_pwwn = prop_array[idx];
15751 		while (*curr_pwwn == ' ') {
15752 			curr_pwwn++;
15753 		}
15754 		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15755 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15756 			    ", please check.", curr_pwwn);
15757 			continue;
15758 		}
15759 		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15760 		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15761 			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15762 			    ", please check.", curr_pwwn);
15763 			continue;
15764 		}
15765 		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15766 			if (isxdigit(curr_pwwn[len]) != TRUE) {
15767 				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15768 				    "blacklist, please check.", curr_pwwn);
15769 				break;
15770 			}
15771 		}
15772 		if (len != sizeof (la_wwn_t) * 2) {
15773 			continue;
15774 		}
15775 
15776 		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15777 		*(curr_lun - 1) = '\0';
15778 		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15779 	}
15780 
15781 	ddi_prop_free(prop_array);
15782 }
15783 
15784 /*
15785  * Get the masking info about one remote target port designated by wwn.
15786  * Lun ids could be separated by ',' or white spaces.
15787  */
15788 static void
15789 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15790     struct fcp_black_list_entry **pplun_blacklist) {
15791 	int		idx			= 0;
15792 	uint32_t	offset			= 0;
15793 	unsigned long	lun_id			= 0;
15794 	char		lunid_buf[16];
15795 	char		*pend			= NULL;
15796 	int		illegal_digit		= 0;
15797 
15798 	while (offset < strlen(curr_lun)) {
15799 		while ((curr_lun[offset + idx] != ',') &&
15800 		    (curr_lun[offset + idx] != '\0') &&
15801 		    (curr_lun[offset + idx] != ' ')) {
15802 			if (isdigit(curr_lun[offset + idx]) == 0) {
15803 				illegal_digit++;
15804 			}
15805 			idx++;
15806 		}
15807 		if (illegal_digit > 0) {
15808 			offset += (idx+1);	/* To the start of next lun */
15809 			idx = 0;
15810 			illegal_digit = 0;
15811 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15812 			    "the blacklist, please check digits.",
15813 			    curr_lun, curr_pwwn);
15814 			continue;
15815 		}
15816 		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
15817 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15818 			    "the blacklist, please check the length of LUN#.",
15819 			    curr_lun, curr_pwwn);
15820 			break;
15821 		}
15822 		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
15823 		    offset++;
15824 		    continue;
15825 		}
15826 
15827 		bcopy(curr_lun + offset, lunid_buf, idx);
15828 		lunid_buf[idx] = '\0';
15829 		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
15830 			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
15831 		} else {
15832 			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15833 			    "the blacklist, please check %s.",
15834 			    curr_lun, curr_pwwn, lunid_buf);
15835 		}
15836 		offset += (idx+1);	/* To the start of next lun */
15837 		idx = 0;
15838 	}
15839 }
15840 
15841 /*
15842  * Add one masking record
15843  */
15844 static void
15845 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
15846     struct fcp_black_list_entry **pplun_blacklist) {
15847 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
15848 	struct fcp_black_list_entry	*new_entry	= NULL;
15849 	la_wwn_t			wwn;
15850 
15851 	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
15852 	while (tmp_entry) {
15853 		if ((bcmp(&tmp_entry->wwn, &wwn,
15854 		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
15855 			return;
15856 		}
15857 
15858 		tmp_entry = tmp_entry->next;
15859 	}
15860 
15861 	/* add to black list */
15862 	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
15863 	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
15864 	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
15865 	new_entry->lun = lun_id;
15866 	new_entry->masked = 0;
15867 	new_entry->next = *pplun_blacklist;
15868 	*pplun_blacklist = new_entry;
15869 }
15870 
15871 /*
15872  * Check if we should mask the specified lun of this fcp_tgt
15873  */
15874 static int
15875 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
15876 	struct fcp_black_list_entry *remote_port;
15877 
15878 	remote_port = fcp_lun_blacklist;
15879 	while (remote_port != NULL) {
15880 		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
15881 			if (remote_port->lun == lun_id) {
15882 				remote_port->masked++;
15883 				if (remote_port->masked == 1) {
15884 					fcp_log(CE_NOTE, NULL, "LUN %d of port "
15885 					    "%02x%02x%02x%02x%02x%02x%02x%02x "
15886 					    "is masked due to black listing.\n",
15887 					    lun_id, wwn->raw_wwn[0],
15888 					    wwn->raw_wwn[1], wwn->raw_wwn[2],
15889 					    wwn->raw_wwn[3], wwn->raw_wwn[4],
15890 					    wwn->raw_wwn[5], wwn->raw_wwn[6],
15891 					    wwn->raw_wwn[7]);
15892 				}
15893 				return (TRUE);
15894 			}
15895 		}
15896 		remote_port = remote_port->next;
15897 	}
15898 	return (FALSE);
15899 }
15900 
15901 /*
15902  * Release all allocated resources
15903  */
15904 static void
15905 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
15906 	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
15907 	struct fcp_black_list_entry	*current_entry	= NULL;
15908 
15909 	ASSERT(mutex_owned(&fcp_global_mutex));
15910 	/*
15911 	 * Traverse all luns
15912 	 */
15913 	while (tmp_entry) {
15914 		current_entry = tmp_entry;
15915 		tmp_entry = tmp_entry->next;
15916 		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
15917 	}
15918 	*pplun_blacklist = NULL;
15919 }
15920