1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 *
24 * Fibre Channel SCSI ULP Mapping driver
25 */
26
27#include <sys/scsi/scsi.h>
28#include <sys/types.h>
29#include <sys/varargs.h>
30#include <sys/devctl.h>
31#include <sys/thread.h>
32#include <sys/thread.h>
33#include <sys/open.h>
34#include <sys/file.h>
35#include <sys/sunndi.h>
36#include <sys/console.h>
37#include <sys/proc.h>
38#include <sys/time.h>
39#include <sys/utsname.h>
40#include <sys/scsi/impl/scsi_reset_notify.h>
41#include <sys/ndi_impldefs.h>
42#include <sys/byteorder.h>
43#include <sys/fs/dv_node.h>
44#include <sys/ctype.h>
45#include <sys/sunmdi.h>
46
47#include <sys/fibre-channel/fc.h>
48#include <sys/fibre-channel/impl/fc_ulpif.h>
49#include <sys/fibre-channel/ulp/fcpvar.h>
50
51/*
52 * Discovery Process
53 * =================
54 *
55 *    The discovery process is a major function of FCP.	 In order to help
56 * understand that function a flow diagram is given here.  This diagram
57 * doesn't claim to cover all the cases and the events that can occur during
58 * the discovery process nor the subtleties of the code.  The code paths shown
59 * are simplified.  Its purpose is to help the reader (and potentially bug
60 * fixer) have an overall view of the logic of the code.  For that reason the
61 * diagram covers the simple case of the line coming up cleanly or of a new
62 * port attaching to FCP the link being up.  The reader must keep in mind
63 * that:
64 *
65 *	- There are special cases where bringing devices online and offline
66 *	  is driven by Ioctl.
67 *
68 *	- The behavior of the discovery process can be modified through the
69 *	  .conf file.
70 *
71 *	- The line can go down and come back up at any time during the
72 *	  discovery process which explains some of the complexity of the code.
73 *
74 * ............................................................................
75 *
76 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
77 *
78 *
79 *			+-------------------------+
80 *   fp/fctl module --->|    fcp_port_attach	  |
81 *			+-------------------------+
82 *	   |			     |
83 *	   |			     |
84 *	   |			     v
85 *	   |		+-------------------------+
86 *	   |		| fcp_handle_port_attach  |
87 *	   |		+-------------------------+
88 *	   |				|
89 *	   |				|
90 *	   +--------------------+	|
91 *				|	|
92 *				v	v
93 *			+-------------------------+
94 *			|   fcp_statec_callback	  |
95 *			+-------------------------+
96 *				    |
97 *				    |
98 *				    v
99 *			+-------------------------+
100 *			|    fcp_handle_devices	  |
101 *			+-------------------------+
102 *				    |
103 *				    |
104 *				    v
105 *			+-------------------------+
106 *			|   fcp_handle_mapflags	  |
107 *			+-------------------------+
108 *				    |
109 *				    |
110 *				    v
111 *			+-------------------------+
112 *			|     fcp_send_els	  |
113 *			|			  |
114 *			| PLOGI or PRLI To all the|
115 *			| reachable devices.	  |
116 *			+-------------------------+
117 *
118 *
119 * ............................................................................
120 *
121 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
122 *	   STEP 1 are called (it is actually the same function).
123 *
124 *
125 *			+-------------------------+
126 *			|    fcp_icmd_callback	  |
127 *   fp/fctl module --->|			  |
128 *			| callback for PLOGI and  |
129 *			| PRLI.			  |
130 *			+-------------------------+
131 *				     |
132 *				     |
133 *	    Received PLOGI Accept   /-\	  Received PRLI Accept
134 *		       _ _ _ _ _ _ /   \_ _ _ _ _ _
135 *		      |		   \   /	   |
136 *		      |		    \-/		   |
137 *		      |				   |
138 *		      v				   v
139 *	+-------------------------+	+-------------------------+
140 *	|     fcp_send_els	  |	|     fcp_send_scsi	  |
141 *	|			  |	|			  |
142 *	|	  PRLI		  |	|	REPORT_LUN	  |
143 *	+-------------------------+	+-------------------------+
144 *
145 * ............................................................................
146 *
147 * STEP 3: The callback functions of the SCSI commands issued by FCP are called
148 *	   (It is actually the same function).
149 *
150 *
151 *			    +-------------------------+
152 *   fp/fctl module ------->|	 fcp_scsi_callback    |
153 *			    +-------------------------+
154 *					|
155 *					|
156 *					|
157 *	Receive REPORT_LUN reply       /-\	Receive INQUIRY PAGE83 reply
158 *		  _ _ _ _ _ _ _ _ _ _ /	  \_ _ _ _ _ _ _ _ _ _ _ _
159 *		 |		      \	  /			  |
160 *		 |		       \-/			  |
161 *		 |			|			  |
162 *		 | Receive INQUIRY reply|			  |
163 *		 |			|			  |
164 *		 v			v			  v
165 * +------------------------+ +----------------------+ +----------------------+
166 * |  fcp_handle_reportlun  | |	 fcp_handle_inquiry  | |  fcp_handle_page83   |
167 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
168 * +------------------------+ +----------------------+ +----------------------+
169 *		 |			|			  |
170 *		 |			|			  |
171 *		 |			|			  |
172 *		 v			v			  |
173 *     +-----------------+	+-----------------+		  |
174 *     |  fcp_send_scsi	 |	|  fcp_send_scsi  |		  |
175 *     |		 |	|		  |		  |
176 *     |     INQUIRY	 |	| INQUIRY PAGE83  |		  |
177 *     |  (To each LUN)	 |	+-----------------+		  |
178 *     +-----------------+					  |
179 *								  |
180 *								  v
181 *						      +------------------------+
182 *						      |	 fcp_call_finish_init  |
183 *						      +------------------------+
184 *								  |
185 *								  v
186 *						 +-----------------------------+
187 *						 |  fcp_call_finish_init_held  |
188 *						 +-----------------------------+
189 *								  |
190 *								  |
191 *			   All LUNs scanned			 /-\
192 *			       _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
193 *			      |					\   /
194 *			      |					 \-/
195 *			      v					  |
196 *		     +------------------+			  |
197 *		     |	fcp_finish_tgt	|			  |
198 *		     +------------------+			  |
199 *			      |	  Target Not Offline and	  |
200 *  Target Not Offline and    |	  not marked and tgt_node_state	  |
201 *  marked		     /-\  not FCP_TGT_NODE_ON_DEMAND	  |
202 *		_ _ _ _ _ _ /	\_ _ _ _ _ _ _ _		  |
203 *	       |	    \	/		|		  |
204 *	       |	     \-/		|		  |
205 *	       v				v		  |
206 * +----------------------------+     +-------------------+	  |
207 * |	 fcp_offline_target	|     |	 fcp_create_luns  |	  |
208 * |				|     +-------------------+	  |
209 * | A structure fcp_tgt_elem	|		|		  |
210 * | is created and queued in	|		v		  |
211 * | the FCP port list		|     +-------------------+	  |
212 * | port_offline_tgts.	 It	|     |	 fcp_pass_to_hp	  |	  |
213 * | will be unqueued by the	|     |			  |	  |
214 * | watchdog timer.		|     | Called for each	  |	  |
215 * +----------------------------+     | LUN. Dispatches	  |	  |
216 *		  |		      | fcp_hp_task	  |	  |
217 *		  |		      +-------------------+	  |
218 *		  |				|		  |
219 *		  |				|		  |
220 *		  |				|		  |
221 *		  |				+---------------->|
222 *		  |						  |
223 *		  +---------------------------------------------->|
224 *								  |
225 *								  |
226 *		All the targets (devices) have been scanned	 /-\
227 *				_ _ _ _	_ _ _ _	_ _ _ _ _ _ _ _ /   \
228 *			       |				\   /
229 *			       |				 \-/
230 *	    +-------------------------------------+		  |
231 *	    |		fcp_finish_init		  |		  |
232 *	    |					  |		  |
233 *	    | Signal broadcasts the condition	  |		  |
234 *	    | variable port_config_cv of the FCP  |		  |
235 *	    | port.  One potential code sequence  |		  |
236 *	    | waiting on the condition variable	  |		  |
237 *	    | the code sequence handling	  |		  |
238 *	    | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|		  |
239 *	    | The other is in the function	  |		  |
240 *	    | fcp_reconfig_wait which is called	  |		  |
241 *	    | in the transmit path preventing IOs |		  |
242 *	    | from going through till the disco-  |		  |
243 *	    | very process is over.		  |		  |
244 *	    +-------------------------------------+		  |
245 *			       |				  |
246 *			       |				  |
247 *			       +--------------------------------->|
248 *								  |
249 *								  v
250 *								Return
251 *
252 * ............................................................................
253 *
254 * STEP 4: The hot plug task is called (for each fcp_hp_elem).
255 *
256 *
257 *			+-------------------------+
258 *			|      fcp_hp_task	  |
259 *			+-------------------------+
260 *				     |
261 *				     |
262 *				     v
263 *			+-------------------------+
264 *			|     fcp_trigger_lun	  |
265 *			+-------------------------+
266 *				     |
267 *				     |
268 *				     v
269 *		   Bring offline    /-\	 Bring online
270 *		  _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
271 *		 |		   \   /		   |
272 *		 |		    \-/			   |
273 *		 v					   v
274 *    +---------------------+			+-----------------------+
275 *    |	 fcp_offline_child  |			|      fcp_get_cip	|
276 *    +---------------------+			|			|
277 *						| Creates a dev_info_t	|
278 *						| or a mdi_pathinfo_t	|
279 *						| depending on whether	|
280 *						| mpxio is on or off.	|
281 *						+-----------------------+
282 *							   |
283 *							   |
284 *							   v
285 *						+-----------------------+
286 *						|  fcp_online_child	|
287 *						|			|
288 *						| Set device online	|
289 *						| using NDI or MDI.	|
290 *						+-----------------------+
291 *
292 * ............................................................................
293 *
294 * STEP 5: The watchdog timer expires.	The watch dog timer does much more that
295 *	   what is described here.  We only show the target offline path.
296 *
297 *
298 *			 +--------------------------+
299 *			 |	  fcp_watch	    |
300 *			 +--------------------------+
301 *				       |
302 *				       |
303 *				       v
304 *			 +--------------------------+
305 *			 |  fcp_scan_offline_tgts   |
306 *			 +--------------------------+
307 *				       |
308 *				       |
309 *				       v
310 *			 +--------------------------+
311 *			 |  fcp_offline_target_now  |
312 *			 +--------------------------+
313 *				       |
314 *				       |
315 *				       v
316 *			 +--------------------------+
317 *			 |   fcp_offline_tgt_luns   |
318 *			 +--------------------------+
319 *				       |
320 *				       |
321 *				       v
322 *			 +--------------------------+
323 *			 |     fcp_offline_lun	    |
324 *			 +--------------------------+
325 *				       |
326 *				       |
327 *				       v
328 *		     +----------------------------------+
329 *		     |	     fcp_offline_lun_now	|
330 *		     |					|
331 *		     | A request (or two if mpxio) is	|
332 *		     | sent to the hot plug task using	|
333 *		     | a fcp_hp_elem structure.		|
334 *		     +----------------------------------+
335 */
336
337/*
338 * Functions registered with DDI framework
339 */
340static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
341static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
342static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
343static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
344static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
345    cred_t *credp, int *rval);
346
347/*
348 * Functions registered with FC Transport framework
349 */
350static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
351    fc_attach_cmd_t cmd,  uint32_t s_id);
352static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
353    fc_detach_cmd_t cmd);
354static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
355    int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
356    uint32_t claimed);
357static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
358    fc_unsol_buf_t *buf, uint32_t claimed);
359static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
360    fc_unsol_buf_t *buf, uint32_t claimed);
361static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
362    uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
363    uint32_t  dev_cnt, uint32_t port_sid);
364
365/*
366 * Functions registered with SCSA framework
367 */
368static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
369    scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
370static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
371    scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
372static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
373    scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
374static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
375static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
376static int fcp_scsi_reset(struct scsi_address *ap, int level);
377static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
378static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
379    int whom);
380static void fcp_pkt_teardown(struct scsi_pkt *pkt);
381static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
382    void (*callback)(caddr_t), caddr_t arg);
383static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
384    char *name, ddi_eventcookie_t *event_cookiep);
385static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
386    ddi_eventcookie_t eventid, void (*callback)(), void *arg,
387    ddi_callback_id_t *cb_id);
388static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
389    ddi_callback_id_t cb_id);
390static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
391    ddi_eventcookie_t eventid, void *impldata);
392static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
393    ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
394static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
395    ddi_bus_config_op_t op, void *arg);
396
397/*
398 * Internal functions
399 */
400static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
401    int mode, int *rval);
402
403static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
404    int mode, int *rval);
405static int fcp_copyin_scsi_cmd(caddr_t base_addr,
406    struct fcp_scsi_cmd *fscsi, int mode);
407static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
408    caddr_t base_addr, int mode);
409static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
410
411static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
412    la_wwn_t *pwwn, int	*ret_val, int *fc_status, int *fc_pkt_state,
413    int *fc_pkt_reason, int *fc_pkt_action);
414static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
415    int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
416static int fcp_tgt_send_prli(struct fcp_tgt	*ptgt, int *fc_status,
417    int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
418static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
419static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
420static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
421static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
422
423static void fcp_handle_devices(struct fcp_port *pptr,
424    fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
425    fcp_map_tag_t *map_tag, int cause);
426static int fcp_handle_mapflags(struct fcp_port *pptr,
427    struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
428    int tgt_cnt, int cause);
429static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
430static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
431    struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
432static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
433    int cause);
434static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
435    uint32_t state);
436static struct fcp_port *fcp_get_port(opaque_t port_handle);
437static void fcp_unsol_callback(fc_packet_t *fpkt);
438static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
439    uchar_t r_ctl, uchar_t type);
440static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
441static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
442    struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
443    int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
444static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
445static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
446    int nodma, int flags);
447static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
448static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
449    uchar_t *wwn);
450static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
451    uint32_t d_id);
452static void fcp_icmd_callback(fc_packet_t *fpkt);
453static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
454    int len, int lcount, int tcount, int cause, uint32_t rscn_count);
455static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
456static void fcp_scsi_callback(fc_packet_t *fpkt);
457static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
458static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
459static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
460static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
461    uint16_t lun_num);
462static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
463    int link_cnt, int tgt_cnt, int cause);
464static void fcp_finish_init(struct fcp_port *pptr);
465static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
466    int tgt_cnt, int cause);
467static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
468    int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
469static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
470    int link_cnt, int tgt_cnt, int nowait, int flags);
471static void fcp_offline_target_now(struct fcp_port *pptr,
472    struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
473static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
474    int tgt_cnt, int flags);
475static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
476    int nowait, int flags);
477static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
478    int tgt_cnt);
479static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
480    int tgt_cnt, int flags);
481static void fcp_scan_offline_luns(struct fcp_port *pptr);
482static void fcp_scan_offline_tgts(struct fcp_port *pptr);
483static void fcp_update_offline_flags(struct fcp_lun *plun);
484static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
485static void fcp_abort_commands(struct fcp_pkt *head, struct
486    fcp_port *pptr);
487static void fcp_cmd_callback(fc_packet_t *fpkt);
488static void fcp_complete_pkt(fc_packet_t *fpkt);
489static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
490    struct fcp_port *pptr);
491static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
492    fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
493static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
494static void fcp_dealloc_lun(struct fcp_lun *plun);
495static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
496    fc_portmap_t *map_entry, int link_cnt);
497static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
498static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
499static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
500    int internal);
501static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
502static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
503    uint32_t s_id, int instance);
504static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
505    int instance);
506static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
507static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
508    int);
509static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
510static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
511static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
512    int flags);
513static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
514static int fcp_reset_target(struct scsi_address *ap, int level);
515static int fcp_commoncap(struct scsi_address *ap, char *cap,
516    int val, int tgtonly, int doset);
517static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
518static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
519static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
520    int sleep);
521static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
522    uint32_t s_id, fc_attach_cmd_t cmd, int instance);
523static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
524static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
525static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
526    int lcount, int tcount);
527static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
528static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
529static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
530    int tgt_cnt);
531static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
532    dev_info_t *pdip, caddr_t name);
533static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
534    int lcount, int tcount, int flags, int *circ);
535static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
536    int lcount, int tcount, int flags, int *circ);
537static void fcp_remove_child(struct fcp_lun *plun);
538static void fcp_watch(void *arg);
539static void fcp_check_reset_delay(struct fcp_port *pptr);
540static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
541    struct fcp_lun *rlun, int tgt_cnt);
542struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
543static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
544    uchar_t *wwn, uint16_t lun);
545static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
546    struct fcp_lun *plun);
547static void fcp_post_callback(struct fcp_pkt *cmd);
548static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
549static struct fcp_port *fcp_dip2port(dev_info_t *dip);
550struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
551    child_info_t *cip);
552static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
553    struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
554    int tgt_cnt, int flags);
555static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
556    struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
557    int tgt_cnt, int flags, int wait);
558static void fcp_retransport_cmd(struct fcp_port *pptr,
559    struct fcp_pkt *cmd);
560static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
561    uint_t statistics);
562static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
563static void fcp_update_targets(struct fcp_port *pptr,
564    fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
565static int fcp_call_finish_init(struct fcp_port *pptr,
566    struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
567static int fcp_call_finish_init_held(struct fcp_port *pptr,
568    struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
569static void fcp_reconfigure_luns(void * tgt_handle);
570static void fcp_free_targets(struct fcp_port *pptr);
571static void fcp_free_target(struct fcp_tgt *ptgt);
572static int fcp_is_retryable(struct fcp_ipkt *icmd);
573static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
574static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
575static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
576static void fcp_print_error(fc_packet_t *fpkt);
577static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
578    struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
579static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
580static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
581    uint32_t *dev_cnt);
582static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
583static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
584static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
585    struct fcp_ioctl *, struct fcp_port **);
586static char *fcp_get_lun_path(struct fcp_lun *plun);
587static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
588    int *rval);
589static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
590static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
591static char *fcp_get_lun_path(struct fcp_lun *plun);
592static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
593    int *rval);
594static void fcp_reconfig_wait(struct fcp_port *pptr);
595
596/*
597 * New functions added for mpxio support
598 */
599static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
600    scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
601static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
602    int tcount);
603static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
604    dev_info_t *pdip);
605static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
606static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
607static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
608static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
609static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
610    int what);
611static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
612    fc_packet_t *fpkt);
613static int fcp_symmetric_device_probe(struct fcp_lun *plun);
614
615/*
616 * New functions added for lun masking support
617 */
618static void fcp_read_blacklist(dev_info_t *dip,
619    struct fcp_black_list_entry **pplun_blacklist);
620static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
621    struct fcp_black_list_entry **pplun_blacklist);
622static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
623    struct fcp_black_list_entry **pplun_blacklist);
624static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
625static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
626
627/*
628 * New functions to support software FCA (like fcoei)
629 */
630static struct scsi_pkt *fcp_pseudo_init_pkt(
631	struct scsi_address *ap, struct scsi_pkt *pkt,
632	struct buf *bp, int cmdlen, int statuslen,
633	int tgtlen, int flags, int (*callback)(), caddr_t arg);
634static void fcp_pseudo_destroy_pkt(
635	struct scsi_address *ap, struct scsi_pkt *pkt);
636static void fcp_pseudo_sync_pkt(
637	struct scsi_address *ap, struct scsi_pkt *pkt);
638static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
639static void fcp_pseudo_dmafree(
640	struct scsi_address *ap, struct scsi_pkt *pkt);
641
642extern struct mod_ops	mod_driverops;
643/*
644 * This variable is defined in modctl.c and set to '1' after the root driver
645 * and fs are loaded.  It serves as an indication that the root filesystem can
646 * be used.
647 */
648extern int		modrootloaded;
649/*
650 * This table contains strings associated with the SCSI sense key codes.  It
651 * is used by FCP to print a clear explanation of the code returned in the
652 * sense information by a device.
653 */
654extern char		*sense_keys[];
655/*
656 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
657 * under this device that the paths to a physical device are created when
658 * MPxIO is used.
659 */
660extern dev_info_t	*scsi_vhci_dip;
661
662/*
663 * Report lun processing
664 */
665#define	FCP_LUN_ADDRESSING		0x80
666#define	FCP_PD_ADDRESSING		0x00
667#define	FCP_VOLUME_ADDRESSING		0x40
668
669#define	FCP_SVE_THROTTLE		0x28 /* Vicom */
670#define	MAX_INT_DMA			0x7fffffff
671/*
672 * Property definitions
673 */
674#define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
675#define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
676#define	TARGET_PROP	(char *)fcp_target_prop
677#define	LUN_PROP	(char *)fcp_lun_prop
678#define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
679#define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
680#define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
681#define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
682#define	INIT_PORT_PROP	(char *)fcp_init_port_prop
683#define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
684#define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
685/*
686 * Short hand macros.
687 */
688#define	LUN_PORT	(plun->lun_tgt->tgt_port)
689#define	LUN_TGT		(plun->lun_tgt)
690
691/*
692 * Driver private macros
693 */
694#define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
695			((x) >= 'a' && (x) <= 'f') ?			\
696			((x) - 'a' + 10) : ((x) - 'A' + 10))
697
698#define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
699
700#define	FCP_N_NDI_EVENTS						\
701	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
702
703#define	FCP_LINK_STATE_CHANGED(p, c)			\
704	((p)->port_link_cnt != (c)->ipkt_link_cnt)
705
706#define	FCP_TGT_STATE_CHANGED(t, c)			\
707	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
708
709#define	FCP_STATE_CHANGED(p, t, c)		\
710	(FCP_TGT_STATE_CHANGED(t, c))
711
712#define	FCP_MUST_RETRY(fpkt)				\
713	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
714	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
715	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
716	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
717	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
718	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
719	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
720	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
721
722#define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
723	((es)->es_key == KEY_UNIT_ATTENTION &&	\
724	(es)->es_add_code == 0x3f &&		\
725	(es)->es_qual_code == 0x0e)
726
727#define	FCP_SENSE_NO_LUN(es)			\
728	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
729	(es)->es_add_code == 0x25 &&		\
730	(es)->es_qual_code == 0x0)
731
732#define	FCP_VERSION		"20091208-1.192"
733#define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
734
735#define	FCP_NUM_ELEMENTS(array)			\
736	(sizeof (array) / sizeof ((array)[0]))
737
738/*
739 * Debugging, Error reporting, and tracing
740 */
741#define	FCP_LOG_SIZE		1024 * 1024
742
743#define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
744#define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
745#define	FCP_LEVEL_3		0x00004		/* state change, discovery */
746#define	FCP_LEVEL_4		0x00008		/* ULP messages */
747#define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
748#define	FCP_LEVEL_6		0x00020		/* Transport failures */
749#define	FCP_LEVEL_7		0x00040
750#define	FCP_LEVEL_8		0x00080		/* I/O tracing */
751#define	FCP_LEVEL_9		0x00100		/* I/O tracing */
752
753
754
755/*
756 * Log contents to system messages file
757 */
758#define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
759#define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
760#define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
761#define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
762#define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
763#define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
764#define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
765#define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
766#define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
767
768
769/*
770 * Log contents to trace buffer
771 */
772#define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
773#define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
774#define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
775#define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
776#define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
777#define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
778#define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
779#define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
780#define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
781
782
783/*
784 * Log contents to both system messages file and trace buffer
785 */
786#define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
787				FC_TRACE_LOG_MSG)
788#define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
789				FC_TRACE_LOG_MSG)
790#define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
791				FC_TRACE_LOG_MSG)
792#define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
793				FC_TRACE_LOG_MSG)
794#define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
795				FC_TRACE_LOG_MSG)
796#define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
797				FC_TRACE_LOG_MSG)
798#define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
799				FC_TRACE_LOG_MSG)
800#define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
801				FC_TRACE_LOG_MSG)
802#define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
803				FC_TRACE_LOG_MSG)
804#ifdef DEBUG
805#define	FCP_DTRACE	fc_trace_debug
806#else
807#define	FCP_DTRACE
808#endif
809
810#define	FCP_TRACE	fc_trace_debug
811
812static struct cb_ops fcp_cb_ops = {
813	fcp_open,			/* open */
814	fcp_close,			/* close */
815	nodev,				/* strategy */
816	nodev,				/* print */
817	nodev,				/* dump */
818	nodev,				/* read */
819	nodev,				/* write */
820	fcp_ioctl,			/* ioctl */
821	nodev,				/* devmap */
822	nodev,				/* mmap */
823	nodev,				/* segmap */
824	nochpoll,			/* chpoll */
825	ddi_prop_op,			/* cb_prop_op */
826	0,				/* streamtab */
827	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
828	CB_REV,				/* rev */
829	nodev,				/* aread */
830	nodev				/* awrite */
831};
832
833
834static struct dev_ops fcp_ops = {
835	DEVO_REV,
836	0,
837	ddi_getinfo_1to1,
838	nulldev,		/* identify */
839	nulldev,		/* probe */
840	fcp_attach,		/* attach and detach are mandatory */
841	fcp_detach,
842	nodev,			/* reset */
843	&fcp_cb_ops,		/* cb_ops */
844	NULL,			/* bus_ops */
845	NULL,			/* power */
846};
847
848
849char *fcp_version = FCP_NAME_VERSION;
850
851static struct modldrv modldrv = {
852	&mod_driverops,
853	FCP_NAME_VERSION,
854	&fcp_ops
855};
856
857
858static struct modlinkage modlinkage = {
859	MODREV_1,
860	&modldrv,
861	NULL
862};
863
864
865static fc_ulp_modinfo_t fcp_modinfo = {
866	&fcp_modinfo,			/* ulp_handle */
867	FCTL_ULP_MODREV_4,		/* ulp_rev */
868	FC4_SCSI_FCP,			/* ulp_type */
869	"fcp",				/* ulp_name */
870	FCP_STATEC_MASK,		/* ulp_statec_mask */
871	fcp_port_attach,		/* ulp_port_attach */
872	fcp_port_detach,		/* ulp_port_detach */
873	fcp_port_ioctl,			/* ulp_port_ioctl */
874	fcp_els_callback,		/* ulp_els_callback */
875	fcp_data_callback,		/* ulp_data_callback */
876	fcp_statec_callback		/* ulp_statec_callback */
877};
878
879#ifdef	DEBUG
880#define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
881				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
882				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
883				FCP_LEVEL_6 | FCP_LEVEL_7)
884#else
885#define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
886				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
887				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
888				FCP_LEVEL_6 | FCP_LEVEL_7)
889#endif
890
891/* FCP global variables */
892int			fcp_bus_config_debug = 0;
893static int		fcp_log_size = FCP_LOG_SIZE;
894static int		fcp_trace = FCP_TRACE_DEFAULT;
895static fc_trace_logq_t	*fcp_logq = NULL;
896static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
897/*
898 * The auto-configuration is set by default.  The only way of disabling it is
899 * through the property MANUAL_CFG_ONLY in the fcp.conf file.
900 */
901static int		fcp_enable_auto_configuration = 1;
902static int		fcp_max_bus_config_retries	= 4;
903static int		fcp_lun_ready_retry = 300;
904/*
905 * The value assigned to the following variable has changed several times due
906 * to a problem with the data underruns reporting of some firmware(s).	The
907 * current value of 50 gives a timeout value of 25 seconds for a max number
908 * of 256 LUNs.
909 */
910static int		fcp_max_target_retries = 50;
911/*
912 * Watchdog variables
913 * ------------------
914 *
915 * fcp_watchdog_init
916 *
917 *	Indicates if the watchdog timer is running or not.  This is actually
918 *	a counter of the number of Fibre Channel ports that attached.  When
919 *	the first port attaches the watchdog is started.  When the last port
920 *	detaches the watchdog timer is stopped.
921 *
922 * fcp_watchdog_time
923 *
924 *	This is the watchdog clock counter.  It is incremented by
925 *	fcp_watchdog_time each time the watchdog timer expires.
926 *
927 * fcp_watchdog_timeout
928 *
929 *	Increment value of the variable fcp_watchdog_time as well as the
930 *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
931 *	is strange that this is not a #define	but a variable since the code
932 *	never changes this value.  The reason why it can be said that the
933 *	unit is 1 second is because the number of ticks for the watchdog
934 *	timer is determined like this:
935 *
936 *	    fcp_watchdog_tick = fcp_watchdog_timeout *
937 *				  drv_usectohz(1000000);
938 *
939 *	The value 1000000 is hard coded in the code.
940 *
941 * fcp_watchdog_tick
942 *
943 *	Watchdog timer value in ticks.
944 */
945static int		fcp_watchdog_init = 0;
946static int		fcp_watchdog_time = 0;
947static int		fcp_watchdog_timeout = 1;
948static int		fcp_watchdog_tick;
949
950/*
951 * fcp_offline_delay is a global variable to enable customisation of
952 * the timeout on link offlines or RSCNs. The default value is set
953 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
954 * specified in FCP4 Chapter 11 (see www.t10.org).
955 *
956 * The variable fcp_offline_delay is specified in SECONDS.
957 *
958 * If we made this a static var then the user would not be able to
959 * change it. This variable is set in fcp_attach().
960 */
961unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
962
963static void		*fcp_softstate = NULL; /* for soft state */
964static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
965static kmutex_t		fcp_global_mutex;
966static kmutex_t		fcp_ioctl_mutex;
967static dev_info_t	*fcp_global_dip = NULL;
968static timeout_id_t	fcp_watchdog_id;
969const char		*fcp_lun_prop = "lun";
970const char		*fcp_sam_lun_prop = "sam-lun";
971const char		*fcp_target_prop = "target";
972/*
973 * NOTE: consumers of "node-wwn" property include stmsboot in ON
974 * consolidation.
975 */
976const char		*fcp_node_wwn_prop = "node-wwn";
977const char		*fcp_port_wwn_prop = "port-wwn";
978const char		*fcp_conf_wwn_prop = "fc-port-wwn";
979const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
980const char		*fcp_manual_config_only = "manual_configuration_only";
981const char		*fcp_init_port_prop = "initiator-port";
982const char		*fcp_tgt_port_prop = "target-port";
983const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
984
985static struct fcp_port	*fcp_port_head = NULL;
986static ddi_eventcookie_t	fcp_insert_eid;
987static ddi_eventcookie_t	fcp_remove_eid;
988
989static ndi_event_definition_t	fcp_ndi_event_defs[] = {
990	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
991	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
992};
993
994/*
995 * List of valid commands for the scsi_ioctl call
996 */
997static uint8_t scsi_ioctl_list[] = {
998	SCMD_INQUIRY,
999	SCMD_REPORT_LUN,
1000	SCMD_READ_CAPACITY
1001};
1002
1003/*
1004 * this is used to dummy up a report lun response for cases
1005 * where the target doesn't support it
1006 */
1007static uchar_t fcp_dummy_lun[] = {
1008	0x00,		/* MSB length (length = no of luns * 8) */
1009	0x00,
1010	0x00,
1011	0x08,		/* LSB length */
1012	0x00,		/* MSB reserved */
1013	0x00,
1014	0x00,
1015	0x00,		/* LSB reserved */
1016	FCP_PD_ADDRESSING,
1017	0x00,		/* LUN is ZERO at the first level */
1018	0x00,
1019	0x00,		/* second level is zero */
1020	0x00,
1021	0x00,		/* third level is zero */
1022	0x00,
1023	0x00		/* fourth level is zero */
1024};
1025
1026static uchar_t fcp_alpa_to_switch[] = {
1027	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1028	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1029	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1030	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1031	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1032	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1033	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1034	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1035	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1036	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1037	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1038	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1039	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1040	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1041	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1042	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1043	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1044	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1045	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1046	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1047	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1048	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1049	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1050	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051};
1052
1053static caddr_t pid = "SESS01	      ";
1054
1055#if	!defined(lint)
1056
1057_NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1058    fcp_port::fcp_next fcp_watchdog_id))
1059
1060_NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1061
1062_NOTE(SCHEME_PROTECTS_DATA("Unshared",
1063    fcp_insert_eid
1064    fcp_remove_eid
1065    fcp_watchdog_time))
1066
1067_NOTE(SCHEME_PROTECTS_DATA("Unshared",
1068    fcp_cb_ops
1069    fcp_ops
1070    callb_cpr))
1071
1072#endif /* lint */
1073
1074/*
1075 * This table is used to determine whether or not it's safe to copy in
1076 * the target node name for a lun.  Since all luns behind the same target
1077 * have the same wwnn, only tagets that do not support multiple luns are
1078 * eligible to be enumerated under mpxio if they aren't page83 compliant.
1079 */
1080
1081char *fcp_symmetric_disk_table[] = {
1082	"SEAGATE ST",
1083	"IBM	 DDYFT",
1084	"SUNW	 SUNWGS",	/* Daktari enclosure */
1085	"SUN	 SENA",		/* SES device */
1086	"SUN	 SESS01"	/* VICOM SVE box */
1087};
1088
1089int fcp_symmetric_disk_table_size =
1090	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1091
1092/*
1093 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1094 * will panic if you don't pass this in to the routine, this information.
1095 * Need to determine what the actual impact to the system is by providing
1096 * this information if any. Since dma allocation is done in pkt_init it may
1097 * not have any impact. These values are straight from the Writing Device
1098 * Driver manual.
1099 */
1100static ddi_dma_attr_t pseudo_fca_dma_attr = {
1101	DMA_ATTR_V0,	/* ddi_dma_attr version */
1102	0,		/* low address */
1103	0xffffffff,	/* high address */
1104	0x00ffffff,	/* counter upper bound */
1105	1,		/* alignment requirements */
1106	0x3f,		/* burst sizes */
1107	1,		/* minimum DMA access */
1108	0xffffffff,	/* maximum DMA access */
1109	(1 << 24) - 1,	/* segment boundary restrictions */
1110	1,		/* scater/gather list length */
1111	512,		/* device granularity */
1112	0		/* DMA flags */
1113};
1114
1115/*
1116 * The _init(9e) return value should be that of mod_install(9f). Under
1117 * some circumstances, a failure may not be related mod_install(9f) and
1118 * one would then require a return value to indicate the failure. Looking
1119 * at mod_install(9f), it is expected to return 0 for success and non-zero
1120 * for failure. mod_install(9f) for device drivers, further goes down the
1121 * calling chain and ends up in ddi_installdrv(), whose return values are
1122 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1123 * calling chain of mod_install(9f) which return values like EINVAL and
1124 * in some even return -1.
1125 *
1126 * To work around the vagaries of the mod_install() calling chain, return
1127 * either 0 or ENODEV depending on the success or failure of mod_install()
1128 */
1129int
1130_init(void)
1131{
1132	int rval;
1133
1134	/*
1135	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1136	 * before registering with the transport first.
1137	 */
1138	if (ddi_soft_state_init(&fcp_softstate,
1139	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1140		return (EINVAL);
1141	}
1142
1143	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1144	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1145
1146	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1147		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1148		mutex_destroy(&fcp_global_mutex);
1149		mutex_destroy(&fcp_ioctl_mutex);
1150		ddi_soft_state_fini(&fcp_softstate);
1151		return (ENODEV);
1152	}
1153
1154	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1155
1156	if ((rval = mod_install(&modlinkage)) != 0) {
1157		fc_trace_free_logq(fcp_logq);
1158		(void) fc_ulp_remove(&fcp_modinfo);
1159		mutex_destroy(&fcp_global_mutex);
1160		mutex_destroy(&fcp_ioctl_mutex);
1161		ddi_soft_state_fini(&fcp_softstate);
1162		rval = ENODEV;
1163	}
1164
1165	return (rval);
1166}
1167
1168
1169/*
1170 * the system is done with us as a driver, so clean up
1171 */
1172int
1173_fini(void)
1174{
1175	int rval;
1176
1177	/*
1178	 * don't start cleaning up until we know that the module remove
1179	 * has worked  -- if this works, then we know that each instance
1180	 * has successfully been DDI_DETACHed
1181	 */
1182	if ((rval = mod_remove(&modlinkage)) != 0) {
1183		return (rval);
1184	}
1185
1186	(void) fc_ulp_remove(&fcp_modinfo);
1187
1188	ddi_soft_state_fini(&fcp_softstate);
1189	mutex_destroy(&fcp_global_mutex);
1190	mutex_destroy(&fcp_ioctl_mutex);
1191	fc_trace_free_logq(fcp_logq);
1192
1193	return (rval);
1194}
1195
1196
1197int
1198_info(struct modinfo *modinfop)
1199{
1200	return (mod_info(&modlinkage, modinfop));
1201}
1202
1203
1204/*
1205 * attach the module
1206 */
1207static int
1208fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1209{
1210	int rval = DDI_SUCCESS;
1211
1212	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1213	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1214
1215	if (cmd == DDI_ATTACH) {
1216		/* The FCP pseudo device is created here. */
1217		mutex_enter(&fcp_global_mutex);
1218		fcp_global_dip = devi;
1219		mutex_exit(&fcp_global_mutex);
1220
1221		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1222		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1223			ddi_report_dev(fcp_global_dip);
1224		} else {
1225			cmn_err(CE_WARN, "FCP: Cannot create minor node");
1226			mutex_enter(&fcp_global_mutex);
1227			fcp_global_dip = NULL;
1228			mutex_exit(&fcp_global_mutex);
1229
1230			rval = DDI_FAILURE;
1231		}
1232		/*
1233		 * We check the fcp_offline_delay property at this
1234		 * point. This variable is global for the driver,
1235		 * not specific to an instance.
1236		 *
1237		 * We do not recommend setting the value to less
1238		 * than 10 seconds (RA_TOV_els), or greater than
1239		 * 60 seconds.
1240		 */
1241		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1242		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1243		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
1244		if ((fcp_offline_delay < 10) ||
1245		    (fcp_offline_delay > 60)) {
1246			cmn_err(CE_WARN, "Setting fcp_offline_delay "
1247			    "to %d second(s). This is outside the "
1248			    "recommended range of 10..60 seconds.",
1249			    fcp_offline_delay);
1250		}
1251	}
1252
1253	return (rval);
1254}
1255
1256
1257/*ARGSUSED*/
1258static int
1259fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1260{
1261	int	res = DDI_SUCCESS;
1262
1263	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1264	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
1265
1266	if (cmd == DDI_DETACH) {
1267		/*
1268		 * Check if there are active ports/threads. If there
1269		 * are any, we will fail, else we will succeed (there
1270		 * should not be much to clean up)
1271		 */
1272		mutex_enter(&fcp_global_mutex);
1273		FCP_DTRACE(fcp_logq, "fcp",
1274		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1275		    (void *) fcp_port_head);
1276
1277		if (fcp_port_head == NULL) {
1278			ddi_remove_minor_node(fcp_global_dip, NULL);
1279			fcp_global_dip = NULL;
1280			mutex_exit(&fcp_global_mutex);
1281		} else {
1282			mutex_exit(&fcp_global_mutex);
1283			res = DDI_FAILURE;
1284		}
1285	}
1286	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1287	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
1288
1289	return (res);
1290}
1291
1292
1293/* ARGSUSED */
1294static int
1295fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1296{
1297	if (otype != OTYP_CHR) {
1298		return (EINVAL);
1299	}
1300
1301	/*
1302	 * Allow only root to talk;
1303	 */
1304	if (drv_priv(credp)) {
1305		return (EPERM);
1306	}
1307
1308	mutex_enter(&fcp_global_mutex);
1309	if (fcp_oflag & FCP_EXCL) {
1310		mutex_exit(&fcp_global_mutex);
1311		return (EBUSY);
1312	}
1313
1314	if (flag & FEXCL) {
1315		if (fcp_oflag & FCP_OPEN) {
1316			mutex_exit(&fcp_global_mutex);
1317			return (EBUSY);
1318		}
1319		fcp_oflag |= FCP_EXCL;
1320	}
1321	fcp_oflag |= FCP_OPEN;
1322	mutex_exit(&fcp_global_mutex);
1323
1324	return (0);
1325}
1326
1327
1328/* ARGSUSED */
1329static int
1330fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1331{
1332	if (otype != OTYP_CHR) {
1333		return (EINVAL);
1334	}
1335
1336	mutex_enter(&fcp_global_mutex);
1337	if (!(fcp_oflag & FCP_OPEN)) {
1338		mutex_exit(&fcp_global_mutex);
1339		return (ENODEV);
1340	}
1341	fcp_oflag = FCP_IDLE;
1342	mutex_exit(&fcp_global_mutex);
1343
1344	return (0);
1345}
1346
1347
1348/*
1349 * fcp_ioctl
1350 *	Entry point for the FCP ioctls
1351 *
1352 * Input:
1353 *	See ioctl(9E)
1354 *
1355 * Output:
1356 *	See ioctl(9E)
1357 *
1358 * Returns:
1359 *	See ioctl(9E)
1360 *
1361 * Context:
1362 *	Kernel context.
1363 */
1364/* ARGSUSED */
1365static int
1366fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1367    int *rval)
1368{
1369	int			ret = 0;
1370
1371	mutex_enter(&fcp_global_mutex);
1372	if (!(fcp_oflag & FCP_OPEN)) {
1373		mutex_exit(&fcp_global_mutex);
1374		return (ENXIO);
1375	}
1376	mutex_exit(&fcp_global_mutex);
1377
1378	switch (cmd) {
1379	case FCP_TGT_INQUIRY:
1380	case FCP_TGT_CREATE:
1381	case FCP_TGT_DELETE:
1382		ret = fcp_setup_device_data_ioctl(cmd,
1383		    (struct fcp_ioctl *)data, mode, rval);
1384		break;
1385
1386	case FCP_TGT_SEND_SCSI:
1387		mutex_enter(&fcp_ioctl_mutex);
1388		ret = fcp_setup_scsi_ioctl(
1389		    (struct fcp_scsi_cmd *)data, mode, rval);
1390		mutex_exit(&fcp_ioctl_mutex);
1391		break;
1392
1393	case FCP_STATE_COUNT:
1394		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1395		    mode, rval);
1396		break;
1397	case FCP_GET_TARGET_MAPPINGS:
1398		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1399		    mode, rval);
1400		break;
1401	default:
1402		fcp_log(CE_WARN, NULL,
1403		    "!Invalid ioctl opcode = 0x%x", cmd);
1404		ret	= EINVAL;
1405	}
1406
1407	return (ret);
1408}
1409
1410
1411/*
1412 * fcp_setup_device_data_ioctl
1413 *	Setup handler for the "device data" style of
1414 *	ioctl for FCP.	See "fcp_util.h" for data structure
1415 *	definition.
1416 *
1417 * Input:
1418 *	cmd	= FCP ioctl command
1419 *	data	= ioctl data
1420 *	mode	= See ioctl(9E)
1421 *
1422 * Output:
1423 *	data	= ioctl data
1424 *	rval	= return value - see ioctl(9E)
1425 *
1426 * Returns:
1427 *	See ioctl(9E)
1428 *
1429 * Context:
1430 *	Kernel context.
1431 */
1432/* ARGSUSED */
1433static int
1434fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1435    int *rval)
1436{
1437	struct fcp_port	*pptr;
1438	struct	device_data	*dev_data;
1439	uint32_t		link_cnt;
1440	la_wwn_t		*wwn_ptr = NULL;
1441	struct fcp_tgt		*ptgt = NULL;
1442	struct fcp_lun		*plun = NULL;
1443	int			i, error;
1444	struct fcp_ioctl	fioctl;
1445
1446#ifdef	_MULTI_DATAMODEL
1447	switch (ddi_model_convert_from(mode & FMODELS)) {
1448	case DDI_MODEL_ILP32: {
1449		struct fcp32_ioctl f32_ioctl;
1450
1451		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1452		    sizeof (struct fcp32_ioctl), mode)) {
1453			return (EFAULT);
1454		}
1455		fioctl.fp_minor = f32_ioctl.fp_minor;
1456		fioctl.listlen = f32_ioctl.listlen;
1457		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1458		break;
1459	}
1460	case DDI_MODEL_NONE:
1461		if (ddi_copyin((void *)data, (void *)&fioctl,
1462		    sizeof (struct fcp_ioctl), mode)) {
1463			return (EFAULT);
1464		}
1465		break;
1466	}
1467
1468#else	/* _MULTI_DATAMODEL */
1469	if (ddi_copyin((void *)data, (void *)&fioctl,
1470	    sizeof (struct fcp_ioctl), mode)) {
1471		return (EFAULT);
1472	}
1473#endif	/* _MULTI_DATAMODEL */
1474
1475	/*
1476	 * Right now we can assume that the minor number matches with
1477	 * this instance of fp. If this changes we will need to
1478	 * revisit this logic.
1479	 */
1480	mutex_enter(&fcp_global_mutex);
1481	pptr = fcp_port_head;
1482	while (pptr) {
1483		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1484			break;
1485		} else {
1486			pptr = pptr->port_next;
1487		}
1488	}
1489	mutex_exit(&fcp_global_mutex);
1490	if (pptr == NULL) {
1491		return (ENXIO);
1492	}
1493	mutex_enter(&pptr->port_mutex);
1494
1495
1496	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1497	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
1498		mutex_exit(&pptr->port_mutex);
1499		return (ENOMEM);
1500	}
1501
1502	if (ddi_copyin(fioctl.list, dev_data,
1503	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1504		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1505		mutex_exit(&pptr->port_mutex);
1506		return (EFAULT);
1507	}
1508	link_cnt = pptr->port_link_cnt;
1509
1510	if (cmd == FCP_TGT_INQUIRY) {
1511		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1512		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1513		    sizeof (wwn_ptr->raw_wwn)) == 0) {
1514			/* This ioctl is requesting INQ info of local HBA */
1515			mutex_exit(&pptr->port_mutex);
1516			dev_data[0].dev0_type = DTYPE_UNKNOWN;
1517			dev_data[0].dev_status = 0;
1518			if (ddi_copyout(dev_data, fioctl.list,
1519			    (sizeof (struct device_data)) * fioctl.listlen,
1520			    mode)) {
1521				kmem_free(dev_data,
1522				    sizeof (*dev_data) * fioctl.listlen);
1523				return (EFAULT);
1524			}
1525			kmem_free(dev_data,
1526			    sizeof (*dev_data) * fioctl.listlen);
1527#ifdef	_MULTI_DATAMODEL
1528			switch (ddi_model_convert_from(mode & FMODELS)) {
1529			case DDI_MODEL_ILP32: {
1530				struct fcp32_ioctl f32_ioctl;
1531				f32_ioctl.fp_minor = fioctl.fp_minor;
1532				f32_ioctl.listlen = fioctl.listlen;
1533				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1534				if (ddi_copyout((void *)&f32_ioctl,
1535				    (void *)data,
1536				    sizeof (struct fcp32_ioctl), mode)) {
1537					return (EFAULT);
1538				}
1539				break;
1540			}
1541			case DDI_MODEL_NONE:
1542				if (ddi_copyout((void *)&fioctl, (void *)data,
1543				    sizeof (struct fcp_ioctl), mode)) {
1544					return (EFAULT);
1545				}
1546				break;
1547			}
1548#else	/* _MULTI_DATAMODEL */
1549			if (ddi_copyout((void *)&fioctl, (void *)data,
1550			    sizeof (struct fcp_ioctl), mode)) {
1551				return (EFAULT);
1552			}
1553#endif	/* _MULTI_DATAMODEL */
1554			return (0);
1555		}
1556	}
1557
1558	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1559		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1560		mutex_exit(&pptr->port_mutex);
1561		return (ENXIO);
1562	}
1563
1564	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1565	    i++) {
1566		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1567
1568		dev_data[i].dev0_type = DTYPE_UNKNOWN;
1569
1570
1571		dev_data[i].dev_status = ENXIO;
1572
1573		if ((ptgt = fcp_lookup_target(pptr,
1574		    (uchar_t *)wwn_ptr)) == NULL) {
1575			mutex_exit(&pptr->port_mutex);
1576			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1577			    wwn_ptr, &error, 0) == NULL) {
1578				dev_data[i].dev_status = ENODEV;
1579				mutex_enter(&pptr->port_mutex);
1580				continue;
1581			} else {
1582
1583				dev_data[i].dev_status = EAGAIN;
1584
1585				mutex_enter(&pptr->port_mutex);
1586				continue;
1587			}
1588		} else {
1589			mutex_enter(&ptgt->tgt_mutex);
1590			if (ptgt->tgt_state & (FCP_TGT_MARK |
1591			    FCP_TGT_BUSY)) {
1592				dev_data[i].dev_status = EAGAIN;
1593				mutex_exit(&ptgt->tgt_mutex);
1594				continue;
1595			}
1596
1597			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1598				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1599					dev_data[i].dev_status = ENOTSUP;
1600				} else {
1601					dev_data[i].dev_status = ENXIO;
1602				}
1603				mutex_exit(&ptgt->tgt_mutex);
1604				continue;
1605			}
1606
1607			switch (cmd) {
1608			case FCP_TGT_INQUIRY:
1609				/*
1610				 * The reason we give device type of
1611				 * lun 0 only even though in some
1612				 * cases(like maxstrat) lun 0 device
1613				 * type may be 0x3f(invalid) is that
1614				 * for bridge boxes target will appear
1615				 * as luns and the first lun could be
1616				 * a device that utility may not care
1617				 * about (like a tape device).
1618				 */
1619				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1620				dev_data[i].dev_status = 0;
1621				mutex_exit(&ptgt->tgt_mutex);
1622
1623				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1624					dev_data[i].dev0_type = DTYPE_UNKNOWN;
1625				} else {
1626					dev_data[i].dev0_type = plun->lun_type;
1627				}
1628				mutex_enter(&ptgt->tgt_mutex);
1629				break;
1630
1631			case FCP_TGT_CREATE:
1632				mutex_exit(&ptgt->tgt_mutex);
1633				mutex_exit(&pptr->port_mutex);
1634
1635				/*
1636				 * serialize state change call backs.
1637				 * only one call back will be handled
1638				 * at a time.
1639				 */
1640				mutex_enter(&fcp_global_mutex);
1641				if (fcp_oflag & FCP_BUSY) {
1642					mutex_exit(&fcp_global_mutex);
1643					if (dev_data) {
1644						kmem_free(dev_data,
1645						    sizeof (*dev_data) *
1646						    fioctl.listlen);
1647					}
1648					return (EBUSY);
1649				}
1650				fcp_oflag |= FCP_BUSY;
1651				mutex_exit(&fcp_global_mutex);
1652
1653				dev_data[i].dev_status =
1654				    fcp_create_on_demand(pptr,
1655				    wwn_ptr->raw_wwn);
1656
1657				if (dev_data[i].dev_status != 0) {
1658					char	buf[25];
1659
1660					for (i = 0; i < FC_WWN_SIZE; i++) {
1661						(void) sprintf(&buf[i << 1],
1662						    "%02x",
1663						    wwn_ptr->raw_wwn[i]);
1664					}
1665
1666					fcp_log(CE_WARN, pptr->port_dip,
1667					    "!Failed to create nodes for"
1668					    " pwwn=%s; error=%x", buf,
1669					    dev_data[i].dev_status);
1670				}
1671
1672				/* allow state change call backs again */
1673				mutex_enter(&fcp_global_mutex);
1674				fcp_oflag &= ~FCP_BUSY;
1675				mutex_exit(&fcp_global_mutex);
1676
1677				mutex_enter(&pptr->port_mutex);
1678				mutex_enter(&ptgt->tgt_mutex);
1679
1680				break;
1681
1682			case FCP_TGT_DELETE:
1683				break;
1684
1685			default:
1686				fcp_log(CE_WARN, pptr->port_dip,
1687				    "!Invalid device data ioctl "
1688				    "opcode = 0x%x", cmd);
1689			}
1690			mutex_exit(&ptgt->tgt_mutex);
1691		}
1692	}
1693	mutex_exit(&pptr->port_mutex);
1694
1695	if (ddi_copyout(dev_data, fioctl.list,
1696	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1697		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1698		return (EFAULT);
1699	}
1700	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1701
1702#ifdef	_MULTI_DATAMODEL
1703	switch (ddi_model_convert_from(mode & FMODELS)) {
1704	case DDI_MODEL_ILP32: {
1705		struct fcp32_ioctl f32_ioctl;
1706
1707		f32_ioctl.fp_minor = fioctl.fp_minor;
1708		f32_ioctl.listlen = fioctl.listlen;
1709		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1710		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1711		    sizeof (struct fcp32_ioctl), mode)) {
1712			return (EFAULT);
1713		}
1714		break;
1715	}
1716	case DDI_MODEL_NONE:
1717		if (ddi_copyout((void *)&fioctl, (void *)data,
1718		    sizeof (struct fcp_ioctl), mode)) {
1719			return (EFAULT);
1720		}
1721		break;
1722	}
1723#else	/* _MULTI_DATAMODEL */
1724
1725	if (ddi_copyout((void *)&fioctl, (void *)data,
1726	    sizeof (struct fcp_ioctl), mode)) {
1727		return (EFAULT);
1728	}
1729#endif	/* _MULTI_DATAMODEL */
1730
1731	return (0);
1732}
1733
1734/*
1735 * Fetch the target mappings (path, etc.) for all LUNs
1736 * on this port.
1737 */
1738/* ARGSUSED */
1739static int
1740fcp_get_target_mappings(struct fcp_ioctl *data,
1741    int mode, int *rval)
1742{
1743	struct fcp_port	    *pptr;
1744	fc_hba_target_mappings_t    *mappings;
1745	fc_hba_mapping_entry_t	    *map;
1746	struct fcp_tgt	    *ptgt = NULL;
1747	struct fcp_lun	    *plun = NULL;
1748	int			    i, mapIndex, mappingSize;
1749	int			    listlen;
1750	struct fcp_ioctl	    fioctl;
1751	char			    *path;
1752	fcp_ent_addr_t		    sam_lun_addr;
1753
1754#ifdef	_MULTI_DATAMODEL
1755	switch (ddi_model_convert_from(mode & FMODELS)) {
1756	case DDI_MODEL_ILP32: {
1757		struct fcp32_ioctl f32_ioctl;
1758
1759		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1760		    sizeof (struct fcp32_ioctl), mode)) {
1761			return (EFAULT);
1762		}
1763		fioctl.fp_minor = f32_ioctl.fp_minor;
1764		fioctl.listlen = f32_ioctl.listlen;
1765		fioctl.list = (caddr_t)(long)f32_ioctl.list;
1766		break;
1767	}
1768	case DDI_MODEL_NONE:
1769		if (ddi_copyin((void *)data, (void *)&fioctl,
1770		    sizeof (struct fcp_ioctl), mode)) {
1771			return (EFAULT);
1772		}
1773		break;
1774	}
1775
1776#else	/* _MULTI_DATAMODEL */
1777	if (ddi_copyin((void *)data, (void *)&fioctl,
1778	    sizeof (struct fcp_ioctl), mode)) {
1779		return (EFAULT);
1780	}
1781#endif	/* _MULTI_DATAMODEL */
1782
1783	/*
1784	 * Right now we can assume that the minor number matches with
1785	 * this instance of fp. If this changes we will need to
1786	 * revisit this logic.
1787	 */
1788	mutex_enter(&fcp_global_mutex);
1789	pptr = fcp_port_head;
1790	while (pptr) {
1791		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1792			break;
1793		} else {
1794			pptr = pptr->port_next;
1795		}
1796	}
1797	mutex_exit(&fcp_global_mutex);
1798	if (pptr == NULL) {
1799		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1800		    fioctl.fp_minor);
1801		return (ENXIO);
1802	}
1803
1804
1805	/* We use listlen to show the total buffer size */
1806	mappingSize = fioctl.listlen;
1807
1808	/* Now calculate how many mapping entries will fit */
1809	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1810	    - sizeof (fc_hba_target_mappings_t);
1811	if (listlen <= 0) {
1812		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1813		return (ENXIO);
1814	}
1815	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1816
1817	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1818		return (ENOMEM);
1819	}
1820	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1821
1822	/* Now get to work */
1823	mapIndex = 0;
1824
1825	mutex_enter(&pptr->port_mutex);
1826	/* Loop through all targets on this port */
1827	for (i = 0; i < FCP_NUM_HASH; i++) {
1828		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1829		    ptgt = ptgt->tgt_next) {
1830
1831			mutex_enter(&ptgt->tgt_mutex);
1832
1833			/* Loop through all LUNs on this target */
1834			for (plun = ptgt->tgt_lun; plun != NULL;
1835			    plun = plun->lun_next) {
1836				if (plun->lun_state & FCP_LUN_OFFLINE) {
1837					continue;
1838				}
1839
1840				path = fcp_get_lun_path(plun);
1841				if (path == NULL) {
1842					continue;
1843				}
1844
1845				if (mapIndex >= listlen) {
1846					mapIndex ++;
1847					kmem_free(path, MAXPATHLEN);
1848					continue;
1849				}
1850				map = &mappings->entries[mapIndex++];
1851				bcopy(path, map->targetDriver,
1852				    sizeof (map->targetDriver));
1853				map->d_id = ptgt->tgt_d_id;
1854				map->busNumber = 0;
1855				map->targetNumber = ptgt->tgt_d_id;
1856				map->osLUN = plun->lun_num;
1857
1858				/*
1859				 * We had swapped lun when we stored it in
1860				 * lun_addr. We need to swap it back before
1861				 * returning it to user land
1862				 */
1863
1864				sam_lun_addr.ent_addr_0 =
1865				    BE_16(plun->lun_addr.ent_addr_0);
1866				sam_lun_addr.ent_addr_1 =
1867				    BE_16(plun->lun_addr.ent_addr_1);
1868				sam_lun_addr.ent_addr_2 =
1869				    BE_16(plun->lun_addr.ent_addr_2);
1870				sam_lun_addr.ent_addr_3 =
1871				    BE_16(plun->lun_addr.ent_addr_3);
1872
1873				bcopy(&sam_lun_addr, &map->samLUN,
1874				    FCP_LUN_SIZE);
1875				bcopy(ptgt->tgt_node_wwn.raw_wwn,
1876				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1877				bcopy(ptgt->tgt_port_wwn.raw_wwn,
1878				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1879
1880				if (plun->lun_guid) {
1881
1882					/* convert ascii wwn to bytes */
1883					fcp_ascii_to_wwn(plun->lun_guid,
1884					    map->guid, sizeof (map->guid));
1885
1886					if ((sizeof (map->guid)) <
1887					    plun->lun_guid_size / 2) {
1888						cmn_err(CE_WARN,
1889						    "fcp_get_target_mappings:"
1890						    "guid copy space "
1891						    "insufficient."
1892						    "Copy Truncation - "
1893						    "available %d; need %d",
1894						    (int)sizeof (map->guid),
1895						    (int)
1896						    plun->lun_guid_size / 2);
1897					}
1898				}
1899				kmem_free(path, MAXPATHLEN);
1900			}
1901			mutex_exit(&ptgt->tgt_mutex);
1902		}
1903	}
1904	mutex_exit(&pptr->port_mutex);
1905	mappings->numLuns = mapIndex;
1906
1907	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1908		kmem_free(mappings, mappingSize);
1909		return (EFAULT);
1910	}
1911	kmem_free(mappings, mappingSize);
1912
1913#ifdef	_MULTI_DATAMODEL
1914	switch (ddi_model_convert_from(mode & FMODELS)) {
1915	case DDI_MODEL_ILP32: {
1916		struct fcp32_ioctl f32_ioctl;
1917
1918		f32_ioctl.fp_minor = fioctl.fp_minor;
1919		f32_ioctl.listlen = fioctl.listlen;
1920		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1921		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1922		    sizeof (struct fcp32_ioctl), mode)) {
1923			return (EFAULT);
1924		}
1925		break;
1926	}
1927	case DDI_MODEL_NONE:
1928		if (ddi_copyout((void *)&fioctl, (void *)data,
1929		    sizeof (struct fcp_ioctl), mode)) {
1930			return (EFAULT);
1931		}
1932		break;
1933	}
1934#else	/* _MULTI_DATAMODEL */
1935
1936	if (ddi_copyout((void *)&fioctl, (void *)data,
1937	    sizeof (struct fcp_ioctl), mode)) {
1938		return (EFAULT);
1939	}
1940#endif	/* _MULTI_DATAMODEL */
1941
1942	return (0);
1943}
1944
1945/*
1946 * fcp_setup_scsi_ioctl
1947 *	Setup handler for the "scsi passthru" style of
1948 *	ioctl for FCP.	See "fcp_util.h" for data structure
1949 *	definition.
1950 *
1951 * Input:
1952 *	u_fscsi	= ioctl data (user address space)
1953 *	mode	= See ioctl(9E)
1954 *
1955 * Output:
1956 *	u_fscsi	= ioctl data (user address space)
1957 *	rval	= return value - see ioctl(9E)
1958 *
1959 * Returns:
1960 *	0	= OK
1961 *	EAGAIN	= See errno.h
1962 *	EBUSY	= See errno.h
1963 *	EFAULT	= See errno.h
1964 *	EINTR	= See errno.h
1965 *	EINVAL	= See errno.h
1966 *	EIO	= See errno.h
1967 *	ENOMEM	= See errno.h
1968 *	ENXIO	= See errno.h
1969 *
1970 * Context:
1971 *	Kernel context.
1972 */
1973/* ARGSUSED */
1974static int
1975fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1976    int mode, int *rval)
1977{
1978	int			ret		= 0;
1979	int			temp_ret;
1980	caddr_t			k_cdbbufaddr	= NULL;
1981	caddr_t			k_bufaddr	= NULL;
1982	caddr_t			k_rqbufaddr	= NULL;
1983	caddr_t			u_cdbbufaddr;
1984	caddr_t			u_bufaddr;
1985	caddr_t			u_rqbufaddr;
1986	struct fcp_scsi_cmd	k_fscsi;
1987
1988	/*
1989	 * Get fcp_scsi_cmd array element from user address space
1990	 */
1991	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1992	    != 0) {
1993		return (ret);
1994	}
1995
1996
1997	/*
1998	 * Even though kmem_alloc() checks the validity of the
1999	 * buffer length, this check is needed when the
2000	 * kmem_flags set and the zero buffer length is passed.
2001	 */
2002	if ((k_fscsi.scsi_cdblen <= 0) ||
2003	    (k_fscsi.scsi_buflen <= 0) ||
2004	    (k_fscsi.scsi_rqlen <= 0)) {
2005		return (EINVAL);
2006	}
2007
2008	/*
2009	 * Allocate data for fcp_scsi_cmd pointer fields
2010	 */
2011	if (ret == 0) {
2012		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2013		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2014		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2015
2016		if (k_cdbbufaddr == NULL ||
2017		    k_bufaddr	 == NULL ||
2018		    k_rqbufaddr	 == NULL) {
2019			ret = ENOMEM;
2020		}
2021	}
2022
2023	/*
2024	 * Get fcp_scsi_cmd pointer fields from user
2025	 * address space
2026	 */
2027	if (ret == 0) {
2028		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2029		u_bufaddr    = k_fscsi.scsi_bufaddr;
2030		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2031
2032		if (ddi_copyin(u_cdbbufaddr,
2033		    k_cdbbufaddr,
2034		    k_fscsi.scsi_cdblen,
2035		    mode)) {
2036			ret = EFAULT;
2037		} else if (ddi_copyin(u_bufaddr,
2038		    k_bufaddr,
2039		    k_fscsi.scsi_buflen,
2040		    mode)) {
2041			ret = EFAULT;
2042		} else if (ddi_copyin(u_rqbufaddr,
2043		    k_rqbufaddr,
2044		    k_fscsi.scsi_rqlen,
2045		    mode)) {
2046			ret = EFAULT;
2047		}
2048	}
2049
2050	/*
2051	 * Send scsi command (blocking)
2052	 */
2053	if (ret == 0) {
2054		/*
2055		 * Prior to sending the scsi command, the
2056		 * fcp_scsi_cmd data structure must contain kernel,
2057		 * not user, addresses.
2058		 */
2059		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
2060		k_fscsi.scsi_bufaddr	= k_bufaddr;
2061		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
2062
2063		ret = fcp_send_scsi_ioctl(&k_fscsi);
2064
2065		/*
2066		 * After sending the scsi command, the
2067		 * fcp_scsi_cmd data structure must contain user,
2068		 * not kernel, addresses.
2069		 */
2070		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
2071		k_fscsi.scsi_bufaddr	= u_bufaddr;
2072		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
2073	}
2074
2075	/*
2076	 * Put fcp_scsi_cmd pointer fields to user address space
2077	 */
2078	if (ret == 0) {
2079		if (ddi_copyout(k_cdbbufaddr,
2080		    u_cdbbufaddr,
2081		    k_fscsi.scsi_cdblen,
2082		    mode)) {
2083			ret = EFAULT;
2084		} else if (ddi_copyout(k_bufaddr,
2085		    u_bufaddr,
2086		    k_fscsi.scsi_buflen,
2087		    mode)) {
2088			ret = EFAULT;
2089		} else if (ddi_copyout(k_rqbufaddr,
2090		    u_rqbufaddr,
2091		    k_fscsi.scsi_rqlen,
2092		    mode)) {
2093			ret = EFAULT;
2094		}
2095	}
2096
2097	/*
2098	 * Free data for fcp_scsi_cmd pointer fields
2099	 */
2100	if (k_cdbbufaddr != NULL) {
2101		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2102	}
2103	if (k_bufaddr != NULL) {
2104		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2105	}
2106	if (k_rqbufaddr != NULL) {
2107		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2108	}
2109
2110	/*
2111	 * Put fcp_scsi_cmd array element to user address space
2112	 */
2113	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2114	if (temp_ret != 0) {
2115		ret = temp_ret;
2116	}
2117
2118	/*
2119	 * Return status
2120	 */
2121	return (ret);
2122}
2123
2124
2125/*
2126 * fcp_copyin_scsi_cmd
2127 *	Copy in fcp_scsi_cmd data structure from user address space.
2128 *	The data may be in 32 bit or 64 bit modes.
2129 *
2130 * Input:
2131 *	base_addr	= from address (user address space)
2132 *	mode		= See ioctl(9E) and ddi_copyin(9F)
2133 *
2134 * Output:
2135 *	fscsi		= to address (kernel address space)
2136 *
2137 * Returns:
2138 *	0	= OK
2139 *	EFAULT	= Error
2140 *
2141 * Context:
2142 *	Kernel context.
2143 */
2144static int
2145fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2146{
2147#ifdef	_MULTI_DATAMODEL
2148	struct fcp32_scsi_cmd	f32scsi;
2149
2150	switch (ddi_model_convert_from(mode & FMODELS)) {
2151	case DDI_MODEL_ILP32:
2152		/*
2153		 * Copy data from user address space
2154		 */
2155		if (ddi_copyin((void *)base_addr,
2156		    &f32scsi,
2157		    sizeof (struct fcp32_scsi_cmd),
2158		    mode)) {
2159			return (EFAULT);
2160		}
2161		/*
2162		 * Convert from 32 bit to 64 bit
2163		 */
2164		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2165		break;
2166	case DDI_MODEL_NONE:
2167		/*
2168		 * Copy data from user address space
2169		 */
2170		if (ddi_copyin((void *)base_addr,
2171		    fscsi,
2172		    sizeof (struct fcp_scsi_cmd),
2173		    mode)) {
2174			return (EFAULT);
2175		}
2176		break;
2177	}
2178#else	/* _MULTI_DATAMODEL */
2179	/*
2180	 * Copy data from user address space
2181	 */
2182	if (ddi_copyin((void *)base_addr,
2183	    fscsi,
2184	    sizeof (struct fcp_scsi_cmd),
2185	    mode)) {
2186		return (EFAULT);
2187	}
2188#endif	/* _MULTI_DATAMODEL */
2189
2190	return (0);
2191}
2192
2193
2194/*
2195 * fcp_copyout_scsi_cmd
2196 *	Copy out fcp_scsi_cmd data structure to user address space.
2197 *	The data may be in 32 bit or 64 bit modes.
2198 *
2199 * Input:
2200 *	fscsi		= to address (kernel address space)
2201 *	mode		= See ioctl(9E) and ddi_copyin(9F)
2202 *
2203 * Output:
2204 *	base_addr	= from address (user address space)
2205 *
2206 * Returns:
2207 *	0	= OK
2208 *	EFAULT	= Error
2209 *
2210 * Context:
2211 *	Kernel context.
2212 */
2213static int
2214fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2215{
2216#ifdef	_MULTI_DATAMODEL
2217	struct fcp32_scsi_cmd	f32scsi;
2218
2219	switch (ddi_model_convert_from(mode & FMODELS)) {
2220	case DDI_MODEL_ILP32:
2221		/*
2222		 * Convert from 64 bit to 32 bit
2223		 */
2224		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2225		/*
2226		 * Copy data to user address space
2227		 */
2228		if (ddi_copyout(&f32scsi,
2229		    (void *)base_addr,
2230		    sizeof (struct fcp32_scsi_cmd),
2231		    mode)) {
2232			return (EFAULT);
2233		}
2234		break;
2235	case DDI_MODEL_NONE:
2236		/*
2237		 * Copy data to user address space
2238		 */
2239		if (ddi_copyout(fscsi,
2240		    (void *)base_addr,
2241		    sizeof (struct fcp_scsi_cmd),
2242		    mode)) {
2243			return (EFAULT);
2244		}
2245		break;
2246	}
2247#else	/* _MULTI_DATAMODEL */
2248	/*
2249	 * Copy data to user address space
2250	 */
2251	if (ddi_copyout(fscsi,
2252	    (void *)base_addr,
2253	    sizeof (struct fcp_scsi_cmd),
2254	    mode)) {
2255		return (EFAULT);
2256	}
2257#endif	/* _MULTI_DATAMODEL */
2258
2259	return (0);
2260}
2261
2262
2263/*
2264 * fcp_send_scsi_ioctl
2265 *	Sends the SCSI command in blocking mode.
2266 *
2267 * Input:
2268 *	fscsi		= SCSI command data structure
2269 *
2270 * Output:
2271 *	fscsi		= SCSI command data structure
2272 *
2273 * Returns:
2274 *	0	= OK
2275 *	EAGAIN	= See errno.h
2276 *	EBUSY	= See errno.h
2277 *	EINTR	= See errno.h
2278 *	EINVAL	= See errno.h
2279 *	EIO	= See errno.h
2280 *	ENOMEM	= See errno.h
2281 *	ENXIO	= See errno.h
2282 *
2283 * Context:
2284 *	Kernel context.
2285 */
2286static int
2287fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2288{
2289	struct fcp_lun	*plun		= NULL;
2290	struct fcp_port	*pptr		= NULL;
2291	struct fcp_tgt	*ptgt		= NULL;
2292	fc_packet_t		*fpkt		= NULL;
2293	struct fcp_ipkt	*icmd		= NULL;
2294	int			target_created	= FALSE;
2295	fc_frame_hdr_t		*hp;
2296	struct fcp_cmd		fcp_cmd;
2297	struct fcp_cmd		*fcmd;
2298	union scsi_cdb		*scsi_cdb;
2299	la_wwn_t		*wwn_ptr;
2300	int			nodma;
2301	struct fcp_rsp		*rsp;
2302	struct fcp_rsp_info	*rsp_info;
2303	caddr_t			rsp_sense;
2304	int			buf_len;
2305	int			info_len;
2306	int			sense_len;
2307	struct scsi_extended_sense	*sense_to = NULL;
2308	timeout_id_t		tid;
2309	uint8_t			reconfig_lun = FALSE;
2310	uint8_t			reconfig_pending = FALSE;
2311	uint8_t			scsi_cmd;
2312	int			rsp_len;
2313	int			cmd_index;
2314	int			fc_status;
2315	int			pkt_state;
2316	int			pkt_action;
2317	int			pkt_reason;
2318	int			ret, xport_retval = ~FC_SUCCESS;
2319	int			lcount;
2320	int			tcount;
2321	int			reconfig_status;
2322	int			port_busy = FALSE;
2323	uchar_t			*lun_string;
2324
2325	/*
2326	 * Check valid SCSI command
2327	 */
2328	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2329	ret = EINVAL;
2330	for (cmd_index = 0;
2331	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2332	    ret != 0;
2333	    cmd_index++) {
2334		/*
2335		 * First byte of CDB is the SCSI command
2336		 */
2337		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2338			ret = 0;
2339		}
2340	}
2341
2342	/*
2343	 * Check inputs
2344	 */
2345	if (fscsi->scsi_flags != FCP_SCSI_READ) {
2346		ret = EINVAL;
2347	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2348		/* no larger than */
2349		ret = EINVAL;
2350	}
2351
2352
2353	/*
2354	 * Find FC port
2355	 */
2356	if (ret == 0) {
2357		/*
2358		 * Acquire global mutex
2359		 */
2360		mutex_enter(&fcp_global_mutex);
2361
2362		pptr = fcp_port_head;
2363		while (pptr) {
2364			if (pptr->port_instance ==
2365			    (uint32_t)fscsi->scsi_fc_port_num) {
2366				break;
2367			} else {
2368				pptr = pptr->port_next;
2369			}
2370		}
2371
2372		if (pptr == NULL) {
2373			ret = ENXIO;
2374		} else {
2375			/*
2376			 * fc_ulp_busy_port can raise power
2377			 *  so, we must not hold any mutexes involved in PM
2378			 */
2379			mutex_exit(&fcp_global_mutex);
2380			ret = fc_ulp_busy_port(pptr->port_fp_handle);
2381		}
2382
2383		if (ret == 0) {
2384
2385			/* remember port is busy, so we will release later */
2386			port_busy = TRUE;
2387
2388			/*
2389			 * If there is a reconfiguration in progress, wait
2390			 * for it to complete.
2391			 */
2392
2393			fcp_reconfig_wait(pptr);
2394
2395			/* reacquire mutexes in order */
2396			mutex_enter(&fcp_global_mutex);
2397			mutex_enter(&pptr->port_mutex);
2398
2399			/*
2400			 * Will port accept DMA?
2401			 */
2402			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2403			    ? 1 : 0;
2404
2405			/*
2406			 * If init or offline, device not known
2407			 *
2408			 * If we are discovering (onlining), we can
2409			 * NOT obviously provide reliable data about
2410			 * devices until it is complete
2411			 */
2412			if (pptr->port_state &	  (FCP_STATE_INIT |
2413			    FCP_STATE_OFFLINE)) {
2414				ret = ENXIO;
2415			} else if (pptr->port_state & FCP_STATE_ONLINING) {
2416				ret = EBUSY;
2417			} else {
2418				/*
2419				 * Find target from pwwn
2420				 *
2421				 * The wwn must be put into a local
2422				 * variable to ensure alignment.
2423				 */
2424				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2425				ptgt = fcp_lookup_target(pptr,
2426				    (uchar_t *)wwn_ptr);
2427
2428				/*
2429				 * If target not found,
2430				 */
2431				if (ptgt == NULL) {
2432					/*
2433					 * Note: Still have global &
2434					 * port mutexes
2435					 */
2436					mutex_exit(&pptr->port_mutex);
2437					ptgt = fcp_port_create_tgt(pptr,
2438					    wwn_ptr, &ret, &fc_status,
2439					    &pkt_state, &pkt_action,
2440					    &pkt_reason);
2441					mutex_enter(&pptr->port_mutex);
2442
2443					fscsi->scsi_fc_status  = fc_status;
2444					fscsi->scsi_pkt_state  =
2445					    (uchar_t)pkt_state;
2446					fscsi->scsi_pkt_reason = pkt_reason;
2447					fscsi->scsi_pkt_action =
2448					    (uchar_t)pkt_action;
2449
2450					if (ptgt != NULL) {
2451						target_created = TRUE;
2452					} else if (ret == 0) {
2453						ret = ENOMEM;
2454					}
2455				}
2456
2457				if (ret == 0) {
2458					/*
2459					 * Acquire target
2460					 */
2461					mutex_enter(&ptgt->tgt_mutex);
2462
2463					/*
2464					 * If target is mark or busy,
2465					 * then target can not be used
2466					 */
2467					if (ptgt->tgt_state &
2468					    (FCP_TGT_MARK |
2469					    FCP_TGT_BUSY)) {
2470						ret = EBUSY;
2471					} else {
2472						/*
2473						 * Mark target as busy
2474						 */
2475						ptgt->tgt_state |=
2476						    FCP_TGT_BUSY;
2477					}
2478
2479					/*
2480					 * Release target
2481					 */
2482					lcount = pptr->port_link_cnt;
2483					tcount = ptgt->tgt_change_cnt;
2484					mutex_exit(&ptgt->tgt_mutex);
2485				}
2486			}
2487
2488			/*
2489			 * Release port
2490			 */
2491			mutex_exit(&pptr->port_mutex);
2492		}
2493
2494		/*
2495		 * Release global mutex
2496		 */
2497		mutex_exit(&fcp_global_mutex);
2498	}
2499
2500	if (ret == 0) {
2501		uint64_t belun = BE_64(fscsi->scsi_lun);
2502
2503		/*
2504		 * If it's a target device, find lun from pwwn
2505		 * The wwn must be put into a local
2506		 * variable to ensure alignment.
2507		 */
2508		mutex_enter(&pptr->port_mutex);
2509		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2510		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2511			/* this is not a target */
2512			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2513			ret = ENXIO;
2514		} else if ((belun << 16) != 0) {
2515			/*
2516			 * Since fcp only support PD and LU addressing method
2517			 * so far, the last 6 bytes of a valid LUN are expected
2518			 * to be filled with 00h.
2519			 */
2520			fscsi->scsi_fc_status = FC_INVALID_LUN;
2521			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2522			    " method 0x%02x with LUN number 0x%016" PRIx64,
2523			    (uint8_t)(belun >> 62), belun);
2524			ret = ENXIO;
2525		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2526		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2527			/*
2528			 * This is a SCSI target, but no LUN at this
2529			 * address.
2530			 *
2531			 * In the future, we may want to send this to
2532			 * the target, and let it respond
2533			 * appropriately
2534			 */
2535			ret = ENXIO;
2536		}
2537		mutex_exit(&pptr->port_mutex);
2538	}
2539
2540	/*
2541	 * Finished grabbing external resources
2542	 * Allocate internal packet (icmd)
2543	 */
2544	if (ret == 0) {
2545		/*
2546		 * Calc rsp len assuming rsp info included
2547		 */
2548		rsp_len = sizeof (struct fcp_rsp) +
2549		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2550
2551		icmd = fcp_icmd_alloc(pptr, ptgt,
2552		    sizeof (struct fcp_cmd),
2553		    rsp_len,
2554		    fscsi->scsi_buflen,
2555		    nodma,
2556		    lcount,			/* ipkt_link_cnt */
2557		    tcount,			/* ipkt_change_cnt */
2558		    0,				/* cause */
2559		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
2560
2561		if (icmd == NULL) {
2562			ret = ENOMEM;
2563		} else {
2564			/*
2565			 * Setup internal packet as sema sync
2566			 */
2567			fcp_ipkt_sema_init(icmd);
2568		}
2569	}
2570
2571	if (ret == 0) {
2572		/*
2573		 * Init fpkt pointer for use.
2574		 */
2575
2576		fpkt = icmd->ipkt_fpkt;
2577
2578		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
2579		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
2580		fpkt->pkt_timeout	= fscsi->scsi_timeout;
2581
2582		/*
2583		 * Init fcmd pointer for use by SCSI command
2584		 */
2585
2586		if (nodma) {
2587			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2588		} else {
2589			fcmd = &fcp_cmd;
2590		}
2591		bzero(fcmd, sizeof (struct fcp_cmd));
2592		ptgt = plun->lun_tgt;
2593
2594		lun_string = (uchar_t *)&fscsi->scsi_lun;
2595
2596		fcmd->fcp_ent_addr.ent_addr_0 =
2597		    BE_16(*(uint16_t *)&(lun_string[0]));
2598		fcmd->fcp_ent_addr.ent_addr_1 =
2599		    BE_16(*(uint16_t *)&(lun_string[2]));
2600		fcmd->fcp_ent_addr.ent_addr_2 =
2601		    BE_16(*(uint16_t *)&(lun_string[4]));
2602		fcmd->fcp_ent_addr.ent_addr_3 =
2603		    BE_16(*(uint16_t *)&(lun_string[6]));
2604
2605		/*
2606		 * Setup internal packet(icmd)
2607		 */
2608		icmd->ipkt_lun		= plun;
2609		icmd->ipkt_restart	= 0;
2610		icmd->ipkt_retries	= 0;
2611		icmd->ipkt_opcode	= 0;
2612
2613		/*
2614		 * Init the frame HEADER Pointer for use
2615		 */
2616		hp = &fpkt->pkt_cmd_fhdr;
2617
2618		hp->s_id	= pptr->port_id;
2619		hp->d_id	= ptgt->tgt_d_id;
2620		hp->r_ctl	= R_CTL_COMMAND;
2621		hp->type	= FC_TYPE_SCSI_FCP;
2622		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2623		hp->rsvd	= 0;
2624		hp->seq_id	= 0;
2625		hp->seq_cnt	= 0;
2626		hp->ox_id	= 0xffff;
2627		hp->rx_id	= 0xffff;
2628		hp->ro		= 0;
2629
2630		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
2631		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
2632		fcmd->fcp_cntl.cntl_write_data	= 0;
2633		fcmd->fcp_data_len	= fscsi->scsi_buflen;
2634
2635		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2636		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2637		    fscsi->scsi_cdblen);
2638
2639		if (!nodma) {
2640			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2641			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2642		}
2643
2644		/*
2645		 * Send SCSI command to FC transport
2646		 */
2647
2648		if (ret == 0) {
2649			mutex_enter(&ptgt->tgt_mutex);
2650
2651			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2652				mutex_exit(&ptgt->tgt_mutex);
2653				fscsi->scsi_fc_status = xport_retval =
2654				    fc_ulp_transport(pptr->port_fp_handle,
2655				    fpkt);
2656				if (fscsi->scsi_fc_status != FC_SUCCESS) {
2657					ret = EIO;
2658				}
2659			} else {
2660				mutex_exit(&ptgt->tgt_mutex);
2661				ret = EBUSY;
2662			}
2663		}
2664	}
2665
2666	/*
2667	 * Wait for completion only if fc_ulp_transport was called and it
2668	 * returned a success. This is the only time callback will happen.
2669	 * Otherwise, there is no point in waiting
2670	 */
2671	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2672		ret = fcp_ipkt_sema_wait(icmd);
2673	}
2674
2675	/*
2676	 * Copy data to IOCTL data structures
2677	 */
2678	rsp = NULL;
2679	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2680		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2681
2682		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2683			fcp_log(CE_WARN, pptr->port_dip,
2684			    "!SCSI command to d_id=0x%x lun=0x%x"
2685			    " failed, Bad FCP response values:"
2686			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2687			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2688			    ptgt->tgt_d_id, plun->lun_num,
2689			    rsp->reserved_0, rsp->reserved_1,
2690			    rsp->fcp_u.fcp_status.reserved_0,
2691			    rsp->fcp_u.fcp_status.reserved_1,
2692			    rsp->fcp_response_len, rsp->fcp_sense_len);
2693
2694			ret = EIO;
2695		}
2696	}
2697
2698	if ((ret == 0) && (rsp != NULL)) {
2699		/*
2700		 * Calc response lengths
2701		 */
2702		sense_len = 0;
2703		info_len = 0;
2704
2705		if (rsp->fcp_u.fcp_status.rsp_len_set) {
2706			info_len = rsp->fcp_response_len;
2707		}
2708
2709		rsp_info   = (struct fcp_rsp_info *)
2710		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2711
2712		/*
2713		 * Get SCSI status
2714		 */
2715		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2716		/*
2717		 * If a lun was just added or removed and the next command
2718		 * comes through this interface, we need to capture the check
2719		 * condition so we can discover the new topology.
2720		 */
2721		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2722		    rsp->fcp_u.fcp_status.sense_len_set) {
2723			sense_len = rsp->fcp_sense_len;
2724			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2725			sense_to = (struct scsi_extended_sense *)rsp_sense;
2726			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2727			    (FCP_SENSE_NO_LUN(sense_to))) {
2728				reconfig_lun = TRUE;
2729			}
2730		}
2731
2732		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2733		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2734			if (reconfig_lun == FALSE) {
2735				reconfig_status =
2736				    fcp_is_reconfig_needed(ptgt, fpkt);
2737			}
2738
2739			if ((reconfig_lun == TRUE) ||
2740			    (reconfig_status == TRUE)) {
2741				mutex_enter(&ptgt->tgt_mutex);
2742				if (ptgt->tgt_tid == NULL) {
2743					/*
2744					 * Either we've been notified the
2745					 * REPORT_LUN data has changed, or
2746					 * we've determined on our own that
2747					 * we're out of date.  Kick off
2748					 * rediscovery.
2749					 */
2750					tid = timeout(fcp_reconfigure_luns,
2751					    (caddr_t)ptgt, drv_usectohz(1));
2752
2753					ptgt->tgt_tid = tid;
2754					ptgt->tgt_state |= FCP_TGT_BUSY;
2755					ret = EBUSY;
2756					reconfig_pending = TRUE;
2757				}
2758				mutex_exit(&ptgt->tgt_mutex);
2759			}
2760		}
2761
2762		/*
2763		 * Calc residuals and buffer lengths
2764		 */
2765
2766		if (ret == 0) {
2767			buf_len = fscsi->scsi_buflen;
2768			fscsi->scsi_bufresid	= 0;
2769			if (rsp->fcp_u.fcp_status.resid_under) {
2770				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2771					fscsi->scsi_bufresid = rsp->fcp_resid;
2772				} else {
2773					cmn_err(CE_WARN, "fcp: bad residue %x "
2774					    "for txfer len %x", rsp->fcp_resid,
2775					    fscsi->scsi_buflen);
2776					fscsi->scsi_bufresid =
2777					    fscsi->scsi_buflen;
2778				}
2779				buf_len -= fscsi->scsi_bufresid;
2780			}
2781			if (rsp->fcp_u.fcp_status.resid_over) {
2782				fscsi->scsi_bufresid = -rsp->fcp_resid;
2783			}
2784
2785			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
2786			if (fscsi->scsi_rqlen < sense_len) {
2787				sense_len = fscsi->scsi_rqlen;
2788			}
2789
2790			fscsi->scsi_fc_rspcode	= 0;
2791			if (rsp->fcp_u.fcp_status.rsp_len_set) {
2792				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
2793			}
2794			fscsi->scsi_pkt_state	= fpkt->pkt_state;
2795			fscsi->scsi_pkt_action	= fpkt->pkt_action;
2796			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
2797
2798			/*
2799			 * Copy data and request sense
2800			 *
2801			 * Data must be copied by using the FCP_CP_IN macro.
2802			 * This will ensure the proper byte order since the data
2803			 * is being copied directly from the memory mapped
2804			 * device register.
2805			 *
2806			 * The response (and request sense) will be in the
2807			 * correct byte order.	No special copy is necessary.
2808			 */
2809
2810			if (buf_len) {
2811				FCP_CP_IN(fpkt->pkt_data,
2812				    fscsi->scsi_bufaddr,
2813				    fpkt->pkt_data_acc,
2814				    buf_len);
2815			}
2816			bcopy((void *)rsp_sense,
2817			    (void *)fscsi->scsi_rqbufaddr,
2818			    sense_len);
2819		}
2820	}
2821
2822	/*
2823	 * Cleanup transport data structures if icmd was alloc-ed
2824	 * So, cleanup happens in the same thread that icmd was alloc-ed
2825	 */
2826	if (icmd != NULL) {
2827		fcp_ipkt_sema_cleanup(icmd);
2828	}
2829
2830	/* restore pm busy/idle status */
2831	if (port_busy) {
2832		fc_ulp_idle_port(pptr->port_fp_handle);
2833	}
2834
2835	/*
2836	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2837	 * flag, it'll be cleared when the reconfig is complete.
2838	 */
2839	if ((ptgt != NULL) && !reconfig_pending) {
2840		/*
2841		 * If target was created,
2842		 */
2843		if (target_created) {
2844			mutex_enter(&ptgt->tgt_mutex);
2845			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2846			mutex_exit(&ptgt->tgt_mutex);
2847		} else {
2848			/*
2849			 * De-mark target as busy
2850			 */
2851			mutex_enter(&ptgt->tgt_mutex);
2852			ptgt->tgt_state &= ~FCP_TGT_BUSY;
2853			mutex_exit(&ptgt->tgt_mutex);
2854		}
2855	}
2856	return (ret);
2857}
2858
2859
2860static int
2861fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2862    fc_packet_t	*fpkt)
2863{
2864	uchar_t			*lun_string;
2865	uint16_t		lun_num, i;
2866	int			num_luns;
2867	int			actual_luns;
2868	int			num_masked_luns;
2869	int			lun_buflen;
2870	struct fcp_lun	*plun	= NULL;
2871	struct fcp_reportlun_resp	*report_lun;
2872	uint8_t			reconfig_needed = FALSE;
2873	uint8_t			lun_exists = FALSE;
2874	fcp_port_t			*pptr		 = ptgt->tgt_port;
2875
2876	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2877
2878	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2879	    fpkt->pkt_datalen);
2880
2881	/* get number of luns (which is supplied as LUNS * 8) */
2882	num_luns = BE_32(report_lun->num_lun) >> 3;
2883
2884	/*
2885	 * Figure out exactly how many lun strings our response buffer
2886	 * can hold.
2887	 */
2888	lun_buflen = (fpkt->pkt_datalen -
2889	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
2890
2891	/*
2892	 * Is our response buffer full or not? We don't want to
2893	 * potentially walk beyond the number of luns we have.
2894	 */
2895	if (num_luns <= lun_buflen) {
2896		actual_luns = num_luns;
2897	} else {
2898		actual_luns = lun_buflen;
2899	}
2900
2901	mutex_enter(&ptgt->tgt_mutex);
2902
2903	/* Scan each lun to see if we have masked it. */
2904	num_masked_luns = 0;
2905	if (fcp_lun_blacklist != NULL) {
2906		for (i = 0; i < actual_luns; i++) {
2907			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2908			switch (lun_string[0] & 0xC0) {
2909			case FCP_LUN_ADDRESSING:
2910			case FCP_PD_ADDRESSING:
2911			case FCP_VOLUME_ADDRESSING:
2912				lun_num = ((lun_string[0] & 0x3F) << 8)
2913				    | lun_string[1];
2914				if (fcp_should_mask(&ptgt->tgt_port_wwn,
2915				    lun_num) == TRUE) {
2916					num_masked_luns++;
2917				}
2918				break;
2919			default:
2920				break;
2921			}
2922		}
2923	}
2924
2925	/*
2926	 * The quick and easy check.  If the number of LUNs reported
2927	 * doesn't match the number we currently know about, we need
2928	 * to reconfigure.
2929	 */
2930	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2931		mutex_exit(&ptgt->tgt_mutex);
2932		kmem_free(report_lun, fpkt->pkt_datalen);
2933		return (TRUE);
2934	}
2935
2936	/*
2937	 * If the quick and easy check doesn't turn up anything, we walk
2938	 * the list of luns from the REPORT_LUN response and look for
2939	 * any luns we don't know about.  If we find one, we know we need
2940	 * to reconfigure. We will skip LUNs that are masked because of the
2941	 * blacklist.
2942	 */
2943	for (i = 0; i < actual_luns; i++) {
2944		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2945		lun_exists = FALSE;
2946		switch (lun_string[0] & 0xC0) {
2947		case FCP_LUN_ADDRESSING:
2948		case FCP_PD_ADDRESSING:
2949		case FCP_VOLUME_ADDRESSING:
2950			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2951
2952			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2953			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2954				lun_exists = TRUE;
2955				break;
2956			}
2957
2958			for (plun = ptgt->tgt_lun; plun;
2959			    plun = plun->lun_next) {
2960				if (plun->lun_num == lun_num) {
2961					lun_exists = TRUE;
2962					break;
2963				}
2964			}
2965			break;
2966		default:
2967			break;
2968		}
2969
2970		if (lun_exists == FALSE) {
2971			reconfig_needed = TRUE;
2972			break;
2973		}
2974	}
2975
2976	mutex_exit(&ptgt->tgt_mutex);
2977	kmem_free(report_lun, fpkt->pkt_datalen);
2978
2979	return (reconfig_needed);
2980}
2981
2982/*
2983 * This function is called by fcp_handle_page83 and uses inquiry response data
2984 * stored in plun->lun_inq to determine whether or not a device is a member of
2985 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2986 * otherwise 1.
2987 */
2988static int
2989fcp_symmetric_device_probe(struct fcp_lun *plun)
2990{
2991	struct scsi_inquiry	*stdinq = &plun->lun_inq;
2992	char			*devidptr;
2993	int			i, len;
2994
2995	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2996		devidptr = fcp_symmetric_disk_table[i];
2997		len = (int)strlen(devidptr);
2998
2999		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3000			return (0);
3001		}
3002	}
3003	return (1);
3004}
3005
3006
3007/*
3008 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3009 * It basically returns the current count of # of state change callbacks
3010 * i.e the value of tgt_change_cnt.
3011 *
3012 * INPUT:
3013 *   fcp_ioctl.fp_minor -> The minor # of the fp port
3014 *   fcp_ioctl.listlen	-> 1
3015 *   fcp_ioctl.list	-> Pointer to a 32 bit integer
3016 */
3017/*ARGSUSED2*/
3018static int
3019fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3020{
3021	int			ret;
3022	uint32_t		link_cnt;
3023	struct fcp_ioctl	fioctl;
3024	struct fcp_port	*pptr = NULL;
3025
3026	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3027	    &pptr)) != 0) {
3028		return (ret);
3029	}
3030
3031	ASSERT(pptr != NULL);
3032
3033	if (fioctl.listlen != 1) {
3034		return (EINVAL);
3035	}
3036
3037	mutex_enter(&pptr->port_mutex);
3038	if (pptr->port_state & FCP_STATE_OFFLINE) {
3039		mutex_exit(&pptr->port_mutex);
3040		return (ENXIO);
3041	}
3042
3043	/*
3044	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3045	 * When the fcp initially attaches to the port and there are nothing
3046	 * hanging out of the port or if there was a repeat offline state change
3047	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3048	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
3049	 * will differentiate the 2 cases.
3050	 */
3051	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3052		mutex_exit(&pptr->port_mutex);
3053		return (ENXIO);
3054	}
3055
3056	link_cnt = pptr->port_link_cnt;
3057	mutex_exit(&pptr->port_mutex);
3058
3059	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3060		return (EFAULT);
3061	}
3062
3063#ifdef	_MULTI_DATAMODEL
3064	switch (ddi_model_convert_from(mode & FMODELS)) {
3065	case DDI_MODEL_ILP32: {
3066		struct fcp32_ioctl f32_ioctl;
3067
3068		f32_ioctl.fp_minor = fioctl.fp_minor;
3069		f32_ioctl.listlen = fioctl.listlen;
3070		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3071		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3072		    sizeof (struct fcp32_ioctl), mode)) {
3073			return (EFAULT);
3074		}
3075		break;
3076	}
3077	case DDI_MODEL_NONE:
3078		if (ddi_copyout((void *)&fioctl, (void *)data,
3079		    sizeof (struct fcp_ioctl), mode)) {
3080			return (EFAULT);
3081		}
3082		break;
3083	}
3084#else	/* _MULTI_DATAMODEL */
3085
3086	if (ddi_copyout((void *)&fioctl, (void *)data,
3087	    sizeof (struct fcp_ioctl), mode)) {
3088		return (EFAULT);
3089	}
3090#endif	/* _MULTI_DATAMODEL */
3091
3092	return (0);
3093}
3094
3095/*
3096 * This function copies the fcp_ioctl structure passed in from user land
3097 * into kernel land. Handles 32 bit applications.
3098 */
3099/*ARGSUSED*/
3100static int
3101fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3102    struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3103{
3104	struct fcp_port	*t_pptr;
3105
3106#ifdef	_MULTI_DATAMODEL
3107	switch (ddi_model_convert_from(mode & FMODELS)) {
3108	case DDI_MODEL_ILP32: {
3109		struct fcp32_ioctl f32_ioctl;
3110
3111		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3112		    sizeof (struct fcp32_ioctl), mode)) {
3113			return (EFAULT);
3114		}
3115		fioctl->fp_minor = f32_ioctl.fp_minor;
3116		fioctl->listlen = f32_ioctl.listlen;
3117		fioctl->list = (caddr_t)(long)f32_ioctl.list;
3118		break;
3119	}
3120	case DDI_MODEL_NONE:
3121		if (ddi_copyin((void *)data, (void *)fioctl,
3122		    sizeof (struct fcp_ioctl), mode)) {
3123			return (EFAULT);
3124		}
3125		break;
3126	}
3127
3128#else	/* _MULTI_DATAMODEL */
3129	if (ddi_copyin((void *)data, (void *)fioctl,
3130	    sizeof (struct fcp_ioctl), mode)) {
3131		return (EFAULT);
3132	}
3133#endif	/* _MULTI_DATAMODEL */
3134
3135	/*
3136	 * Right now we can assume that the minor number matches with
3137	 * this instance of fp. If this changes we will need to
3138	 * revisit this logic.
3139	 */
3140	mutex_enter(&fcp_global_mutex);
3141	t_pptr = fcp_port_head;
3142	while (t_pptr) {
3143		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3144			break;
3145		} else {
3146			t_pptr = t_pptr->port_next;
3147		}
3148	}
3149	*pptr = t_pptr;
3150	mutex_exit(&fcp_global_mutex);
3151	if (t_pptr == NULL) {
3152		return (ENXIO);
3153	}
3154
3155	return (0);
3156}
3157
3158/*
3159 *     Function: fcp_port_create_tgt
3160 *
3161 *  Description: As the name suggest this function creates the target context
3162 *		 specified by the the WWN provided by the caller.  If the
3163 *		 creation goes well and the target is known by fp/fctl a PLOGI
3164 *		 followed by a PRLI are issued.
3165 *
3166 *     Argument: pptr		fcp port structure
3167 *		 pwwn		WWN of the target
3168 *		 ret_val	Address of the return code.  It could be:
3169 *				EIO, ENOMEM or 0.
3170 *		 fc_status	PLOGI or PRLI status completion
3171 *		 fc_pkt_state	PLOGI or PRLI state completion
3172 *		 fc_pkt_reason	PLOGI or PRLI reason completion
3173 *		 fc_pkt_action	PLOGI or PRLI action completion
3174 *
3175 * Return Value: NULL if it failed
3176 *		 Target structure address if it succeeds
3177 */
3178static struct fcp_tgt *
3179fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3180    int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3181{
3182	struct fcp_tgt	*ptgt = NULL;
3183	fc_portmap_t		devlist;
3184	int			lcount;
3185	int			error;
3186
3187	*ret_val = 0;
3188
3189	/*
3190	 * Check FC port device & get port map
3191	 */
3192	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3193	    &error, 1) == NULL) {
3194		*ret_val = EIO;
3195	} else {
3196		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3197		    &devlist) != FC_SUCCESS) {
3198			*ret_val = EIO;
3199		}
3200	}
3201
3202	/* Set port map flags */
3203	devlist.map_type = PORT_DEVICE_USER_CREATE;
3204
3205	/* Allocate target */
3206	if (*ret_val == 0) {
3207		lcount = pptr->port_link_cnt;
3208		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3209		if (ptgt == NULL) {
3210			fcp_log(CE_WARN, pptr->port_dip,
3211			    "!FC target allocation failed");
3212			*ret_val = ENOMEM;
3213		} else {
3214			/* Setup target */
3215			mutex_enter(&ptgt->tgt_mutex);
3216
3217			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
3218			ptgt->tgt_tmp_cnt	= 1;
3219			ptgt->tgt_d_id		= devlist.map_did.port_id;
3220			ptgt->tgt_hard_addr	=
3221			    devlist.map_hard_addr.hard_addr;
3222			ptgt->tgt_pd_handle	= devlist.map_pd;
3223			ptgt->tgt_fca_dev	= NULL;
3224
3225			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3226			    FC_WWN_SIZE);
3227			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3228			    FC_WWN_SIZE);
3229
3230			mutex_exit(&ptgt->tgt_mutex);
3231		}
3232	}
3233
3234	/* Release global mutex for PLOGI and PRLI */
3235	mutex_exit(&fcp_global_mutex);
3236
3237	/* Send PLOGI (If necessary) */
3238	if (*ret_val == 0) {
3239		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3240		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3241	}
3242
3243	/* Send PRLI (If necessary) */
3244	if (*ret_val == 0) {
3245		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3246		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3247	}
3248
3249	mutex_enter(&fcp_global_mutex);
3250
3251	return (ptgt);
3252}
3253
3254/*
3255 *     Function: fcp_tgt_send_plogi
3256 *
3257 *  Description: This function sends a PLOGI to the target specified by the
3258 *		 caller and waits till it completes.
3259 *
3260 *     Argument: ptgt		Target to send the plogi to.
3261 *		 fc_status	Status returned by fp/fctl in the PLOGI request.
3262 *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
3263 *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
3264 *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
3265 *
3266 * Return Value: 0
3267 *		 ENOMEM
3268 *		 EIO
3269 *
3270 *	Context: User context.
3271 */
3272static int
3273fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3274    int *fc_pkt_reason, int *fc_pkt_action)
3275{
3276	struct fcp_port	*pptr;
3277	struct fcp_ipkt	*icmd;
3278	struct fc_packet	*fpkt;
3279	fc_frame_hdr_t		*hp;
3280	struct la_els_logi	logi;
3281	int			tcount;
3282	int			lcount;
3283	int			ret, login_retval = ~FC_SUCCESS;
3284
3285	ret = 0;
3286
3287	pptr = ptgt->tgt_port;
3288
3289	lcount = pptr->port_link_cnt;
3290	tcount = ptgt->tgt_change_cnt;
3291
3292	/* Alloc internal packet */
3293	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3294	    sizeof (la_els_logi_t), 0,
3295	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3296	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3297
3298	if (icmd == NULL) {
3299		ret = ENOMEM;
3300	} else {
3301		/*
3302		 * Setup internal packet as sema sync
3303		 */
3304		fcp_ipkt_sema_init(icmd);
3305
3306		/*
3307		 * Setup internal packet (icmd)
3308		 */
3309		icmd->ipkt_lun		= NULL;
3310		icmd->ipkt_restart	= 0;
3311		icmd->ipkt_retries	= 0;
3312		icmd->ipkt_opcode	= LA_ELS_PLOGI;
3313
3314		/*
3315		 * Setup fc_packet
3316		 */
3317		fpkt = icmd->ipkt_fpkt;
3318
3319		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
3320		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
3321		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
3322
3323		/*
3324		 * Setup FC frame header
3325		 */
3326		hp = &fpkt->pkt_cmd_fhdr;
3327
3328		hp->s_id	= pptr->port_id;	/* source ID */
3329		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
3330		hp->r_ctl	= R_CTL_ELS_REQ;
3331		hp->type	= FC_TYPE_EXTENDED_LS;
3332		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3333		hp->seq_id	= 0;
3334		hp->rsvd	= 0;
3335		hp->df_ctl	= 0;
3336		hp->seq_cnt	= 0;
3337		hp->ox_id	= 0xffff;		/* i.e. none */
3338		hp->rx_id	= 0xffff;		/* i.e. none */
3339		hp->ro		= 0;
3340
3341		/*
3342		 * Setup PLOGI
3343		 */
3344		bzero(&logi, sizeof (struct la_els_logi));
3345		logi.ls_code.ls_code = LA_ELS_PLOGI;
3346
3347		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3348		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3349
3350		/*
3351		 * Send PLOGI
3352		 */
3353		*fc_status = login_retval =
3354		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3355		if (*fc_status != FC_SUCCESS) {
3356			ret = EIO;
3357		}
3358	}
3359
3360	/*
3361	 * Wait for completion
3362	 */
3363	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3364		ret = fcp_ipkt_sema_wait(icmd);
3365
3366		*fc_pkt_state	= fpkt->pkt_state;
3367		*fc_pkt_reason	= fpkt->pkt_reason;
3368		*fc_pkt_action	= fpkt->pkt_action;
3369	}
3370
3371	/*
3372	 * Cleanup transport data structures if icmd was alloc-ed AND if there
3373	 * is going to be no callback (i.e if fc_ulp_login() failed).
3374	 * Otherwise, cleanup happens in callback routine.
3375	 */
3376	if (icmd != NULL) {
3377		fcp_ipkt_sema_cleanup(icmd);
3378	}
3379
3380	return (ret);
3381}
3382
3383/*
3384 *     Function: fcp_tgt_send_prli
3385 *
3386 *  Description: Does nothing as of today.
3387 *
3388 *     Argument: ptgt		Target to send the prli to.
3389 *		 fc_status	Status returned by fp/fctl in the PRLI request.
3390 *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
3391 *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
3392 *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
3393 *
3394 * Return Value: 0
3395 */
3396/*ARGSUSED*/
3397static int
3398fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3399    int *fc_pkt_reason, int *fc_pkt_action)
3400{
3401	return (0);
3402}
3403
3404/*
3405 *     Function: fcp_ipkt_sema_init
3406 *
3407 *  Description: Initializes the semaphore contained in the internal packet.
3408 *
3409 *     Argument: icmd	Internal packet the semaphore of which must be
3410 *			initialized.
3411 *
3412 * Return Value: None
3413 *
3414 *	Context: User context only.
3415 */
3416static void
3417fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3418{
3419	struct fc_packet	*fpkt;
3420
3421	fpkt = icmd->ipkt_fpkt;
3422
3423	/* Create semaphore for sync */
3424	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3425
3426	/* Setup the completion callback */
3427	fpkt->pkt_comp = fcp_ipkt_sema_callback;
3428}
3429
3430/*
3431 *     Function: fcp_ipkt_sema_wait
3432 *
3433 *  Description: Wait on the semaphore embedded in the internal packet.	 The
3434 *		 semaphore is released in the callback.
3435 *
3436 *     Argument: icmd	Internal packet to wait on for completion.
3437 *
3438 * Return Value: 0
3439 *		 EIO
3440 *		 EBUSY
3441 *		 EAGAIN
3442 *
3443 *	Context: User context only.
3444 *
3445 * This function does a conversion between the field pkt_state of the fc_packet
3446 * embedded in the internal packet (icmd) and the code it returns.
3447 */
3448static int
3449fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3450{
3451	struct fc_packet	*fpkt;
3452	int	ret;
3453
3454	ret = EIO;
3455	fpkt = icmd->ipkt_fpkt;
3456
3457	/*
3458	 * Wait on semaphore
3459	 */
3460	sema_p(&(icmd->ipkt_sema));
3461
3462	/*
3463	 * Check the status of the FC packet
3464	 */
3465	switch (fpkt->pkt_state) {
3466	case FC_PKT_SUCCESS:
3467		ret = 0;
3468		break;
3469	case FC_PKT_LOCAL_RJT:
3470		switch (fpkt->pkt_reason) {
3471		case FC_REASON_SEQ_TIMEOUT:
3472		case FC_REASON_RX_BUF_TIMEOUT:
3473			ret = EAGAIN;
3474			break;
3475		case FC_REASON_PKT_BUSY:
3476			ret = EBUSY;
3477			break;
3478		}
3479		break;
3480	case FC_PKT_TIMEOUT:
3481		ret = EAGAIN;
3482		break;
3483	case FC_PKT_LOCAL_BSY:
3484	case FC_PKT_TRAN_BSY:
3485	case FC_PKT_NPORT_BSY:
3486	case FC_PKT_FABRIC_BSY:
3487		ret = EBUSY;
3488		break;
3489	case FC_PKT_LS_RJT:
3490	case FC_PKT_BA_RJT:
3491		switch (fpkt->pkt_reason) {
3492		case FC_REASON_LOGICAL_BSY:
3493			ret = EBUSY;
3494			break;
3495		}
3496		break;
3497	case FC_PKT_FS_RJT:
3498		switch (fpkt->pkt_reason) {
3499		case FC_REASON_FS_LOGICAL_BUSY:
3500			ret = EBUSY;
3501			break;
3502		}
3503		break;
3504	}
3505
3506	return (ret);
3507}
3508
3509/*
3510 *     Function: fcp_ipkt_sema_callback
3511 *
3512 *  Description: Registered as the completion callback function for the FC
3513 *		 transport when the ipkt semaphore is used for sync. This will
3514 *		 cleanup the used data structures, if necessary and wake up
3515 *		 the user thread to complete the transaction.
3516 *
3517 *     Argument: fpkt	FC packet (points to the icmd)
3518 *
3519 * Return Value: None
3520 *
3521 *	Context: User context only
3522 */
3523static void
3524fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3525{
3526	struct fcp_ipkt	*icmd;
3527
3528	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3529
3530	/*
3531	 * Wake up user thread
3532	 */
3533	sema_v(&(icmd->ipkt_sema));
3534}
3535
3536/*
3537 *     Function: fcp_ipkt_sema_cleanup
3538 *
3539 *  Description: Called to cleanup (if necessary) the data structures used
3540 *		 when ipkt sema is used for sync.  This function will detect
3541 *		 whether the caller is the last thread (via counter) and
3542 *		 cleanup only if necessary.
3543 *
3544 *     Argument: icmd	Internal command packet
3545 *
3546 * Return Value: None
3547 *
3548 *	Context: User context only
3549 */
3550static void
3551fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3552{
3553	struct fcp_tgt	*ptgt;
3554	struct fcp_port	*pptr;
3555
3556	ptgt = icmd->ipkt_tgt;
3557	pptr = icmd->ipkt_port;
3558
3559	/*
3560	 * Acquire data structure
3561	 */
3562	mutex_enter(&ptgt->tgt_mutex);
3563
3564	/*
3565	 * Destroy semaphore
3566	 */
3567	sema_destroy(&(icmd->ipkt_sema));
3568
3569	/*
3570	 * Cleanup internal packet
3571	 */
3572	mutex_exit(&ptgt->tgt_mutex);
3573	fcp_icmd_free(pptr, icmd);
3574}
3575
3576/*
3577 *     Function: fcp_port_attach
3578 *
3579 *  Description: Called by the transport framework to resume, suspend or
3580 *		 attach a new port.
3581 *
3582 *     Argument: ulph		Port handle
3583 *		 *pinfo		Port information
3584 *		 cmd		Command
3585 *		 s_id		Port ID
3586 *
3587 * Return Value: FC_FAILURE or FC_SUCCESS
3588 */
3589/*ARGSUSED*/
3590static int
3591fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3592    fc_attach_cmd_t cmd, uint32_t s_id)
3593{
3594	int	instance;
3595	int	res = FC_FAILURE; /* default result */
3596
3597	ASSERT(pinfo != NULL);
3598
3599	instance = ddi_get_instance(pinfo->port_dip);
3600
3601	switch (cmd) {
3602	case FC_CMD_ATTACH:
3603		/*
3604		 * this port instance attaching for the first time (or after
3605		 * being detached before)
3606		 */
3607		if (fcp_handle_port_attach(ulph, pinfo, s_id,
3608		    instance) == DDI_SUCCESS) {
3609			res = FC_SUCCESS;
3610		} else {
3611			ASSERT(ddi_get_soft_state(fcp_softstate,
3612			    instance) == NULL);
3613		}
3614		break;
3615
3616	case FC_CMD_RESUME:
3617	case FC_CMD_POWER_UP:
3618		/*
3619		 * this port instance was attached and the suspended and
3620		 * will now be resumed
3621		 */
3622		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3623		    instance) == DDI_SUCCESS) {
3624			res = FC_SUCCESS;
3625		}
3626		break;
3627
3628	default:
3629		/* shouldn't happen */
3630		FCP_TRACE(fcp_logq, "fcp",
3631		    fcp_trace, FCP_BUF_LEVEL_2, 0,
3632		    "port_attach: unknown cmdcommand: %d", cmd);
3633		break;
3634	}
3635
3636	/* return result */
3637	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3638	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3639
3640	return (res);
3641}
3642
3643
3644/*
3645 * detach or suspend this port instance
3646 *
3647 * acquires and releases the global mutex
3648 *
3649 * acquires and releases the mutex for this port
3650 *
3651 * acquires and releases the hotplug mutex for this port
3652 */
3653/*ARGSUSED*/
3654static int
3655fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3656    fc_detach_cmd_t cmd)
3657{
3658	int			flag;
3659	int			instance;
3660	struct fcp_port		*pptr;
3661
3662	instance = ddi_get_instance(info->port_dip);
3663	pptr = ddi_get_soft_state(fcp_softstate, instance);
3664
3665	switch (cmd) {
3666	case FC_CMD_SUSPEND:
3667		FCP_DTRACE(fcp_logq, "fcp",
3668		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3669		    "port suspend called for port %d", instance);
3670		flag = FCP_STATE_SUSPENDED;
3671		break;
3672
3673	case FC_CMD_POWER_DOWN:
3674		FCP_DTRACE(fcp_logq, "fcp",
3675		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3676		    "port power down called for port %d", instance);
3677		flag = FCP_STATE_POWER_DOWN;
3678		break;
3679
3680	case FC_CMD_DETACH:
3681		FCP_DTRACE(fcp_logq, "fcp",
3682		    fcp_trace, FCP_BUF_LEVEL_8, 0,
3683		    "port detach called for port %d", instance);
3684		flag = FCP_STATE_DETACHING;
3685		break;
3686
3687	default:
3688		/* shouldn't happen */
3689		return (FC_FAILURE);
3690	}
3691	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3692	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3693
3694	return (fcp_handle_port_detach(pptr, flag, instance));
3695}
3696
3697
3698/*
3699 * called for ioctls on the transport's devctl interface, and the transport
3700 * has passed it to us
3701 *
3702 * this will only be called for device control ioctls (i.e. hotplugging stuff)
3703 *
3704 * return FC_SUCCESS if we decide to claim the ioctl,
3705 * else return FC_UNCLAIMED
3706 *
3707 * *rval is set iff we decide to claim the ioctl
3708 */
3709/*ARGSUSED*/
3710static int
3711fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3712    intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3713{
3714	int			retval = FC_UNCLAIMED;	/* return value */
3715	struct fcp_port		*pptr = NULL;		/* our soft state */
3716	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
3717	dev_info_t		*cdip;
3718	mdi_pathinfo_t		*pip = NULL;
3719	char			*ndi_nm;		/* NDI name */
3720	char			*ndi_addr;		/* NDI addr */
3721	int			is_mpxio, circ;
3722	int			devi_entered = 0;
3723	clock_t			end_time;
3724
3725	ASSERT(rval != NULL);
3726
3727	FCP_DTRACE(fcp_logq, "fcp",
3728	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3729	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3730
3731	/* if already claimed then forget it */
3732	if (claimed) {
3733		/*
3734		 * for now, if this ioctl has already been claimed, then
3735		 * we just ignore it
3736		 */
3737		return (retval);
3738	}
3739
3740	/* get our port info */
3741	if ((pptr = fcp_get_port(port_handle)) == NULL) {
3742		fcp_log(CE_WARN, NULL,
3743		    "!fcp:Invalid port handle handle in ioctl");
3744		*rval = ENXIO;
3745		return (retval);
3746	}
3747	is_mpxio = pptr->port_mpxio;
3748
3749	switch (cmd) {
3750	case DEVCTL_BUS_GETSTATE:
3751	case DEVCTL_BUS_QUIESCE:
3752	case DEVCTL_BUS_UNQUIESCE:
3753	case DEVCTL_BUS_RESET:
3754	case DEVCTL_BUS_RESETALL:
3755
3756	case DEVCTL_BUS_DEV_CREATE:
3757		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3758			return (retval);
3759		}
3760		break;
3761
3762	case DEVCTL_DEVICE_GETSTATE:
3763	case DEVCTL_DEVICE_OFFLINE:
3764	case DEVCTL_DEVICE_ONLINE:
3765	case DEVCTL_DEVICE_REMOVE:
3766	case DEVCTL_DEVICE_RESET:
3767		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3768			return (retval);
3769		}
3770
3771		ASSERT(dcp != NULL);
3772
3773		/* ensure we have a name and address */
3774		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3775		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3776			FCP_TRACE(fcp_logq, pptr->port_instbuf,
3777			    fcp_trace, FCP_BUF_LEVEL_2, 0,
3778			    "ioctl: can't get name (%s) or addr (%s)",
3779			    ndi_nm ? ndi_nm : "<null ptr>",
3780			    ndi_addr ? ndi_addr : "<null ptr>");
3781			ndi_dc_freehdl(dcp);
3782			return (retval);
3783		}
3784
3785
3786		/* get our child's DIP */
3787		ASSERT(pptr != NULL);
3788		if (is_mpxio) {
3789			mdi_devi_enter(pptr->port_dip, &circ);
3790		} else {
3791			ndi_devi_enter(pptr->port_dip, &circ);
3792		}
3793		devi_entered = 1;
3794
3795		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3796		    ndi_addr)) == NULL) {
3797			/* Look for virtually enumerated devices. */
3798			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3799			if (pip == NULL ||
3800			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3801				*rval = ENXIO;
3802				goto out;
3803			}
3804		}
3805		break;
3806
3807	default:
3808		*rval = ENOTTY;
3809		return (retval);
3810	}
3811
3812	/* this ioctl is ours -- process it */
3813
3814	retval = FC_SUCCESS;		/* just means we claim the ioctl */
3815
3816	/* we assume it will be a success; else we'll set error value */
3817	*rval = 0;
3818
3819
3820	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3821	    fcp_trace, FCP_BUF_LEVEL_8, 0,
3822	    "ioctl: claiming this one");
3823
3824	/* handle ioctls now */
3825	switch (cmd) {
3826	case DEVCTL_DEVICE_GETSTATE:
3827		ASSERT(cdip != NULL);
3828		ASSERT(dcp != NULL);
3829		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3830			*rval = EFAULT;
3831		}
3832		break;
3833
3834	case DEVCTL_DEVICE_REMOVE:
3835	case DEVCTL_DEVICE_OFFLINE: {
3836		int			flag = 0;
3837		int			lcount;
3838		int			tcount;
3839		struct fcp_pkt	*head = NULL;
3840		struct fcp_lun	*plun;
3841		child_info_t		*cip = CIP(cdip);
3842		int			all = 1;
3843		struct fcp_lun	*tplun;
3844		struct fcp_tgt	*ptgt;
3845
3846		ASSERT(pptr != NULL);
3847		ASSERT(cdip != NULL);
3848
3849		mutex_enter(&pptr->port_mutex);
3850		if (pip != NULL) {
3851			cip = CIP(pip);
3852		}
3853		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3854			mutex_exit(&pptr->port_mutex);
3855			*rval = ENXIO;
3856			break;
3857		}
3858
3859		head = fcp_scan_commands(plun);
3860		if (head != NULL) {
3861			fcp_abort_commands(head, LUN_PORT);
3862		}
3863		lcount = pptr->port_link_cnt;
3864		tcount = plun->lun_tgt->tgt_change_cnt;
3865		mutex_exit(&pptr->port_mutex);
3866
3867		if (cmd == DEVCTL_DEVICE_REMOVE) {
3868			flag = NDI_DEVI_REMOVE;
3869		}
3870
3871		if (is_mpxio) {
3872			mdi_devi_exit(pptr->port_dip, circ);
3873		} else {
3874			ndi_devi_exit(pptr->port_dip, circ);
3875		}
3876		devi_entered = 0;
3877
3878		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3879		    FCP_OFFLINE, lcount, tcount, flag);
3880
3881		if (*rval != NDI_SUCCESS) {
3882			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3883			break;
3884		}
3885
3886		fcp_update_offline_flags(plun);
3887
3888		ptgt = plun->lun_tgt;
3889		mutex_enter(&ptgt->tgt_mutex);
3890		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3891		    tplun->lun_next) {
3892			mutex_enter(&tplun->lun_mutex);
3893			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3894				all = 0;
3895			}
3896			mutex_exit(&tplun->lun_mutex);
3897		}
3898
3899		if (all) {
3900			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3901			/*
3902			 * The user is unconfiguring/offlining the device.
3903			 * If fabric and the auto configuration is set
3904			 * then make sure the user is the only one who
3905			 * can reconfigure the device.
3906			 */
3907			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3908			    fcp_enable_auto_configuration) {
3909				ptgt->tgt_manual_config_only = 1;
3910			}
3911		}
3912		mutex_exit(&ptgt->tgt_mutex);
3913		break;
3914	}
3915
3916	case DEVCTL_DEVICE_ONLINE: {
3917		int			lcount;
3918		int			tcount;
3919		struct fcp_lun	*plun;
3920		child_info_t		*cip = CIP(cdip);
3921
3922		ASSERT(cdip != NULL);
3923		ASSERT(pptr != NULL);
3924
3925		mutex_enter(&pptr->port_mutex);
3926		if (pip != NULL) {
3927			cip = CIP(pip);
3928		}
3929		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3930			mutex_exit(&pptr->port_mutex);
3931			*rval = ENXIO;
3932			break;
3933		}
3934		lcount = pptr->port_link_cnt;
3935		tcount = plun->lun_tgt->tgt_change_cnt;
3936		mutex_exit(&pptr->port_mutex);
3937
3938		/*
3939		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3940		 * to allow the device attach to occur when the device is
3941		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3942		 * from the scsi_probe()).
3943		 */
3944		mutex_enter(&LUN_TGT->tgt_mutex);
3945		plun->lun_state |= FCP_LUN_ONLINING;
3946		mutex_exit(&LUN_TGT->tgt_mutex);
3947
3948		if (is_mpxio) {
3949			mdi_devi_exit(pptr->port_dip, circ);
3950		} else {
3951			ndi_devi_exit(pptr->port_dip, circ);
3952		}
3953		devi_entered = 0;
3954
3955		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3956		    FCP_ONLINE, lcount, tcount, 0);
3957
3958		if (*rval != NDI_SUCCESS) {
3959			/* Reset the FCP_LUN_ONLINING bit */
3960			mutex_enter(&LUN_TGT->tgt_mutex);
3961			plun->lun_state &= ~FCP_LUN_ONLINING;
3962			mutex_exit(&LUN_TGT->tgt_mutex);
3963			*rval = EIO;
3964			break;
3965		}
3966		mutex_enter(&LUN_TGT->tgt_mutex);
3967		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3968		    FCP_LUN_ONLINING);
3969		mutex_exit(&LUN_TGT->tgt_mutex);
3970		break;
3971	}
3972
3973	case DEVCTL_BUS_DEV_CREATE: {
3974		uchar_t			*bytes = NULL;
3975		uint_t			nbytes;
3976		struct fcp_tgt		*ptgt = NULL;
3977		struct fcp_lun		*plun = NULL;
3978		dev_info_t		*useless_dip = NULL;
3979
3980		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3981		    DEVCTL_CONSTRUCT, &useless_dip);
3982		if (*rval != 0 || useless_dip == NULL) {
3983			break;
3984		}
3985
3986		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3987		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3988		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3989			*rval = EINVAL;
3990			(void) ndi_devi_free(useless_dip);
3991			if (bytes != NULL) {
3992				ddi_prop_free(bytes);
3993			}
3994			break;
3995		}
3996
3997		*rval = fcp_create_on_demand(pptr, bytes);
3998		if (*rval == 0) {
3999			mutex_enter(&pptr->port_mutex);
4000			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4001			if (ptgt) {
4002				/*
4003				 * We now have a pointer to the target that
4004				 * was created. Lets point to the first LUN on
4005				 * this new target.
4006				 */
4007				mutex_enter(&ptgt->tgt_mutex);
4008
4009				plun = ptgt->tgt_lun;
4010				/*
4011				 * There may be stale/offline LUN entries on
4012				 * this list (this is by design) and so we have
4013				 * to make sure we point to the first online
4014				 * LUN
4015				 */
4016				while (plun &&
4017				    plun->lun_state & FCP_LUN_OFFLINE) {
4018					plun = plun->lun_next;
4019				}
4020
4021				mutex_exit(&ptgt->tgt_mutex);
4022			}
4023			mutex_exit(&pptr->port_mutex);
4024		}
4025
4026		if (*rval == 0 && ptgt && plun) {
4027			mutex_enter(&plun->lun_mutex);
4028			/*
4029			 * Allow up to fcp_lun_ready_retry seconds to
4030			 * configure all the luns behind the target.
4031			 *
4032			 * The intent here is to allow targets with long
4033			 * reboot/reset-recovery times to become available
4034			 * while limiting the maximum wait time for an
4035			 * unresponsive target.
4036			 */
4037			end_time = ddi_get_lbolt() +
4038			    SEC_TO_TICK(fcp_lun_ready_retry);
4039
4040			while (ddi_get_lbolt() < end_time) {
4041				retval = FC_SUCCESS;
4042
4043				/*
4044				 * The new ndi interfaces for on-demand creation
4045				 * are inflexible, Do some more work to pass on
4046				 * a path name of some LUN (design is broken !)
4047				 */
4048				if (plun->lun_cip) {
4049					if (plun->lun_mpxio == 0) {
4050						cdip = DIP(plun->lun_cip);
4051					} else {
4052						cdip = mdi_pi_get_client(
4053						    PIP(plun->lun_cip));
4054					}
4055					if (cdip == NULL) {
4056						*rval = ENXIO;
4057						break;
4058					}
4059
4060					if (!i_ddi_devi_attached(cdip)) {
4061						mutex_exit(&plun->lun_mutex);
4062						delay(drv_usectohz(1000000));
4063						mutex_enter(&plun->lun_mutex);
4064					} else {
4065						/*
4066						 * This Lun is ready, lets
4067						 * check the next one.
4068						 */
4069						mutex_exit(&plun->lun_mutex);
4070						plun = plun->lun_next;
4071						while (plun && (plun->lun_state
4072						    & FCP_LUN_OFFLINE)) {
4073							plun = plun->lun_next;
4074						}
4075						if (!plun) {
4076							break;
4077						}
4078						mutex_enter(&plun->lun_mutex);
4079					}
4080				} else {
4081					/*
4082					 * lun_cip field for a valid lun
4083					 * should never be NULL. Fail the
4084					 * command.
4085					 */
4086					*rval = ENXIO;
4087					break;
4088				}
4089			}
4090			if (plun) {
4091				mutex_exit(&plun->lun_mutex);
4092			} else {
4093				char devnm[MAXNAMELEN];
4094				int nmlen;
4095
4096				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4097				    ddi_node_name(cdip),
4098				    ddi_get_name_addr(cdip));
4099
4100				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4101				    0) {
4102					*rval = EFAULT;
4103				}
4104			}
4105		} else {
4106			int	i;
4107			char	buf[25];
4108
4109			for (i = 0; i < FC_WWN_SIZE; i++) {
4110				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4111			}
4112
4113			fcp_log(CE_WARN, pptr->port_dip,
4114			    "!Failed to create nodes for pwwn=%s; error=%x",
4115			    buf, *rval);
4116		}
4117
4118		(void) ndi_devi_free(useless_dip);
4119		ddi_prop_free(bytes);
4120		break;
4121	}
4122
4123	case DEVCTL_DEVICE_RESET: {
4124		struct fcp_lun		*plun;
4125		child_info_t		*cip = CIP(cdip);
4126
4127		ASSERT(cdip != NULL);
4128		ASSERT(pptr != NULL);
4129		mutex_enter(&pptr->port_mutex);
4130		if (pip != NULL) {
4131			cip = CIP(pip);
4132		}
4133		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4134			mutex_exit(&pptr->port_mutex);
4135			*rval = ENXIO;
4136			break;
4137		}
4138		mutex_exit(&pptr->port_mutex);
4139
4140		mutex_enter(&plun->lun_tgt->tgt_mutex);
4141		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4142			mutex_exit(&plun->lun_tgt->tgt_mutex);
4143
4144			*rval = ENXIO;
4145			break;
4146		}
4147
4148		if (plun->lun_sd == NULL) {
4149			mutex_exit(&plun->lun_tgt->tgt_mutex);
4150
4151			*rval = ENXIO;
4152			break;
4153		}
4154		mutex_exit(&plun->lun_tgt->tgt_mutex);
4155
4156		/*
4157		 * set up ap so that fcp_reset can figure out
4158		 * which target to reset
4159		 */
4160		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4161		    RESET_TARGET) == FALSE) {
4162			*rval = EIO;
4163		}
4164		break;
4165	}
4166
4167	case DEVCTL_BUS_GETSTATE:
4168		ASSERT(dcp != NULL);
4169		ASSERT(pptr != NULL);
4170		ASSERT(pptr->port_dip != NULL);
4171		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4172		    NDI_SUCCESS) {
4173			*rval = EFAULT;
4174		}
4175		break;
4176
4177	case DEVCTL_BUS_QUIESCE:
4178	case DEVCTL_BUS_UNQUIESCE:
4179		*rval = ENOTSUP;
4180		break;
4181
4182	case DEVCTL_BUS_RESET:
4183	case DEVCTL_BUS_RESETALL:
4184		ASSERT(pptr != NULL);
4185		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4186		break;
4187
4188	default:
4189		ASSERT(dcp != NULL);
4190		*rval = ENOTTY;
4191		break;
4192	}
4193
4194	/* all done -- clean up and return */
4195out:	if (devi_entered) {
4196		if (is_mpxio) {
4197			mdi_devi_exit(pptr->port_dip, circ);
4198		} else {
4199			ndi_devi_exit(pptr->port_dip, circ);
4200		}
4201	}
4202
4203	if (dcp != NULL) {
4204		ndi_dc_freehdl(dcp);
4205	}
4206
4207	return (retval);
4208}
4209
4210
4211/*ARGSUSED*/
4212static int
4213fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4214    uint32_t claimed)
4215{
4216	uchar_t			r_ctl;
4217	uchar_t			ls_code;
4218	struct fcp_port	*pptr;
4219
4220	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4221		return (FC_UNCLAIMED);
4222	}
4223
4224	mutex_enter(&pptr->port_mutex);
4225	if (pptr->port_state & (FCP_STATE_DETACHING |
4226	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4227		mutex_exit(&pptr->port_mutex);
4228		return (FC_UNCLAIMED);
4229	}
4230	mutex_exit(&pptr->port_mutex);
4231
4232	r_ctl = buf->ub_frame.r_ctl;
4233
4234	switch (r_ctl & R_CTL_ROUTING) {
4235	case R_CTL_EXTENDED_SVC:
4236		if (r_ctl == R_CTL_ELS_REQ) {
4237			ls_code = buf->ub_buffer[0];
4238
4239			switch (ls_code) {
4240			case LA_ELS_PRLI:
4241				/*
4242				 * We really don't care if something fails.
4243				 * If the PRLI was not sent out, then the
4244				 * other end will time it out.
4245				 */
4246				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4247					return (FC_SUCCESS);
4248				}
4249				return (FC_UNCLAIMED);
4250				/* NOTREACHED */
4251
4252			default:
4253				break;
4254			}
4255		}
4256		/* FALLTHROUGH */
4257
4258	default:
4259		return (FC_UNCLAIMED);
4260	}
4261}
4262
4263
4264/*ARGSUSED*/
4265static int
4266fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4267    uint32_t claimed)
4268{
4269	return (FC_UNCLAIMED);
4270}
4271
4272/*
4273 *     Function: fcp_statec_callback
4274 *
4275 *  Description: The purpose of this function is to handle a port state change.
4276 *		 It is called from fp/fctl and, in a few instances, internally.
4277 *
4278 *     Argument: ulph		fp/fctl port handle
4279 *		 port_handle	fcp_port structure
4280 *		 port_state	Physical state of the port
4281 *		 port_top	Topology
4282 *		 *devlist	Pointer to the first entry of a table
4283 *				containing the remote ports that can be
4284 *				reached.
4285 *		 dev_cnt	Number of entries pointed by devlist.
4286 *		 port_sid	Port ID of the local port.
4287 *
4288 * Return Value: None
4289 */
4290/*ARGSUSED*/
4291static void
4292fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4293    uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4294    uint32_t dev_cnt, uint32_t port_sid)
4295{
4296	uint32_t		link_count;
4297	int			map_len = 0;
4298	struct fcp_port	*pptr;
4299	fcp_map_tag_t		*map_tag = NULL;
4300
4301	if ((pptr = fcp_get_port(port_handle)) == NULL) {
4302		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4303		return;			/* nothing to work with! */
4304	}
4305
4306	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4307	    fcp_trace, FCP_BUF_LEVEL_2, 0,
4308	    "fcp_statec_callback: port state/dev_cnt/top ="
4309	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4310	    dev_cnt, port_top);
4311
4312	mutex_enter(&pptr->port_mutex);
4313
4314	/*
4315	 * If a thread is in detach, don't do anything.
4316	 */
4317	if (pptr->port_state & (FCP_STATE_DETACHING |
4318	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4319		mutex_exit(&pptr->port_mutex);
4320		return;
4321	}
4322
4323	/*
4324	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4325	 * init_pkt is called, it knows whether or not the target's status
4326	 * (or pd) might be changing.
4327	 */
4328
4329	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4330		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4331	}
4332
4333	/*
4334	 * the transport doesn't allocate or probe unless being
4335	 * asked to by either the applications or ULPs
4336	 *
4337	 * in cases where the port is OFFLINE at the time of port
4338	 * attach callback and the link comes ONLINE later, for
4339	 * easier automatic node creation (i.e. without you having to
4340	 * go out and run the utility to perform LOGINs) the
4341	 * following conditional is helpful
4342	 */
4343	pptr->port_phys_state = port_state;
4344
4345	if (dev_cnt) {
4346		mutex_exit(&pptr->port_mutex);
4347
4348		map_len = sizeof (*map_tag) * dev_cnt;
4349		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4350		if (map_tag == NULL) {
4351			fcp_log(CE_WARN, pptr->port_dip,
4352			    "!fcp%d: failed to allocate for map tags; "
4353			    " state change will not be processed",
4354			    pptr->port_instance);
4355
4356			mutex_enter(&pptr->port_mutex);
4357			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4358			mutex_exit(&pptr->port_mutex);
4359
4360			return;
4361		}
4362
4363		mutex_enter(&pptr->port_mutex);
4364	}
4365
4366	if (pptr->port_id != port_sid) {
4367		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4368		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4369		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4370		    port_sid);
4371		/*
4372		 * The local port changed ID. It is the first time a port ID
4373		 * is assigned or something drastic happened.  We might have
4374		 * been unplugged and replugged on another loop or fabric port
4375		 * or somebody grabbed the AL_PA we had or somebody rezoned
4376		 * the fabric we were plugged into.
4377		 */
4378		pptr->port_id = port_sid;
4379	}
4380
4381	switch (FC_PORT_STATE_MASK(port_state)) {
4382	case FC_STATE_OFFLINE:
4383	case FC_STATE_RESET_REQUESTED:
4384		/*
4385		 * link has gone from online to offline -- just update the
4386		 * state of this port to BUSY and MARKed to go offline
4387		 */
4388		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4389		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4390		    "link went offline");
4391		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4392			/*
4393			 * We were offline a while ago and this one
4394			 * seems to indicate that the loop has gone
4395			 * dead forever.
4396			 */
4397			pptr->port_tmp_cnt += dev_cnt;
4398			pptr->port_state &= ~FCP_STATE_OFFLINE;
4399			pptr->port_state |= FCP_STATE_INIT;
4400			link_count = pptr->port_link_cnt;
4401			fcp_handle_devices(pptr, devlist, dev_cnt,
4402			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4403		} else {
4404			pptr->port_link_cnt++;
4405			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4406			fcp_update_state(pptr, (FCP_LUN_BUSY |
4407			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4408			if (pptr->port_mpxio) {
4409				fcp_update_mpxio_path_verifybusy(pptr);
4410			}
4411			pptr->port_state |= FCP_STATE_OFFLINE;
4412			pptr->port_state &=
4413			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4414			pptr->port_tmp_cnt = 0;
4415		}
4416		mutex_exit(&pptr->port_mutex);
4417		break;
4418
4419	case FC_STATE_ONLINE:
4420	case FC_STATE_LIP:
4421	case FC_STATE_LIP_LBIT_SET:
4422		/*
4423		 * link has gone from offline to online
4424		 */
4425		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4426		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4427		    "link went online");
4428
4429		pptr->port_link_cnt++;
4430
4431		while (pptr->port_ipkt_cnt) {
4432			mutex_exit(&pptr->port_mutex);
4433			delay(drv_usectohz(1000000));
4434			mutex_enter(&pptr->port_mutex);
4435		}
4436
4437		pptr->port_topology = port_top;
4438
4439		/*
4440		 * The state of the targets and luns accessible through this
4441		 * port is updated.
4442		 */
4443		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4444		    FCP_CAUSE_LINK_CHANGE);
4445
4446		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4447		pptr->port_state |= FCP_STATE_ONLINING;
4448		pptr->port_tmp_cnt = dev_cnt;
4449		link_count = pptr->port_link_cnt;
4450
4451		pptr->port_deadline = fcp_watchdog_time +
4452		    FCP_ICMD_DEADLINE;
4453
4454		if (!dev_cnt) {
4455			/*
4456			 * We go directly to the online state if no remote
4457			 * ports were discovered.
4458			 */
4459			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4460			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4461			    "No remote ports discovered");
4462
4463			pptr->port_state &= ~FCP_STATE_ONLINING;
4464			pptr->port_state |= FCP_STATE_ONLINE;
4465		}
4466
4467		switch (port_top) {
4468		case FC_TOP_FABRIC:
4469		case FC_TOP_PUBLIC_LOOP:
4470		case FC_TOP_PRIVATE_LOOP:
4471		case FC_TOP_PT_PT:
4472
4473			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4474				fcp_retry_ns_registry(pptr, port_sid);
4475			}
4476
4477			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4478			    map_tag, FCP_CAUSE_LINK_CHANGE);
4479			break;
4480
4481		default:
4482			/*
4483			 * We got here because we were provided with an unknown
4484			 * topology.
4485			 */
4486			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4487				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4488			}
4489
4490			pptr->port_tmp_cnt -= dev_cnt;
4491			fcp_log(CE_WARN, pptr->port_dip,
4492			    "!unknown/unsupported topology (0x%x)", port_top);
4493			break;
4494		}
4495		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4496		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4497		    "Notify ssd of the reset to reinstate the reservations");
4498
4499		scsi_hba_reset_notify_callback(&pptr->port_mutex,
4500		    &pptr->port_reset_notify_listf);
4501
4502		mutex_exit(&pptr->port_mutex);
4503
4504		break;
4505
4506	case FC_STATE_RESET:
4507		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4508		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4509		    fcp_trace, FCP_BUF_LEVEL_3, 0,
4510		    "RESET state, waiting for Offline/Online state_cb");
4511		mutex_exit(&pptr->port_mutex);
4512		break;
4513
4514	case FC_STATE_DEVICE_CHANGE:
4515		/*
4516		 * We come here when an application has requested
4517		 * Dynamic node creation/deletion in Fabric connectivity.
4518		 */
4519		if (pptr->port_state & (FCP_STATE_OFFLINE |
4520		    FCP_STATE_INIT)) {
4521			/*
4522			 * This case can happen when the FCTL is in the
4523			 * process of giving us on online and the host on
4524			 * the other side issues a PLOGI/PLOGO. Ideally
4525			 * the state changes should be serialized unless
4526			 * they are opposite (online-offline).
4527			 * The transport will give us a final state change
4528			 * so we can ignore this for the time being.
4529			 */
4530			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4531			mutex_exit(&pptr->port_mutex);
4532			break;
4533		}
4534
4535		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4536			fcp_retry_ns_registry(pptr, port_sid);
4537		}
4538
4539		/*
4540		 * Extend the deadline under steady state conditions
4541		 * to provide more time for the device-change-commands
4542		 */
4543		if (!pptr->port_ipkt_cnt) {
4544			pptr->port_deadline = fcp_watchdog_time +
4545			    FCP_ICMD_DEADLINE;
4546		}
4547
4548		/*
4549		 * There is another race condition here, where if we were
4550		 * in ONLINEING state and a devices in the map logs out,
4551		 * fp will give another state change as DEVICE_CHANGE
4552		 * and OLD. This will result in that target being offlined.
4553		 * The pd_handle is freed. If from the first statec callback
4554		 * we were going to fire a PLOGI/PRLI, the system will
4555		 * panic in fc_ulp_transport with invalid pd_handle.
4556		 * The fix is to check for the link_cnt before issuing
4557		 * any command down.
4558		 */
4559		fcp_update_targets(pptr, devlist, dev_cnt,
4560		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4561
4562		link_count = pptr->port_link_cnt;
4563
4564		fcp_handle_devices(pptr, devlist, dev_cnt,
4565		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4566
4567		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4568
4569		mutex_exit(&pptr->port_mutex);
4570		break;
4571
4572	case FC_STATE_TARGET_PORT_RESET:
4573		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4574			fcp_retry_ns_registry(pptr, port_sid);
4575		}
4576
4577		/* Do nothing else */
4578		mutex_exit(&pptr->port_mutex);
4579		break;
4580
4581	default:
4582		fcp_log(CE_WARN, pptr->port_dip,
4583		    "!Invalid state change=0x%x", port_state);
4584		mutex_exit(&pptr->port_mutex);
4585		break;
4586	}
4587
4588	if (map_tag) {
4589		kmem_free(map_tag, map_len);
4590	}
4591}
4592
4593/*
4594 *     Function: fcp_handle_devices
4595 *
4596 *  Description: This function updates the devices currently known by
4597 *		 walking the list provided by the caller.  The list passed
4598 *		 by the caller is supposed to be the list of reachable
4599 *		 devices.
4600 *
4601 *     Argument: *pptr		Fcp port structure.
4602 *		 *devlist	Pointer to the first entry of a table
4603 *				containing the remote ports that can be
4604 *				reached.
4605 *		 dev_cnt	Number of entries pointed by devlist.
4606 *		 link_cnt	Link state count.
4607 *		 *map_tag	Array of fcp_map_tag_t structures.
4608 *		 cause		What caused this function to be called.
4609 *
4610 * Return Value: None
4611 *
4612 *	  Notes: The pptr->port_mutex must be held.
4613 */
4614static void
4615fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4616    uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4617{
4618	int			i;
4619	int			check_finish_init = 0;
4620	fc_portmap_t		*map_entry;
4621	struct fcp_tgt	*ptgt = NULL;
4622
4623	FCP_TRACE(fcp_logq, pptr->port_instbuf,
4624	    fcp_trace, FCP_BUF_LEVEL_3, 0,
4625	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4626
4627	if (dev_cnt) {
4628		ASSERT(map_tag != NULL);
4629	}
4630
4631	/*
4632	 * The following code goes through the list of remote ports that are
4633	 * accessible through this (pptr) local port (The list walked is the
4634	 * one provided by the caller which is the list of the remote ports
4635	 * currently reachable).  It checks if any of them was already
4636	 * known by looking for the corresponding target structure based on
4637	 * the world wide name.	 If a target is part of the list it is tagged
4638	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4639	 *
4640	 * Old comment
4641	 * -----------
4642	 * Before we drop port mutex; we MUST get the tags updated; This
4643	 * two step process is somewhat slow, but more reliable.
4644	 */
4645	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4646		map_entry = &(devlist[i]);
4647
4648		/*
4649		 * get ptr to this map entry in our port's
4650		 * list (if any)
4651		 */
4652		ptgt = fcp_lookup_target(pptr,
4653		    (uchar_t *)&(map_entry->map_pwwn));
4654
4655		if (ptgt) {
4656			map_tag[i] = ptgt->tgt_change_cnt;
4657			if (cause == FCP_CAUSE_LINK_CHANGE) {
4658				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4659			}
4660		}
4661	}
4662
4663	/*
4664	 * At this point we know which devices of the new list were already
4665	 * known (The field tgt_aux_state of the target structure has been
4666	 * set to FCP_TGT_TAGGED).
4667	 *
4668	 * The following code goes through the list of targets currently known
4669	 * by the local port (the list is actually a hashing table).  If a
4670	 * target is found and is not tagged, it means the target cannot
4671	 * be reached anymore through the local port (pptr).  It is offlined.
4672	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4673	 */
4674	for (i = 0; i < FCP_NUM_HASH; i++) {
4675		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4676		    ptgt = ptgt->tgt_next) {
4677			mutex_enter(&ptgt->tgt_mutex);
4678			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4679			    (cause == FCP_CAUSE_LINK_CHANGE) &&
4680			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4681				fcp_offline_target_now(pptr, ptgt,
4682				    link_cnt, ptgt->tgt_change_cnt, 0);
4683			}
4684			mutex_exit(&ptgt->tgt_mutex);
4685		}
4686	}
4687
4688	/*
4689	 * At this point, the devices that were known but cannot be reached
4690	 * anymore, have most likely been offlined.
4691	 *
4692	 * The following section of code seems to go through the list of
4693	 * remote ports that can now be reached.  For every single one it
4694	 * checks if it is already known or if it is a new port.
4695	 */
4696	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4697
4698		if (check_finish_init) {
4699			ASSERT(i > 0);
4700			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4701			    map_tag[i - 1], cause);
4702			check_finish_init = 0;
4703		}
4704
4705		/* get a pointer to this map entry */
4706		map_entry = &(devlist[i]);
4707
4708		/*
4709		 * Check for the duplicate map entry flag. If we have marked
4710		 * this entry as a duplicate we skip it since the correct
4711		 * (perhaps even same) state change will be encountered
4712		 * later in the list.
4713		 */
4714		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4715			continue;
4716		}
4717
4718		/* get ptr to this map entry in our port's list (if any) */
4719		ptgt = fcp_lookup_target(pptr,
4720		    (uchar_t *)&(map_entry->map_pwwn));
4721
4722		if (ptgt) {
4723			/*
4724			 * This device was already known.  The field
4725			 * tgt_aux_state is reset (was probably set to
4726			 * FCP_TGT_TAGGED previously in this routine).
4727			 */
4728			ptgt->tgt_aux_state = 0;
4729			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4730			    fcp_trace, FCP_BUF_LEVEL_3, 0,
4731			    "handle_devices: map did/state/type/flags = "
4732			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4733			    "tgt_state=%d",
4734			    map_entry->map_did.port_id, map_entry->map_state,
4735			    map_entry->map_type, map_entry->map_flags,
4736			    ptgt->tgt_d_id, ptgt->tgt_state);
4737		}
4738
4739		if (map_entry->map_type == PORT_DEVICE_OLD ||
4740		    map_entry->map_type == PORT_DEVICE_NEW ||
4741		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4742		    map_entry->map_type == PORT_DEVICE_CHANGED) {
4743			FCP_TRACE(fcp_logq, pptr->port_instbuf,
4744			    fcp_trace, FCP_BUF_LEVEL_2, 0,
4745			    "map_type=%x, did = %x",
4746			    map_entry->map_type,
4747			    map_entry->map_did.port_id);
4748		}
4749
4750		switch (map_entry->map_type) {
4751		case PORT_DEVICE_NOCHANGE:
4752		case PORT_DEVICE_USER_CREATE:
4753		case PORT_DEVICE_USER_LOGIN:
4754		case PORT_DEVICE_NEW:
4755		case PORT_DEVICE_REPORTLUN_CHANGED:
4756			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4757
4758			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4759			    link_cnt, (ptgt) ? map_tag[i] : 0,
4760			    cause) == TRUE) {
4761
4762				FCP_TGT_TRACE(ptgt, map_tag[i],
4763				    FCP_TGT_TRACE_2);
4764				check_finish_init++;
4765			}
4766			break;
4767
4768		case PORT_DEVICE_OLD:
4769			if (ptgt != NULL) {
4770				FCP_TGT_TRACE(ptgt, map_tag[i],
4771				    FCP_TGT_TRACE_3);
4772
4773				mutex_enter(&ptgt->tgt_mutex);
4774				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4775					/*
4776					 * Must do an in-line wait for I/Os
4777					 * to get drained
4778					 */
4779					mutex_exit(&ptgt->tgt_mutex);
4780					mutex_exit(&pptr->port_mutex);
4781
4782					mutex_enter(&ptgt->tgt_mutex);
4783					while (ptgt->tgt_ipkt_cnt ||
4784					    fcp_outstanding_lun_cmds(ptgt)
4785					    == FC_SUCCESS) {
4786						mutex_exit(&ptgt->tgt_mutex);
4787						delay(drv_usectohz(1000000));
4788						mutex_enter(&ptgt->tgt_mutex);
4789					}
4790					mutex_exit(&ptgt->tgt_mutex);
4791
4792					mutex_enter(&pptr->port_mutex);
4793					mutex_enter(&ptgt->tgt_mutex);
4794
4795					(void) fcp_offline_target(pptr, ptgt,
4796					    link_cnt, map_tag[i], 0, 0);
4797				}
4798				mutex_exit(&ptgt->tgt_mutex);
4799			}
4800			check_finish_init++;
4801			break;
4802
4803		case PORT_DEVICE_USER_DELETE:
4804		case PORT_DEVICE_USER_LOGOUT:
4805			if (ptgt != NULL) {
4806				FCP_TGT_TRACE(ptgt, map_tag[i],
4807				    FCP_TGT_TRACE_4);
4808
4809				mutex_enter(&ptgt->tgt_mutex);
4810				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4811					(void) fcp_offline_target(pptr, ptgt,
4812					    link_cnt, map_tag[i], 1, 0);
4813				}
4814				mutex_exit(&ptgt->tgt_mutex);
4815			}
4816			check_finish_init++;
4817			break;
4818
4819		case PORT_DEVICE_CHANGED:
4820			if (ptgt != NULL) {
4821				FCP_TGT_TRACE(ptgt, map_tag[i],
4822				    FCP_TGT_TRACE_5);
4823
4824				if (fcp_device_changed(pptr, ptgt,
4825				    map_entry, link_cnt, map_tag[i],
4826				    cause) == TRUE) {
4827					check_finish_init++;
4828				}
4829			} else {
4830				if (fcp_handle_mapflags(pptr, ptgt,
4831				    map_entry, link_cnt, 0, cause) == TRUE) {
4832					check_finish_init++;
4833				}
4834			}
4835			break;
4836
4837		default:
4838			fcp_log(CE_WARN, pptr->port_dip,
4839			    "!Invalid map_type=0x%x", map_entry->map_type);
4840			check_finish_init++;
4841			break;
4842		}
4843	}
4844
4845	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4846		ASSERT(i > 0);
4847		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4848		    map_tag[i-1], cause);
4849	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4850		fcp_offline_all(pptr, link_cnt, cause);
4851	}
4852}
4853
4854static int
4855fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4856{
4857	struct fcp_lun	*plun;
4858	struct fcp_port *pptr;
4859	int		 rscn_count;
4860	int		 lun0_newalloc;
4861	int		 ret  = TRUE;
4862
4863	ASSERT(ptgt);
4864	pptr = ptgt->tgt_port;
4865	lun0_newalloc = 0;
4866	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4867		/*
4868		 * no LUN struct for LUN 0 yet exists,
4869		 * so create one
4870		 */
4871		plun = fcp_alloc_lun(ptgt);
4872		if (plun == NULL) {
4873			fcp_log(CE_WARN, pptr->port_dip,
4874			    "!Failed to allocate lun 0 for"
4875			    " D_ID=%x", ptgt->tgt_d_id);
4876			return (ret);
4877		}
4878		lun0_newalloc = 1;
4879	}
4880
4881	mutex_enter(&ptgt->tgt_mutex);
4882	/*
4883	 * consider lun 0 as device not connected if it is
4884	 * offlined or newly allocated
4885	 */
4886	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4887		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4888	}
4889	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4890	plun->lun_state &= ~FCP_LUN_OFFLINE;
4891	ptgt->tgt_lun_cnt = 1;
4892	ptgt->tgt_report_lun_cnt = 0;
4893	mutex_exit(&ptgt->tgt_mutex);
4894
4895	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4896	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4897	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4898	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4899		FCP_TRACE(fcp_logq, pptr->port_instbuf,
4900		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4901		    "to D_ID=%x", ptgt->tgt_d_id);
4902	} else {
4903		ret = FALSE;
4904	}
4905
4906	return (ret);
4907}
4908
4909/*
4910 *     Function: fcp_handle_mapflags
4911 *
4912 *  Description: This function creates a target structure if the ptgt passed
4913 *		 is NULL.  It also kicks off the PLOGI if we are not logged
4914 *		 into the target yet or the PRLI if we are logged into the
4915 *		 target already.  The rest of the treatment is done in the
4916 *		 callbacks of the PLOGI or PRLI.
4917 *
4918 *     Argument: *pptr		FCP Port structure.
4919 *		 *ptgt		Target structure.
4920 *		 *map_entry	Array of fc_portmap_t structures.
4921 *		 link_cnt	Link state count.
4922 *		 tgt_cnt	Target state count.
4923 *		 cause		What caused this function to be called.
4924 *
4925 * Return Value: TRUE	Failed
4926 *		 FALSE	Succeeded
4927 *
4928 *	  Notes: pptr->port_mutex must be owned.
4929 */
4930static int
4931fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
4932    fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4933{
4934	int			lcount;
4935	int			tcount;
4936	int			ret = TRUE;
4937	int			alloc;
4938	struct fcp_ipkt	*icmd;
4939	struct fcp_lun	*pseq_lun = NULL;
4940	uchar_t			opcode;
4941	int			valid_ptgt_was_passed = FALSE;
4942
4943	ASSERT(mutex_owned(&pptr->port_mutex));
4944
4945	/*
4946	 * This case is possible where the FCTL has come up and done discovery
4947	 * before FCP was loaded and attached. FCTL would have discovered the
4948	 * devices and later the ULP came online. In this case ULP's would get
4949	 * PORT_DEVICE_NOCHANGE but target would be NULL.
4950	 */
4951	if (ptgt == NULL) {
4952		/* don't already have a target */
4953		mutex_exit(&pptr->port_mutex);
4954		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4955		mutex_enter(&pptr->port_mutex);
4956
4957		if (ptgt == NULL) {
4958			fcp_log(CE_WARN, pptr->port_dip,
4959			    "!FC target allocation failed");
4960			return (ret);
4961		}
4962		mutex_enter(&ptgt->tgt_mutex);
4963		ptgt->tgt_statec_cause = cause;
4964		ptgt->tgt_tmp_cnt = 1;
4965		mutex_exit(&ptgt->tgt_mutex);
4966	} else {
4967		valid_ptgt_was_passed = TRUE;
4968	}
4969
4970	/*
4971	 * Copy in the target parameters
4972	 */
4973	mutex_enter(&ptgt->tgt_mutex);
4974	ptgt->tgt_d_id = map_entry->map_did.port_id;
4975	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4976	ptgt->tgt_pd_handle = map_entry->map_pd;
4977	ptgt->tgt_fca_dev = NULL;
4978
4979	/* Copy port and node WWNs */
4980	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4981	    FC_WWN_SIZE);
4982	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4983	    FC_WWN_SIZE);
4984
4985	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4986	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4987	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4988	    valid_ptgt_was_passed) {
4989		/*
4990		 * determine if there are any tape LUNs on this target
4991		 */
4992		for (pseq_lun = ptgt->tgt_lun;
4993		    pseq_lun != NULL;
4994		    pseq_lun = pseq_lun->lun_next) {
4995			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4996			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4997				fcp_update_tgt_state(ptgt, FCP_RESET,
4998				    FCP_LUN_MARK);
4999				mutex_exit(&ptgt->tgt_mutex);
5000				return (ret);
5001			}
5002		}
5003	}
5004
5005	/*
5006	 * if UA'REPORT_LUN_CHANGED received,
5007	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
5008	 */
5009	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5010		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5011		mutex_exit(&ptgt->tgt_mutex);
5012		mutex_exit(&pptr->port_mutex);
5013
5014		ret = fcp_handle_reportlun_changed(ptgt, cause);
5015
5016		mutex_enter(&pptr->port_mutex);
5017		return (ret);
5018	}
5019
5020	/*
5021	 * If ptgt was NULL when this function was entered, then tgt_node_state
5022	 * was never specifically initialized but zeroed out which means
5023	 * FCP_TGT_NODE_NONE.
5024	 */
5025	switch (ptgt->tgt_node_state) {
5026	case FCP_TGT_NODE_NONE:
5027	case FCP_TGT_NODE_ON_DEMAND:
5028		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5029		    !fcp_enable_auto_configuration &&
5030		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5031			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5032		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5033		    fcp_enable_auto_configuration &&
5034		    (ptgt->tgt_manual_config_only == 1) &&
5035		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5036			/*
5037			 * If auto configuration is set and
5038			 * the tgt_manual_config_only flag is set then
5039			 * we only want the user to be able to change
5040			 * the state through create_on_demand.
5041			 */
5042			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5043		} else {
5044			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5045		}
5046		break;
5047
5048	case FCP_TGT_NODE_PRESENT:
5049		break;
5050	}
5051	/*
5052	 * If we are booting from a fabric device, make sure we
5053	 * mark the node state appropriately for this target to be
5054	 * enumerated
5055	 */
5056	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5057		if (bcmp((caddr_t)pptr->port_boot_wwn,
5058		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5059		    sizeof (ptgt->tgt_port_wwn)) == 0) {
5060			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5061		}
5062	}
5063	mutex_exit(&ptgt->tgt_mutex);
5064
5065	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5066	    fcp_trace, FCP_BUF_LEVEL_3, 0,
5067	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5068	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5069	    map_entry->map_rscn_info.ulp_rscn_count);
5070
5071	mutex_enter(&ptgt->tgt_mutex);
5072
5073	/*
5074	 * Reset target OFFLINE state and mark the target BUSY
5075	 */
5076	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5077	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5078
5079	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5080	lcount = link_cnt;
5081
5082	mutex_exit(&ptgt->tgt_mutex);
5083	mutex_exit(&pptr->port_mutex);
5084
5085	/*
5086	 * if we are already logged in, then we do a PRLI, else
5087	 * we do a PLOGI first (to get logged in)
5088	 *
5089	 * We will not check if we are the PLOGI initiator
5090	 */
5091	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5092	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5093
5094	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5095
5096	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5097	    pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5098	    cause, map_entry->map_rscn_info.ulp_rscn_count);
5099
5100	if (icmd == NULL) {
5101		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5102		/*
5103		 * We've exited port_mutex before calling fcp_icmd_alloc,
5104		 * we need to make sure we reacquire it before returning.
5105		 */
5106		mutex_enter(&pptr->port_mutex);
5107		return (FALSE);
5108	}
5109
5110	/* TRUE is only returned while target is intended skipped */
5111	ret = FALSE;
5112	/* discover info about this target */
5113	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5114	    lcount, tcount, cause)) == DDI_SUCCESS) {
5115		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5116	} else {
5117		fcp_icmd_free(pptr, icmd);
5118		ret = TRUE;
5119	}
5120	mutex_enter(&pptr->port_mutex);
5121
5122	return (ret);
5123}
5124
5125/*
5126 *     Function: fcp_send_els
5127 *
5128 *  Description: Sends an ELS to the target specified by the caller.  Supports
5129 *		 PLOGI and PRLI.
5130 *
5131 *     Argument: *pptr		Fcp port.
5132 *		 *ptgt		Target to send the ELS to.
5133 *		 *icmd		Internal packet
5134 *		 opcode		ELS opcode
5135 *		 lcount		Link state change counter
5136 *		 tcount		Target state change counter
5137 *		 cause		What caused the call
5138 *
5139 * Return Value: DDI_SUCCESS
5140 *		 Others
5141 */
5142static int
5143fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5144    struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5145{
5146	fc_packet_t		*fpkt;
5147	fc_frame_hdr_t		*hp;
5148	int			internal = 0;
5149	int			alloc;
5150	int			cmd_len;
5151	int			resp_len;
5152	int			res = DDI_FAILURE; /* default result */
5153	int			rval = DDI_FAILURE;
5154
5155	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5156	ASSERT(ptgt->tgt_port == pptr);
5157
5158	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5159	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5160	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5161	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5162
5163	if (opcode == LA_ELS_PLOGI) {
5164		cmd_len = sizeof (la_els_logi_t);
5165		resp_len = sizeof (la_els_logi_t);
5166	} else {
5167		ASSERT(opcode == LA_ELS_PRLI);
5168		cmd_len = sizeof (la_els_prli_t);
5169		resp_len = sizeof (la_els_prli_t);
5170	}
5171
5172	if (icmd == NULL) {
5173		alloc = FCP_MAX(sizeof (la_els_logi_t),
5174		    sizeof (la_els_prli_t));
5175		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5176		    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5177		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5178		if (icmd == NULL) {
5179			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5180			return (res);
5181		}
5182		internal++;
5183	}
5184	fpkt = icmd->ipkt_fpkt;
5185
5186	fpkt->pkt_cmdlen = cmd_len;
5187	fpkt->pkt_rsplen = resp_len;
5188	fpkt->pkt_datalen = 0;
5189	icmd->ipkt_retries = 0;
5190
5191	/* fill in fpkt info */
5192	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5193	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5194	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5195
5196	/* get ptr to frame hdr in fpkt */
5197	hp = &fpkt->pkt_cmd_fhdr;
5198
5199	/*
5200	 * fill in frame hdr
5201	 */
5202	hp->r_ctl = R_CTL_ELS_REQ;
5203	hp->s_id = pptr->port_id;	/* source ID */
5204	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
5205	hp->type = FC_TYPE_EXTENDED_LS;
5206	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5207	hp->seq_id = 0;
5208	hp->rsvd = 0;
5209	hp->df_ctl  = 0;
5210	hp->seq_cnt = 0;
5211	hp->ox_id = 0xffff;		/* i.e. none */
5212	hp->rx_id = 0xffff;		/* i.e. none */
5213	hp->ro = 0;
5214
5215	/*
5216	 * at this point we have a filled in cmd pkt
5217	 *
5218	 * fill in the respective info, then use the transport to send
5219	 * the packet
5220	 *
5221	 * for a PLOGI call fc_ulp_login(), and
5222	 * for a PRLI call fc_ulp_issue_els()
5223	 */
5224	switch (opcode) {
5225	case LA_ELS_PLOGI: {
5226		struct la_els_logi logi;
5227
5228		bzero(&logi, sizeof (struct la_els_logi));
5229
5230		hp = &fpkt->pkt_cmd_fhdr;
5231		hp->r_ctl = R_CTL_ELS_REQ;
5232		logi.ls_code.ls_code = LA_ELS_PLOGI;
5233		logi.ls_code.mbz = 0;
5234
5235		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5236		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5237
5238		icmd->ipkt_opcode = LA_ELS_PLOGI;
5239
5240		mutex_enter(&pptr->port_mutex);
5241		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5242
5243			mutex_exit(&pptr->port_mutex);
5244
5245			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5246			if (rval == FC_SUCCESS) {
5247				res = DDI_SUCCESS;
5248				break;
5249			}
5250
5251			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5252
5253			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5254			    rval, "PLOGI");
5255		} else {
5256			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5257			    fcp_trace, FCP_BUF_LEVEL_5, 0,
5258			    "fcp_send_els1: state change occured"
5259			    " for D_ID=0x%x", ptgt->tgt_d_id);
5260			mutex_exit(&pptr->port_mutex);
5261			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5262		}
5263		break;
5264	}
5265
5266	case LA_ELS_PRLI: {
5267		struct la_els_prli	prli;
5268		struct fcp_prli		*fprli;
5269
5270		bzero(&prli, sizeof (struct la_els_prli));
5271
5272		hp = &fpkt->pkt_cmd_fhdr;
5273		hp->r_ctl = R_CTL_ELS_REQ;
5274
5275		/* fill in PRLI cmd ELS fields */
5276		prli.ls_code = LA_ELS_PRLI;
5277		prli.page_length = 0x10;	/* huh? */
5278		prli.payload_length = sizeof (struct la_els_prli);
5279
5280		icmd->ipkt_opcode = LA_ELS_PRLI;
5281
5282		/* get ptr to PRLI service params */
5283		fprli = (struct fcp_prli *)prli.service_params;
5284
5285		/* fill in service params */
5286		fprli->type = 0x08;
5287		fprli->resvd1 = 0;
5288		fprli->orig_process_assoc_valid = 0;
5289		fprli->resp_process_assoc_valid = 0;
5290		fprli->establish_image_pair = 1;
5291		fprli->resvd2 = 0;
5292		fprli->resvd3 = 0;
5293		fprli->obsolete_1 = 0;
5294		fprli->obsolete_2 = 0;
5295		fprli->data_overlay_allowed = 0;
5296		fprli->initiator_fn = 1;
5297		fprli->confirmed_compl_allowed = 1;
5298
5299		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5300			fprli->target_fn = 1;
5301		} else {
5302			fprli->target_fn = 0;
5303		}
5304
5305		fprli->retry = 1;
5306		fprli->read_xfer_rdy_disabled = 1;
5307		fprli->write_xfer_rdy_disabled = 0;
5308
5309		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5310		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5311
5312		/* issue the PRLI request */
5313
5314		mutex_enter(&pptr->port_mutex);
5315		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5316
5317			mutex_exit(&pptr->port_mutex);
5318
5319			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5320			if (rval == FC_SUCCESS) {
5321				res = DDI_SUCCESS;
5322				break;
5323			}
5324
5325			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5326
5327			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5328			    rval, "PRLI");
5329		} else {
5330			mutex_exit(&pptr->port_mutex);
5331			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5332		}
5333		break;
5334	}
5335
5336	default:
5337		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5338		break;
5339	}
5340
5341	FCP_TRACE(fcp_logq, pptr->port_instbuf,
5342	    fcp_trace, FCP_BUF_LEVEL_5, 0,
5343	    "fcp_send_els: returning %d", res);
5344
5345	if (res != DDI_SUCCESS) {
5346		if (internal) {
5347			fcp_icmd_free(pptr, icmd);
5348		}
5349	}
5350
5351	return (res);
5352}
5353
5354
5355/*
5356 * called internally update the state of all of the tgts and each LUN
5357 * for this port (i.e. each target  known to be attached to this port)
5358 * if they are not already offline
5359 *
5360 * must be called with the port mutex owned
5361 *
5362 * acquires and releases the target mutexes for each target attached
5363 * to this port
5364 */
5365void
5366fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5367{
5368	int i;
5369	struct fcp_tgt *ptgt;
5370
5371	ASSERT(mutex_owned(&pptr->port_mutex));
5372
5373	for (i = 0; i < FCP_NUM_HASH; i++) {
5374		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5375		    ptgt = ptgt->tgt_next) {
5376			mutex_enter(&ptgt->tgt_mutex);
5377			fcp_update_tgt_state(ptgt, FCP_SET, state);
5378			ptgt->tgt_change_cnt++;
5379			ptgt->tgt_statec_cause = cause;
5380			ptgt->tgt_tmp_cnt = 1;
5381			ptgt->tgt_done = 0;
5382			mutex_exit(&ptgt->tgt_mutex);
5383		}
5384	}
5385}
5386
5387
5388static void
5389fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5390{
5391	int i;
5392	int ndevs;
5393	struct fcp_tgt *ptgt;
5394
5395	ASSERT(mutex_owned(&pptr->port_mutex));
5396
5397	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5398		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5399		    ptgt = ptgt->tgt_next) {
5400			ndevs++;
5401		}
5402	}
5403
5404	if (ndevs == 0) {
5405		return;
5406	}
5407	pptr->port_tmp_cnt = ndevs;
5408
5409	for (i = 0; i < FCP_NUM_HASH; i++) {
5410		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5411		    ptgt = ptgt->tgt_next) {
5412			(void) fcp_call_finish_init_held(pptr, ptgt,
5413			    lcount, ptgt->tgt_change_cnt, cause);
5414		}
5415	}
5416}
5417
5418/*
5419 *     Function: fcp_update_tgt_state
5420 *
5421 *  Description: This function updates the field tgt_state of a target.	 That
5422 *		 field is a bitmap and which bit can be set or reset
5423 *		 individually.	The action applied to the target state is also
5424 *		 applied to all the LUNs belonging to the target (provided the
5425 *		 LUN is not offline).  A side effect of applying the state
5426 *		 modification to the target and the LUNs is the field tgt_trace
5427 *		 of the target and lun_trace of the LUNs is set to zero.
5428 *
5429 *
5430 *     Argument: *ptgt	Target structure.
5431 *		 flag	Flag indication what action to apply (set/reset).
5432 *		 state	State bits to update.
5433 *
5434 * Return Value: None
5435 *
5436 *	Context: Interrupt, Kernel or User context.
5437 *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5438 *		 calling this function.
5439 */
5440void
5441fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5442{
5443	struct fcp_lun *plun;
5444
5445	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5446
5447	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5448		/* The target is not offline. */
5449		if (flag == FCP_SET) {
5450			ptgt->tgt_state |= state;
5451			ptgt->tgt_trace = 0;
5452		} else {
5453			ptgt->tgt_state &= ~state;
5454		}
5455
5456		for (plun = ptgt->tgt_lun; plun != NULL;
5457		    plun = plun->lun_next) {
5458			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5459				/* The LUN is not offline. */
5460				if (flag == FCP_SET) {
5461					plun->lun_state |= state;
5462					plun->lun_trace = 0;
5463				} else {
5464					plun->lun_state &= ~state;
5465				}
5466			}
5467		}
5468	}
5469}
5470
5471/*
5472 *     Function: fcp_update_tgt_state
5473 *
5474 *  Description: This function updates the field lun_state of a LUN.  That
5475 *		 field is a bitmap and which bit can be set or reset
5476 *		 individually.
5477 *
5478 *     Argument: *plun	LUN structure.
5479 *		 flag	Flag indication what action to apply (set/reset).
5480 *		 state	State bits to update.
5481 *
5482 * Return Value: None
5483 *
5484 *	Context: Interrupt, Kernel or User context.
5485 *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
5486 *		 calling this function.
5487 */
5488void
5489fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5490{
5491	struct fcp_tgt	*ptgt = plun->lun_tgt;
5492
5493	ASSERT(mutex_owned(&ptgt->tgt_mutex));
5494
5495	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5496		if (flag == FCP_SET) {
5497			plun->lun_state |= state;
5498		} else {
5499			plun->lun_state &= ~state;
5500		}
5501	}
5502}
5503
5504/*
5505 *     Function: fcp_get_port
5506 *
5507 *  Description: This function returns the fcp_port structure from the opaque
5508 *		 handle passed by the caller.  That opaque handle is the handle
5509 *		 used by fp/fctl to identify a particular local port.  That
5510 *		 handle has been stored in the corresponding fcp_port
5511 *		 structure.  This function is going to walk the global list of
5512 *		 fcp_port structures till one has a port_fp_handle that matches
5513 *		 the handle passed by the caller.  This function enters the
5514 *		 mutex fcp_global_mutex while walking the global list and then
5515 *		 releases it.
5516 *
5517 *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
5518 *				particular port.
5519 *
5520 * Return Value: NULL		Not found.
5521 *		 Not NULL	Pointer to the fcp_port structure.
5522 *
5523 *	Context: Interrupt, Kernel or User context.
5524 */
5525static struct fcp_port *
5526fcp_get_port(opaque_t port_handle)
5527{
5528	struct fcp_port *pptr;
5529
5530	ASSERT(port_handle != NULL);
5531
5532	mutex_enter(&fcp_global_mutex);
5533	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5534		if (pptr->port_fp_handle == port_handle) {
5535			break;
5536		}
5537	}
5538	mutex_exit(&fcp_global_mutex);
5539
5540	return (pptr);
5541}
5542
5543
5544static void
5545fcp_unsol_callback(fc_packet_t *fpkt)
5546{
5547	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5548	struct fcp_port *pptr = icmd->ipkt_port;
5549
5550	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5551		caddr_t state, reason, action, expln;
5552
5553		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
5554		    &action, &expln);
5555
5556		fcp_log(CE_WARN, pptr->port_dip,
5557		    "!couldn't post response to unsolicited request: "
5558		    " state=%s reason=%s rx_id=%x ox_id=%x",
5559		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5560		    fpkt->pkt_cmd_fhdr.rx_id);
5561	}
5562	fcp_icmd_free(pptr, icmd);
5563}
5564
5565
5566/*
5567 * Perform general purpose preparation of a response to an unsolicited request
5568 */
5569static void
5570fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5571    uchar_t r_ctl, uchar_t type)
5572{
5573	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5574	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5575	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5576	pkt->pkt_cmd_fhdr.type = type;
5577	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5578	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5579	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5580	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5581	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5582	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5583	pkt->pkt_cmd_fhdr.ro = 0;
5584	pkt->pkt_cmd_fhdr.rsvd = 0;
5585	pkt->pkt_comp = fcp_unsol_callback;
5586	pkt->pkt_pd = NULL;
5587	pkt->pkt_ub_resp_token = (opaque_t)buf;
5588}
5589
5590
5591/*ARGSUSED*/
5592static int
5593fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5594{
5595	fc_packet_t		*fpkt;
5596	struct la_els_prli	prli;
5597	struct fcp_prli		*fprli;
5598	struct fcp_ipkt	*icmd;
5599	struct la_els_prli	*from;
5600	struct fcp_prli		*orig;
5601	struct fcp_tgt	*ptgt;
5602	int			tcount = 0;
5603	int			lcount;
5604
5605	from = (struct la_els_prli *)buf->ub_buffer;
5606	orig = (struct fcp_prli *)from->service_params;
5607	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5608	    NULL) {
5609		mutex_enter(&ptgt->tgt_mutex);
5610		tcount = ptgt->tgt_change_cnt;
5611		mutex_exit(&ptgt->tgt_mutex);
5612	}
5613
5614	mutex_enter(&pptr->port_mutex);
5615	lcount = pptr->port_link_cnt;
5616	mutex_exit(&pptr->port_mutex);
5617
5618	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5619	    sizeof (la_els_prli_t), 0,
5620	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5621	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5622		return (FC_FAILURE);
5623	}
5624
5625	fpkt = icmd->ipkt_fpkt;
5626	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5627	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5628	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5629	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5630	fpkt->pkt_rsplen = 0;
5631	fpkt->pkt_datalen = 0;
5632
5633	icmd->ipkt_opcode = LA_ELS_PRLI;
5634
5635	bzero(&prli, sizeof (struct la_els_prli));
5636	fprli = (struct fcp_prli *)prli.service_params;
5637	prli.ls_code = LA_ELS_ACC;
5638	prli.page_length = 0x10;
5639	prli.payload_length = sizeof (struct la_els_prli);
5640
5641	/* fill in service params */
5642	fprli->type = 0x08;
5643	fprli->resvd1 = 0;
5644	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5645	fprli->orig_process_associator = orig->orig_process_associator;
5646	fprli->resp_process_assoc_valid = 0;
5647	fprli->establish_image_pair = 1;
5648	fprli->resvd2 = 0;
5649	fprli->resvd3 = 0;
5650	fprli->obsolete_1 = 0;
5651	fprli->obsolete_2 = 0;
5652	fprli->data_overlay_allowed = 0;
5653	fprli->initiator_fn = 1;
5654	fprli->confirmed_compl_allowed = 1;
5655
5656	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5657		fprli->target_fn = 1;
5658	} else {
5659		fprli->target_fn = 0;
5660	}
5661
5662	fprli->retry = 1;
5663	fprli->read_xfer_rdy_disabled = 1;
5664	fprli->write_xfer_rdy_disabled = 0;
5665
5666	/* save the unsol prli payload first */
5667	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5668	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5669
5670	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5671	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5672
5673	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5674
5675	mutex_enter(&pptr->port_mutex);
5676	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5677		int rval;
5678		mutex_exit(&pptr->port_mutex);
5679
5680		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5681		    FC_SUCCESS) {
5682			if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5683			    ptgt != NULL) {
5684				fcp_queue_ipkt(pptr, fpkt);
5685				return (FC_SUCCESS);
5686			}
5687			/* Let it timeout */
5688			fcp_icmd_free(pptr, icmd);
5689			return (FC_FAILURE);
5690		}
5691	} else {
5692		mutex_exit(&pptr->port_mutex);
5693		fcp_icmd_free(pptr, icmd);
5694		return (FC_FAILURE);
5695	}
5696
5697	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5698
5699	return (FC_SUCCESS);
5700}
5701
5702/*
5703 *     Function: fcp_icmd_alloc
5704 *
5705 *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
5706 *		 field is initialized to fcp_icmd_callback.  Sometimes it is
5707 *		 modified by the caller (such as fcp_send_scsi).  The
5708 *		 structure is also tied to the state of the line and of the
5709 *		 target at a particular time.  That link is established by
5710 *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5711 *		 and tcount which came respectively from pptr->link_cnt and
5712 *		 ptgt->tgt_change_cnt.
5713 *
5714 *     Argument: *pptr		Fcp port.
5715 *		 *ptgt		Target (destination of the command).
5716 *		 cmd_len	Length of the command.
5717 *		 resp_len	Length of the expected response.
5718 *		 data_len	Length of the data.
5719 *		 nodma		Indicates weither the command and response.
5720 *				will be transfer through DMA or not.
5721 *		 lcount		Link state change counter.
5722 *		 tcount		Target state change counter.
5723 *		 cause		Reason that lead to this call.
5724 *
5725 * Return Value: NULL		Failed.
5726 *		 Not NULL	Internal packet address.
5727 */
5728static struct fcp_ipkt *
5729fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5730    int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5731    uint32_t rscn_count)
5732{
5733	int			dma_setup = 0;
5734	fc_packet_t		*fpkt;
5735	struct fcp_ipkt	*icmd = NULL;
5736
5737	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5738	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5739	    KM_NOSLEEP);
5740	if (icmd == NULL) {
5741		fcp_log(CE_WARN, pptr->port_dip,
5742		    "!internal packet allocation failed");
5743		return (NULL);
5744	}
5745
5746	/*
5747	 * initialize the allocated packet
5748	 */
5749	icmd->ipkt_nodma = nodma;
5750	icmd->ipkt_next = icmd->ipkt_prev = NULL;
5751	icmd->ipkt_lun = NULL;
5752
5753	icmd->ipkt_link_cnt = lcount;
5754	icmd->ipkt_change_cnt = tcount;
5755	icmd->ipkt_cause = cause;
5756
5757	mutex_enter(&pptr->port_mutex);
5758	icmd->ipkt_port = pptr;
5759	mutex_exit(&pptr->port_mutex);
5760
5761	/* keep track of amt of data to be sent in pkt */
5762	icmd->ipkt_cmdlen = cmd_len;
5763	icmd->ipkt_resplen = resp_len;
5764	icmd->ipkt_datalen = data_len;
5765
5766	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5767	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5768
5769	/* set pkt's private ptr to point to cmd pkt */
5770	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5771
5772	/* set FCA private ptr to memory just beyond */
5773	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5774	    ((char *)icmd + sizeof (struct fcp_ipkt) +
5775	    pptr->port_dmacookie_sz);
5776
5777	/* get ptr to fpkt substruct and fill it in */
5778	fpkt = icmd->ipkt_fpkt;
5779	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5780	    sizeof (struct fcp_ipkt));
5781
5782	if (ptgt != NULL) {
5783		icmd->ipkt_tgt = ptgt;
5784		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5785	}
5786
5787	fpkt->pkt_comp = fcp_icmd_callback;
5788	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5789	fpkt->pkt_cmdlen = cmd_len;
5790	fpkt->pkt_rsplen = resp_len;
5791	fpkt->pkt_datalen = data_len;
5792
5793	/*
5794	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5795	 * rscn_count as fcp knows down to the transport. If a valid count was
5796	 * passed into this function, we allocate memory to actually pass down
5797	 * this info.
5798	 *
5799	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5800	 * basically mean that fcp will not be able to help transport
5801	 * distinguish if a new RSCN has come after fcp was last informed about
5802	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
5803	 * 5068068 where the device might end up going offline in case of RSCN
5804	 * storms.
5805	 */
5806	fpkt->pkt_ulp_rscn_infop = NULL;
5807	if (rscn_count != FC_INVALID_RSCN_COUNT) {
5808		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5809		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5810		if (fpkt->pkt_ulp_rscn_infop == NULL) {
5811			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5812			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5813			    "Failed to alloc memory to pass rscn info");
5814		}
5815	}
5816
5817	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5818		fc_ulp_rscn_info_t	*rscnp;
5819
5820		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5821		rscnp->ulp_rscn_count = rscn_count;
5822	}
5823
5824	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5825		goto fail;
5826	}
5827	dma_setup++;
5828
5829	/*
5830	 * Must hold target mutex across setting of pkt_pd and call to
5831	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
5832	 * away while we're not looking.
5833	 */
5834	if (ptgt != NULL) {
5835		mutex_enter(&ptgt->tgt_mutex);
5836		fpkt->pkt_pd = ptgt->tgt_pd_handle;
5837
5838		/* ask transport to do its initialization on this pkt */
5839		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5840		    != FC_SUCCESS) {
5841			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5842			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5843			    "fc_ulp_init_packet failed");
5844			mutex_exit(&ptgt->tgt_mutex);
5845			goto fail;
5846		}
5847		mutex_exit(&ptgt->tgt_mutex);
5848	} else {
5849		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5850		    != FC_SUCCESS) {
5851			FCP_TRACE(fcp_logq, pptr->port_instbuf,
5852			    fcp_trace, FCP_BUF_LEVEL_6, 0,
5853			    "fc_ulp_init_packet failed");
5854			goto fail;
5855		}
5856	}
5857
5858	mutex_enter(&pptr->port_mutex);
5859	if (pptr->port_state & (FCP_STATE_DETACHING |
5860	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5861		int rval;
5862
5863		mutex_exit(&pptr->port_mutex);
5864
5865		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5866		ASSERT(rval == FC_SUCCESS);
5867
5868		goto fail;
5869	}
5870
5871	if (ptgt != NULL) {
5872		mutex_enter(&ptgt->tgt_mutex);
5873		ptgt->tgt_ipkt_cnt++;
5874		mutex_exit(&ptgt->tgt_mutex);
5875	}
5876
5877	pptr->port_ipkt_cnt++;
5878
5879	mutex_exit(&pptr->port_mutex);
5880
5881	return (icmd);
5882
5883fail:
5884	if (fpkt->pkt_ulp_rscn_infop != NULL) {
5885		kmem_free(fpkt->pkt_ulp_rscn_infop,
5886		    sizeof (fc_ulp_rscn_info_t));
5887		fpkt->pkt_ulp_rscn_infop = NULL;
5888	}
5889
5890	if (dma_setup) {
5891		fcp_free_dma(pptr, icmd);
5892	}
5893	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5894	    (size_t)pptr->port_dmacookie_sz);
5895
5896	return (NULL);
5897}
5898
5899/*
5900 *     Function: fcp_icmd_free
5901 *
5902 *  Description: Frees the internal command passed by the caller.
5903 *
5904 *     Argument: *pptr		Fcp port.
5905 *		 *icmd		Internal packet to free.
5906 *
5907 * Return Value: None
5908 */
5909static void
5910fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5911{
5912	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
5913
5914	/* Let the underlying layers do their cleanup. */
5915	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5916	    icmd->ipkt_fpkt);
5917
5918	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5919		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5920		    sizeof (fc_ulp_rscn_info_t));
5921	}
5922
5923	fcp_free_dma(pptr, icmd);
5924
5925	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5926	    (size_t)pptr->port_dmacookie_sz);
5927
5928	mutex_enter(&pptr->port_mutex);
5929
5930	if (ptgt) {
5931		mutex_enter(&ptgt->tgt_mutex);
5932		ptgt->tgt_ipkt_cnt--;
5933		mutex_exit(&ptgt->tgt_mutex);
5934	}
5935
5936	pptr->port_ipkt_cnt--;
5937	mutex_exit(&pptr->port_mutex);
5938}
5939
5940/*
5941 *     Function: fcp_alloc_dma
5942 *
5943 *  Description: Allocated the DMA resources required for the internal
5944 *		 packet.
5945 *
5946 *     Argument: *pptr	FCP port.
5947 *		 *icmd	Internal FCP packet.
5948 *		 nodma	Indicates if the Cmd and Resp will be DMAed.
5949 *		 flags	Allocation flags (Sleep or NoSleep).
5950 *
5951 * Return Value: FC_SUCCESS
5952 *		 FC_NOMEM
5953 */
5954static int
5955fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5956    int nodma, int flags)
5957{
5958	int		rval;
5959	size_t		real_size;
5960	uint_t		ccount;
5961	int		bound = 0;
5962	int		cmd_resp = 0;
5963	fc_packet_t	*fpkt;
5964	ddi_dma_cookie_t	pkt_data_cookie;
5965	ddi_dma_cookie_t	*cp;
5966	uint32_t		cnt;
5967
5968	fpkt = &icmd->ipkt_fc_packet;
5969
5970	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5971	    fpkt->pkt_resp_dma == NULL);
5972
5973	icmd->ipkt_nodma = nodma;
5974
5975	if (nodma) {
5976		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5977		if (fpkt->pkt_cmd == NULL) {
5978			goto fail;
5979		}
5980
5981		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5982		if (fpkt->pkt_resp == NULL) {
5983			goto fail;
5984		}
5985	} else {
5986		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5987
5988		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5989		if (rval == FC_FAILURE) {
5990			ASSERT(fpkt->pkt_cmd_dma == NULL &&
5991			    fpkt->pkt_resp_dma == NULL);
5992			goto fail;
5993		}
5994		cmd_resp++;
5995	}
5996
5997	if ((fpkt->pkt_datalen != 0) &&
5998	    !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
5999		/*
6000		 * set up DMA handle and memory for the data in this packet
6001		 */
6002		if (ddi_dma_alloc_handle(pptr->port_dip,
6003		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6004		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6005			goto fail;
6006		}
6007
6008		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6009		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6010		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6011		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6012			goto fail;
6013		}
6014
6015		/* was DMA mem size gotten < size asked for/needed ?? */
6016		if (real_size < fpkt->pkt_datalen) {
6017			goto fail;
6018		}
6019
6020		/* bind DMA address and handle together */
6021		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6022		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6023		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6024		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6025			goto fail;
6026		}
6027		bound++;
6028
6029		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6030			goto fail;
6031		}
6032
6033		fpkt->pkt_data_cookie_cnt = ccount;
6034
6035		cp = fpkt->pkt_data_cookie;
6036		*cp = pkt_data_cookie;
6037		cp++;
6038
6039		for (cnt = 1; cnt < ccount; cnt++, cp++) {
6040			ddi_dma_nextcookie(fpkt->pkt_data_dma,
6041			    &pkt_data_cookie);
6042			*cp = pkt_data_cookie;
6043		}
6044
6045	} else if (fpkt->pkt_datalen != 0) {
6046		/*
6047		 * If it's a pseudo FCA, then it can't support DMA even in
6048		 * SCSI data phase.
6049		 */
6050		fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6051		if (fpkt->pkt_data == NULL) {
6052			goto fail;
6053		}
6054
6055	}
6056
6057	return (FC_SUCCESS);
6058
6059fail:
6060	if (bound) {
6061		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6062	}
6063
6064	if (fpkt->pkt_data_dma) {
6065		if (fpkt->pkt_data) {
6066			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6067		}
6068		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6069	} else {
6070		if (fpkt->pkt_data) {
6071			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6072		}
6073	}
6074
6075	if (nodma) {
6076		if (fpkt->pkt_cmd) {
6077			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6078		}
6079		if (fpkt->pkt_resp) {
6080			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6081		}
6082	} else {
6083		if (cmd_resp) {
6084			fcp_free_cmd_resp(pptr, fpkt);
6085		}
6086	}
6087
6088	return (FC_NOMEM);
6089}
6090
6091
6092static void
6093fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6094{
6095	fc_packet_t *fpkt = icmd->ipkt_fpkt;
6096
6097	if (fpkt->pkt_data_dma) {
6098		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6099		if (fpkt->pkt_data) {
6100			ddi_dma_mem_free(&fpkt->pkt_data_acc);
6101		}
6102		ddi_dma_free_handle(&fpkt->pkt_data_dma);
6103	} else {
6104		if (fpkt->pkt_data) {
6105			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6106		}
6107		/*
6108		 * Need we reset pkt_* to zero???
6109		 */
6110	}
6111
6112	if (icmd->ipkt_nodma) {
6113		if (fpkt->pkt_cmd) {
6114			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6115		}
6116		if (fpkt->pkt_resp) {
6117			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6118		}
6119	} else {
6120		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6121
6122		fcp_free_cmd_resp(pptr, fpkt);
6123	}
6124}
6125
6126/*
6127 *     Function: fcp_lookup_target
6128 *
6129 *  Description: Finds a target given a WWN.
6130 *
6131 *     Argument: *pptr	FCP port.
6132 *		 *wwn	World Wide Name of the device to look for.
6133 *
6134 * Return Value: NULL		No target found
6135 *		 Not NULL	Target structure
6136 *
6137 *	Context: Interrupt context.
6138 *		 The mutex pptr->port_mutex must be owned.
6139 */
6140/* ARGSUSED */
6141static struct fcp_tgt *
6142fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6143{
6144	int			hash;
6145	struct fcp_tgt	*ptgt;
6146
6147	ASSERT(mutex_owned(&pptr->port_mutex));
6148
6149	hash = FCP_HASH(wwn);
6150
6151	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6152	    ptgt = ptgt->tgt_next) {
6153		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6154		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6155		    sizeof (ptgt->tgt_port_wwn)) == 0) {
6156			break;
6157		}
6158	}
6159
6160	return (ptgt);
6161}
6162
6163
6164/*
6165 * Find target structure given a port identifier
6166 */
6167static struct fcp_tgt *
6168fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6169{
6170	fc_portid_t		port_id;
6171	la_wwn_t		pwwn;
6172	struct fcp_tgt	*ptgt = NULL;
6173
6174	port_id.priv_lilp_posit = 0;
6175	port_id.port_id = d_id;
6176	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6177	    &pwwn) == FC_SUCCESS) {
6178		mutex_enter(&pptr->port_mutex);
6179		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6180		mutex_exit(&pptr->port_mutex);
6181	}
6182
6183	return (ptgt);
6184}
6185
6186
6187/*
6188 * the packet completion callback routine for info cmd pkts
6189 *
6190 * this means fpkt pts to a response to either a PLOGI or a PRLI
6191 *
6192 * if there is an error an attempt is made to call a routine to resend
6193 * the command that failed
6194 */
6195static void
6196fcp_icmd_callback(fc_packet_t *fpkt)
6197{
6198	struct fcp_ipkt	*icmd;
6199	struct fcp_port	*pptr;
6200	struct fcp_tgt	*ptgt;
6201	struct la_els_prli	*prli;
6202	struct la_els_prli	prli_s;
6203	struct fcp_prli		*fprli;
6204	struct fcp_lun	*plun;
6205	int		free_pkt = 1;
6206	int		rval;
6207	ls_code_t	resp;
6208	uchar_t		prli_acc = 0;
6209	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
6210	int		lun0_newalloc;
6211
6212	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6213
6214	/* get ptrs to the port and target structs for the cmd */
6215	pptr = icmd->ipkt_port;
6216	ptgt = icmd->ipkt_tgt;
6217
6218	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6219
6220	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6221		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6222		    sizeof (prli_s));
6223		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6224	}
6225
6226	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6227	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6228	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
6229	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6230	    ptgt->tgt_d_id);
6231
6232	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6233	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6234
6235		mutex_enter(&ptgt->tgt_mutex);
6236		if (ptgt->tgt_pd_handle == NULL) {
6237			/*
6238			 * in a fabric environment the port device handles
6239			 * get created only after successful LOGIN into the
6240			 * transport, so the transport makes this port
6241			 * device (pd) handle available in this packet, so
6242			 * save it now
6243			 */
6244			ASSERT(fpkt->pkt_pd != NULL);
6245			ptgt->tgt_pd_handle = fpkt->pkt_pd;
6246		}
6247		mutex_exit(&ptgt->tgt_mutex);
6248
6249		/* which ELS cmd is this response for ?? */
6250		switch (icmd->ipkt_opcode) {
6251		case LA_ELS_PLOGI:
6252			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6253			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6254			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6255			    ptgt->tgt_d_id,
6256			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6257			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6258
6259			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6260			    FCP_TGT_TRACE_15);
6261
6262			/* Note that we are not allocating a new icmd */
6263			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6264			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6265			    icmd->ipkt_cause) != DDI_SUCCESS) {
6266				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6267				    FCP_TGT_TRACE_16);
6268				goto fail;
6269			}
6270			break;
6271
6272		case LA_ELS_PRLI:
6273			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6274			    fcp_trace, FCP_BUF_LEVEL_5, 0,
6275			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6276
6277			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6278			    FCP_TGT_TRACE_17);
6279
6280			prli = &prli_s;
6281
6282			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6283			    sizeof (prli_s));
6284
6285			fprli = (struct fcp_prli *)prli->service_params;
6286
6287			mutex_enter(&ptgt->tgt_mutex);
6288			ptgt->tgt_icap = fprli->initiator_fn;
6289			ptgt->tgt_tcap = fprli->target_fn;
6290			mutex_exit(&ptgt->tgt_mutex);
6291
6292			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6293				/*
6294				 * this FCP device does not support target mode
6295				 */
6296				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6297				    FCP_TGT_TRACE_18);
6298				goto fail;
6299			}
6300			if (fprli->retry == 1) {
6301				fc_ulp_disable_relogin(pptr->port_fp_handle,
6302				    &ptgt->tgt_port_wwn);
6303			}
6304
6305			/* target is no longer offline */
6306			mutex_enter(&pptr->port_mutex);
6307			mutex_enter(&ptgt->tgt_mutex);
6308			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6309				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6310				    FCP_TGT_MARK);
6311			} else {
6312				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6313				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6314				    "fcp_icmd_callback,1: state change "
6315				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6316				mutex_exit(&ptgt->tgt_mutex);
6317				mutex_exit(&pptr->port_mutex);
6318				goto fail;
6319			}
6320			mutex_exit(&ptgt->tgt_mutex);
6321			mutex_exit(&pptr->port_mutex);
6322
6323			/*
6324			 * lun 0 should always respond to inquiry, so
6325			 * get the LUN struct for LUN 0
6326			 *
6327			 * Currently we deal with first level of addressing.
6328			 * If / when we start supporting 0x device types
6329			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6330			 * this logic will need revisiting.
6331			 */
6332			lun0_newalloc = 0;
6333			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6334				/*
6335				 * no LUN struct for LUN 0 yet exists,
6336				 * so create one
6337				 */
6338				plun = fcp_alloc_lun(ptgt);
6339				if (plun == NULL) {
6340					fcp_log(CE_WARN, pptr->port_dip,
6341					    "!Failed to allocate lun 0 for"
6342					    " D_ID=%x", ptgt->tgt_d_id);
6343					goto fail;
6344				}
6345				lun0_newalloc = 1;
6346			}
6347
6348			/* fill in LUN info */
6349			mutex_enter(&ptgt->tgt_mutex);
6350			/*
6351			 * consider lun 0 as device not connected if it is
6352			 * offlined or newly allocated
6353			 */
6354			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6355			    lun0_newalloc) {
6356				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6357			}
6358			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6359			plun->lun_state &= ~FCP_LUN_OFFLINE;
6360			ptgt->tgt_lun_cnt = 1;
6361			ptgt->tgt_report_lun_cnt = 0;
6362			mutex_exit(&ptgt->tgt_mutex);
6363
6364			/* Retrieve the rscn count (if a valid one exists) */
6365			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6366				rscn_count = ((fc_ulp_rscn_info_t *)
6367				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6368				    ->ulp_rscn_count;
6369			} else {
6370				rscn_count = FC_INVALID_RSCN_COUNT;
6371			}
6372
6373			/* send Report Lun request to target */
6374			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6375			    sizeof (struct fcp_reportlun_resp),
6376			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6377			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6378				mutex_enter(&pptr->port_mutex);
6379				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6380					fcp_log(CE_WARN, pptr->port_dip,
6381					    "!Failed to send REPORT LUN to"
6382					    "  D_ID=%x", ptgt->tgt_d_id);
6383				} else {
6384					FCP_TRACE(fcp_logq,
6385					    pptr->port_instbuf, fcp_trace,
6386					    FCP_BUF_LEVEL_5, 0,
6387					    "fcp_icmd_callback,2:state change"
6388					    " occured for D_ID=0x%x",
6389					    ptgt->tgt_d_id);
6390				}
6391				mutex_exit(&pptr->port_mutex);
6392
6393				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6394				    FCP_TGT_TRACE_19);
6395
6396				goto fail;
6397			} else {
6398				free_pkt = 0;
6399				fcp_icmd_free(pptr, icmd);
6400			}
6401			break;
6402
6403		default:
6404			fcp_log(CE_WARN, pptr->port_dip,
6405			    "!fcp_icmd_callback Invalid opcode");
6406			goto fail;
6407		}
6408
6409		return;
6410	}
6411
6412
6413	/*
6414	 * Other PLOGI failures are not retried as the
6415	 * transport does it already
6416	 */
6417	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6418		if (fcp_is_retryable(icmd) &&
6419		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6420
6421			if (FCP_MUST_RETRY(fpkt)) {
6422				fcp_queue_ipkt(pptr, fpkt);
6423				return;
6424			}
6425
6426			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6427			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6428			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
6429			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6430			    fpkt->pkt_reason);
6431
6432			/*
6433			 * Retry by recalling the routine that
6434			 * originally queued this packet
6435			 */
6436			mutex_enter(&pptr->port_mutex);
6437			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6438				caddr_t msg;
6439
6440				mutex_exit(&pptr->port_mutex);
6441
6442				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6443
6444				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6445					fpkt->pkt_timeout +=
6446					    FCP_TIMEOUT_DELTA;
6447				}
6448
6449				rval = fc_ulp_issue_els(pptr->port_fp_handle,
6450				    fpkt);
6451				if (rval == FC_SUCCESS) {
6452					return;
6453				}
6454
6455				if (rval == FC_STATEC_BUSY ||
6456				    rval == FC_OFFLINE) {
6457					fcp_queue_ipkt(pptr, fpkt);
6458					return;
6459				}
6460				(void) fc_ulp_error(rval, &msg);
6461
6462				fcp_log(CE_NOTE, pptr->port_dip,
6463				    "!ELS 0x%x failed to d_id=0x%x;"
6464				    " %s", icmd->ipkt_opcode,
6465				    ptgt->tgt_d_id, msg);
6466			} else {
6467				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6468				    fcp_trace, FCP_BUF_LEVEL_2, 0,
6469				    "fcp_icmd_callback,3: state change "
6470				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
6471				mutex_exit(&pptr->port_mutex);
6472			}
6473		}
6474	} else {
6475		if (fcp_is_retryable(icmd) &&
6476		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6477			if (FCP_MUST_RETRY(fpkt)) {
6478				fcp_queue_ipkt(pptr, fpkt);
6479				return;
6480			}
6481		}
6482		mutex_enter(&pptr->port_mutex);
6483		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6484		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6485			mutex_exit(&pptr->port_mutex);
6486			fcp_print_error(fpkt);
6487		} else {
6488			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6489			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6490			    "fcp_icmd_callback,4: state change occured"
6491			    " for D_ID=0x%x", ptgt->tgt_d_id);
6492			mutex_exit(&pptr->port_mutex);
6493		}
6494	}
6495
6496fail:
6497	if (free_pkt) {
6498		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6499		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6500		fcp_icmd_free(pptr, icmd);
6501	}
6502}
6503
6504
6505/*
6506 * called internally to send an info cmd using the transport
6507 *
6508 * sends either an INQ or a REPORT_LUN
6509 *
6510 * when the packet is completed fcp_scsi_callback is called
6511 */
6512static int
6513fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6514    int lcount, int tcount, int cause, uint32_t rscn_count)
6515{
6516	int			nodma;
6517	struct fcp_ipkt		*icmd;
6518	struct fcp_tgt		*ptgt;
6519	struct fcp_port		*pptr;
6520	fc_frame_hdr_t		*hp;
6521	fc_packet_t		*fpkt;
6522	struct fcp_cmd		fcp_cmd;
6523	struct fcp_cmd		*fcmd;
6524	union scsi_cdb		*scsi_cdb;
6525
6526	ASSERT(plun != NULL);
6527
6528	ptgt = plun->lun_tgt;
6529	ASSERT(ptgt != NULL);
6530
6531	pptr = ptgt->tgt_port;
6532	ASSERT(pptr != NULL);
6533
6534	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6535	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6536	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6537
6538	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6539	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6540	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6541	    rscn_count);
6542
6543	if (icmd == NULL) {
6544		return (DDI_FAILURE);
6545	}
6546
6547	fpkt = icmd->ipkt_fpkt;
6548	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6549	icmd->ipkt_retries = 0;
6550	icmd->ipkt_opcode = opcode;
6551	icmd->ipkt_lun = plun;
6552
6553	if (nodma) {
6554		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6555	} else {
6556		fcmd = &fcp_cmd;
6557	}
6558	bzero(fcmd, sizeof (struct fcp_cmd));
6559
6560	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6561
6562	hp = &fpkt->pkt_cmd_fhdr;
6563
6564	hp->s_id = pptr->port_id;
6565	hp->d_id = ptgt->tgt_d_id;
6566	hp->r_ctl = R_CTL_COMMAND;
6567	hp->type = FC_TYPE_SCSI_FCP;
6568	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6569	hp->rsvd = 0;
6570	hp->seq_id = 0;
6571	hp->seq_cnt = 0;
6572	hp->ox_id = 0xffff;
6573	hp->rx_id = 0xffff;
6574	hp->ro = 0;
6575
6576	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6577
6578	/*
6579	 * Request SCSI target for expedited processing
6580	 */
6581
6582	/*
6583	 * Set up for untagged queuing because we do not
6584	 * know if the fibre device supports queuing.
6585	 */
6586	fcmd->fcp_cntl.cntl_reserved_0 = 0;
6587	fcmd->fcp_cntl.cntl_reserved_1 = 0;
6588	fcmd->fcp_cntl.cntl_reserved_2 = 0;
6589	fcmd->fcp_cntl.cntl_reserved_3 = 0;
6590	fcmd->fcp_cntl.cntl_reserved_4 = 0;
6591	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6592	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6593
6594	switch (opcode) {
6595	case SCMD_INQUIRY_PAGE83:
6596		/*
6597		 * Prepare to get the Inquiry VPD page 83 information
6598		 */
6599		fcmd->fcp_cntl.cntl_read_data = 1;
6600		fcmd->fcp_cntl.cntl_write_data = 0;
6601		fcmd->fcp_data_len = alloc_len;
6602
6603		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6604		fpkt->pkt_comp = fcp_scsi_callback;
6605
6606		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6607		scsi_cdb->g0_addr2 = 0x01;
6608		scsi_cdb->g0_addr1 = 0x83;
6609		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6610		break;
6611
6612	case SCMD_INQUIRY:
6613		fcmd->fcp_cntl.cntl_read_data = 1;
6614		fcmd->fcp_cntl.cntl_write_data = 0;
6615		fcmd->fcp_data_len = alloc_len;
6616
6617		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6618		fpkt->pkt_comp = fcp_scsi_callback;
6619
6620		scsi_cdb->scc_cmd = SCMD_INQUIRY;
6621		scsi_cdb->g0_count0 = SUN_INQSIZE;
6622		break;
6623
6624	case SCMD_REPORT_LUN: {
6625		fc_portid_t	d_id;
6626		opaque_t	fca_dev;
6627
6628		ASSERT(alloc_len >= 16);
6629
6630		d_id.priv_lilp_posit = 0;
6631		d_id.port_id = ptgt->tgt_d_id;
6632
6633		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6634
6635		mutex_enter(&ptgt->tgt_mutex);
6636		ptgt->tgt_fca_dev = fca_dev;
6637		mutex_exit(&ptgt->tgt_mutex);
6638
6639		fcmd->fcp_cntl.cntl_read_data = 1;
6640		fcmd->fcp_cntl.cntl_write_data = 0;
6641		fcmd->fcp_data_len = alloc_len;
6642
6643		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6644		fpkt->pkt_comp = fcp_scsi_callback;
6645
6646		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6647		scsi_cdb->scc5_count0 = alloc_len & 0xff;
6648		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6649		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6650		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6651		break;
6652	}
6653
6654	default:
6655		fcp_log(CE_WARN, pptr->port_dip,
6656		    "!fcp_send_scsi Invalid opcode");
6657		break;
6658	}
6659
6660	if (!nodma) {
6661		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6662		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6663	}
6664
6665	mutex_enter(&pptr->port_mutex);
6666	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6667
6668		mutex_exit(&pptr->port_mutex);
6669		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6670		    FC_SUCCESS) {
6671			fcp_icmd_free(pptr, icmd);
6672			return (DDI_FAILURE);
6673		}
6674		return (DDI_SUCCESS);
6675	} else {
6676		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6677		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6678		    "fcp_send_scsi,1: state change occured"
6679		    " for D_ID=0x%x", ptgt->tgt_d_id);
6680		mutex_exit(&pptr->port_mutex);
6681		fcp_icmd_free(pptr, icmd);
6682		return (DDI_FAILURE);
6683	}
6684}
6685
6686
6687/*
6688 * called by fcp_scsi_callback to check to handle the case where
6689 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6690 */
6691static int
6692fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6693{
6694	uchar_t				rqlen;
6695	int				rval = DDI_FAILURE;
6696	struct scsi_extended_sense	sense_info, *sense;
6697	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
6698	    fpkt->pkt_ulp_private;
6699	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
6700	struct fcp_port		*pptr = ptgt->tgt_port;
6701
6702	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6703
6704	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6705		/*
6706		 * SCSI-II Reserve Release support. Some older FC drives return
6707		 * Reservation conflict for Report Luns command.
6708		 */
6709		if (icmd->ipkt_nodma) {
6710			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6711			rsp->fcp_u.fcp_status.sense_len_set = 0;
6712			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6713		} else {
6714			fcp_rsp_t	new_resp;
6715
6716			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6717			    fpkt->pkt_resp_acc, sizeof (new_resp));
6718
6719			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6720			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6721			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6722
6723			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6724			    fpkt->pkt_resp_acc, sizeof (new_resp));
6725		}
6726
6727		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6728		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6729
6730		return (DDI_SUCCESS);
6731	}
6732
6733	sense = &sense_info;
6734	if (!rsp->fcp_u.fcp_status.sense_len_set) {
6735		/* no need to continue if sense length is not set */
6736		return (rval);
6737	}
6738
6739	/* casting 64-bit integer to 8-bit */
6740	rqlen = (uchar_t)min(rsp->fcp_sense_len,
6741	    sizeof (struct scsi_extended_sense));
6742
6743	if (rqlen < 14) {
6744		/* no need to continue if request length isn't long enough */
6745		return (rval);
6746	}
6747
6748	if (icmd->ipkt_nodma) {
6749		/*
6750		 * We can safely use fcp_response_len here since the
6751		 * only path that calls fcp_check_reportlun,
6752		 * fcp_scsi_callback, has already called
6753		 * fcp_validate_fcp_response.
6754		 */
6755		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6756		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6757	} else {
6758		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6759		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6760		    sizeof (struct scsi_extended_sense));
6761	}
6762
6763	if (!FCP_SENSE_NO_LUN(sense)) {
6764		mutex_enter(&ptgt->tgt_mutex);
6765		/* clear the flag if any */
6766		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6767		mutex_exit(&ptgt->tgt_mutex);
6768	}
6769
6770	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6771	    (sense->es_add_code == 0x20)) {
6772		if (icmd->ipkt_nodma) {
6773			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6774			rsp->fcp_u.fcp_status.sense_len_set = 0;
6775			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6776		} else {
6777			fcp_rsp_t	new_resp;
6778
6779			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6780			    fpkt->pkt_resp_acc, sizeof (new_resp));
6781
6782			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6783			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6784			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6785
6786			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6787			    fpkt->pkt_resp_acc, sizeof (new_resp));
6788		}
6789
6790		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6791		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6792
6793		return (DDI_SUCCESS);
6794	}
6795
6796	/*
6797	 * This is for the STK library which returns a check condition,
6798	 * to indicate device is not ready, manual assistance needed.
6799	 * This is to a report lun command when the door is open.
6800	 */
6801	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6802		if (icmd->ipkt_nodma) {
6803			rsp->fcp_u.fcp_status.rsp_len_set = 0;
6804			rsp->fcp_u.fcp_status.sense_len_set = 0;
6805			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6806		} else {
6807			fcp_rsp_t	new_resp;
6808
6809			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6810			    fpkt->pkt_resp_acc, sizeof (new_resp));
6811
6812			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6813			new_resp.fcp_u.fcp_status.sense_len_set = 0;
6814			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6815
6816			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6817			    fpkt->pkt_resp_acc, sizeof (new_resp));
6818		}
6819
6820		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6821		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6822
6823		return (DDI_SUCCESS);
6824	}
6825
6826	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6827	    (FCP_SENSE_NO_LUN(sense))) {
6828		mutex_enter(&ptgt->tgt_mutex);
6829		if ((FCP_SENSE_NO_LUN(sense)) &&
6830		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6831			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6832			mutex_exit(&ptgt->tgt_mutex);
6833			/*
6834			 * reconfig was triggred by ILLEGAL REQUEST but
6835			 * got ILLEGAL REQUEST again
6836			 */
6837			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6838			    fcp_trace, FCP_BUF_LEVEL_3, 0,
6839			    "!FCP: Unable to obtain Report Lun data"
6840			    " target=%x", ptgt->tgt_d_id);
6841		} else {
6842			if (ptgt->tgt_tid == NULL) {
6843				timeout_id_t	tid;
6844				/*
6845				 * REPORT LUN data has changed.	 Kick off
6846				 * rediscovery
6847				 */
6848				tid = timeout(fcp_reconfigure_luns,
6849				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6850
6851				ptgt->tgt_tid = tid;
6852				ptgt->tgt_state |= FCP_TGT_BUSY;
6853			}
6854			if (FCP_SENSE_NO_LUN(sense)) {
6855				ptgt->tgt_state |= FCP_TGT_ILLREQ;
6856			}
6857			mutex_exit(&ptgt->tgt_mutex);
6858			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6859				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6860				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6861				    "!FCP:Report Lun Has Changed"
6862				    " target=%x", ptgt->tgt_d_id);
6863			} else if (FCP_SENSE_NO_LUN(sense)) {
6864				FCP_TRACE(fcp_logq, pptr->port_instbuf,
6865				    fcp_trace, FCP_BUF_LEVEL_3, 0,
6866				    "!FCP:LU Not Supported"
6867				    " target=%x", ptgt->tgt_d_id);
6868			}
6869		}
6870		rval = DDI_SUCCESS;
6871	}
6872
6873	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6874	    fcp_trace, FCP_BUF_LEVEL_5, 0,
6875	    "D_ID=%x, sense=%x, status=%x",
6876	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6877	    rsp->fcp_u.fcp_status.scsi_status);
6878
6879	return (rval);
6880}
6881
6882/*
6883 *     Function: fcp_scsi_callback
6884 *
6885 *  Description: This is the callback routine set by fcp_send_scsi() after
6886 *		 it calls fcp_icmd_alloc().  The SCSI command completed here
6887 *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
6888 *		 INQUIRY_PAGE83.
6889 *
6890 *     Argument: *fpkt	 FC packet used to convey the command
6891 *
6892 * Return Value: None
6893 */
6894static void
6895fcp_scsi_callback(fc_packet_t *fpkt)
6896{
6897	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
6898	    fpkt->pkt_ulp_private;
6899	struct fcp_rsp_info	fcp_rsp_err, *bep;
6900	struct fcp_port	*pptr;
6901	struct fcp_tgt	*ptgt;
6902	struct fcp_lun	*plun;
6903	struct fcp_rsp		response, *rsp;
6904
6905	ptgt = icmd->ipkt_tgt;
6906	pptr = ptgt->tgt_port;
6907	plun = icmd->ipkt_lun;
6908
6909	if (icmd->ipkt_nodma) {
6910		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6911	} else {
6912		rsp = &response;
6913		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6914		    sizeof (struct fcp_rsp));
6915	}
6916
6917	FCP_TRACE(fcp_logq, pptr->port_instbuf,
6918	    fcp_trace, FCP_BUF_LEVEL_2, 0,
6919	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
6920	    "status=%x, lun num=%x",
6921	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6922	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6923
6924	/*
6925	 * Pre-init LUN GUID with NWWN if it is not a device that
6926	 * supports multiple luns and we know it's not page83
6927	 * compliant.  Although using a NWWN is not lun unique,
6928	 * we will be fine since there is only one lun behind the taget
6929	 * in this case.
6930	 */
6931	if ((plun->lun_guid_size == 0) &&
6932	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6933	    (fcp_symmetric_device_probe(plun) == 0)) {
6934
6935		char ascii_wwn[FC_WWN_SIZE*2+1];
6936		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6937		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6938	}
6939
6940	/*
6941	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6942	 * when thay have more data than what is asked in CDB. An overrun
6943	 * is really when FCP_DL is smaller than the data length in CDB.
6944	 * In the case here we know that REPORT LUN command we formed within
6945	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6946	 * behavior. In reality this is FC_SUCCESS.
6947	 */
6948	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6949	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6950	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6951		fpkt->pkt_state = FC_PKT_SUCCESS;
6952	}
6953
6954	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6955		FCP_TRACE(fcp_logq, pptr->port_instbuf,
6956		    fcp_trace, FCP_BUF_LEVEL_2, 0,
6957		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6958		    ptgt->tgt_d_id);
6959
6960		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6961			/*
6962			 * Inquiry VPD page command on A5K SES devices would
6963			 * result in data CRC errors.
6964			 */
6965			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6966				(void) fcp_handle_page83(fpkt, icmd, 1);
6967				return;
6968			}
6969		}
6970		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6971		    FCP_MUST_RETRY(fpkt)) {
6972			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6973			fcp_retry_scsi_cmd(fpkt);
6974			return;
6975		}
6976
6977		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6978		    FCP_TGT_TRACE_20);
6979
6980		mutex_enter(&pptr->port_mutex);
6981		mutex_enter(&ptgt->tgt_mutex);
6982		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6983			mutex_exit(&ptgt->tgt_mutex);
6984			mutex_exit(&pptr->port_mutex);
6985			fcp_print_error(fpkt);
6986		} else {
6987			FCP_TRACE(fcp_logq, pptr->port_instbuf,
6988			    fcp_trace, FCP_BUF_LEVEL_2, 0,
6989			    "fcp_scsi_callback,1: state change occured"
6990			    " for D_ID=0x%x", ptgt->tgt_d_id);
6991			mutex_exit(&ptgt->tgt_mutex);
6992			mutex_exit(&pptr->port_mutex);
6993		}
6994		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6995		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
6996		fcp_icmd_free(pptr, icmd);
6997		return;
6998	}
6999
7000	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7001
7002	mutex_enter(&pptr->port_mutex);
7003	mutex_enter(&ptgt->tgt_mutex);
7004	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7005		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7006		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7007		    "fcp_scsi_callback,2: state change occured"
7008		    " for D_ID=0x%x", ptgt->tgt_d_id);
7009		mutex_exit(&ptgt->tgt_mutex);
7010		mutex_exit(&pptr->port_mutex);
7011		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7012		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7013		fcp_icmd_free(pptr, icmd);
7014		return;
7015	}
7016	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7017
7018	mutex_exit(&ptgt->tgt_mutex);
7019	mutex_exit(&pptr->port_mutex);
7020
7021	if (icmd->ipkt_nodma) {
7022		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7023		    sizeof (struct fcp_rsp));
7024	} else {
7025		bep = &fcp_rsp_err;
7026		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7027		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7028	}
7029
7030	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7031		fcp_retry_scsi_cmd(fpkt);
7032		return;
7033	}
7034
7035	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7036	    FCP_NO_FAILURE) {
7037		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7038		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7039		    "rsp_code=0x%x, rsp_len_set=0x%x",
7040		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7041		fcp_retry_scsi_cmd(fpkt);
7042		return;
7043	}
7044
7045	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7046	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7047		fcp_queue_ipkt(pptr, fpkt);
7048		return;
7049	}
7050
7051	/*
7052	 * Devices that do not support INQUIRY_PAGE83, return check condition
7053	 * with illegal request as per SCSI spec.
7054	 * Crossbridge is one such device and Daktari's SES node is another.
7055	 * We want to ideally enumerate these devices as a non-mpxio devices.
7056	 * SES nodes (Daktari only currently) are an exception to this.
7057	 */
7058	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7059	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7060
7061		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7062		    fcp_trace, FCP_BUF_LEVEL_3, 0,
7063		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7064		    "check condition. May enumerate as non-mpxio device",
7065		    ptgt->tgt_d_id, plun->lun_type);
7066
7067		/*
7068		 * If we let Daktari's SES be enumerated as a non-mpxio
7069		 * device, there will be a discrepency in that the other
7070		 * internal FC disks will get enumerated as mpxio devices.
7071		 * Applications like luxadm expect this to be consistent.
7072		 *
7073		 * So, we put in a hack here to check if this is an SES device
7074		 * and handle it here.
7075		 */
7076		if (plun->lun_type == DTYPE_ESI) {
7077			/*
7078			 * Since, pkt_state is actually FC_PKT_SUCCESS
7079			 * at this stage, we fake a failure here so that
7080			 * fcp_handle_page83 will create a device path using
7081			 * the WWN instead of the GUID which is not there anyway
7082			 */
7083			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7084			(void) fcp_handle_page83(fpkt, icmd, 1);
7085			return;
7086		}
7087
7088		mutex_enter(&ptgt->tgt_mutex);
7089		plun->lun_state &= ~(FCP_LUN_OFFLINE |
7090		    FCP_LUN_MARK | FCP_LUN_BUSY);
7091		mutex_exit(&ptgt->tgt_mutex);
7092
7093		(void) fcp_call_finish_init(pptr, ptgt,
7094		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7095		    icmd->ipkt_cause);
7096		fcp_icmd_free(pptr, icmd);
7097		return;
7098	}
7099
7100	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7101		int rval = DDI_FAILURE;
7102
7103		/*
7104		 * handle cases where report lun isn't supported
7105		 * by faking up our own REPORT_LUN response or
7106		 * UNIT ATTENTION
7107		 */
7108		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7109			rval = fcp_check_reportlun(rsp, fpkt);
7110
7111			/*
7112			 * fcp_check_reportlun might have modified the
7113			 * FCP response. Copy it in again to get an updated
7114			 * FCP response
7115			 */
7116			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7117				rsp = &response;
7118
7119				FCP_CP_IN(fpkt->pkt_resp, rsp,
7120				    fpkt->pkt_resp_acc,
7121				    sizeof (struct fcp_rsp));
7122			}
7123		}
7124
7125		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7126			if (rval == DDI_SUCCESS) {
7127				(void) fcp_call_finish_init(pptr, ptgt,
7128				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7129				    icmd->ipkt_cause);
7130				fcp_icmd_free(pptr, icmd);
7131			} else {
7132				fcp_retry_scsi_cmd(fpkt);
7133			}
7134
7135			return;
7136		}
7137	} else {
7138		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7139			mutex_enter(&ptgt->tgt_mutex);
7140			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7141			mutex_exit(&ptgt->tgt_mutex);
7142		}
7143	}
7144
7145	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7146	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7147		(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7148		    DDI_DMA_SYNC_FORCPU);
7149	}
7150
7151	switch (icmd->ipkt_opcode) {
7152	case SCMD_INQUIRY:
7153		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7154		fcp_handle_inquiry(fpkt, icmd);
7155		break;
7156
7157	case SCMD_REPORT_LUN:
7158		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7159		    FCP_TGT_TRACE_22);
7160		fcp_handle_reportlun(fpkt, icmd);
7161		break;
7162
7163	case SCMD_INQUIRY_PAGE83:
7164		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7165		(void) fcp_handle_page83(fpkt, icmd, 0);
7166		break;
7167
7168	default:
7169		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7170		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7171		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7172		fcp_icmd_free(pptr, icmd);
7173		break;
7174	}
7175}
7176
7177
7178static void
7179fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7180{
7181	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
7182	    fpkt->pkt_ulp_private;
7183	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
7184	struct fcp_port	*pptr = ptgt->tgt_port;
7185
7186	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7187	    fcp_is_retryable(icmd)) {
7188		mutex_enter(&pptr->port_mutex);
7189		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7190			mutex_exit(&pptr->port_mutex);
7191			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7192			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7193			    "Retrying %s to %x; state=%x, reason=%x",
7194			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7195			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7196			    fpkt->pkt_state, fpkt->pkt_reason);
7197
7198			fcp_queue_ipkt(pptr, fpkt);
7199		} else {
7200			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7201			    fcp_trace, FCP_BUF_LEVEL_3, 0,
7202			    "fcp_retry_scsi_cmd,1: state change occured"
7203			    " for D_ID=0x%x", ptgt->tgt_d_id);
7204			mutex_exit(&pptr->port_mutex);
7205			(void) fcp_call_finish_init(pptr, ptgt,
7206			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7207			    icmd->ipkt_cause);
7208			fcp_icmd_free(pptr, icmd);
7209		}
7210	} else {
7211		fcp_print_error(fpkt);
7212		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7213		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7214		fcp_icmd_free(pptr, icmd);
7215	}
7216}
7217
7218/*
7219 *     Function: fcp_handle_page83
7220 *
7221 *  Description: Treats the response to INQUIRY_PAGE83.
7222 *
7223 *     Argument: *fpkt	FC packet used to convey the command.
7224 *		 *icmd	Original fcp_ipkt structure.
7225 *		 ignore_page83_data
7226 *			if it's 1, that means it's a special devices's
7227 *			page83 response, it should be enumerated under mpxio
7228 *
7229 * Return Value: None
7230 */
7231static void
7232fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7233    int ignore_page83_data)
7234{
7235	struct fcp_port	*pptr;
7236	struct fcp_lun	*plun;
7237	struct fcp_tgt	*ptgt;
7238	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7239	int			fail = 0;
7240	ddi_devid_t		devid;
7241	char			*guid = NULL;
7242	int			ret;
7243
7244	ASSERT(icmd != NULL && fpkt != NULL);
7245
7246	pptr = icmd->ipkt_port;
7247	ptgt = icmd->ipkt_tgt;
7248	plun = icmd->ipkt_lun;
7249
7250	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7251		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7252
7253		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7254		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
7255
7256		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7257		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7258		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7259		    "dtype=0x%x, lun num=%x",
7260		    pptr->port_instance, ptgt->tgt_d_id,
7261		    dev_id_page[0], plun->lun_num);
7262
7263		ret = ddi_devid_scsi_encode(
7264		    DEVID_SCSI_ENCODE_VERSION_LATEST,
7265		    NULL,		/* driver name */
7266		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
7267		    sizeof (plun->lun_inq), /* size of standard inquiry */
7268		    NULL,		/* page 80 data */
7269		    0,		/* page 80 len */
7270		    dev_id_page,	/* page 83 data */
7271		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7272		    &devid);
7273
7274		if (ret == DDI_SUCCESS) {
7275
7276			guid = ddi_devid_to_guid(devid);
7277
7278			if (guid) {
7279				/*
7280				 * Check our current guid.  If it's non null
7281				 * and it has changed, we need to copy it into
7282				 * lun_old_guid since we might still need it.
7283				 */
7284				if (plun->lun_guid &&
7285				    strcmp(guid, plun->lun_guid)) {
7286					unsigned int len;
7287
7288					/*
7289					 * If the guid of the LUN changes,
7290					 * reconfiguration should be triggered
7291					 * to reflect the changes.
7292					 * i.e. we should offline the LUN with
7293					 * the old guid, and online the LUN with
7294					 * the new guid.
7295					 */
7296					plun->lun_state |= FCP_LUN_CHANGED;
7297
7298					if (plun->lun_old_guid) {
7299						kmem_free(plun->lun_old_guid,
7300						    plun->lun_old_guid_size);
7301					}
7302
7303					len = plun->lun_guid_size;
7304					plun->lun_old_guid_size = len;
7305
7306					plun->lun_old_guid = kmem_zalloc(len,
7307					    KM_NOSLEEP);
7308
7309					if (plun->lun_old_guid) {
7310						/*
7311						 * The alloc was successful then
7312						 * let's do the copy.
7313						 */
7314						bcopy(plun->lun_guid,
7315						    plun->lun_old_guid, len);
7316					} else {
7317						fail = 1;
7318						plun->lun_old_guid_size = 0;
7319					}
7320				}
7321				if (!fail) {
7322					if (fcp_copy_guid_2_lun_block(
7323					    plun, guid)) {
7324						fail = 1;
7325					}
7326				}
7327				ddi_devid_free_guid(guid);
7328
7329			} else {
7330				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7331				    fcp_trace, FCP_BUF_LEVEL_2, 0,
7332				    "fcp_handle_page83: unable to create "
7333				    "GUID");
7334
7335				/* couldn't create good guid from devid */
7336				fail = 1;
7337			}
7338			ddi_devid_free(devid);
7339
7340		} else if (ret == DDI_NOT_WELL_FORMED) {
7341			/* NULL filled data for page 83 */
7342			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7343			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7344			    "fcp_handle_page83: retry GUID");
7345
7346			icmd->ipkt_retries = 0;
7347			fcp_retry_scsi_cmd(fpkt);
7348			return;
7349		} else {
7350			FCP_TRACE(fcp_logq, pptr->port_instbuf,
7351			    fcp_trace, FCP_BUF_LEVEL_2, 0,
7352			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7353			    ret);
7354			/*
7355			 * Since the page83 validation
7356			 * introduced late, we are being
7357			 * tolerant to the existing devices
7358			 * that already found to be working
7359			 * under mpxio, like A5200's SES device,
7360			 * its page83 response will not be standard-compliant,
7361			 * but we still want it to be enumerated under mpxio.
7362			 */
7363			if (fcp_symmetric_device_probe(plun) != 0) {
7364				fail = 1;
7365			}
7366		}
7367
7368	} else {
7369		/* bad packet state */
7370		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7371
7372		/*
7373		 * For some special devices (A5K SES and Daktari's SES devices),
7374		 * they should be enumerated under mpxio
7375		 * or "luxadm dis" will fail
7376		 */
7377		if (ignore_page83_data) {
7378			fail = 0;
7379		} else {
7380			fail = 1;
7381		}
7382		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7383		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7384		    "!Devid page cmd failed. "
7385		    "fpkt_state: %x fpkt_reason: %x",
7386		    "ignore_page83: %d",
7387		    fpkt->pkt_state, fpkt->pkt_reason,
7388		    ignore_page83_data);
7389	}
7390
7391	mutex_enter(&pptr->port_mutex);
7392	mutex_enter(&plun->lun_mutex);
7393	/*
7394	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7395	 * mismatch between lun_cip and lun_mpxio.
7396	 */
7397	if (plun->lun_cip == NULL) {
7398		/*
7399		 * If we don't have a guid for this lun it's because we were
7400		 * unable to glean one from the page 83 response.  Set the
7401		 * control flag to 0 here to make sure that we don't attempt to
7402		 * enumerate it under mpxio.
7403		 */
7404		if (fail || pptr->port_mpxio == 0) {
7405			plun->lun_mpxio = 0;
7406		} else {
7407			plun->lun_mpxio = 1;
7408		}
7409	}
7410	mutex_exit(&plun->lun_mutex);
7411	mutex_exit(&pptr->port_mutex);
7412
7413	mutex_enter(&ptgt->tgt_mutex);
7414	plun->lun_state &=
7415	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7416	mutex_exit(&ptgt->tgt_mutex);
7417
7418	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7419	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7420
7421	fcp_icmd_free(pptr, icmd);
7422}
7423
7424/*
7425 *     Function: fcp_handle_inquiry
7426 *
7427 *  Description: Called by fcp_scsi_callback to handle the response to an
7428 *		 INQUIRY request.
7429 *
7430 *     Argument: *fpkt	FC packet used to convey the command.
7431 *		 *icmd	Original fcp_ipkt structure.
7432 *
7433 * Return Value: None
7434 */
7435static void
7436fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7437{
7438	struct fcp_port	*pptr;
7439	struct fcp_lun	*plun;
7440	struct fcp_tgt	*ptgt;
7441	uchar_t		dtype;
7442	uchar_t		pqual;
7443	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
7444
7445	ASSERT(icmd != NULL && fpkt != NULL);
7446
7447	pptr = icmd->ipkt_port;
7448	ptgt = icmd->ipkt_tgt;
7449	plun = icmd->ipkt_lun;
7450
7451	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7452	    sizeof (struct scsi_inquiry));
7453
7454	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7455	pqual = plun->lun_inq.inq_dtype >> 5;
7456
7457	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7458	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7459	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7460	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7461	    plun->lun_num, dtype, pqual);
7462
7463	if (pqual != 0) {
7464		/*
7465		 * Non-zero peripheral qualifier
7466		 */
7467		fcp_log(CE_CONT, pptr->port_dip,
7468		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7469		    "Device type=0x%x Peripheral qual=0x%x\n",
7470		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7471
7472		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7473		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7474		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7475		    "Device type=0x%x Peripheral qual=0x%x\n",
7476		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7477
7478		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7479
7480		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7481		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7482		fcp_icmd_free(pptr, icmd);
7483		return;
7484	}
7485
7486	/*
7487	 * If the device is already initialized, check the dtype
7488	 * for a change. If it has changed then update the flags
7489	 * so the create_luns will offline the old device and
7490	 * create the new device. Refer to bug: 4764752
7491	 */
7492	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7493		plun->lun_state |= FCP_LUN_CHANGED;
7494	}
7495	plun->lun_type = plun->lun_inq.inq_dtype;
7496
7497	/*
7498	 * This code is setting/initializing the throttling in the FCA
7499	 * driver.
7500	 */
7501	mutex_enter(&pptr->port_mutex);
7502	if (!pptr->port_notify) {
7503		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7504			uint32_t cmd = 0;
7505			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7506			    ((cmd & 0xFFFFFF00 >> 8) |
7507			    FCP_SVE_THROTTLE << 8));
7508			pptr->port_notify = 1;
7509			mutex_exit(&pptr->port_mutex);
7510			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7511			mutex_enter(&pptr->port_mutex);
7512		}
7513	}
7514
7515	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7516		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7517		    fcp_trace, FCP_BUF_LEVEL_2, 0,
7518		    "fcp_handle_inquiry,1:state change occured"
7519		    " for D_ID=0x%x", ptgt->tgt_d_id);
7520		mutex_exit(&pptr->port_mutex);
7521
7522		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7523		(void) fcp_call_finish_init(pptr, ptgt,
7524		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7525		    icmd->ipkt_cause);
7526		fcp_icmd_free(pptr, icmd);
7527		return;
7528	}
7529	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7530	mutex_exit(&pptr->port_mutex);
7531
7532	/* Retrieve the rscn count (if a valid one exists) */
7533	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7534		rscn_count = ((fc_ulp_rscn_info_t *)
7535		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7536	} else {
7537		rscn_count = FC_INVALID_RSCN_COUNT;
7538	}
7539
7540	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7541	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
7542	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7543	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7544		fcp_log(CE_WARN, NULL, "!failed to send page 83");
7545		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7546		(void) fcp_call_finish_init(pptr, ptgt,
7547		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7548		    icmd->ipkt_cause);
7549	}
7550
7551	/*
7552	 * Read Inquiry VPD Page 0x83 to uniquely
7553	 * identify this logical unit.
7554	 */
7555	fcp_icmd_free(pptr, icmd);
7556}
7557
7558/*
7559 *     Function: fcp_handle_reportlun
7560 *
7561 *  Description: Called by fcp_scsi_callback to handle the response to a
7562 *		 REPORT_LUN request.
7563 *
7564 *     Argument: *fpkt	FC packet used to convey the command.
7565 *		 *icmd	Original fcp_ipkt structure.
7566 *
7567 * Return Value: None
7568 */
7569static void
7570fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7571{
7572	int				i;
7573	int				nluns_claimed;
7574	int				nluns_bufmax;
7575	int				len;
7576	uint16_t			lun_num;
7577	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
7578	struct fcp_port			*pptr;
7579	struct fcp_tgt			*ptgt;
7580	struct fcp_lun			*plun;
7581	struct fcp_reportlun_resp	*report_lun;
7582
7583	pptr = icmd->ipkt_port;
7584	ptgt = icmd->ipkt_tgt;
7585	len = fpkt->pkt_datalen;
7586
7587	if ((len < FCP_LUN_HEADER) ||
7588	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7589		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7590		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7591		fcp_icmd_free(pptr, icmd);
7592		return;
7593	}
7594
7595	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7596	    fpkt->pkt_datalen);
7597
7598	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7599	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7600	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7601	    pptr->port_instance, ptgt->tgt_d_id);
7602
7603	/*
7604	 * Get the number of luns (which is supplied as LUNS * 8) the
7605	 * device claims it has.
7606	 */
7607	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7608
7609	/*
7610	 * Get the maximum number of luns the buffer submitted can hold.
7611	 */
7612	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7613
7614	/*
7615	 * Due to limitations of certain hardware, we support only 16 bit LUNs
7616	 */
7617	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7618		kmem_free(report_lun, len);
7619
7620		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7621		    " 0x%x number of LUNs for target=%x", nluns_claimed,
7622		    ptgt->tgt_d_id);
7623
7624		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7625		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7626		fcp_icmd_free(pptr, icmd);
7627		return;
7628	}
7629
7630	/*
7631	 * If there are more LUNs than we have allocated memory for,
7632	 * allocate more space and send down yet another report lun if
7633	 * the maximum number of attempts hasn't been reached.
7634	 */
7635	mutex_enter(&ptgt->tgt_mutex);
7636
7637	if ((nluns_claimed > nluns_bufmax) &&
7638	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7639
7640		struct fcp_lun *plun;
7641
7642		ptgt->tgt_report_lun_cnt++;
7643		plun = ptgt->tgt_lun;
7644		ASSERT(plun != NULL);
7645		mutex_exit(&ptgt->tgt_mutex);
7646
7647		kmem_free(report_lun, len);
7648
7649		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7650		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7651		    "!Dynamically discovered %d LUNs for D_ID=%x",
7652		    nluns_claimed, ptgt->tgt_d_id);
7653
7654		/* Retrieve the rscn count (if a valid one exists) */
7655		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7656			rscn_count = ((fc_ulp_rscn_info_t *)
7657			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7658			    ulp_rscn_count;
7659		} else {
7660			rscn_count = FC_INVALID_RSCN_COUNT;
7661		}
7662
7663		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7664		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7665		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7666		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7667			(void) fcp_call_finish_init(pptr, ptgt,
7668			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7669			    icmd->ipkt_cause);
7670		}
7671
7672		fcp_icmd_free(pptr, icmd);
7673		return;
7674	}
7675
7676	if (nluns_claimed > nluns_bufmax) {
7677		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7678		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7679		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7680		    "	 Number of LUNs lost=%x",
7681		    ptgt->tgt_port_wwn.raw_wwn[0],
7682		    ptgt->tgt_port_wwn.raw_wwn[1],
7683		    ptgt->tgt_port_wwn.raw_wwn[2],
7684		    ptgt->tgt_port_wwn.raw_wwn[3],
7685		    ptgt->tgt_port_wwn.raw_wwn[4],
7686		    ptgt->tgt_port_wwn.raw_wwn[5],
7687		    ptgt->tgt_port_wwn.raw_wwn[6],
7688		    ptgt->tgt_port_wwn.raw_wwn[7],
7689		    nluns_claimed - nluns_bufmax);
7690
7691		nluns_claimed = nluns_bufmax;
7692	}
7693	ptgt->tgt_lun_cnt = nluns_claimed;
7694
7695	/*
7696	 * Identify missing LUNs and print warning messages
7697	 */
7698	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7699		int offline;
7700		int exists = 0;
7701
7702		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7703
7704		for (i = 0; i < nluns_claimed && exists == 0; i++) {
7705			uchar_t		*lun_string;
7706
7707			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7708
7709			switch (lun_string[0] & 0xC0) {
7710			case FCP_LUN_ADDRESSING:
7711			case FCP_PD_ADDRESSING:
7712			case FCP_VOLUME_ADDRESSING:
7713				lun_num = ((lun_string[0] & 0x3F) << 8) |
7714				    lun_string[1];
7715				if (plun->lun_num == lun_num) {
7716					exists++;
7717					break;
7718				}
7719				break;
7720
7721			default:
7722				break;
7723			}
7724		}
7725
7726		if (!exists && !offline) {
7727			mutex_exit(&ptgt->tgt_mutex);
7728
7729			mutex_enter(&pptr->port_mutex);
7730			mutex_enter(&ptgt->tgt_mutex);
7731			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7732				/*
7733				 * set disappear flag when device was connected
7734				 */
7735				if (!(plun->lun_state &
7736				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7737					plun->lun_state |= FCP_LUN_DISAPPEARED;
7738				}
7739				mutex_exit(&ptgt->tgt_mutex);
7740				mutex_exit(&pptr->port_mutex);
7741				if (!(plun->lun_state &
7742				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
7743					fcp_log(CE_NOTE, pptr->port_dip,
7744					    "!Lun=%x for target=%x disappeared",
7745					    plun->lun_num, ptgt->tgt_d_id);
7746				}
7747				mutex_enter(&ptgt->tgt_mutex);
7748			} else {
7749				FCP_TRACE(fcp_logq, pptr->port_instbuf,
7750				    fcp_trace, FCP_BUF_LEVEL_5, 0,
7751				    "fcp_handle_reportlun,1: state change"
7752				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
7753				mutex_exit(&ptgt->tgt_mutex);
7754				mutex_exit(&pptr->port_mutex);
7755				kmem_free(report_lun, len);
7756				(void) fcp_call_finish_init(pptr, ptgt,
7757				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7758				    icmd->ipkt_cause);
7759				fcp_icmd_free(pptr, icmd);
7760				return;
7761			}
7762		} else if (exists) {
7763			/*
7764			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7765			 * actually exists in REPORT_LUN response
7766			 */
7767			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7768				plun->lun_state &=
7769				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
7770			}
7771			if (offline || plun->lun_num == 0) {
7772				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7773					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7774					mutex_exit(&ptgt->tgt_mutex);
7775					fcp_log(CE_NOTE, pptr->port_dip,
7776					    "!Lun=%x for target=%x reappeared",
7777					    plun->lun_num, ptgt->tgt_d_id);
7778					mutex_enter(&ptgt->tgt_mutex);
7779				}
7780			}
7781		}
7782	}
7783
7784	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7785	mutex_exit(&ptgt->tgt_mutex);
7786
7787	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7788	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7789	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7790	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7791
7792	/* scan each lun */
7793	for (i = 0; i < nluns_claimed; i++) {
7794		uchar_t	*lun_string;
7795
7796		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7797
7798		FCP_TRACE(fcp_logq, pptr->port_instbuf,
7799		    fcp_trace, FCP_BUF_LEVEL_5, 0,
7800		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7801		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7802		    lun_string[0]);
7803
7804		switch (lun_string[0] & 0xC0) {
7805		case FCP_LUN_ADDRESSING:
7806		case FCP_PD_ADDRESSING:
7807		case FCP_VOLUME_ADDRESSING:
7808			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7809
7810			/* We will skip masked LUNs because of the blacklist. */
7811			if (fcp_lun_blacklist != NULL) {
7812				mutex_enter(&ptgt->tgt_mutex);
7813				if (fcp_should_mask(&ptgt->tgt_port_wwn,
7814				    lun_num) == TRUE) {
7815					ptgt->tgt_lun_cnt--;
7816					mutex_exit(&ptgt->tgt_mutex);
7817					break;
7818				}
7819				mutex_exit(&ptgt->tgt_mutex);
7820			}
7821
7822			/* see if this LUN is already allocated */
7823			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7824				plun = fcp_alloc_lun(ptgt);
7825				if (plun == NULL) {
7826					fcp_log(CE_NOTE, pptr->port_dip,
7827					    "!Lun allocation failed"
7828					    " target=%x lun=%x",
7829					    ptgt->tgt_d_id, lun_num);
7830					break;
7831				}
7832			}
7833
7834			mutex_enter(&plun->lun_tgt->tgt_mutex);
7835			/* convert to LUN */
7836			plun->lun_addr.ent_addr_0 =
7837			    BE_16(*(uint16_t *)&(lun_string[0]));
7838			plun->lun_addr.ent_addr_1 =
7839			    BE_16(*(uint16_t *)&(lun_string[2]));
7840			plun->lun_addr.ent_addr_2 =
7841			    BE_16(*(uint16_t *)&(lun_string[4]));
7842			plun->lun_addr.ent_addr_3 =
7843			    BE_16(*(uint16_t *)&(lun_string[6]));
7844
7845			plun->lun_num = lun_num;
7846			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7847			plun->lun_state &= ~FCP_LUN_OFFLINE;
7848			mutex_exit(&plun->lun_tgt->tgt_mutex);
7849
7850			/* Retrieve the rscn count (if a valid one exists) */
7851			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7852				rscn_count = ((fc_ulp_rscn_info_t *)
7853				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7854				    ulp_rscn_count;
7855			} else {
7856				rscn_count = FC_INVALID_RSCN_COUNT;
7857			}
7858
7859			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7860			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7861			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7862				mutex_enter(&pptr->port_mutex);
7863				mutex_enter(&plun->lun_tgt->tgt_mutex);
7864				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7865					fcp_log(CE_NOTE, pptr->port_dip,
7866					    "!failed to send INQUIRY"
7867					    " target=%x lun=%x",
7868					    ptgt->tgt_d_id, plun->lun_num);
7869				} else {
7870					FCP_TRACE(fcp_logq,
7871					    pptr->port_instbuf, fcp_trace,
7872					    FCP_BUF_LEVEL_5, 0,
7873					    "fcp_handle_reportlun,2: state"
7874					    " change occured for D_ID=0x%x",
7875					    ptgt->tgt_d_id);
7876				}
7877				mutex_exit(&plun->lun_tgt->tgt_mutex);
7878				mutex_exit(&pptr->port_mutex);
7879			} else {
7880				continue;
7881			}
7882			break;
7883
7884		default:
7885			fcp_log(CE_WARN, NULL,
7886			    "!Unsupported LUN Addressing method %x "
7887			    "in response to REPORT_LUN", lun_string[0]);
7888			break;
7889		}
7890
7891		/*
7892		 * each time through this loop we should decrement
7893		 * the tmp_cnt by one -- since we go through this loop
7894		 * one time for each LUN, the tmp_cnt should never be <=0
7895		 */
7896		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7897		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7898	}
7899
7900	if (i == 0) {
7901		fcp_log(CE_WARN, pptr->port_dip,
7902		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7903		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7904		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
7905	}
7906
7907	kmem_free(report_lun, len);
7908	fcp_icmd_free(pptr, icmd);
7909}
7910
7911
7912/*
7913 * called internally to return a LUN given a target and a LUN number
7914 */
7915static struct fcp_lun *
7916fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7917{
7918	struct fcp_lun	*plun;
7919
7920	mutex_enter(&ptgt->tgt_mutex);
7921	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7922		if (plun->lun_num == lun_num) {
7923			mutex_exit(&ptgt->tgt_mutex);
7924			return (plun);
7925		}
7926	}
7927	mutex_exit(&ptgt->tgt_mutex);
7928
7929	return (NULL);
7930}
7931
7932
7933/*
7934 * handle finishing one target for fcp_finish_init
7935 *
7936 * return true (non-zero) if we want finish_init to continue with the
7937 * next target
7938 *
7939 * called with the port mutex held
7940 */
7941/*ARGSUSED*/
7942static int
7943fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7944    int link_cnt, int tgt_cnt, int cause)
7945{
7946	int	rval = 1;
7947	ASSERT(pptr != NULL);
7948	ASSERT(ptgt != NULL);
7949
7950	FCP_TRACE(fcp_logq, pptr->port_instbuf,
7951	    fcp_trace, FCP_BUF_LEVEL_5, 0,
7952	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7953	    ptgt->tgt_state);
7954
7955	ASSERT(mutex_owned(&pptr->port_mutex));
7956
7957	if ((pptr->port_link_cnt != link_cnt) ||
7958	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7959		/*
7960		 * oh oh -- another link reset or target change
7961		 * must have occurred while we are in here
7962		 */
7963		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7964
7965		return (0);
7966	} else {
7967		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7968	}
7969
7970	mutex_enter(&ptgt->tgt_mutex);
7971
7972	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7973		/*
7974		 * tgt is not offline -- is it marked (i.e. needs
7975		 * to be offlined) ??
7976		 */
7977		if (ptgt->tgt_state & FCP_TGT_MARK) {
7978			/*
7979			 * this target not offline *and*
7980			 * marked
7981			 */
7982			ptgt->tgt_state &= ~FCP_TGT_MARK;
7983			rval = fcp_offline_target(pptr, ptgt, link_cnt,
7984			    tgt_cnt, 0, 0);
7985		} else {
7986			ptgt->tgt_state &= ~FCP_TGT_BUSY;
7987
7988			/* create the LUNs */
7989			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7990				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7991				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7992				    cause);
7993				ptgt->tgt_device_created = 1;
7994			} else {
7995				fcp_update_tgt_state(ptgt, FCP_RESET,
7996				    FCP_LUN_BUSY);
7997			}
7998		}
7999	}
8000
8001	mutex_exit(&ptgt->tgt_mutex);
8002
8003	return (rval);
8004}
8005
8006
8007/*
8008 * this routine is called to finish port initialization
8009 *
8010 * Each port has a "temp" counter -- when a state change happens (e.g.
8011 * port online), the temp count is set to the number of devices in the map.
8012 * Then, as each device gets "discovered", the temp counter is decremented
8013 * by one.  When this count reaches zero we know that all of the devices
8014 * in the map have been discovered (or an error has occurred), so we can
8015 * then finish initialization -- which is done by this routine (well, this
8016 * and fcp-finish_tgt())
8017 *
8018 * acquires and releases the global mutex
8019 *
8020 * called with the port mutex owned
8021 */
8022static void
8023fcp_finish_init(struct fcp_port *pptr)
8024{
8025#ifdef	DEBUG
8026	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8027	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8028	    FCP_STACK_DEPTH);
8029#endif /* DEBUG */
8030
8031	ASSERT(mutex_owned(&pptr->port_mutex));
8032
8033	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8034	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8035	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8036
8037	if ((pptr->port_state & FCP_STATE_ONLINING) &&
8038	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
8039	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8040		pptr->port_state &= ~FCP_STATE_ONLINING;
8041		pptr->port_state |= FCP_STATE_ONLINE;
8042	}
8043
8044	/* Wake up threads waiting on config done */
8045	cv_broadcast(&pptr->port_config_cv);
8046}
8047
8048
8049/*
8050 * called from fcp_finish_init to create the LUNs for a target
8051 *
8052 * called with the port mutex owned
8053 */
8054static void
8055fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8056{
8057	struct fcp_lun	*plun;
8058	struct fcp_port	*pptr;
8059	child_info_t		*cip = NULL;
8060
8061	ASSERT(ptgt != NULL);
8062	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8063
8064	pptr = ptgt->tgt_port;
8065
8066	ASSERT(pptr != NULL);
8067
8068	/* scan all LUNs for this target */
8069	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8070		if (plun->lun_state & FCP_LUN_OFFLINE) {
8071			continue;
8072		}
8073
8074		if (plun->lun_state & FCP_LUN_MARK) {
8075			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8076			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8077			    "fcp_create_luns: offlining marked LUN!");
8078			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8079			continue;
8080		}
8081
8082		plun->lun_state &= ~FCP_LUN_BUSY;
8083
8084		/*
8085		 * There are conditions in which FCP_LUN_INIT flag is cleared
8086		 * but we have a valid plun->lun_cip. To cover this case also
8087		 * CLEAR_BUSY whenever we have a valid lun_cip.
8088		 */
8089		if (plun->lun_mpxio && plun->lun_cip &&
8090		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8091		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8092		    0, 0))) {
8093			FCP_TRACE(fcp_logq, pptr->port_instbuf,
8094			    fcp_trace, FCP_BUF_LEVEL_2, 0,
8095			    "fcp_create_luns: enable lun %p failed!",
8096			    plun);
8097		}
8098
8099		if (plun->lun_state & FCP_LUN_INIT &&
8100		    !(plun->lun_state & FCP_LUN_CHANGED)) {
8101			continue;
8102		}
8103
8104		if (cause == FCP_CAUSE_USER_CREATE) {
8105			continue;
8106		}
8107
8108		FCP_TRACE(fcp_logq, pptr->port_instbuf,
8109		    fcp_trace, FCP_BUF_LEVEL_6, 0,
8110		    "create_luns: passing ONLINE elem to HP thread");
8111
8112		/*
8113		 * If lun has changed, prepare for offlining the old path.
8114		 * Do not offline the old path right now, since it may be
8115		 * still opened.
8116		 */
8117		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8118			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8119		}
8120
8121		/* pass an ONLINE element to the hotplug thread */
8122		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8123		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8124
8125			/*
8126			 * We can not synchronous attach (i.e pass
8127			 * NDI_ONLINE_ATTACH) here as we might be
8128			 * coming from an interrupt or callback
8129			 * thread.
8130			 */
8131			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8132			    link_cnt, tgt_cnt, 0, 0)) {
8133				fcp_log(CE_CONT, pptr->port_dip,
8134				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8135				    plun->lun_tgt->tgt_d_id, plun->lun_num);
8136			}
8137		}
8138	}
8139}
8140
8141
8142/*
8143 * function to online/offline devices
8144 */
8145static int
8146fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8147    int online, int lcount, int tcount, int flags)
8148{
8149	int			rval = NDI_FAILURE;
8150	int			circ;
8151	child_info_t		*ccip;
8152	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
8153	int			is_mpxio = pptr->port_mpxio;
8154	dev_info_t		*cdip, *pdip;
8155	char			*devname;
8156
8157	if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8158		/*
8159		 * When this event gets serviced, lun_cip and lun_mpxio
8160		 * has changed, so it should be invalidated now.
8161		 */
8162		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8163		    FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8164		    "plun: %p, cip: %p, what:%d", plun, cip, online);
8165		return (rval);
8166	}
8167
8168	FCP_TRACE(fcp_logq, pptr->port_instbuf,
8169	    fcp_trace, FCP_BUF_LEVEL_2, 0,
8170	    "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8171	    "flags=%x mpxio=%x\n",
8172	    plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8173	    plun->lun_mpxio);
8174
8175	/*
8176	 * lun_mpxio needs checking here because we can end up in a race
8177	 * condition where this task has been dispatched while lun_mpxio is
8178	 * set, but an earlier FCP_ONLINE task for the same LUN tried to
8179	 * enable MPXIO for the LUN, but was unable to, and hence cleared
8180	 * the flag. We rely on the serialization of the tasks here. We return
8181	 * NDI_SUCCESS so any callers continue without reporting spurious
8182	 * errors, and the still think we're an MPXIO LUN.
8183	 */
8184
8185	if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8186	    online == FCP_MPXIO_PATH_SET_BUSY) {
8187		if (plun->lun_mpxio) {
8188			rval = fcp_update_mpxio_path(plun, cip, online);
8189		} else {
8190			rval = NDI_SUCCESS;
8191		}
8192		return (rval);
8193	}
8194
8195	/*
8196	 * Explicit devfs_clean() due to ndi_devi_offline() not
8197	 * executing devfs_clean() if parent lock is held.
8198	 */
8199	ASSERT(!servicing_interrupt());
8200	if (online == FCP_OFFLINE) {
8201		if (plun->lun_mpxio == 0) {
8202			if (plun->lun_cip == cip) {
8203				cdip = DIP(plun->lun_cip);
8204			} else {
8205				cdip = DIP(cip);
8206			}
8207		} else if ((plun->lun_cip == cip) && plun->lun_cip) {
8208			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8209		} else if ((plun->lun_cip != cip) && cip) {
8210			/*
8211			 * This means a DTYPE/GUID change, we shall get the
8212			 * dip of the old cip instead of the current lun_cip.
8213			 */
8214			cdip = mdi_pi_get_client(PIP(cip));
8215		}
8216		if (cdip) {
8217			if (i_ddi_devi_attached(cdip)) {
8218				pdip = ddi_get_parent(cdip);
8219				devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8220				ndi_devi_enter(pdip, &circ);
8221				(void) ddi_deviname(cdip, devname);
8222				ndi_devi_exit(pdip, circ);
8223				/*
8224				 * Release parent lock before calling
8225				 * devfs_clean().
8226				 */
8227				rval = devfs_clean(pdip, devname + 1,
8228				    DV_CLEAN_FORCE);
8229				kmem_free(devname, MAXNAMELEN + 1);
8230				/*
8231				 * Return if devfs_clean() fails for
8232				 * non-MPXIO case.
8233				 * For MPXIO case, another path could be
8234				 * offlined.
8235				 */
8236				if (rval && plun->lun_mpxio == 0) {
8237					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8238					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8239					    "fcp_trigger_lun: devfs_clean "
8240					    "failed rval=%x  dip=%p",
8241					    rval, pdip);
8242					return (NDI_FAILURE);
8243				}
8244			}
8245		}
8246	}
8247
8248	if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8249		return (NDI_FAILURE);
8250	}
8251
8252	if (is_mpxio) {
8253		mdi_devi_enter(pptr->port_dip, &circ);
8254	} else {
8255		ndi_devi_enter(pptr->port_dip, &circ);
8256	}
8257
8258	mutex_enter(&pptr->port_mutex);
8259	mutex_enter(&plun->lun_mutex);
8260
8261	if (online == FCP_ONLINE) {
8262		ccip = fcp_get_cip(plun, cip, lcount, tcount);
8263		if (ccip == NULL) {
8264			goto fail;
8265		}
8266	} else {
8267		if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8268			goto fail;
8269		}
8270		ccip = cip;
8271	}
8272
8273	if (online == FCP_ONLINE) {
8274		rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8275		    &circ);
8276		fc_ulp_log_device_event(pptr->port_fp_handle,
8277		    FC_ULP_DEVICE_ONLINE);
8278	} else {
8279		rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8280		    &circ);
8281		fc_ulp_log_device_event(pptr->port_fp_handle,
8282		    FC_ULP_DEVICE_OFFLINE);
8283	}
8284
8285fail:	mutex_exit(&plun->lun_mutex);
8286	mutex_exit(&pptr->port_mutex);
8287
8288	if (is_mpxio) {
8289		mdi_devi_exit(pptr->port_dip, circ);
8290	} else {
8291		ndi_devi_exit(pptr->port_dip, circ);
8292	}
8293
8294	fc_ulp_idle_port(pptr->port_fp_handle);
8295
8296	return (rval);
8297}
8298
8299
8300/*
8301 * take a target offline by taking all of its LUNs offline
8302 */
8303/*ARGSUSED*/
8304static int
8305fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8306    int link_cnt, int tgt_cnt, int nowait, int flags)
8307{
8308	struct fcp_tgt_elem	*elem;
8309
8310	ASSERT(mutex_owned(&pptr->port_mutex));
8311	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8312
8313	ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8314
8315	if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8316	    ptgt->tgt_change_cnt)) {
8317		mutex_exit(&ptgt->tgt_mutex);
8318		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8319		mutex_enter(&ptgt->tgt_mutex);
8320
8321		return (0);
8322	}
8323
8324	ptgt->tgt_pd_handle = NULL;
8325	mutex_exit(&ptgt->tgt_mutex);
8326	FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8327	mutex_enter(&ptgt->tgt_mutex);
8328
8329	tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8330
8331	if (ptgt->tgt_tcap &&
8332	    (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8333		elem->flags = flags;
8334		elem->time = fcp_watchdog_time;
8335		if (nowait == 0) {
8336			elem->time += fcp_offline_delay;
8337		}
8338		elem->ptgt = ptgt;
8339		elem->link_cnt = link_cnt;
8340		elem->tgt_cnt = tgt_cnt;
8341		elem->next = pptr->port_offline_tgts;
8342		pptr->port_offline_tgts = elem;
8343	} else {
8344		fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8345	}
8346
8347	return (1);
8348}
8349
8350
8351static void
8352fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8353    int link_cnt, int tgt_cnt, int flags)
8354{
8355	ASSERT(mutex_owned(&pptr->port_mutex));
8356	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8357
8358	fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8359	ptgt->tgt_state = FCP_TGT_OFFLINE;
8360	ptgt->tgt_pd_handle = NULL;
8361	fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8362}
8363
8364
8365static void
8366fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8367    int flags)
8368{
8369	struct	fcp_lun	*plun;
8370
8371	ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8372	ASSERT(mutex_owned(&ptgt->tgt_mutex));
8373
8374	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8375		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8376			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8377		}
8378	}
8379}
8380
8381
8382/*
8383 * take a LUN offline
8384 *
8385 * enters and leaves with the target mutex held, releasing it in the process
8386 *
8387 * allocates memory in non-sleep mode
8388 */
8389static void
8390fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8391    int nowait, int flags)
8392{
8393	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
8394	struct fcp_lun_elem	*elem;
8395
8396	ASSERT(plun != NULL);
8397	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8398
8399	if (nowait) {
8400		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8401		return;
8402	}
8403
8404	if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8405		elem->flags = flags;
8406		elem->time = fcp_watchdog_time;
8407		if (nowait == 0) {
8408			elem->time += fcp_offline_delay;
8409		}
8410		elem->plun = plun;
8411		elem->link_cnt = link_cnt;
8412		elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8413		elem->next = pptr->port_offline_luns;
8414		pptr->port_offline_luns = elem;
8415	} else {
8416		fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8417	}
8418}
8419
8420
8421static void
8422fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8423{
8424	struct fcp_pkt	*head = NULL;
8425
8426	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8427
8428	mutex_exit(&LUN_TGT->tgt_mutex);
8429
8430	head = fcp_scan_commands(plun);
8431	if (head != NULL) {
8432		fcp_abort_commands(head, LUN_PORT);
8433	}
8434
8435	mutex_enter(&LUN_TGT->tgt_mutex);
8436
8437	if (plun->lun_cip && plun->lun_mpxio) {
8438		/*
8439		 * Intimate MPxIO lun busy is cleared
8440		 */
8441		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8442		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8443		    0, 0)) {
8444			fcp_log(CE_NOTE, LUN_PORT->port_dip,
8445			    "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8446			    LUN_TGT->tgt_d_id, plun->lun_num);
8447		}
8448		/*
8449		 * Intimate MPxIO that the lun is now marked for offline
8450		 */
8451		mutex_exit(&LUN_TGT->tgt_mutex);
8452		(void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8453		mutex_enter(&LUN_TGT->tgt_mutex);
8454	}
8455}
8456
8457static void
8458fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8459    int flags)
8460{
8461	ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8462
8463	mutex_exit(&LUN_TGT->tgt_mutex);
8464	fcp_update_offline_flags(plun);
8465	mutex_enter(&LUN_TGT->tgt_mutex);
8466
8467	fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8468
8469	FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8470	    fcp_trace, FCP_BUF_LEVEL_4, 0,
8471	    "offline_lun: passing OFFLINE elem to HP thread");
8472
8473	if (plun->lun_cip) {
8474		fcp_log(CE_NOTE, LUN_PORT->port_dip,
8475		    "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8476		    plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8477		    LUN_TGT->tgt_trace);
8478
8479		if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8480		    link_cnt, tgt_cnt, flags, 0)) {
8481			fcp_log(CE_CONT, LUN_PORT->port_dip,
8482			    "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8483			    LUN_TGT->tgt_d_id, plun->lun_num);
8484		}
8485	}
8486}
8487
8488static void
8489fcp_scan_offline_luns(struct fcp_port *pptr)
8490{
8491	struct fcp_lun_elem	*elem;
8492	struct fcp_lun_elem	*prev;
8493	struct fcp_lun_elem	*next;
8494
8495	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8496
8497	prev = NULL;
8498	elem = pptr->port_offline_luns;
8499	while (elem) {
8500		next = elem->next;
8501		if (elem->time <= fcp_watchdog_time) {
8502			int			changed = 1;
8503			struct fcp_tgt	*ptgt = elem->plun->lun_tgt;
8504
8505			mutex_enter(&ptgt->tgt_mutex);
8506			if (pptr->port_link_cnt == elem->link_cnt &&
8507			    ptgt->tgt_change_cnt == elem->tgt_cnt) {
8508				changed = 0;
8509			}
8510
8511			if (!changed &&
8512			    !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8513				fcp_offline_lun_now(elem->plun,
8514				    elem->link_cnt, elem->tgt_cnt, elem->flags);
8515			}
8516			mutex_exit(&ptgt->tgt_mutex);
8517
8518			kmem_free(elem, sizeof (*elem));
8519
8520			if (prev) {
8521				prev->next = next;
8522			} else {
8523				pptr->port_offline_luns = next;
8524			}
8525		} else {
8526			prev = elem;
8527		}
8528		elem = next;
8529	}
8530}
8531
8532
8533static void
8534fcp_scan_offline_tgts(struct fcp_port *pptr)
8535{
8536	struct fcp_tgt_elem	*elem;
8537	struct fcp_tgt_elem	*prev;
8538	struct fcp_tgt_elem	*next;
8539
8540	ASSERT(MUTEX_HELD(&pptr->port_mutex));
8541
8542	prev = NULL;
8543	elem = pptr->port_offline_tgts;
8544	while (elem) {
8545		next = elem->next;
8546		if (elem->time <= fcp_watchdog_time) {
8547			int		outdated = 1;
8548			struct fcp_tgt	*ptgt = elem->ptgt;
8549
8550			mutex_enter(&ptgt->tgt_mutex);
8551
8552			if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8553				/* No change on tgt since elem was created. */
8554				outdated = 0;
8555			} else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8556			    pptr->port_link_cnt == elem->link_cnt + 1 &&
8557			    ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8558				/*
8559				 * Exactly one thing happened to the target
8560				 * inbetween: the local port went offline.
8561				 * For fp the remote port is already gone so
8562				 * it will not tell us again to offline the
8563				 * target. We must offline it now.
8564				 */
8565				outdated = 0;
8566			}
8567
8568			if (!outdated && !(ptgt->tgt_state &
8569			    FCP_TGT_OFFLINE)) {
8570				fcp_offline_target_now(pptr,
8571				    ptgt, elem->link_cnt, elem->tgt_cnt,
8572				    elem->flags);
8573			}
8574
8575			mutex_exit(&ptgt->tgt_mutex);
8576
8577			kmem_free(elem, sizeof (*elem));
8578
8579			if (prev) {
8580				prev->next = next;
8581			} else {
8582				pptr->port_offline_tgts = next;
8583			}
8584		} else {
8585			prev = elem;
8586		}
8587		elem = next;
8588	}
8589}
8590
8591
8592static void
8593fcp_update_offline_flags(struct fcp_lun *plun)
8594{
8595	struct fcp_port	*pptr = LUN_PORT;
8596	ASSERT(plun != NULL);
8597
8598	mutex_enter(&LUN_TGT->tgt_mutex);
8599	plun->lun_state |= FCP_LUN_OFFLINE;
8600	plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8601
8602	mutex_enter(&plun->lun_mutex);
8603	if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8604		dev_info_t *cdip = NULL;
8605
8606		mutex_exit(&LUN_TGT->tgt_mutex);
8607
8608		if (plun->lun_mpxio == 0) {
8609			cdip = DIP(plun->lun_cip);
8610		} else if (plun->lun_cip) {
8611			cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8612		}
8613
8614		mutex_exit(&plun->lun_mutex);
8615		if (cdip) {
8616			(void) ndi_event_retrieve_cookie(
8617			    pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8618			    &fcp_remove_eid, NDI_EVENT_NOPASS);
8619			(void) ndi_event_run_callbacks(
8620			    pptr->port_ndi_event_hdl, cdip,
8621			    fcp_remove_eid, NULL);
8622		}
8623	} else {
8624		mutex_exit(&plun->lun_mutex);
8625		mutex_exit(&LUN_TGT->tgt_mutex);
8626	}
8627}
8628
8629
8630/*
8631 * Scan all of the command pkts for this port, moving pkts that
8632 * match our LUN onto our own list (headed by "head")
8633 */
8634static struct fcp_pkt *
8635fcp_scan_commands(struct fcp_lun *plun)
8636{
8637	struct fcp_port	*pptr = LUN_PORT;
8638
8639	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8640	struct fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8641	struct fcp_pkt	*pcmd = NULL;	/* the previous command */
8642
8643	struct fcp_pkt	*head = NULL;	/* head of our list */
8644	struct fcp_pkt	*tail = NULL;	/* tail of our list */
8645
8646	int			cmds_found = 0;
8647
8648	mutex_enter(&pptr->port_pkt_mutex);
8649	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8650		struct fcp_lun *tlun =
8651		    ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8652
8653		ncmd = cmd->cmd_next;	/* set next command */
8654
8655		/*
8656		 * if this pkt is for a different LUN  or the
8657		 * command is sent down, skip it.
8658		 */
8659		if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8660		    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8661			pcmd = cmd;
8662			continue;
8663		}
8664		cmds_found++;
8665		if (pcmd != NULL) {
8666			ASSERT(pptr->port_pkt_head != cmd);
8667			pcmd->cmd_next = cmd->cmd_next;
8668		} else {
8669			ASSERT(cmd == pptr->port_pkt_head);
8670			pptr->port_pkt_head = cmd->cmd_next;
8671		}
8672
8673		if (cmd == pptr->port_pkt_tail) {
8674			pptr->port_pkt_tail = pcmd;
8675			if (pcmd) {
8676				pcmd->cmd_next = NULL;
8677			}
8678		}
8679
8680		if (head == NULL) {
8681			head = tail = cmd;
8682		} else {
8683			ASSERT(tail != NULL);
8684
8685			tail->cmd_next = cmd;
8686			tail = cmd;
8687		}
8688		cmd->cmd_next = NULL;
8689	}
8690	mutex_exit(&pptr->port_pkt_mutex);
8691
8692	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8693	    fcp_trace, FCP_BUF_LEVEL_8, 0,
8694	    "scan commands: %d cmd(s) found", cmds_found);
8695
8696	return (head);
8697}
8698
8699
8700/*
8701 * Abort all the commands in the command queue
8702 */
8703static void
8704fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8705{
8706	struct fcp_pkt	*cmd = NULL;	/* pkt cmd ptr */
8707	struct	fcp_pkt	*ncmd = NULL;	/* next pkt ptr */
8708
8709	ASSERT(mutex_owned(&pptr->port_mutex));
8710
8711	/* scan through the pkts and invalid them */
8712	for (cmd = head; cmd != NULL; cmd = ncmd) {
8713		struct scsi_pkt *pkt = cmd->cmd_pkt;
8714
8715		ncmd = cmd->cmd_next;
8716		ASSERT(pkt != NULL);
8717
8718		/*
8719		 * The lun is going to be marked offline. Indicate
8720		 * the target driver not to requeue or retry this command
8721		 * as the device is going to be offlined pretty soon.
8722		 */
8723		pkt->pkt_reason = CMD_DEV_GONE;
8724		pkt->pkt_statistics = 0;
8725		pkt->pkt_state = 0;
8726
8727		/* reset cmd flags/state */
8728		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8729		cmd->cmd_state = FCP_PKT_IDLE;
8730
8731		/*
8732		 * ensure we have a packet completion routine,
8733		 * then call it.
8734		 */
8735		ASSERT(pkt->pkt_comp != NULL);
8736
8737		mutex_exit(&pptr->port_mutex);
8738		fcp_post_callback(cmd);
8739		mutex_enter(&pptr->port_mutex);
8740	}
8741}
8742
8743
8744/*
8745 * the pkt_comp callback for command packets
8746 */
8747static void
8748fcp_cmd_callback(fc_packet_t *fpkt)
8749{
8750	struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8751	struct scsi_pkt *pkt = cmd->cmd_pkt;
8752	struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8753
8754	ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8755
8756	if (cmd->cmd_state == FCP_PKT_IDLE) {
8757		cmn_err(CE_PANIC, "Packet already completed %p",
8758		    (void *)cmd);
8759	}
8760
8761	/*
8762	 * Watch thread should be freeing the packet, ignore the pkt.
8763	 */
8764	if (cmd->cmd_state == FCP_PKT_ABORTING) {
8765		fcp_log(CE_CONT, pptr->port_dip,
8766		    "!FCP: Pkt completed while aborting\n");
8767		return;
8768	}
8769	cmd->cmd_state = FCP_PKT_IDLE;
8770
8771	fcp_complete_pkt(fpkt);
8772
8773#ifdef	DEBUG
8774	mutex_enter(&pptr->port_pkt_mutex);
8775	pptr->port_npkts--;
8776	mutex_exit(&pptr->port_pkt_mutex);
8777#endif /* DEBUG */
8778
8779	fcp_post_callback(cmd);
8780}
8781
8782
8783static void
8784fcp_complete_pkt(fc_packet_t *fpkt)
8785{
8786	int			error = 0;
8787	struct fcp_pkt	*cmd = (struct fcp_pkt *)
8788	    fpkt->pkt_ulp_private;
8789	struct scsi_pkt		*pkt = cmd->cmd_pkt;
8790	struct fcp_port		*pptr = ADDR2FCP(&pkt->pkt_address);
8791	struct fcp_lun	*plun;
8792	struct fcp_tgt	*ptgt;
8793	struct fcp_rsp		*rsp;
8794	struct scsi_address	save;
8795
8796#ifdef	DEBUG
8797	save = pkt->pkt_address;
8798#endif /* DEBUG */
8799
8800	rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8801
8802	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8803		if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8804			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8805			    sizeof (struct fcp_rsp));
8806		}
8807
8808		pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8809		    STATE_SENT_CMD | STATE_GOT_STATUS;
8810
8811		pkt->pkt_resid = 0;
8812
8813		if (fpkt->pkt_datalen) {
8814			pkt->pkt_state |= STATE_XFERRED_DATA;
8815			if (fpkt->pkt_data_resid) {
8816				error++;
8817			}
8818		}
8819
8820		if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8821		    rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8822			/*
8823			 * The next two checks make sure that if there
8824			 * is no sense data or a valid response and
8825			 * the command came back with check condition,
8826			 * the command should be retried.
8827			 */
8828			if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8829			    !rsp->fcp_u.fcp_status.sense_len_set) {
8830				pkt->pkt_state &= ~STATE_XFERRED_DATA;
8831				pkt->pkt_resid = cmd->cmd_dmacount;
8832			}
8833		}
8834
8835		if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8836			return;
8837		}
8838
8839		plun = ADDR2LUN(&pkt->pkt_address);
8840		ptgt = plun->lun_tgt;
8841		ASSERT(ptgt != NULL);
8842
8843		/*
8844		 * Update the transfer resid, if appropriate
8845		 */
8846		if (rsp->fcp_u.fcp_status.resid_over ||
8847		    rsp->fcp_u.fcp_status.resid_under) {
8848			pkt->pkt_resid = rsp->fcp_resid;
8849		}
8850
8851		/*
8852		 * First see if we got a FCP protocol error.
8853		 */
8854		if (rsp->fcp_u.fcp_status.rsp_len_set) {
8855			struct fcp_rsp_info	*bep;
8856			bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8857			    sizeof (struct fcp_rsp));
8858
8859			if (fcp_validate_fcp_response(rsp, pptr) !=
8860			    FC_SUCCESS) {
8861				pkt->pkt_reason = CMD_CMPLT;
8862				*(pkt->pkt_scbp) = STATUS_CHECK;
8863
8864				fcp_log(CE_WARN, pptr->port_dip,
8865				    "!SCSI command to d_id=0x%x lun=0x%x"
8866				    " failed, Bad FCP response values:"
8867				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8868				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8869				    ptgt->tgt_d_id, plun->lun_num,
8870				    rsp->reserved_0, rsp->reserved_1,
8871				    rsp->fcp_u.fcp_status.reserved_0,
8872				    rsp->fcp_u.fcp_status.reserved_1,
8873				    rsp->fcp_response_len, rsp->fcp_sense_len);
8874
8875				return;
8876			}
8877
8878			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8879				FCP_CP_IN(fpkt->pkt_resp +
8880				    sizeof (struct fcp_rsp), bep,
8881				    fpkt->pkt_resp_acc,
8882				    sizeof (struct fcp_rsp_info));
8883			}
8884
8885			if (bep->rsp_code != FCP_NO_FAILURE) {
8886				child_info_t	*cip;
8887
8888				pkt->pkt_reason = CMD_TRAN_ERR;
8889
8890				mutex_enter(&plun->lun_mutex);
8891				cip = plun->lun_cip;
8892				mutex_exit(&plun->lun_mutex);
8893
8894				FCP_TRACE(fcp_logq, pptr->port_instbuf,
8895				    fcp_trace, FCP_BUF_LEVEL_2, 0,
8896				    "FCP response error on cmd=%p"
8897				    " target=0x%x, cip=%p", cmd,
8898				    ptgt->tgt_d_id, cip);
8899			}
8900		}
8901
8902		/*
8903		 * See if we got a SCSI error with sense data
8904		 */
8905		if (rsp->fcp_u.fcp_status.sense_len_set) {
8906			uchar_t				rqlen;
8907			caddr_t				sense_from;
8908			child_info_t			*cip;
8909			timeout_id_t			tid;
8910			struct scsi_arq_status		*arq;
8911			struct scsi_extended_sense	*sense_to;
8912
8913			arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8914			sense_to = &arq->sts_sensedata;
8915
8916			rqlen = (uchar_t)min(rsp->fcp_sense_len,
8917			    sizeof (struct scsi_extended_sense));
8918
8919			sense_from = (caddr_t)fpkt->pkt_resp +
8920			    sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8921
8922			if (fcp_validate_fcp_response(rsp, pptr) !=
8923			    FC_SUCCESS) {
8924				pkt->pkt_reason = CMD_CMPLT;
8925				*(pkt->pkt_scbp) = STATUS_CHECK;
8926
8927				fcp_log(CE_WARN, pptr->port_dip,
8928				    "!SCSI command to d_id=0x%x lun=0x%x"
8929				    " failed, Bad FCP response values:"
8930				    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8931				    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8932				    ptgt->tgt_d_id, plun->lun_num,
8933				    rsp->reserved_0, rsp->reserved_1,
8934				    rsp->fcp_u.fcp_status.reserved_0,
8935				    rsp->fcp_u.fcp_status.reserved_1,
8936				    rsp->fcp_response_len, rsp->fcp_sense_len);
8937
8938				return;
8939			}
8940
8941			/*
8942			 * copy in sense information
8943			 */
8944			if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8945				FCP_CP_IN(sense_from, sense_to,
8946				    fpkt->pkt_resp_acc, rqlen);
8947			} else {
8948				bcopy(sense_from, sense_to, rqlen);
8949			}
8950
8951			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8952			    (FCP_SENSE_NO_LUN(sense_to))) {
8953				mutex_enter(&ptgt->tgt_mutex);
8954				if (ptgt->tgt_tid == NULL) {
8955					/*
8956					 * Kick off rediscovery
8957					 */
8958					tid = timeout(fcp_reconfigure_luns,
8959					    (caddr_t)ptgt, drv_usectohz(1));
8960
8961					ptgt->tgt_tid = tid;
8962					ptgt->tgt_state |= FCP_TGT_BUSY;
8963				}
8964				mutex_exit(&ptgt->tgt_mutex);
8965				if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8966					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8967					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8968					    "!FCP: Report Lun Has Changed"
8969					    " target=%x", ptgt->tgt_d_id);
8970				} else if (FCP_SENSE_NO_LUN(sense_to)) {
8971					FCP_TRACE(fcp_logq, pptr->port_instbuf,
8972					    fcp_trace, FCP_BUF_LEVEL_3, 0,
8973					    "!FCP: LU Not Supported"
8974					    " target=%x", ptgt->tgt_d_id);
8975				}
8976			}
8977			ASSERT(pkt->pkt_scbp != NULL);
8978
8979			pkt->pkt_state |= STATE_ARQ_DONE;
8980
8981			arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8982
8983			*((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8984			arq->sts_rqpkt_reason = 0;
8985			arq->sts_rqpkt_statistics = 0;
8986
8987			arq->sts_rqpkt_state = STATE_GOT_BUS |
8988			    STATE_GOT_TARGET | STATE_SENT_CMD |
8989			    STATE_GOT_STATUS | STATE_ARQ_DONE |
8990			    STATE_XFERRED_DATA;
8991
8992			mutex_enter(&plun->lun_mutex);
8993			cip = plun->lun_cip;
8994			mutex_exit(&plun->lun_mutex);
8995
8996			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8997			    fcp_trace, FCP_BUF_LEVEL_8, 0,
8998			    "SCSI Check condition on cmd=%p target=0x%x"
8999			    " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
9000			    " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9001			    cmd->cmd_fcp_cmd.fcp_cdb[0],
9002			    rsp->fcp_u.fcp_status.scsi_status,
9003			    sense_to->es_key, sense_to->es_add_code,
9004			    sense_to->es_qual_code);
9005		}
9006	} else {
9007		plun = ADDR2LUN(&pkt->pkt_address);
9008		ptgt = plun->lun_tgt;
9009		ASSERT(ptgt != NULL);
9010
9011		/*
9012		 * Work harder to translate errors into target driver
9013		 * understandable ones. Note with despair that the target
9014		 * drivers don't decode pkt_state and pkt_reason exhaustively
9015		 * They resort to using the big hammer most often, which
9016		 * may not get fixed in the life time of this driver.
9017		 */
9018		pkt->pkt_state = 0;
9019		pkt->pkt_statistics = 0;
9020
9021		switch (fpkt->pkt_state) {
9022		case FC_PKT_TRAN_ERROR:
9023			switch (fpkt->pkt_reason) {
9024			case FC_REASON_OVERRUN:
9025				pkt->pkt_reason = CMD_CMD_OVR;
9026				pkt->pkt_statistics |= STAT_ABORTED;
9027				break;
9028
9029			case FC_REASON_XCHG_BSY: {
9030				caddr_t ptr;
9031
9032				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9033
9034				ptr = (caddr_t)pkt->pkt_scbp;
9035				if (ptr) {
9036					*ptr = STATUS_BUSY;
9037				}
9038				break;
9039			}
9040
9041			case FC_REASON_ABORTED:
9042				pkt->pkt_reason = CMD_TRAN_ERR;
9043				pkt->pkt_statistics |= STAT_ABORTED;
9044				break;
9045
9046			case FC_REASON_ABORT_FAILED:
9047				pkt->pkt_reason = CMD_ABORT_FAIL;
9048				break;
9049
9050			case FC_REASON_NO_SEQ_INIT:
9051			case FC_REASON_CRC_ERROR:
9052				pkt->pkt_reason = CMD_TRAN_ERR;
9053				pkt->pkt_statistics |= STAT_ABORTED;
9054				break;
9055			default:
9056				pkt->pkt_reason = CMD_TRAN_ERR;
9057				break;
9058			}
9059			break;
9060
9061		case FC_PKT_PORT_OFFLINE: {
9062			dev_info_t	*cdip = NULL;
9063			caddr_t		ptr;
9064
9065			if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9066				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9067				    fcp_trace, FCP_BUF_LEVEL_8, 0,
9068				    "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9069				    ptgt->tgt_d_id);
9070			}
9071
9072			mutex_enter(&plun->lun_mutex);
9073			if (plun->lun_mpxio == 0) {
9074				cdip = DIP(plun->lun_cip);
9075			} else if (plun->lun_cip) {
9076				cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9077			}
9078
9079			mutex_exit(&plun->lun_mutex);
9080
9081			if (cdip) {
9082				(void) ndi_event_retrieve_cookie(
9083				    pptr->port_ndi_event_hdl, cdip,
9084				    FCAL_REMOVE_EVENT, &fcp_remove_eid,
9085				    NDI_EVENT_NOPASS);
9086				(void) ndi_event_run_callbacks(
9087				    pptr->port_ndi_event_hdl, cdip,
9088				    fcp_remove_eid, NULL);
9089			}
9090
9091			/*
9092			 * If the link goes off-line for a lip,
9093			 * this will cause a error to the ST SG
9094			 * SGEN drivers. By setting BUSY we will
9095			 * give the drivers the chance to retry
9096			 * before it blows of the job. ST will
9097			 * remember how many times it has retried.
9098			 */
9099
9100			if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9101			    (plun->lun_type == DTYPE_CHANGER)) {
9102				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9103				ptr = (caddr_t)pkt->pkt_scbp;
9104				if (ptr) {
9105					*ptr = STATUS_BUSY;
9106				}
9107			} else {
9108				pkt->pkt_reason = CMD_TRAN_ERR;
9109				pkt->pkt_statistics |= STAT_BUS_RESET;
9110			}
9111			break;
9112		}
9113
9114		case FC_PKT_TRAN_BSY:
9115			/*
9116			 * Use the ssd Qfull handling here.
9117			 */
9118			*pkt->pkt_scbp = STATUS_INTERMEDIATE;
9119			pkt->pkt_state = STATE_GOT_BUS;
9120			break;
9121
9122		case FC_PKT_TIMEOUT:
9123			pkt->pkt_reason = CMD_TIMEOUT;
9124			if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9125				pkt->pkt_statistics |= STAT_TIMEOUT;
9126			} else {
9127				pkt->pkt_statistics |= STAT_ABORTED;
9128			}
9129			break;
9130
9131		case FC_PKT_LOCAL_RJT:
9132			switch (fpkt->pkt_reason) {
9133			case FC_REASON_OFFLINE: {
9134				dev_info_t	*cdip = NULL;
9135
9136				mutex_enter(&plun->lun_mutex);
9137				if (plun->lun_mpxio == 0) {
9138					cdip = DIP(plun->lun_cip);
9139				} else if (plun->lun_cip) {
9140					cdip = mdi_pi_get_client(
9141					    PIP(plun->lun_cip));
9142				}
9143				mutex_exit(&plun->lun_mutex);
9144
9145				if (cdip) {
9146					(void) ndi_event_retrieve_cookie(
9147					    pptr->port_ndi_event_hdl, cdip,
9148					    FCAL_REMOVE_EVENT,
9149					    &fcp_remove_eid,
9150					    NDI_EVENT_NOPASS);
9151					(void) ndi_event_run_callbacks(
9152					    pptr->port_ndi_event_hdl,
9153					    cdip, fcp_remove_eid, NULL);
9154				}
9155
9156				pkt->pkt_reason = CMD_TRAN_ERR;
9157				pkt->pkt_statistics |= STAT_BUS_RESET;
9158
9159				break;
9160			}
9161
9162			case FC_REASON_NOMEM:
9163			case FC_REASON_QFULL: {
9164				caddr_t ptr;
9165
9166				pkt->pkt_reason = CMD_CMPLT;	/* Lie */
9167				ptr = (caddr_t)pkt->pkt_scbp;
9168				if (ptr) {
9169					*ptr = STATUS_BUSY;
9170				}
9171				break;
9172			}
9173
9174			case FC_REASON_DMA_ERROR:
9175				pkt->pkt_reason = CMD_DMA_DERR;
9176				pkt->pkt_statistics |= STAT_ABORTED;
9177				break;
9178
9179			case FC_REASON_CRC_ERROR:
9180			case FC_REASON_UNDERRUN: {
9181				uchar_t		status;
9182				/*
9183				 * Work around for Bugid: 4240945.
9184				 * IB on A5k doesn't set the Underrun bit
9185				 * in the fcp status, when it is transferring
9186				 * less than requested amount of data. Work
9187				 * around the ses problem to keep luxadm
9188				 * happy till ibfirmware is fixed.
9189				 */
9190				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9191					FCP_CP_IN(fpkt->pkt_resp, rsp,
9192					    fpkt->pkt_resp_acc,
9193					    sizeof (struct fcp_rsp));
9194				}
9195				status = rsp->fcp_u.fcp_status.scsi_status;
9196				if (((plun->lun_type & DTYPE_MASK) ==
9197				    DTYPE_ESI) && (status == STATUS_GOOD)) {
9198					pkt->pkt_reason = CMD_CMPLT;
9199					*pkt->pkt_scbp = status;
9200					pkt->pkt_resid = 0;
9201				} else {
9202					pkt->pkt_reason = CMD_TRAN_ERR;
9203					pkt->pkt_statistics |= STAT_ABORTED;
9204				}
9205				break;
9206			}
9207
9208			case FC_REASON_NO_CONNECTION:
9209			case FC_REASON_UNSUPPORTED:
9210			case FC_REASON_ILLEGAL_REQ:
9211			case FC_REASON_BAD_SID:
9212			case FC_REASON_DIAG_BUSY:
9213			case FC_REASON_FCAL_OPN_FAIL:
9214			case FC_REASON_BAD_XID:
9215			default:
9216				pkt->pkt_reason = CMD_TRAN_ERR;
9217				pkt->pkt_statistics |= STAT_ABORTED;
9218				break;
9219
9220			}
9221			break;
9222
9223		case FC_PKT_NPORT_RJT:
9224		case FC_PKT_FABRIC_RJT:
9225		case FC_PKT_NPORT_BSY:
9226		case FC_PKT_FABRIC_BSY:
9227		default:
9228			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9229			    fcp_trace, FCP_BUF_LEVEL_8, 0,
9230			    "FC Status 0x%x, reason 0x%x",
9231			    fpkt->pkt_state, fpkt->pkt_reason);
9232			pkt->pkt_reason = CMD_TRAN_ERR;
9233			pkt->pkt_statistics |= STAT_ABORTED;
9234			break;
9235		}
9236
9237		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9238		    fcp_trace, FCP_BUF_LEVEL_9, 0,
9239		    "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9240		    " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9241		    fpkt->pkt_reason);
9242	}
9243
9244	ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9245}
9246
9247
9248static int
9249fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9250{
9251	if (rsp->reserved_0 || rsp->reserved_1 ||
9252	    rsp->fcp_u.fcp_status.reserved_0 ||
9253	    rsp->fcp_u.fcp_status.reserved_1) {
9254		/*
9255		 * These reserved fields should ideally be zero. FCP-2 does say
9256		 * that the recipient need not check for reserved fields to be
9257		 * zero. If they are not zero, we will not make a fuss about it
9258		 * - just log it (in debug to both trace buffer and messages
9259		 * file and to trace buffer only in non-debug) and move on.
9260		 *
9261		 * Non-zero reserved fields were seen with minnows.
9262		 *
9263		 * qlc takes care of some of this but we cannot assume that all
9264		 * FCAs will do so.
9265		 */
9266		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9267		    FCP_BUF_LEVEL_5, 0,
9268		    "Got fcp response packet with non-zero reserved fields "
9269		    "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9270		    "status.reserved_0:0x%x, status.reserved_1:0x%x",
9271		    rsp->reserved_0, rsp->reserved_1,
9272		    rsp->fcp_u.fcp_status.reserved_0,
9273		    rsp->fcp_u.fcp_status.reserved_1);
9274	}
9275
9276	if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9277	    (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9278		return (FC_FAILURE);
9279	}
9280
9281	if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9282	    (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9283	    sizeof (struct fcp_rsp))) {
9284		return (FC_FAILURE);
9285	}
9286
9287	return (FC_SUCCESS);
9288}
9289
9290
9291/*
9292 * This is called when there is a change the in device state. The case we're
9293 * handling here is, if the d_id s does not match, offline this tgt and online
9294 * a new tgt with the new d_id.	 called from fcp_handle_devices with
9295 * port_mutex held.
9296 */
9297static int
9298fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9299    fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9300{
9301	ASSERT(mutex_owned(&pptr->port_mutex));
9302
9303	FCP_TRACE(fcp_logq, pptr->port_instbuf,
9304	    fcp_trace, FCP_BUF_LEVEL_3, 0,
9305	    "Starting fcp_device_changed...");
9306
9307	/*
9308	 * The two cases where the port_device_changed is called is
9309	 * either it changes it's d_id or it's hard address.
9310	 */
9311	if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9312	    (FC_TOP_EXTERNAL(pptr->port_topology) &&
9313	    (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9314
9315		/* offline this target */
9316		mutex_enter(&ptgt->tgt_mutex);
9317		if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9318			(void) fcp_offline_target(pptr, ptgt, link_cnt,
9319			    0, 1, NDI_DEVI_REMOVE);
9320		}
9321		mutex_exit(&ptgt->tgt_mutex);
9322
9323		fcp_log(CE_NOTE, pptr->port_dip,
9324		    "Change in target properties: Old D_ID=%x New D_ID=%x"
9325		    " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9326		    map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9327		    map_entry->map_hard_addr.hard_addr);
9328	}
9329
9330	return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9331	    link_cnt, tgt_cnt, cause));
9332}
9333
9334/*
9335 *     Function: fcp_alloc_lun
9336 *
9337 *  Description: Creates a new lun structure and adds it to the list
9338 *		 of luns of the target.
9339 *
9340 *     Argument: ptgt		Target the lun will belong to.
9341 *
9342 * Return Value: NULL		Failed
9343 *		 Not NULL	Succeeded
9344 *
9345 *	Context: Kernel context
9346 */
9347static struct fcp_lun *
9348fcp_alloc_lun(struct fcp_tgt *ptgt)
9349{
9350	struct fcp_lun *plun;
9351
9352	plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9353	if (plun != NULL) {
9354		/*
9355		 * Initialize the mutex before putting in the target list
9356		 * especially before releasing the target mutex.
9357		 */
9358		mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9359		plun->lun_tgt = ptgt;
9360
9361		mutex_enter(&ptgt->tgt_mutex);
9362		plun->lun_next = ptgt->tgt_lun;
9363		ptgt->tgt_lun = plun;
9364		plun->lun_old_guid = NULL;
9365		plun->lun_old_guid_size = 0;
9366		mutex_exit(&ptgt->tgt_mutex);
9367	}
9368
9369	return (plun);
9370}
9371
9372/*
9373 *     Function: fcp_dealloc_lun
9374 *
9375 *  Description: Frees the LUN structure passed by the caller.
9376 *
9377 *     Argument: plun		LUN structure to free.
9378 *
9379 * Return Value: None
9380 *
9381 *	Context: Kernel context.
9382 */
9383static void
9384fcp_dealloc_lun(struct fcp_lun *plun)
9385{
9386	mutex_enter(&plun->lun_mutex);
9387	if (plun->lun_cip) {
9388		fcp_remove_child(plun);
9389	}
9390	mutex_exit(&plun->lun_mutex);
9391
9392	mutex_destroy(&plun->lun_mutex);
9393	if (plun->lun_guid) {
9394		kmem_free(plun->lun_guid, plun->lun_guid_size);
9395	}
9396	if (plun->lun_old_guid) {
9397		kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9398	}
9399	kmem_free(plun, sizeof (*plun));
9400}
9401
9402/*
9403 *     Function: fcp_alloc_tgt
9404 *
9405 *  Description: Creates a new target structure and adds it to the port
9406 *		 hash list.
9407 *
9408 *     Argument: pptr		fcp port structure
9409 *		 *map_entry	entry describing the target to create
9410 *		 link_cnt	Link state change counter
9411 *
9412 * Return Value: NULL		Failed
9413 *		 Not NULL	Succeeded
9414 *
9415 *	Context: Kernel context.
9416 */
9417static struct fcp_tgt *
9418fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9419{
9420	int			hash;
9421	uchar_t			*wwn;
9422	struct fcp_tgt	*ptgt;
9423
9424	ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9425	if (ptgt != NULL) {
9426		mutex_enter(&pptr->port_mutex);
9427		if (link_cnt != pptr->port_link_cnt) {
9428			/*
9429			 * oh oh -- another link reset
9430			 * in progress -- give up
9431			 */
9432			mutex_exit(&pptr->port_mutex);
9433			kmem_free(ptgt, sizeof (*ptgt));
9434			ptgt = NULL;
9435		} else {
9436			/*
9437			 * initialize the mutex before putting in the port
9438			 * wwn list, especially before releasing the port
9439			 * mutex.
9440			 */
9441			mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9442
9443			/* add new target entry to the port's hash list */
9444			wwn = (uchar_t *)&map_entry->map_pwwn;
9445			hash = FCP_HASH(wwn);
9446
9447			ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9448			pptr->port_tgt_hash_table[hash] = ptgt;
9449
9450			/* save cross-ptr */
9451			ptgt->tgt_port = pptr;
9452
9453			ptgt->tgt_change_cnt = 1;
9454
9455			/* initialize the target manual_config_only flag */
9456			if (fcp_enable_auto_configuration) {
9457				ptgt->tgt_manual_config_only = 0;
9458			} else {
9459				ptgt->tgt_manual_config_only = 1;
9460			}
9461
9462			mutex_exit(&pptr->port_mutex);
9463		}
9464	}
9465
9466	return (ptgt);
9467}
9468
9469/*
9470 *     Function: fcp_dealloc_tgt
9471 *
9472 *  Description: Frees the target structure passed by the caller.
9473 *
9474 *     Argument: ptgt		Target structure to free.
9475 *
9476 * Return Value: None
9477 *
9478 *	Context: Kernel context.
9479 */
9480static void
9481fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9482{
9483	mutex_destroy(&ptgt->tgt_mutex);
9484	kmem_free(ptgt, sizeof (*ptgt));
9485}
9486
9487
9488/*
9489 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9490 *
9491 *	Device discovery commands will not be retried for-ever as
9492 *	this will have repercussions on other devices that need to
9493 *	be submitted to the hotplug thread. After a quick glance
9494 *	at the SCSI-3 spec, it was found that the spec doesn't
9495 *	mandate a forever retry, rather recommends a delayed retry.
9496 *
9497 *	Since Photon IB is single threaded, STATUS_BUSY is common
9498 *	in a 4+initiator environment. Make sure the total time
9499 *	spent on retries (including command timeout) does not
9500 *	60 seconds
9501 */
9502static void
9503fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9504{
9505	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9506	struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9507
9508	mutex_enter(&pptr->port_mutex);
9509	mutex_enter(&ptgt->tgt_mutex);
9510	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9511		FCP_TRACE(fcp_logq, pptr->port_instbuf,
9512		    fcp_trace, FCP_BUF_LEVEL_2, 0,
9513		    "fcp_queue_ipkt,1:state change occured"
9514		    " for D_ID=0x%x", ptgt->tgt_d_id);
9515		mutex_exit(&ptgt->tgt_mutex);
9516		mutex_exit(&pptr->port_mutex);
9517		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9518		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
9519		fcp_icmd_free(pptr, icmd);
9520		return;
9521	}
9522	mutex_exit(&ptgt->tgt_mutex);
9523
9524	icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9525
9526	if (pptr->port_ipkt_list != NULL) {
9527		/* add pkt to front of doubly-linked list */
9528		pptr->port_ipkt_list->ipkt_prev = icmd;
9529		icmd->ipkt_next = pptr->port_ipkt_list;
9530		pptr->port_ipkt_list = icmd;
9531		icmd->ipkt_prev = NULL;
9532	} else {
9533		/* this is the first/only pkt on the list */
9534		pptr->port_ipkt_list = icmd;
9535		icmd->ipkt_next = NULL;
9536		icmd->ipkt_prev = NULL;
9537	}
9538	mutex_exit(&pptr->port_mutex);
9539}
9540
9541/*
9542 *     Function: fcp_transport
9543 *
9544 *  Description: This function submits the Fibre Channel packet to the transort
9545 *		 layer by calling fc_ulp_transport().  If fc_ulp_transport()
9546 *		 fails the submission, the treatment depends on the value of
9547 *		 the variable internal.
9548 *
9549 *     Argument: port_handle	fp/fctl port handle.
9550 *		 *fpkt		Packet to submit to the transport layer.
9551 *		 internal	Not zero when it's an internal packet.
9552 *
9553 * Return Value: FC_TRAN_BUSY
9554 *		 FC_STATEC_BUSY
9555 *		 FC_OFFLINE
9556 *		 FC_LOGINREQ
9557 *		 FC_DEVICE_BUSY
9558 *		 FC_SUCCESS
9559 */
9560static int
9561fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9562{
9563	int	rval;
9564
9565	rval = fc_ulp_transport(port_handle, fpkt);
9566	if (rval == FC_SUCCESS) {
9567		return (rval);
9568	}
9569
9570	/*
9571	 * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9572	 * a command, if the underlying modules see that there is a state
9573	 * change, or if a port is OFFLINE, that means, that state change
9574	 * hasn't reached FCP yet, so re-queue the command for deferred
9575	 * submission.
9576	 */
9577	if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9578	    (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9579	    (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9580		/*
9581		 * Defer packet re-submission. Life hang is possible on
9582		 * internal commands if the port driver sends FC_STATEC_BUSY
9583		 * for ever, but that shouldn't happen in a good environment.
9584		 * Limiting re-transport for internal commands is probably a
9585		 * good idea..
9586		 * A race condition can happen when a port sees barrage of
9587		 * link transitions offline to online. If the FCTL has
9588		 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9589		 * internal commands should be queued to do the discovery.
9590		 * The race condition is when an online comes and FCP starts
9591		 * its internal discovery and the link goes offline. It is
9592		 * possible that the statec_callback has not reached FCP
9593		 * and FCP is carrying on with its internal discovery.
9594		 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9595		 * that the link has gone offline. At this point FCP should
9596		 * drop all the internal commands and wait for the
9597		 * statec_callback. It will be facilitated by incrementing
9598		 * port_link_cnt.
9599		 *
9600		 * For external commands, the (FC)pkt_timeout is decremented
9601		 * by the QUEUE Delay added by our driver, Care is taken to
9602		 * ensure that it doesn't become zero (zero means no timeout)
9603		 * If the time expires right inside driver queue itself,
9604		 * the watch thread will return it to the original caller
9605		 * indicating that the command has timed-out.
9606		 */
9607		if (internal) {
9608			char			*op;
9609			struct fcp_ipkt	*icmd;
9610
9611			icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9612			switch (icmd->ipkt_opcode) {
9613			case SCMD_REPORT_LUN:
9614				op = "REPORT LUN";
9615				break;
9616
9617			case SCMD_INQUIRY:
9618				op = "INQUIRY";
9619				break;
9620
9621			case SCMD_INQUIRY_PAGE83:
9622				op = "INQUIRY-83";
9623				break;
9624
9625			default:
9626				op = "Internal SCSI COMMAND";
9627				break;
9628			}
9629
9630			if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9631			    icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9632				rval = FC_SUCCESS;
9633			}
9634		} else {
9635			struct fcp_pkt *cmd;
9636			struct fcp_port *pptr;
9637
9638			cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9639			cmd->cmd_state = FCP_PKT_IDLE;
9640			pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9641
9642			if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9643				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9644				    fcp_trace, FCP_BUF_LEVEL_9, 0,
9645				    "fcp_transport: xport busy for pkt %p",
9646				    cmd->cmd_pkt);
9647				rval = FC_TRAN_BUSY;
9648			} else {
9649				fcp_queue_pkt(pptr, cmd);
9650				rval = FC_SUCCESS;
9651			}
9652		}
9653	}
9654
9655	return (rval);
9656}
9657
9658/*VARARGS3*/
9659static void
9660fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9661{
9662	char		buf[256];
9663	va_list		ap;
9664
9665	if (dip == NULL) {
9666		dip = fcp_global_dip;
9667	}
9668
9669	va_start(ap, fmt);
9670	(void) vsprintf(buf, fmt, ap);
9671	va_end(ap);
9672
9673	scsi_log(dip, "fcp", level, buf);
9674}
9675
9676/*
9677 * This function retries NS registry of FC4 type.
9678 * It assumes that fcp_mutex is held.
9679 * The function does nothing if topology is not fabric
9680 * So, the topology has to be set before this function can be called
9681 */
9682static void
9683fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9684{
9685	int	rval;
9686
9687	ASSERT(MUTEX_HELD(&pptr->port_mutex));
9688
9689	if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9690	    ((pptr->port_topology != FC_TOP_FABRIC) &&
9691	    (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9692		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9693			pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9694		}
9695		return;
9696	}
9697	mutex_exit(&pptr->port_mutex);
9698	rval = fcp_do_ns_registry(pptr, s_id);
9699	mutex_enter(&pptr->port_mutex);
9700
9701	if (rval == 0) {
9702		/* Registry successful. Reset flag */
9703		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9704	}
9705}
9706
9707/*
9708 * This function registers the ULP with the switch by calling transport i/f
9709 */
9710static int
9711fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9712{
9713	fc_ns_cmd_t		ns_cmd;
9714	ns_rfc_type_t		rfc;
9715	uint32_t		types[8];
9716
9717	/*
9718	 * Prepare the Name server structure to
9719	 * register with the transport in case of
9720	 * Fabric configuration.
9721	 */
9722	bzero(&rfc, sizeof (rfc));
9723	bzero(types, sizeof (types));
9724
9725	types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9726	    (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9727
9728	rfc.rfc_port_id.port_id = s_id;
9729	bcopy(types, rfc.rfc_types, sizeof (types));
9730
9731	ns_cmd.ns_flags = 0;
9732	ns_cmd.ns_cmd = NS_RFT_ID;
9733	ns_cmd.ns_req_len = sizeof (rfc);
9734	ns_cmd.ns_req_payload = (caddr_t)&rfc;
9735	ns_cmd.ns_resp_len = 0;
9736	ns_cmd.ns_resp_payload = NULL;
9737
9738	/*
9739	 * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9740	 */
9741	if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9742		fcp_log(CE_WARN, pptr->port_dip,
9743		    "!ns_registry: failed name server registration");
9744		return (1);
9745	}
9746
9747	return (0);
9748}
9749
9750/*
9751 *     Function: fcp_handle_port_attach
9752 *
9753 *  Description: This function is called from fcp_port_attach() to attach a
9754 *		 new port. This routine does the following:
9755 *
9756 *		1) Allocates an fcp_port structure and initializes it.
9757 *		2) Tries to register the new FC-4 (FCP) capablity with the name
9758 *		   server.
9759 *		3) Kicks off the enumeration of the targets/luns visible
9760 *		   through this new port.  That is done by calling
9761 *		   fcp_statec_callback() if the port is online.
9762 *
9763 *     Argument: ulph		fp/fctl port handle.
9764 *		 *pinfo		Port information.
9765 *		 s_id		Port ID.
9766 *		 instance	Device instance number for the local port
9767 *				(returned by ddi_get_instance()).
9768 *
9769 * Return Value: DDI_SUCCESS
9770 *		 DDI_FAILURE
9771 *
9772 *	Context: User and Kernel context.
9773 */
9774/*ARGSUSED*/
9775int
9776fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9777    uint32_t s_id, int instance)
9778{
9779	int			res = DDI_FAILURE;
9780	scsi_hba_tran_t		*tran;
9781	int			mutex_initted = FALSE;
9782	int			hba_attached = FALSE;
9783	int			soft_state_linked = FALSE;
9784	int			event_bind = FALSE;
9785	struct fcp_port		*pptr;
9786	fc_portmap_t		*tmp_list = NULL;
9787	uint32_t		max_cnt, alloc_cnt;
9788	uchar_t			*boot_wwn = NULL;
9789	uint_t			nbytes;
9790	int			manual_cfg;
9791
9792	/*
9793	 * this port instance attaching for the first time (or after
9794	 * being detached before)
9795	 */
9796	FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9797	    FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9798
9799	if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9800		cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9801		    "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9802		    instance);
9803		return (res);
9804	}
9805
9806	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9807		/* this shouldn't happen */
9808		ddi_soft_state_free(fcp_softstate, instance);
9809		cmn_err(CE_WARN, "fcp: bad soft state");
9810		return (res);
9811	}
9812
9813	(void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9814
9815	/*
9816	 * Make a copy of ulp_port_info as fctl allocates
9817	 * a temp struct.
9818	 */
9819	(void) fcp_cp_pinfo(pptr, pinfo);
9820
9821	/*
9822	 * Check for manual_configuration_only property.
9823	 * Enable manual configurtion if the property is
9824	 * set to 1, otherwise disable manual configuration.
9825	 */
9826	if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9827	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9828	    MANUAL_CFG_ONLY,
9829	    -1)) != -1) {
9830		if (manual_cfg == 1) {
9831			char	*pathname;
9832			pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9833			(void) ddi_pathname(pptr->port_dip, pathname);
9834			cmn_err(CE_NOTE,
9835			    "%s (%s%d) %s is enabled via %s.conf.",
9836			    pathname,
9837			    ddi_driver_name(pptr->port_dip),
9838			    ddi_get_instance(pptr->port_dip),
9839			    MANUAL_CFG_ONLY,
9840			    ddi_driver_name(pptr->port_dip));
9841			fcp_enable_auto_configuration = 0;
9842			kmem_free(pathname, MAXPATHLEN);
9843		}
9844	}
9845	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9846	pptr->port_link_cnt = 1;
9847	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9848	pptr->port_id = s_id;
9849	pptr->port_instance = instance;
9850	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9851	pptr->port_state = FCP_STATE_INIT;
9852	if (pinfo->port_acc_attr == NULL) {
9853		/*
9854		 * The corresponding FCA doesn't support DMA at all
9855		 */
9856		pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9857	}
9858
9859	_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9860
9861	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9862		/*
9863		 * If FCA supports DMA in SCSI data phase, we need preallocate
9864		 * dma cookie, so stash the cookie size
9865		 */
9866		pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9867		    pptr->port_data_dma_attr.dma_attr_sgllen;
9868	}
9869
9870	/*
9871	 * The two mutexes of fcp_port are initialized.	 The variable
9872	 * mutex_initted is incremented to remember that fact.	That variable
9873	 * is checked when the routine fails and the mutexes have to be
9874	 * destroyed.
9875	 */
9876	mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9877	mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9878	mutex_initted++;
9879
9880	/*
9881	 * The SCSI tran structure is allocate and initialized now.
9882	 */
9883	if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9884		fcp_log(CE_WARN, pptr->port_dip,
9885		    "!fcp%d: scsi_hba_tran_alloc failed", instance);
9886		goto fail;
9887	}
9888
9889	/* link in the transport structure then fill it in */
9890	pptr->port_tran = tran;
9891	tran->tran_hba_private		= pptr;
9892	tran->tran_tgt_init		= fcp_scsi_tgt_init;
9893	tran->tran_tgt_probe		= NULL;
9894	tran->tran_tgt_free		= fcp_scsi_tgt_free;
9895	tran->tran_start		= fcp_scsi_start;
9896	tran->tran_reset		= fcp_scsi_reset;
9897	tran->tran_abort		= fcp_scsi_abort;
9898	tran->tran_getcap		= fcp_scsi_getcap;
9899	tran->tran_setcap		= fcp_scsi_setcap;
9900	tran->tran_init_pkt		= NULL;
9901	tran->tran_destroy_pkt		= NULL;
9902	tran->tran_dmafree		= NULL;
9903	tran->tran_sync_pkt		= NULL;
9904	tran->tran_reset_notify		= fcp_scsi_reset_notify;
9905	tran->tran_get_bus_addr		= fcp_scsi_get_bus_addr;
9906	tran->tran_get_name		= fcp_scsi_get_name;
9907	tran->tran_clear_aca		= NULL;
9908	tran->tran_clear_task_set	= NULL;
9909	tran->tran_terminate_task	= NULL;
9910	tran->tran_get_eventcookie	= fcp_scsi_bus_get_eventcookie;
9911	tran->tran_add_eventcall	= fcp_scsi_bus_add_eventcall;
9912	tran->tran_remove_eventcall	= fcp_scsi_bus_remove_eventcall;
9913	tran->tran_post_event		= fcp_scsi_bus_post_event;
9914	tran->tran_quiesce		= NULL;
9915	tran->tran_unquiesce		= NULL;
9916	tran->tran_bus_reset		= NULL;
9917	tran->tran_bus_config		= fcp_scsi_bus_config;
9918	tran->tran_bus_unconfig		= fcp_scsi_bus_unconfig;
9919	tran->tran_bus_power		= NULL;
9920	tran->tran_interconnect_type	= INTERCONNECT_FABRIC;
9921
9922	tran->tran_pkt_constructor	= fcp_kmem_cache_constructor;
9923	tran->tran_pkt_destructor	= fcp_kmem_cache_destructor;
9924	tran->tran_setup_pkt		= fcp_pkt_setup;
9925	tran->tran_teardown_pkt		= fcp_pkt_teardown;
9926	tran->tran_hba_len		= pptr->port_priv_pkt_len +
9927	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9928	if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9929		/*
9930		 * If FCA don't support DMA, then we use different vectors to
9931		 * minimize the effects on DMA code flow path
9932		 */
9933		tran->tran_start	   = fcp_pseudo_start;
9934		tran->tran_init_pkt	   = fcp_pseudo_init_pkt;
9935		tran->tran_destroy_pkt	   = fcp_pseudo_destroy_pkt;
9936		tran->tran_sync_pkt	   = fcp_pseudo_sync_pkt;
9937		tran->tran_dmafree	   = fcp_pseudo_dmafree;
9938		tran->tran_setup_pkt	   = NULL;
9939		tran->tran_teardown_pkt	   = NULL;
9940		tran->tran_pkt_constructor = NULL;
9941		tran->tran_pkt_destructor  = NULL;
9942		pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9943	}
9944
9945	/*
9946	 * Allocate an ndi event handle
9947	 */
9948	pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9949	    kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9950
9951	bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9952	    sizeof (fcp_ndi_event_defs));
9953
9954	(void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9955	    &pptr->port_ndi_event_hdl, NDI_SLEEP);
9956
9957	pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9958	pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9959	pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9960
9961	if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9962	    (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9963	    &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9964		goto fail;
9965	}
9966	event_bind++;	/* Checked in fail case */
9967
9968	if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9969	    tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9970	    != DDI_SUCCESS) {
9971		fcp_log(CE_WARN, pptr->port_dip,
9972		    "!fcp%d: scsi_hba_attach_setup failed", instance);
9973		goto fail;
9974	}
9975	hba_attached++;	/* Checked in fail case */
9976
9977	pptr->port_mpxio = 0;
9978	if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9979	    MDI_SUCCESS) {
9980		pptr->port_mpxio++;
9981	}
9982
9983	/*
9984	 * The following code is putting the new port structure in the global
9985	 * list of ports and, if it is the first port to attach, it start the
9986	 * fcp_watchdog_tick.
9987	 *
9988	 * Why put this new port in the global before we are done attaching it?
9989	 * We are actually making the structure globally known before we are
9990	 * done attaching it.  The reason for that is: because of the code that
9991	 * follows.  At this point the resources to handle the port are
9992	 * allocated.  This function is now going to do the following:
9993	 *
9994	 *   1) It is going to try to register with the name server advertizing
9995	 *	the new FCP capability of the port.
9996	 *   2) It is going to play the role of the fp/fctl layer by building
9997	 *	a list of worlwide names reachable through this port and call
9998	 *	itself on fcp_statec_callback().  That requires the port to
9999	 *	be part of the global list.
10000	 */
10001	mutex_enter(&fcp_global_mutex);
10002	if (fcp_port_head == NULL) {
10003		fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10004	}
10005	pptr->port_next = fcp_port_head;
10006	fcp_port_head = pptr;
10007	soft_state_linked++;
10008
10009	if (fcp_watchdog_init++ == 0) {
10010		fcp_watchdog_tick = fcp_watchdog_timeout *
10011		    drv_usectohz(1000000);
10012		fcp_watchdog_id = timeout(fcp_watch, NULL,
10013		    fcp_watchdog_tick);
10014	}
10015	mutex_exit(&fcp_global_mutex);
10016
10017	/*
10018	 * Here an attempt is made to register with the name server, the new
10019	 * FCP capability.  That is done using an RTF_ID to the name server.
10020	 * It is done synchronously.  The function fcp_do_ns_registry()
10021	 * doesn't return till the name server responded.
10022	 * On failures, just ignore it for now and it will get retried during
10023	 * state change callbacks. We'll set a flag to show this failure
10024	 */
10025	if (fcp_do_ns_registry(pptr, s_id)) {
10026		mutex_enter(&pptr->port_mutex);
10027		pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10028		mutex_exit(&pptr->port_mutex);
10029	} else {
10030		mutex_enter(&pptr->port_mutex);
10031		pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10032		mutex_exit(&pptr->port_mutex);
10033	}
10034
10035	/*
10036	 * Lookup for boot WWN property
10037	 */
10038	if (modrootloaded != 1) {
10039		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10040		    ddi_get_parent(pinfo->port_dip),
10041		    DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10042		    &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10043		    (nbytes == FC_WWN_SIZE)) {
10044			bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10045		}
10046		if (boot_wwn) {
10047			ddi_prop_free(boot_wwn);
10048		}
10049	}
10050
10051	/*
10052	 * Handle various topologies and link states.
10053	 */
10054	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10055	case FC_STATE_OFFLINE:
10056
10057		/*
10058		 * we're attaching a port where the link is offline
10059		 *
10060		 * Wait for ONLINE, at which time a state
10061		 * change will cause a statec_callback
10062		 *
10063		 * in the mean time, do not do anything
10064		 */
10065		res = DDI_SUCCESS;
10066		pptr->port_state |= FCP_STATE_OFFLINE;
10067		break;
10068
10069	case FC_STATE_ONLINE: {
10070		if (pptr->port_topology == FC_TOP_UNKNOWN) {
10071			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10072			res = DDI_SUCCESS;
10073			break;
10074		}
10075		/*
10076		 * discover devices and create nodes (a private
10077		 * loop or point-to-point)
10078		 */
10079		ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10080
10081		/*
10082		 * At this point we are going to build a list of all the ports
10083		 * that	can be reached through this local port.	 It looks like
10084		 * we cannot handle more than FCP_MAX_DEVICES per local port
10085		 * (128).
10086		 */
10087		if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10088		    sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10089		    KM_NOSLEEP)) == NULL) {
10090			fcp_log(CE_WARN, pptr->port_dip,
10091			    "!fcp%d: failed to allocate portmap",
10092			    instance);
10093			goto fail;
10094		}
10095
10096		/*
10097		 * fc_ulp_getportmap() is going to provide us with the list of
10098		 * remote ports in the buffer we just allocated.  The way the
10099		 * list is going to be retrieved depends on the topology.
10100		 * However, if we are connected to a Fabric, a name server
10101		 * request may be sent to get the list of FCP capable ports.
10102		 * It should be noted that is the case the request is
10103		 * synchronous.	 This means we are stuck here till the name
10104		 * server replies.  A lot of things can change during that time
10105		 * and including, may be, being called on
10106		 * fcp_statec_callback() for different reasons. I'm not sure
10107		 * the code can handle that.
10108		 */
10109		max_cnt = FCP_MAX_DEVICES;
10110		alloc_cnt = FCP_MAX_DEVICES;
10111		if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10112		    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10113		    FC_SUCCESS) {
10114			caddr_t msg;
10115
10116			(void) fc_ulp_error(res, &msg);
10117
10118			/*
10119			 * this	 just means the transport is
10120			 * busy perhaps building a portmap so,
10121			 * for now, succeed this port attach
10122			 * when the transport has a new map,
10123			 * it'll send us a state change then
10124			 */
10125			fcp_log(CE_WARN, pptr->port_dip,
10126			    "!failed to get port map : %s", msg);
10127
10128			res = DDI_SUCCESS;
10129			break;	/* go return result */
10130		}
10131		if (max_cnt > alloc_cnt) {
10132			alloc_cnt = max_cnt;
10133		}
10134
10135		/*
10136		 * We are now going to call fcp_statec_callback() ourselves.
10137		 * By issuing this call we are trying to kick off the enumera-
10138		 * tion process.
10139		 */
10140		/*
10141		 * let the state change callback do the SCSI device
10142		 * discovery and create the devinfos
10143		 */
10144		fcp_statec_callback(ulph, pptr->port_fp_handle,
10145		    pptr->port_phys_state, pptr->port_topology, tmp_list,
10146		    max_cnt, pptr->port_id);
10147
10148		res = DDI_SUCCESS;
10149		break;
10150	}
10151
10152	default:
10153		/* unknown port state */
10154		fcp_log(CE_WARN, pptr->port_dip,
10155		    "!fcp%d: invalid port state at attach=0x%x",
10156		    instance, pptr->port_phys_state);
10157
10158		mutex_enter(&pptr->port_mutex);
10159		pptr->port_phys_state = FCP_STATE_OFFLINE;
10160		mutex_exit(&pptr->port_mutex);
10161
10162		res = DDI_SUCCESS;
10163		break;
10164	}
10165
10166	/* free temp list if used */
10167	if (tmp_list != NULL) {
10168		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10169	}
10170
10171	/* note the attach time */
10172	pptr->port_attach_time = ddi_get_lbolt64();
10173
10174	/* all done */
10175	return (res);
10176
10177	/* a failure we have to clean up after */
10178fail:
10179	fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10180
10181	if (soft_state_linked) {
10182		/* remove this fcp_port from the linked list */
10183		(void) fcp_soft_state_unlink(pptr);
10184	}
10185
10186	/* unbind and free event set */
10187	if (pptr->port_ndi_event_hdl) {
10188		if (event_bind) {
10189			(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10190			    &pptr->port_ndi_events, NDI_SLEEP);
10191		}
10192		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10193	}
10194
10195	if (pptr->port_ndi_event_defs) {
10196		(void) kmem_free(pptr->port_ndi_event_defs,
10197		    sizeof (fcp_ndi_event_defs));
10198	}
10199
10200	/*
10201	 * Clean up mpxio stuff
10202	 */
10203	if (pptr->port_mpxio) {
10204		(void) mdi_phci_unregister(pptr->port_dip, 0);
10205		pptr->port_mpxio--;
10206	}
10207
10208	/* undo SCSI HBA setup */
10209	if (hba_attached) {
10210		(void) scsi_hba_detach(pptr->port_dip);
10211	}
10212	if (pptr->port_tran != NULL) {
10213		scsi_hba_tran_free(pptr->port_tran);
10214	}
10215
10216	mutex_enter(&fcp_global_mutex);
10217
10218	/*
10219	 * We check soft_state_linked, because it is incremented right before
10220	 * we call increment fcp_watchdog_init.	 Therefore, we know if
10221	 * soft_state_linked is still FALSE, we do not want to decrement
10222	 * fcp_watchdog_init or possibly call untimeout.
10223	 */
10224
10225	if (soft_state_linked) {
10226		if (--fcp_watchdog_init == 0) {
10227			timeout_id_t	tid = fcp_watchdog_id;
10228
10229			mutex_exit(&fcp_global_mutex);
10230			(void) untimeout(tid);
10231		} else {
10232			mutex_exit(&fcp_global_mutex);
10233		}
10234	} else {
10235		mutex_exit(&fcp_global_mutex);
10236	}
10237
10238	if (mutex_initted) {
10239		mutex_destroy(&pptr->port_mutex);
10240		mutex_destroy(&pptr->port_pkt_mutex);
10241	}
10242
10243	if (tmp_list != NULL) {
10244		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10245	}
10246
10247	/* this makes pptr invalid */
10248	ddi_soft_state_free(fcp_softstate, instance);
10249
10250	return (DDI_FAILURE);
10251}
10252
10253
10254static int
10255fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10256{
10257	int count = 0;
10258
10259	mutex_enter(&pptr->port_mutex);
10260
10261	/*
10262	 * if the port is powered down or suspended, nothing else
10263	 * to do; just return.
10264	 */
10265	if (flag != FCP_STATE_DETACHING) {
10266		if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10267		    FCP_STATE_SUSPENDED)) {
10268			pptr->port_state |= flag;
10269			mutex_exit(&pptr->port_mutex);
10270			return (FC_SUCCESS);
10271		}
10272	}
10273
10274	if (pptr->port_state & FCP_STATE_IN_MDI) {
10275		mutex_exit(&pptr->port_mutex);
10276		return (FC_FAILURE);
10277	}
10278
10279	FCP_TRACE(fcp_logq, pptr->port_instbuf,
10280	    fcp_trace, FCP_BUF_LEVEL_2, 0,
10281	    "fcp_handle_port_detach: port is detaching");
10282
10283	pptr->port_state |= flag;
10284
10285	/*
10286	 * Wait for any ongoing reconfig/ipkt to complete, that
10287	 * ensures the freeing to targets/luns is safe.
10288	 * No more ref to this port should happen from statec/ioctl
10289	 * after that as it was removed from the global port list.
10290	 */
10291	while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10292	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10293		/*
10294		 * Let's give sufficient time for reconfig/ipkt
10295		 * to complete.
10296		 */
10297		if (count++ >= FCP_ICMD_DEADLINE) {
10298			break;
10299		}
10300		mutex_exit(&pptr->port_mutex);
10301		delay(drv_usectohz(1000000));
10302		mutex_enter(&pptr->port_mutex);
10303	}
10304
10305	/*
10306	 * if the driver is still busy then fail to
10307	 * suspend/power down.
10308	 */
10309	if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10310	    (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10311		pptr->port_state &= ~flag;
10312		mutex_exit(&pptr->port_mutex);
10313		return (FC_FAILURE);
10314	}
10315
10316	if (flag == FCP_STATE_DETACHING) {
10317		pptr = fcp_soft_state_unlink(pptr);
10318		ASSERT(pptr != NULL);
10319	}
10320
10321	pptr->port_link_cnt++;
10322	pptr->port_state |= FCP_STATE_OFFLINE;
10323	pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10324
10325	fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10326	    FCP_CAUSE_LINK_DOWN);
10327	mutex_exit(&pptr->port_mutex);
10328
10329	/* kill watch dog timer if we're the last */
10330	mutex_enter(&fcp_global_mutex);
10331	if (--fcp_watchdog_init == 0) {
10332		timeout_id_t	tid = fcp_watchdog_id;
10333		mutex_exit(&fcp_global_mutex);
10334		(void) untimeout(tid);
10335	} else {
10336		mutex_exit(&fcp_global_mutex);
10337	}
10338
10339	/* clean up the port structures */
10340	if (flag == FCP_STATE_DETACHING) {
10341		fcp_cleanup_port(pptr, instance);
10342	}
10343
10344	return (FC_SUCCESS);
10345}
10346
10347
10348static void
10349fcp_cleanup_port(struct fcp_port *pptr, int instance)
10350{
10351	ASSERT(pptr != NULL);
10352
10353	/* unbind and free event set */
10354	if (pptr->port_ndi_event_hdl) {
10355		(void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10356		    &pptr->port_ndi_events, NDI_SLEEP);
10357		(void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10358	}
10359
10360	if (pptr->port_ndi_event_defs) {
10361		(void) kmem_free(pptr->port_ndi_event_defs,
10362		    sizeof (fcp_ndi_event_defs));
10363	}
10364
10365	/* free the lun/target structures and devinfos */
10366	fcp_free_targets(pptr);
10367
10368	/*
10369	 * Clean up mpxio stuff
10370	 */
10371	if (pptr->port_mpxio) {
10372		(void) mdi_phci_unregister(pptr->port_dip, 0);
10373		pptr->port_mpxio--;
10374	}
10375
10376	/* clean up SCSA stuff */
10377	(void) scsi_hba_detach(pptr->port_dip);
10378	if (pptr->port_tran != NULL) {
10379		scsi_hba_tran_free(pptr->port_tran);
10380	}
10381
10382#ifdef	KSTATS_CODE
10383	/* clean up kstats */
10384	if (pptr->fcp_ksp != NULL) {
10385		kstat_delete(pptr->fcp_ksp);
10386	}
10387#endif
10388
10389	/* clean up soft state mutexes/condition variables */
10390	mutex_destroy(&pptr->port_mutex);
10391	mutex_destroy(&pptr->port_pkt_mutex);
10392
10393	/* all done with soft state */
10394	ddi_soft_state_free(fcp_softstate, instance);
10395}
10396
10397/*
10398 *     Function: fcp_kmem_cache_constructor
10399 *
10400 *  Description: This function allocates and initializes the resources required
10401 *		 to build a scsi_pkt structure the target driver.  The result
10402 *		 of the allocation and initialization will be cached in the
10403 *		 memory cache.	As DMA resources may be allocated here, that
10404 *		 means DMA resources will be tied up in the cache manager.
10405 *		 This is a tradeoff that has been made for performance reasons.
10406 *
10407 *     Argument: *buf		Memory to preinitialize.
10408 *		 *arg		FCP port structure (fcp_port).
10409 *		 kmflags	Value passed to kmem_cache_alloc() and
10410 *				propagated to the constructor.
10411 *
10412 * Return Value: 0	Allocation/Initialization was successful.
10413 *		 -1	Allocation or Initialization failed.
10414 *
10415 *
10416 * If the returned value is 0, the buffer is initialized like this:
10417 *
10418 *		    +================================+
10419 *	     +----> |	      struct scsi_pkt	     |
10420 *	     |	    |				     |
10421 *	     | +--- | pkt_ha_private		     |
10422 *	     | |    |				     |
10423 *	     | |    +================================+
10424 *	     | |
10425 *	     | |    +================================+
10426 *	     | +--> |	    struct fcp_pkt	     | <---------+
10427 *	     |	    |				     |		 |
10428 *	     +----- | cmd_pkt			     |		 |
10429 *		    |			  cmd_fp_pkt | ---+	 |
10430 *	  +-------->| cmd_fcp_rsp[]		     |	  |	 |
10431 *	  |    +--->| cmd_fcp_cmd[]		     |	  |	 |
10432 *	  |    |    |--------------------------------|	  |	 |
10433 *	  |    |    |	      struct fc_packet	     | <--+	 |
10434 *	  |    |    |				     |		 |
10435 *	  |    |    |		     pkt_ulp_private | ----------+
10436 *	  |    |    |		     pkt_fca_private | -----+
10437 *	  |    |    |		     pkt_data_cookie | ---+ |
10438 *	  |    |    | pkt_cmdlen		     |	  | |
10439 *	  |    |(a) | pkt_rsplen		     |	  | |
10440 *	  |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10441 *	  |	(b) |		      pkt_cmd_cookie | ---|-|----------+    |
10442 *	  +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10443 *		    |		     pkt_resp_cookie | ---|-|--+   |   |    |
10444 *		    | pkt_cmd_dma		     |	  | |  |   |   |    |
10445 *		    | pkt_cmd_acc		     |	  | |  |   |   |    |
10446 *		    +================================+	  | |  |   |   |    |
10447 *		    |	      dma_cookies	     | <--+ |  |   |   |    |
10448 *		    |				     |	    |  |   |   |    |
10449 *		    +================================+	    |  |   |   |    |
10450 *		    |	      fca_private	     | <----+  |   |   |    |
10451 *		    |				     |	       |   |   |    |
10452 *		    +================================+	       |   |   |    |
10453 *							       |   |   |    |
10454 *							       |   |   |    |
10455 *		    +================================+	 (d)   |   |   |    |
10456 *		    |	     fcp_resp cookies	     | <-------+   |   |    |
10457 *		    |				     |		   |   |    |
10458 *		    +================================+		   |   |    |
10459 *								   |   |    |
10460 *		    +================================+	 (d)	   |   |    |
10461 *		    |		fcp_resp	     | <-----------+   |    |
10462 *		    |	(DMA resources associated)   |		       |    |
10463 *		    +================================+		       |    |
10464 *								       |    |
10465 *								       |    |
10466 *								       |    |
10467 *		    +================================+	 (c)	       |    |
10468 *		    |	     fcp_cmd cookies	     | <---------------+    |
10469 *		    |				     |			    |
10470 *		    +================================+			    |
10471 *									    |
10472 *		    +================================+	 (c)		    |
10473 *		    |		 fcp_cmd	     | <--------------------+
10474 *		    |	(DMA resources associated)   |
10475 *		    +================================+
10476 *
10477 * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10478 * (b) Only if DMA is NOT used for the FCP_RESP buffer
10479 * (c) Only if DMA is used for the FCP_CMD buffer.
10480 * (d) Only if DMA is used for the FCP_RESP buffer
10481 */
10482static int
10483fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10484    int kmflags)
10485{
10486	struct fcp_pkt	*cmd;
10487	struct fcp_port	*pptr;
10488	fc_packet_t	*fpkt;
10489
10490	pptr = (struct fcp_port *)tran->tran_hba_private;
10491	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10492	bzero(cmd, tran->tran_hba_len);
10493
10494	cmd->cmd_pkt = pkt;
10495	pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10496	fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10497	cmd->cmd_fp_pkt = fpkt;
10498
10499	cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10500	cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10501	cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10502	    sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10503
10504	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10505	    sizeof (struct fcp_pkt));
10506
10507	fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10508	fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10509
10510	if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10511		/*
10512		 * The underlying HBA doesn't want to DMA the fcp_cmd or
10513		 * fcp_resp.  The transfer of information will be done by
10514		 * bcopy.
10515		 * The naming of the flags (that is actually a value) is
10516		 * unfortunate.	 FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10517		 * DMA" but instead "NO DMA".
10518		 */
10519		fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10520		fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10521		fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10522	} else {
10523		/*
10524		 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10525		 * buffer.  A buffer is allocated for each one the ddi_dma_*
10526		 * interfaces.
10527		 */
10528		if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10529			return (-1);
10530		}
10531	}
10532
10533	return (0);
10534}
10535
10536/*
10537 *     Function: fcp_kmem_cache_destructor
10538 *
10539 *  Description: Called by the destructor of the cache managed by SCSA.
10540 *		 All the resources pre-allocated in fcp_pkt_constructor
10541 *		 and the data also pre-initialized in fcp_pkt_constructor
10542 *		 are freed and uninitialized here.
10543 *
10544 *     Argument: *buf		Memory to uninitialize.
10545 *		 *arg		FCP port structure (fcp_port).
10546 *
10547 * Return Value: None
10548 *
10549 *	Context: kernel
10550 */
10551static void
10552fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10553{
10554	struct fcp_pkt	*cmd;
10555	struct fcp_port	*pptr;
10556
10557	pptr = (struct fcp_port *)(tran->tran_hba_private);
10558	cmd = pkt->pkt_ha_private;
10559
10560	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10561		/*
10562		 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10563		 * buffer and DMA resources allocated to do so are released.
10564		 */
10565		fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10566	}
10567}
10568
10569/*
10570 *     Function: fcp_alloc_cmd_resp
10571 *
10572 *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10573 *		 will be DMAed by the HBA.  The buffer is allocated applying
10574 *		 the DMA requirements for the HBA.  The buffers allocated will
10575 *		 also be bound.	 DMA resources are allocated in the process.
10576 *		 They will be released by fcp_free_cmd_resp().
10577 *
10578 *     Argument: *pptr	FCP port.
10579 *		 *fpkt	fc packet for which the cmd and resp packet should be
10580 *			allocated.
10581 *		 flags	Allocation flags.
10582 *
10583 * Return Value: FC_FAILURE
10584 *		 FC_SUCCESS
10585 *
10586 *	Context: User or Kernel context only if flags == KM_SLEEP.
10587 *		 Interrupt context if the KM_SLEEP is not specified.
10588 */
10589static int
10590fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10591{
10592	int			rval;
10593	int			cmd_len;
10594	int			resp_len;
10595	ulong_t			real_len;
10596	int			(*cb) (caddr_t);
10597	ddi_dma_cookie_t	pkt_cookie;
10598	ddi_dma_cookie_t	*cp;
10599	uint32_t		cnt;
10600
10601	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10602
10603	cmd_len = fpkt->pkt_cmdlen;
10604	resp_len = fpkt->pkt_rsplen;
10605
10606	ASSERT(fpkt->pkt_cmd_dma == NULL);
10607
10608	/* Allocation of a DMA handle used in subsequent calls. */
10609	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10610	    cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10611		return (FC_FAILURE);
10612	}
10613
10614	/* A buffer is allocated that satisfies the DMA requirements. */
10615	rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10616	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10617	    (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10618
10619	if (rval != DDI_SUCCESS) {
10620		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10621		return (FC_FAILURE);
10622	}
10623
10624	if (real_len < cmd_len) {
10625		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10626		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10627		return (FC_FAILURE);
10628	}
10629
10630	/* The buffer allocated is DMA bound. */
10631	rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10632	    fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10633	    cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10634
10635	if (rval != DDI_DMA_MAPPED) {
10636		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10637		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10638		return (FC_FAILURE);
10639	}
10640
10641	if (fpkt->pkt_cmd_cookie_cnt >
10642	    pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10643		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10644		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10645		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10646		return (FC_FAILURE);
10647	}
10648
10649	ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10650
10651	/*
10652	 * The buffer where the scatter/gather list is going to be built is
10653	 * allocated.
10654	 */
10655	cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10656	    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10657	    KM_NOSLEEP);
10658
10659	if (cp == NULL) {
10660		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10661		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10662		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10663		return (FC_FAILURE);
10664	}
10665
10666	/*
10667	 * The scatter/gather list for the buffer we just allocated is built
10668	 * here.
10669	 */
10670	*cp = pkt_cookie;
10671	cp++;
10672
10673	for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10674		ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10675		    &pkt_cookie);
10676		*cp = pkt_cookie;
10677	}
10678
10679	ASSERT(fpkt->pkt_resp_dma == NULL);
10680	if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10681	    cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10682		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10683		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10684		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10685		return (FC_FAILURE);
10686	}
10687
10688	rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10689	    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10690	    (caddr_t *)&fpkt->pkt_resp, &real_len,
10691	    &fpkt->pkt_resp_acc);
10692
10693	if (rval != DDI_SUCCESS) {
10694		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10695		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10696		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10697		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10698		kmem_free(fpkt->pkt_cmd_cookie,
10699		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10700		return (FC_FAILURE);
10701	}
10702
10703	if (real_len < resp_len) {
10704		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10705		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10706		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10707		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10708		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10709		kmem_free(fpkt->pkt_cmd_cookie,
10710		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10711		return (FC_FAILURE);
10712	}
10713
10714	rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10715	    fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10716	    cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10717
10718	if (rval != DDI_DMA_MAPPED) {
10719		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10720		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10721		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10722		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10723		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10724		kmem_free(fpkt->pkt_cmd_cookie,
10725		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10726		return (FC_FAILURE);
10727	}
10728
10729	if (fpkt->pkt_resp_cookie_cnt >
10730	    pptr->port_resp_dma_attr.dma_attr_sgllen) {
10731		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10732		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10733		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10734		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10735		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10736		kmem_free(fpkt->pkt_cmd_cookie,
10737		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10738		return (FC_FAILURE);
10739	}
10740
10741	ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10742
10743	cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10744	    fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10745	    KM_NOSLEEP);
10746
10747	if (cp == NULL) {
10748		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10749		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10750		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10751		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10752		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10753		kmem_free(fpkt->pkt_cmd_cookie,
10754		    fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10755		return (FC_FAILURE);
10756	}
10757
10758	*cp = pkt_cookie;
10759	cp++;
10760
10761	for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10762		ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10763		    &pkt_cookie);
10764		*cp = pkt_cookie;
10765	}
10766
10767	return (FC_SUCCESS);
10768}
10769
10770/*
10771 *     Function: fcp_free_cmd_resp
10772 *
10773 *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10774 *		 allocated by fcp_alloc_cmd_resp() and all the resources
10775 *		 associated with them.	That includes the DMA resources and the
10776 *		 buffer allocated for the cookies of each one of them.
10777 *
10778 *     Argument: *pptr		FCP port context.
10779 *		 *fpkt		fc packet containing the cmd and resp packet
10780 *				to be released.
10781 *
10782 * Return Value: None
10783 *
10784 *	Context: Interrupt, User and Kernel context.
10785 */
10786/* ARGSUSED */
10787static void
10788fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10789{
10790	ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10791
10792	if (fpkt->pkt_resp_dma) {
10793		(void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10794		ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10795		ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10796	}
10797
10798	if (fpkt->pkt_resp_cookie) {
10799		kmem_free(fpkt->pkt_resp_cookie,
10800		    fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10801		fpkt->pkt_resp_cookie = NULL;
10802	}
10803
10804	if (fpkt->pkt_cmd_dma) {
10805		(void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10806		ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10807		ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10808	}
10809
10810	if (fpkt->pkt_cmd_cookie) {
10811		kmem_free(fpkt->pkt_cmd_cookie,
10812		    fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10813		fpkt->pkt_cmd_cookie = NULL;
10814	}
10815}
10816
10817
10818/*
10819 * called by the transport to do our own target initialization
10820 *
10821 * can acquire and release the global mutex
10822 */
10823/* ARGSUSED */
10824static int
10825fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10826    scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10827{
10828	uchar_t			*bytes;
10829	uint_t			nbytes;
10830	uint16_t		lun_num;
10831	struct fcp_tgt	*ptgt;
10832	struct fcp_lun	*plun;
10833	struct fcp_port	*pptr = (struct fcp_port *)
10834	    hba_tran->tran_hba_private;
10835
10836	ASSERT(pptr != NULL);
10837
10838	FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10839	    FCP_BUF_LEVEL_8, 0,
10840	    "fcp_phys_tgt_init: called for %s (instance %d)",
10841	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10842
10843	/* get our port WWN property */
10844	bytes = NULL;
10845	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10846	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10847	    (nbytes != FC_WWN_SIZE)) {
10848		/* no port WWN property */
10849		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10850		    FCP_BUF_LEVEL_8, 0,
10851		    "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10852		    " for %s (instance %d): bytes=%p nbytes=%x",
10853		    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10854		    nbytes);
10855
10856		if (bytes != NULL) {
10857			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10858		}
10859
10860		return (DDI_NOT_WELL_FORMED);
10861	}
10862	ASSERT(bytes != NULL);
10863
10864	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10865	    LUN_PROP, 0xFFFF);
10866	if (lun_num == 0xFFFF) {
10867		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10868		    FCP_BUF_LEVEL_8, 0,
10869		    "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10870		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10871		    ddi_get_instance(tgt_dip));
10872
10873		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10874		return (DDI_NOT_WELL_FORMED);
10875	}
10876
10877	mutex_enter(&pptr->port_mutex);
10878	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10879		mutex_exit(&pptr->port_mutex);
10880		FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10881		    FCP_BUF_LEVEL_8, 0,
10882		    "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10883		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10884		    ddi_get_instance(tgt_dip));
10885
10886		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10887		return (DDI_FAILURE);
10888	}
10889
10890	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10891	    FC_WWN_SIZE) == 0);
10892	ASSERT(plun->lun_num == lun_num);
10893
10894	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10895
10896	ptgt = plun->lun_tgt;
10897
10898	mutex_enter(&ptgt->tgt_mutex);
10899	plun->lun_tgt_count++;
10900	scsi_device_hba_private_set(sd, plun);
10901	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10902	plun->lun_sd = sd;
10903	mutex_exit(&ptgt->tgt_mutex);
10904	mutex_exit(&pptr->port_mutex);
10905
10906	return (DDI_SUCCESS);
10907}
10908
10909/*ARGSUSED*/
10910static int
10911fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10912    scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10913{
10914	uchar_t			*bytes;
10915	uint_t			nbytes;
10916	uint16_t		lun_num;
10917	struct fcp_tgt	*ptgt;
10918	struct fcp_lun	*plun;
10919	struct fcp_port	*pptr = (struct fcp_port *)
10920	    hba_tran->tran_hba_private;
10921	child_info_t		*cip;
10922
10923	ASSERT(pptr != NULL);
10924
10925	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10926	    fcp_trace, FCP_BUF_LEVEL_8, 0,
10927	    "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10928	    " (tgt_dip %p)", ddi_get_name(tgt_dip),
10929	    ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10930
10931	cip = (child_info_t *)sd->sd_pathinfo;
10932	if (cip == NULL) {
10933		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10934		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10935		    "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10936		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10937		    ddi_get_instance(tgt_dip));
10938
10939		return (DDI_NOT_WELL_FORMED);
10940	}
10941
10942	/* get our port WWN property */
10943	bytes = NULL;
10944	if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10945	    PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10946	    (nbytes != FC_WWN_SIZE)) {
10947		if (bytes) {
10948			scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10949		}
10950		return (DDI_NOT_WELL_FORMED);
10951	}
10952
10953	ASSERT(bytes != NULL);
10954
10955	lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10956	    LUN_PROP, 0xFFFF);
10957	if (lun_num == 0xFFFF) {
10958		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10959		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10960		    "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10961		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10962		    ddi_get_instance(tgt_dip));
10963
10964		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10965		return (DDI_NOT_WELL_FORMED);
10966	}
10967
10968	mutex_enter(&pptr->port_mutex);
10969	if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10970		mutex_exit(&pptr->port_mutex);
10971		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10972		    fcp_trace, FCP_BUF_LEVEL_8, 0,
10973		    "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10974		    " for %s (instance %d)", ddi_get_name(tgt_dip),
10975		    ddi_get_instance(tgt_dip));
10976
10977		scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10978		return (DDI_FAILURE);
10979	}
10980
10981	ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10982	    FC_WWN_SIZE) == 0);
10983	ASSERT(plun->lun_num == lun_num);
10984
10985	scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10986
10987	ptgt = plun->lun_tgt;
10988
10989	mutex_enter(&ptgt->tgt_mutex);
10990	plun->lun_tgt_count++;
10991	scsi_device_hba_private_set(sd, plun);
10992	plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10993	plun->lun_sd = sd;
10994	mutex_exit(&ptgt->tgt_mutex);
10995	mutex_exit(&pptr->port_mutex);
10996
10997	return (DDI_SUCCESS);
10998}
10999
11000
11001/*
11002 * called by the transport to do our own target initialization
11003 *
11004 * can acquire and release the global mutex
11005 */
11006/* ARGSUSED */
11007static int
11008fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11009    scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11010{
11011	struct fcp_port	*pptr = (struct fcp_port *)
11012	    hba_tran->tran_hba_private;
11013	int			rval;
11014
11015	ASSERT(pptr != NULL);
11016
11017	/*
11018	 * Child node is getting initialized.  Look at the mpxio component
11019	 * type on the child device to see if this device is mpxio managed
11020	 * or not.
11021	 */
11022	if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11023		rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11024	} else {
11025		rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11026	}
11027
11028	return (rval);
11029}
11030
11031
11032/* ARGSUSED */
11033static void
11034fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11035    scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11036{
11037	struct fcp_lun	*plun = scsi_device_hba_private_get(sd);
11038	struct fcp_tgt	*ptgt;
11039
11040	FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11041	    fcp_trace, FCP_BUF_LEVEL_8, 0,
11042	    "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11043	    ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11044	    ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11045
11046	if (plun == NULL) {
11047		return;
11048	}
11049	ptgt = plun->lun_tgt;
11050
11051	ASSERT(ptgt != NULL);
11052
11053	mutex_enter(&ptgt->tgt_mutex);
11054	ASSERT(plun->lun_tgt_count > 0);
11055
11056	if (--plun->lun_tgt_count == 0) {
11057		plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11058	}
11059	plun->lun_sd = NULL;
11060	mutex_exit(&ptgt->tgt_mutex);
11061}
11062
11063/*
11064 *     Function: fcp_scsi_start
11065 *
11066 *  Description: This function is called by the target driver to request a
11067 *		 command to be sent.
11068 *
11069 *     Argument: *ap		SCSI address of the device.
11070 *		 *pkt		SCSI packet containing the cmd to send.
11071 *
11072 * Return Value: TRAN_ACCEPT
11073 *		 TRAN_BUSY
11074 *		 TRAN_BADPKT
11075 *		 TRAN_FATAL_ERROR
11076 */
11077static int
11078fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11079{
11080	struct fcp_port	*pptr = ADDR2FCP(ap);
11081	struct fcp_lun	*plun = ADDR2LUN(ap);
11082	struct fcp_pkt	*cmd = PKT2CMD(pkt);
11083	struct fcp_tgt	*ptgt = plun->lun_tgt;
11084	int			rval;
11085
11086	/* ensure command isn't already issued */
11087	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11088
11089	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11090	    fcp_trace, FCP_BUF_LEVEL_9, 0,
11091	    "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11092
11093	/*
11094	 * It is strange that we enter the fcp_port mutex and the target
11095	 * mutex to check the lun state (which has a mutex of its own).
11096	 */
11097	mutex_enter(&pptr->port_mutex);
11098	mutex_enter(&ptgt->tgt_mutex);
11099
11100	/*
11101	 * If the device is offline and is not in the process of coming
11102	 * online, fail the request.
11103	 */
11104
11105	if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11106	    !(plun->lun_state & FCP_LUN_ONLINING)) {
11107		mutex_exit(&ptgt->tgt_mutex);
11108		mutex_exit(&pptr->port_mutex);
11109
11110		if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11111			pkt->pkt_reason = CMD_DEV_GONE;
11112		}
11113
11114		return (TRAN_FATAL_ERROR);
11115	}
11116	cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11117
11118	/*
11119	 * If we are suspended, kernel is trying to dump, so don't
11120	 * block, fail or defer requests - send them down right away.
11121	 * NOTE: If we are in panic (i.e. trying to dump), we can't
11122	 * assume we have been suspended.  There is hardware such as
11123	 * the v880 that doesn't do PM.	 Thus, the check for
11124	 * ddi_in_panic.
11125	 *
11126	 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11127	 * of changing.	 So, if we can queue the packet, do it.	 Eventually,
11128	 * either the device will have gone away or changed and we can fail
11129	 * the request, or we can proceed if the device didn't change.
11130	 *
11131	 * If the pd in the target or the packet is NULL it's probably
11132	 * because the device has gone away, we allow the request to be
11133	 * put on the internal queue here in case the device comes back within
11134	 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11135	 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11136	 * could be NULL because the device was disappearing during or since
11137	 * packet initialization.
11138	 */
11139
11140	if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11141	    FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11142	    (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11143	    (ptgt->tgt_pd_handle == NULL) ||
11144	    (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11145		/*
11146		 * If ((LUN is busy AND
11147		 *	LUN not suspended AND
11148		 *	The system is not in panic state) OR
11149		 *	(The port is coming up))
11150		 *
11151		 * We check to see if the any of the flags FLAG_NOINTR or
11152		 * FLAG_NOQUEUE is set.	 If one of them is set the value
11153		 * returned will be TRAN_BUSY.	If not, the request is queued.
11154		 */
11155		mutex_exit(&ptgt->tgt_mutex);
11156		mutex_exit(&pptr->port_mutex);
11157
11158		/* see if using interrupts is allowed (so queueing'll work) */
11159		if (pkt->pkt_flags & FLAG_NOINTR) {
11160			pkt->pkt_resid = 0;
11161			return (TRAN_BUSY);
11162		}
11163		if (pkt->pkt_flags & FLAG_NOQUEUE) {
11164			FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11165			    fcp_trace, FCP_BUF_LEVEL_9, 0,
11166			    "fcp_scsi_start: lun busy for pkt %p", pkt);
11167			return (TRAN_BUSY);
11168		}
11169#ifdef	DEBUG
11170		mutex_enter(&pptr->port_pkt_mutex);
11171		pptr->port_npkts++;
11172		mutex_exit(&pptr->port_pkt_mutex);
11173#endif /* DEBUG */
11174
11175		/* got queue up the pkt for later */
11176		fcp_queue_pkt(pptr, cmd);
11177		return (TRAN_ACCEPT);
11178	}
11179	cmd->cmd_state = FCP_PKT_ISSUED;
11180
11181	mutex_exit(&ptgt->tgt_mutex);
11182	mutex_exit(&pptr->port_mutex);
11183
11184	/*
11185	 * Now that we released the mutexes, what was protected by them can
11186	 * change.
11187	 */
11188
11189	/*
11190	 * If there is a reconfiguration in progress, wait for it to complete.
11191	 */
11192	fcp_reconfig_wait(pptr);
11193
11194	cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11195	    pkt->pkt_time : 0;
11196
11197	/* prepare the packet */
11198
11199	fcp_prepare_pkt(pptr, cmd, plun);
11200
11201	if (cmd->cmd_pkt->pkt_time) {
11202		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11203	} else {
11204		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11205	}
11206
11207	/*
11208	 * if interrupts aren't allowed (e.g. at dump time) then we'll
11209	 * have to do polled I/O
11210	 */
11211	if (pkt->pkt_flags & FLAG_NOINTR) {
11212		cmd->cmd_state &= ~FCP_PKT_ISSUED;
11213		return (fcp_dopoll(pptr, cmd));
11214	}
11215
11216#ifdef	DEBUG
11217	mutex_enter(&pptr->port_pkt_mutex);
11218	pptr->port_npkts++;
11219	mutex_exit(&pptr->port_pkt_mutex);
11220#endif /* DEBUG */
11221
11222	rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11223	if (rval == FC_SUCCESS) {
11224		FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11225		    fcp_trace, FCP_BUF_LEVEL_9, 0,
11226		    "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11227		return (TRAN_ACCEPT);
11228	}
11229
11230	cmd->cmd_state = FCP_PKT_IDLE;
11231
11232#ifdef	DEBUG
11233	mutex_enter(&pptr->port_pkt_mutex);
11234	pptr->port_npkts--;
11235	mutex_exit(&pptr->port_pkt_mutex);
11236#endif /* DEBUG */
11237
11238	/*
11239	 * For lack of clearer definitions, choose
11240	 * between TRAN_BUSY and TRAN_FATAL_ERROR.
11241	 */
11242
11243	if (rval == FC_TRAN_BUSY) {
11244		pkt->pkt_resid = 0;
11245		rval = TRAN_BUSY;
11246	} else {
11247		mutex_enter(&ptgt->tgt_mutex);
11248		if (plun->lun_state & FCP_LUN_OFFLINE) {
11249			child_info_t	*cip;
11250
11251			mutex_enter(&plun->lun_mutex);
11252			cip = plun->lun_cip;
11253			mutex_exit(&plun->lun_mutex);
11254
11255			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11256			    fcp_trace, FCP_BUF_LEVEL_6, 0,
11257			    "fcp_transport failed 2 for %x: %x; dip=%p",
11258			    plun->lun_tgt->tgt_d_id, rval, cip);
11259
11260			rval = TRAN_FATAL_ERROR;
11261		} else {
11262			if (pkt->pkt_flags & FLAG_NOQUEUE) {
11263				FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11264				    fcp_trace, FCP_BUF_LEVEL_9, 0,
11265				    "fcp_scsi_start: FC_BUSY for pkt %p",
11266				    pkt);
11267				rval = TRAN_BUSY;
11268			} else {
11269				rval = TRAN_ACCEPT;
11270				fcp_queue_pkt(pptr, cmd);
11271			}
11272		}
11273		mutex_exit(&ptgt->tgt_mutex);
11274	}
11275
11276	return (rval);
11277}
11278
11279/*
11280 * called by the transport to abort a packet
11281 */
11282/*ARGSUSED*/
11283static int
11284fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11285{
11286	int tgt_cnt;
11287	struct fcp_port		*pptr = ADDR2FCP(ap);
11288	struct fcp_lun	*plun = ADDR2LUN(ap);
11289	struct fcp_tgt	*ptgt = plun->lun_tgt;
11290
11291	if (pkt == NULL) {
11292		if (ptgt) {
11293			mutex_enter(&ptgt->tgt_mutex);
11294			tgt_cnt = ptgt->tgt_change_cnt;
11295			mutex_exit(&ptgt->tgt_mutex);
11296			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11297			return (TRUE);
11298		}
11299	}
11300	return (FALSE);
11301}
11302
11303
11304/*
11305 * Perform reset
11306 */
11307int
11308fcp_scsi_reset(struct scsi_address *ap, int level)
11309{
11310	int			rval = 0;
11311	struct fcp_port		*pptr = ADDR2FCP(ap);
11312	struct fcp_lun	*plun = ADDR2LUN(ap);
11313	struct fcp_tgt	*ptgt = plun->lun_tgt;
11314
11315	if (level == RESET_ALL) {
11316		if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11317			rval = 1;
11318		}
11319	} else if (level == RESET_TARGET || level == RESET_LUN) {
11320		/*
11321		 * If we are in the middle of discovery, return
11322		 * SUCCESS as this target will be rediscovered
11323		 * anyway
11324		 */
11325		mutex_enter(&ptgt->tgt_mutex);
11326		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11327			mutex_exit(&ptgt->tgt_mutex);
11328			return (1);
11329		}
11330		mutex_exit(&ptgt->tgt_mutex);
11331
11332		if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11333			rval = 1;
11334		}
11335	}
11336	return (rval);
11337}
11338
11339
11340/*
11341 * called by the framework to get a SCSI capability
11342 */
11343static int
11344fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11345{
11346	return (fcp_commoncap(ap, cap, 0, whom, 0));
11347}
11348
11349
11350/*
11351 * called by the framework to set a SCSI capability
11352 */
11353static int
11354fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11355{
11356	return (fcp_commoncap(ap, cap, value, whom, 1));
11357}
11358
11359/*
11360 *     Function: fcp_pkt_setup
11361 *
11362 *  Description: This function sets up the scsi_pkt structure passed by the
11363 *		 caller. This function assumes fcp_pkt_constructor has been
11364 *		 called previously for the packet passed by the caller.	 If
11365 *		 successful this call will have the following results:
11366 *
11367 *		   - The resources needed that will be constant through out
11368 *		     the whole transaction are allocated.
11369 *		   - The fields that will be constant through out the whole
11370 *		     transaction are initialized.
11371 *		   - The scsi packet will be linked to the LUN structure
11372 *		     addressed by the transaction.
11373 *
11374 *     Argument:
11375 *		 *pkt		Pointer to a scsi_pkt structure.
11376 *		 callback
11377 *		 arg
11378 *
11379 * Return Value: 0	Success
11380 *		 !0	Failure
11381 *
11382 *	Context: Kernel context or interrupt context
11383 */
11384/* ARGSUSED */
11385static int
11386fcp_pkt_setup(struct scsi_pkt *pkt,
11387    int (*callback)(caddr_t arg),
11388    caddr_t arg)
11389{
11390	struct fcp_pkt	*cmd;
11391	struct fcp_port	*pptr;
11392	struct fcp_lun	*plun;
11393	struct fcp_tgt	*ptgt;
11394	int		kf;
11395	fc_packet_t	*fpkt;
11396	fc_frame_hdr_t	*hp;
11397
11398	pptr = ADDR2FCP(&pkt->pkt_address);
11399	plun = ADDR2LUN(&pkt->pkt_address);
11400	ptgt = plun->lun_tgt;
11401
11402	cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11403	fpkt = cmd->cmd_fp_pkt;
11404
11405	/*
11406	 * this request is for dma allocation only
11407	 */
11408	/*
11409	 * First step of fcp_scsi_init_pkt: pkt allocation
11410	 * We determine if the caller is willing to wait for the
11411	 * resources.
11412	 */
11413	kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11414
11415	/*
11416	 * Selective zeroing of the pkt.
11417	 */
11418	cmd->cmd_back = NULL;
11419	cmd->cmd_next = NULL;
11420
11421	/*
11422	 * Zero out fcp command
11423	 */
11424	bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11425
11426	cmd->cmd_state = FCP_PKT_IDLE;
11427
11428	fpkt = cmd->cmd_fp_pkt;
11429	fpkt->pkt_data_acc = NULL;
11430
11431	/*
11432	 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11433	 * could be destroyed.	We need fail pkt_setup.
11434	 */
11435	if (pptr->port_state & FCP_STATE_OFFLINE) {
11436		return (-1);
11437	}
11438
11439	mutex_enter(&ptgt->tgt_mutex);
11440	fpkt->pkt_pd = ptgt->tgt_pd_handle;
11441
11442	if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11443	    != FC_SUCCESS) {
11444		mutex_exit(&ptgt->tgt_mutex);
11445		return (-1);
11446	}
11447
11448	mutex_exit(&ptgt->tgt_mutex);
11449
11450	/* Fill in the Fabric Channel Header */
11451	hp = &fpkt->pkt_cmd_fhdr;
11452	hp->r_ctl = R_CTL_COMMAND;
11453	hp->rsvd = 0;
11454	hp->type = FC_TYPE_SCSI_FCP;
11455	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11456	hp->seq_id = 0;
11457	hp->df_ctl  = 0;
11458	hp->seq_cnt = 0;
11459	hp->ox_id = 0xffff;
11460	hp->rx_id = 0xffff;
11461	hp->ro = 0;
11462
11463	/*
11464	 * A doubly linked list (cmd_forw, cmd_back) is built
11465	 * out of every allocated packet on a per-lun basis
11466	 *
11467	 * The packets are maintained in the list so as to satisfy
11468	 * scsi_abort() requests. At present (which is unlikely to
11469	 * change in the future) nobody performs a real scsi_abort
11470	 * in the SCSI target drivers (as they don't keep the packets
11471	 * after doing scsi_transport - so they don't know how to
11472	 * abort a packet other than sending a NULL to abort all
11473	 * outstanding packets)
11474	 */
11475	mutex_enter(&plun->lun_mutex);
11476	if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11477		plun->lun_pkt_head->cmd_back = cmd;
11478	} else {
11479		plun->lun_pkt_tail = cmd;
11480	}
11481	plun->lun_pkt_head = cmd;
11482	mutex_exit(&plun->lun_mutex);
11483	return (0);
11484}
11485
11486/*
11487 *     Function: fcp_pkt_teardown
11488 *
11489 *  Description: This function releases a scsi_pkt structure and all the
11490 *		 resources attached to it.
11491 *
11492 *     Argument: *pkt		Pointer to a scsi_pkt structure.
11493 *
11494 * Return Value: None
11495 *
11496 *	Context: User, Kernel or Interrupt context.
11497 */
11498static void
11499fcp_pkt_teardown(struct scsi_pkt *pkt)
11500{
11501	struct fcp_port	*pptr = ADDR2FCP(&pkt->pkt_address);
11502	struct fcp_lun	*plun = ADDR2LUN(&pkt->pkt_address);
11503	struct fcp_pkt	*cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11504
11505	/*
11506	 * Remove the packet from the per-lun list
11507	 */
11508	mutex_enter(&plun->lun_mutex);
11509	if (cmd->cmd_back) {
11510		ASSERT(cmd != plun->lun_pkt_head);
11511		cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11512	} else {
11513		ASSERT(cmd == plun->lun_pkt_head);
11514		plun->lun_pkt_head = cmd->cmd_forw;
11515	}
11516
11517	if (cmd->cmd_forw) {
11518		cmd->cmd_forw->cmd_back = cmd->cmd_back;
11519	} else {
11520		ASSERT(cmd == plun->lun_pkt_tail);
11521		plun->lun_pkt_tail = cmd->cmd_back;
11522	}
11523
11524	mutex_exit(&plun->lun_mutex);
11525
11526	(void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11527}
11528
11529/*
11530 * Routine for reset notification setup, to register or cancel.
11531 * This function is called by SCSA
11532 */
11533/*ARGSUSED*/
11534static int
11535fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11536    void (*callback)(caddr_t), caddr_t arg)
11537{
11538	struct fcp_port *pptr = ADDR2FCP(ap);
11539
11540	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11541	    &pptr->port_mutex, &pptr->port_reset_notify_listf));
11542}
11543
11544
11545static int
11546fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11547    ddi_eventcookie_t *event_cookiep)
11548{
11549	struct fcp_port *pptr = fcp_dip2port(dip);
11550
11551	if (pptr == NULL) {
11552		return (DDI_FAILURE);
11553	}
11554
11555	return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11556	    event_cookiep, NDI_EVENT_NOPASS));
11557}
11558
11559
11560static int
11561fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11562    ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11563    ddi_callback_id_t *cb_id)
11564{
11565	struct fcp_port *pptr = fcp_dip2port(dip);
11566
11567	if (pptr == NULL) {
11568		return (DDI_FAILURE);
11569	}
11570
11571	return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11572	    eventid, callback, arg, NDI_SLEEP, cb_id));
11573}
11574
11575
11576static int
11577fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11578{
11579
11580	struct fcp_port *pptr = fcp_dip2port(dip);
11581
11582	if (pptr == NULL) {
11583		return (DDI_FAILURE);
11584	}
11585	return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11586}
11587
11588
11589/*
11590 * called by the transport to post an event
11591 */
11592static int
11593fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11594    ddi_eventcookie_t eventid, void *impldata)
11595{
11596	struct fcp_port *pptr = fcp_dip2port(dip);
11597
11598	if (pptr == NULL) {
11599		return (DDI_FAILURE);
11600	}
11601
11602	return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11603	    eventid, impldata));
11604}
11605
11606
11607/*
11608 * A target in in many cases in Fibre Channel has a one to one relation
11609 * with a port identifier (which is also known as D_ID and also as AL_PA
11610 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11611 * will most likely result in resetting all LUNs (which means a reset will
11612 * occur on all the SCSI devices connected at the other end of the bridge)
11613 * That is the latest favorite topic for discussion, for, one can debate as
11614 * hot as one likes and come up with arguably a best solution to one's
11615 * satisfaction
11616 *
11617 * To stay on track and not digress much, here are the problems stated
11618 * briefly:
11619 *
11620 *	SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11621 *	target drivers use RESET_TARGET even if their instance is on a
11622 *	LUN. Doesn't that sound a bit broken ?
11623 *
11624 *	FCP SCSI (the current spec) only defines RESET TARGET in the
11625 *	control fields of an FCP_CMND structure. It should have been
11626 *	fixed right there, giving flexibility to the initiators to
11627 *	minimize havoc that could be caused by resetting a target.
11628 */
11629static int
11630fcp_reset_target(struct scsi_address *ap, int level)
11631{
11632	int			rval = FC_FAILURE;
11633	char			lun_id[25];
11634	struct fcp_port		*pptr = ADDR2FCP(ap);
11635	struct fcp_lun	*plun = ADDR2LUN(ap);
11636	struct fcp_tgt	*ptgt = plun->lun_tgt;
11637	struct scsi_pkt		*pkt;
11638	struct fcp_pkt	*cmd;
11639	struct fcp_rsp		*rsp;
11640	uint32_t		tgt_cnt;
11641	struct fcp_rsp_info	*rsp_info;
11642	struct fcp_reset_elem	*p;
11643	int			bval;
11644
11645	if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11646	    KM_NOSLEEP)) == NULL) {
11647		return (rval);
11648	}
11649
11650	mutex_enter(&ptgt->tgt_mutex);
11651	if (level == RESET_TARGET) {
11652		if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11653			mutex_exit(&ptgt->tgt_mutex);
11654			kmem_free(p, sizeof (struct fcp_reset_elem));
11655			return (rval);
11656		}
11657		fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11658		(void) strcpy(lun_id, " ");
11659	} else {
11660		if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11661			mutex_exit(&ptgt->tgt_mutex);
11662			kmem_free(p, sizeof (struct fcp_reset_elem));
11663			return (rval);
11664		}
11665		fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11666
11667		(void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11668	}
11669	tgt_cnt = ptgt->tgt_change_cnt;
11670
11671	mutex_exit(&ptgt->tgt_mutex);
11672
11673	if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11674	    0, 0, NULL, 0)) == NULL) {
11675		kmem_free(p, sizeof (struct fcp_reset_elem));
11676		mutex_enter(&ptgt->tgt_mutex);
11677		fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11678		mutex_exit(&ptgt->tgt_mutex);
11679		return (rval);
11680	}
11681	pkt->pkt_time = FCP_POLL_TIMEOUT;
11682
11683	/* fill in cmd part of packet */
11684	cmd = PKT2CMD(pkt);
11685	if (level == RESET_TARGET) {
11686		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11687	} else {
11688		cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11689	}
11690	cmd->cmd_fp_pkt->pkt_comp = NULL;
11691	cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11692
11693	/* prepare a packet for transport */
11694	fcp_prepare_pkt(pptr, cmd, plun);
11695
11696	if (cmd->cmd_pkt->pkt_time) {
11697		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11698	} else {
11699		cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11700	}
11701
11702	(void) fc_ulp_busy_port(pptr->port_fp_handle);
11703	bval = fcp_dopoll(pptr, cmd);
11704	fc_ulp_idle_port(pptr->port_fp_handle);
11705
11706	/* submit the packet */
11707	if (bval == TRAN_ACCEPT) {
11708		int error = 3;
11709
11710		rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11711		rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11712		    sizeof (struct fcp_rsp));
11713
11714		if (rsp->fcp_u.fcp_status.rsp_len_set) {
11715			if (fcp_validate_fcp_response(rsp, pptr) ==
11716			    FC_SUCCESS) {
11717				if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11718					FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11719					    sizeof (struct fcp_rsp), rsp_info,
11720					    cmd->cmd_fp_pkt->pkt_resp_acc,
11721					    sizeof (struct fcp_rsp_info));
11722				}
11723				if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11724					rval = FC_SUCCESS;
11725					error = 0;
11726				} else {
11727					error = 1;
11728				}
11729			} else {
11730				error = 2;
11731			}
11732		}
11733
11734		switch (error) {
11735		case 0:
11736			fcp_log(CE_WARN, pptr->port_dip,
11737			    "!FCP: WWN 0x%08x%08x %s reset successfully",
11738			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11739			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11740			break;
11741
11742		case 1:
11743			fcp_log(CE_WARN, pptr->port_dip,
11744			    "!FCP: Reset to WWN	 0x%08x%08x %s failed,"
11745			    " response code=%x",
11746			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11747			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11748			    rsp_info->rsp_code);
11749			break;
11750
11751		case 2:
11752			fcp_log(CE_WARN, pptr->port_dip,
11753			    "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11754			    " Bad FCP response values: rsvd1=%x,"
11755			    " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11756			    " rsplen=%x, senselen=%x",
11757			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11758			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11759			    rsp->reserved_0, rsp->reserved_1,
11760			    rsp->fcp_u.fcp_status.reserved_0,
11761			    rsp->fcp_u.fcp_status.reserved_1,
11762			    rsp->fcp_response_len, rsp->fcp_sense_len);
11763			break;
11764
11765		default:
11766			fcp_log(CE_WARN, pptr->port_dip,
11767			    "!FCP: Reset to WWN	 0x%08x%08x %s failed",
11768			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11769			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11770			break;
11771		}
11772	}
11773	scsi_destroy_pkt(pkt);
11774
11775	if (rval == FC_FAILURE) {
11776		mutex_enter(&ptgt->tgt_mutex);
11777		if (level == RESET_TARGET) {
11778			fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11779		} else {
11780			fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11781		}
11782		mutex_exit(&ptgt->tgt_mutex);
11783		kmem_free(p, sizeof (struct fcp_reset_elem));
11784		return (rval);
11785	}
11786
11787	mutex_enter(&pptr->port_mutex);
11788	if (level == RESET_TARGET) {
11789		p->tgt = ptgt;
11790		p->lun = NULL;
11791	} else {
11792		p->tgt = NULL;
11793		p->lun = plun;
11794	}
11795	p->tgt = ptgt;
11796	p->tgt_cnt = tgt_cnt;
11797	p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11798	p->next = pptr->port_reset_list;
11799	pptr->port_reset_list = p;
11800
11801	FCP_TRACE(fcp_logq, pptr->port_instbuf,
11802	    fcp_trace, FCP_BUF_LEVEL_3, 0,
11803	    "Notify ssd of the reset to reinstate the reservations");
11804
11805	scsi_hba_reset_notify_callback(&pptr->port_mutex,
11806	    &pptr->port_reset_notify_listf);
11807
11808	mutex_exit(&pptr->port_mutex);
11809
11810	return (rval);
11811}
11812
11813
11814/*
11815 * called by fcp_getcap and fcp_setcap to get and set (respectively)
11816 * SCSI capabilities
11817 */
11818/* ARGSUSED */
11819static int
11820fcp_commoncap(struct scsi_address *ap, char *cap,
11821    int val, int tgtonly, int doset)
11822{
11823	struct fcp_port		*pptr = ADDR2FCP(ap);
11824	struct fcp_lun	*plun = ADDR2LUN(ap);
11825	struct fcp_tgt	*ptgt = plun->lun_tgt;
11826	int			cidx;
11827	int			rval = FALSE;
11828
11829	if (cap == (char *)0) {
11830		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11831		    fcp_trace, FCP_BUF_LEVEL_3, 0,
11832		    "fcp_commoncap: invalid arg");
11833		return (rval);
11834	}
11835
11836	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11837		return (UNDEFINED);
11838	}
11839
11840	/*
11841	 * Process setcap request.
11842	 */
11843	if (doset) {
11844		/*
11845		 * At present, we can only set binary (0/1) values
11846		 */
11847		switch (cidx) {
11848		case SCSI_CAP_ARQ:
11849			if (val == 0) {
11850				rval = FALSE;
11851			} else {
11852				rval = TRUE;
11853			}
11854			break;
11855
11856		case SCSI_CAP_LUN_RESET:
11857			if (val) {
11858				plun->lun_cap |= FCP_LUN_CAP_RESET;
11859			} else {
11860				plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11861			}
11862			rval = TRUE;
11863			break;
11864
11865		case SCSI_CAP_SECTOR_SIZE:
11866			rval = TRUE;
11867			break;
11868		default:
11869			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11870			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11871			    "fcp_setcap: unsupported %d", cidx);
11872			rval = UNDEFINED;
11873			break;
11874		}
11875
11876		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11877		    fcp_trace, FCP_BUF_LEVEL_5, 0,
11878		    "set cap: cap=%s, val/tgtonly/doset/rval = "
11879		    "0x%x/0x%x/0x%x/%d",
11880		    cap, val, tgtonly, doset, rval);
11881
11882	} else {
11883		/*
11884		 * Process getcap request.
11885		 */
11886		switch (cidx) {
11887		case SCSI_CAP_DMA_MAX:
11888			rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11889
11890			/*
11891			 * Need to make an adjustment qlc is uint_t 64
11892			 * st is int, so we will make the adjustment here
11893			 * being as nobody wants to touch this.
11894			 * It still leaves the max single block length
11895			 * of 2 gig. This should last .
11896			 */
11897
11898			if (rval == -1) {
11899				rval = MAX_INT_DMA;
11900			}
11901
11902			break;
11903
11904		case SCSI_CAP_INITIATOR_ID:
11905			rval = pptr->port_id;
11906			break;
11907
11908		case SCSI_CAP_ARQ:
11909		case SCSI_CAP_RESET_NOTIFICATION:
11910		case SCSI_CAP_TAGGED_QING:
11911			rval = TRUE;
11912			break;
11913
11914		case SCSI_CAP_SCSI_VERSION:
11915			rval = 3;
11916			break;
11917
11918		case SCSI_CAP_INTERCONNECT_TYPE:
11919			if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11920			    (ptgt->tgt_hard_addr == 0)) {
11921				rval = INTERCONNECT_FABRIC;
11922			} else {
11923				rval = INTERCONNECT_FIBRE;
11924			}
11925			break;
11926
11927		case SCSI_CAP_LUN_RESET:
11928			rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11929			    TRUE : FALSE;
11930			break;
11931
11932		default:
11933			FCP_TRACE(fcp_logq, pptr->port_instbuf,
11934			    fcp_trace, FCP_BUF_LEVEL_4, 0,
11935			    "fcp_getcap: unsupported %d", cidx);
11936			rval = UNDEFINED;
11937			break;
11938		}
11939
11940		FCP_TRACE(fcp_logq, pptr->port_instbuf,
11941		    fcp_trace, FCP_BUF_LEVEL_8, 0,
11942		    "get cap: cap=%s, val/tgtonly/doset/rval = "
11943		    "0x%x/0x%x/0x%x/%d",
11944		    cap, val, tgtonly, doset, rval);
11945	}
11946
11947	return (rval);
11948}
11949
11950/*
11951 * called by the transport to get the port-wwn and lun
11952 * properties of this device, and to create a "name" based on them
11953 *
11954 * these properties don't exist on sun4m
11955 *
11956 * return 1 for success else return 0
11957 */
11958/* ARGSUSED */
11959static int
11960fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11961{
11962	int			i;
11963	int			*lun;
11964	int			numChars;
11965	uint_t			nlun;
11966	uint_t			count;
11967	uint_t			nbytes;
11968	uchar_t			*bytes;
11969	uint16_t		lun_num;
11970	uint32_t		tgt_id;
11971	char			**conf_wwn;
11972	char			tbuf[(FC_WWN_SIZE << 1) + 1];
11973	uchar_t			barray[FC_WWN_SIZE];
11974	dev_info_t		*tgt_dip;
11975	struct fcp_tgt	*ptgt;
11976	struct fcp_port	*pptr;
11977	struct fcp_lun	*plun;
11978
11979	ASSERT(sd != NULL);
11980	ASSERT(name != NULL);
11981
11982	tgt_dip = sd->sd_dev;
11983	pptr = ddi_get_soft_state(fcp_softstate,
11984	    ddi_get_instance(ddi_get_parent(tgt_dip)));
11985	if (pptr == NULL) {
11986		return (0);
11987	}
11988
11989	ASSERT(tgt_dip != NULL);
11990
11991	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11992	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11993	    LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11994		name[0] = '\0';
11995		return (0);
11996	}
11997
11998	if (nlun == 0) {
11999		ddi_prop_free(lun);
12000		return (0);
12001	}
12002
12003	lun_num = lun[0];
12004	ddi_prop_free(lun);
12005
12006	/*
12007	 * Lookup for .conf WWN property
12008	 */
12009	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12010	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12011	    &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12012		ASSERT(count >= 1);
12013
12014		fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12015		ddi_prop_free(conf_wwn);
12016		mutex_enter(&pptr->port_mutex);
12017		if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12018			mutex_exit(&pptr->port_mutex);
12019			return (0);
12020		}
12021		ptgt = plun->lun_tgt;
12022		mutex_exit(&pptr->port_mutex);
12023
12024		(void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12025		    tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12026
12027		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12028		    ptgt->tgt_hard_addr != 0) {
12029			tgt_id = (uint32_t)fcp_alpa_to_switch[
12030			    ptgt->tgt_hard_addr];
12031		} else {
12032			tgt_id = ptgt->tgt_d_id;
12033		}
12034
12035		(void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12036		    TARGET_PROP, tgt_id);
12037	}
12038
12039	/* get the our port-wwn property */
12040	bytes = NULL;
12041	if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12042	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12043	    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12044		if (bytes != NULL) {
12045			ddi_prop_free(bytes);
12046		}
12047		return (0);
12048	}
12049
12050	for (i = 0; i < FC_WWN_SIZE; i++) {
12051		(void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12052	}
12053
12054	/* Stick in the address of the form "wWWN,LUN" */
12055	numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12056
12057	ASSERT(numChars < len);
12058	if (numChars >= len) {
12059		fcp_log(CE_WARN, pptr->port_dip,
12060		    "!fcp_scsi_get_name: "
12061		    "name parameter length too small, it needs to be %d",
12062		    numChars+1);
12063	}
12064
12065	ddi_prop_free(bytes);
12066
12067	return (1);
12068}
12069
12070
12071/*
12072 * called by the transport to get the SCSI target id value, returning
12073 * it in "name"
12074 *
12075 * this isn't needed/used on sun4m
12076 *
12077 * return 1 for success else return 0
12078 */
12079/* ARGSUSED */
12080static int
12081fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12082{
12083	struct fcp_lun	*plun = ADDR2LUN(&sd->sd_address);
12084	struct fcp_tgt	*ptgt;
12085	int    numChars;
12086
12087	if (plun == NULL) {
12088		return (0);
12089	}
12090
12091	if ((ptgt = plun->lun_tgt) == NULL) {
12092		return (0);
12093	}
12094
12095	numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12096
12097	ASSERT(numChars < len);
12098	if (numChars >= len) {
12099		fcp_log(CE_WARN, NULL,
12100		    "!fcp_scsi_get_bus_addr: "
12101		    "name parameter length too small, it needs to be %d",
12102		    numChars+1);
12103	}
12104
12105	return (1);
12106}
12107
12108
12109/*
12110 * called internally to reset the link where the specified port lives
12111 */
12112static int
12113fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12114{
12115	la_wwn_t		wwn;
12116	struct fcp_lun	*plun;
12117	struct fcp_tgt	*ptgt;
12118
12119	/* disable restart of lip if we're suspended */
12120	mutex_enter(&pptr->port_mutex);
12121
12122	if (pptr->port_state & (FCP_STATE_SUSPENDED |
12123	    FCP_STATE_POWER_DOWN)) {
12124		mutex_exit(&pptr->port_mutex);
12125		FCP_TRACE(fcp_logq, pptr->port_instbuf,
12126		    fcp_trace, FCP_BUF_LEVEL_2, 0,
12127		    "fcp_linkreset, fcp%d: link reset "
12128		    "disabled due to DDI_SUSPEND",
12129		    ddi_get_instance(pptr->port_dip));
12130		return (FC_FAILURE);
12131	}
12132
12133	if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12134		mutex_exit(&pptr->port_mutex);
12135		return (FC_SUCCESS);
12136	}
12137
12138	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12139	    fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12140
12141	/*
12142	 * If ap == NULL assume local link reset.
12143	 */
12144	if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12145		plun = ADDR2LUN(ap);
12146		ptgt = plun->lun_tgt;
12147		bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12148	} else {
12149		bzero((caddr_t)&wwn, sizeof (wwn));
12150	}
12151	mutex_exit(&pptr->port_mutex);
12152
12153	return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12154}
12155
12156
12157/*
12158 * called from fcp_port_attach() to resume a port
12159 * return DDI_* success/failure status
12160 * acquires and releases the global mutex
12161 * acquires and releases the port mutex
12162 */
12163/*ARGSUSED*/
12164
12165static int
12166fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12167    uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12168{
12169	int			res = DDI_FAILURE; /* default result */
12170	struct fcp_port	*pptr;		/* port state ptr */
12171	uint32_t		alloc_cnt;
12172	uint32_t		max_cnt;
12173	fc_portmap_t		*tmp_list = NULL;
12174
12175	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12176	    FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12177	    instance);
12178
12179	if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12180		cmn_err(CE_WARN, "fcp: bad soft state");
12181		return (res);
12182	}
12183
12184	mutex_enter(&pptr->port_mutex);
12185	switch (cmd) {
12186	case FC_CMD_RESUME:
12187		ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12188		pptr->port_state &= ~FCP_STATE_SUSPENDED;
12189		break;
12190
12191	case FC_CMD_POWER_UP:
12192		/*
12193		 * If the port is DDI_SUSPENded, defer rediscovery
12194		 * until DDI_RESUME occurs
12195		 */
12196		if (pptr->port_state & FCP_STATE_SUSPENDED) {
12197			pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12198			mutex_exit(&pptr->port_mutex);
12199			return (DDI_SUCCESS);
12200		}
12201		pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12202	}
12203	pptr->port_id = s_id;
12204	pptr->port_state = FCP_STATE_INIT;
12205	mutex_exit(&pptr->port_mutex);
12206
12207	/*
12208	 * Make a copy of ulp_port_info as fctl allocates
12209	 * a temp struct.
12210	 */
12211	(void) fcp_cp_pinfo(pptr, pinfo);
12212
12213	mutex_enter(&fcp_global_mutex);
12214	if (fcp_watchdog_init++ == 0) {
12215		fcp_watchdog_tick = fcp_watchdog_timeout *
12216		    drv_usectohz(1000000);
12217		fcp_watchdog_id = timeout(fcp_watch,
12218		    NULL, fcp_watchdog_tick);
12219	}
12220	mutex_exit(&fcp_global_mutex);
12221
12222	/*
12223	 * Handle various topologies and link states.
12224	 */
12225	switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12226	case FC_STATE_OFFLINE:
12227		/*
12228		 * Wait for ONLINE, at which time a state
12229		 * change will cause a statec_callback
12230		 */
12231		res = DDI_SUCCESS;
12232		break;
12233
12234	case FC_STATE_ONLINE:
12235
12236		if (pptr->port_topology == FC_TOP_UNKNOWN) {
12237			(void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12238			res = DDI_SUCCESS;
12239			break;
12240		}
12241
12242		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12243		    !fcp_enable_auto_configuration) {
12244			tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12245			if (tmp_list == NULL) {
12246				if (!alloc_cnt) {
12247					res = DDI_SUCCESS;
12248				}
12249				break;
12250			}
12251			max_cnt = alloc_cnt;
12252		} else {
12253			ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12254
12255			alloc_cnt = FCP_MAX_DEVICES;
12256
12257			if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12258			    (sizeof (fc_portmap_t)) * alloc_cnt,
12259			    KM_NOSLEEP)) == NULL) {
12260				fcp_log(CE_WARN, pptr->port_dip,
12261				    "!fcp%d: failed to allocate portmap",
12262				    instance);
12263				break;
12264			}
12265
12266			max_cnt = alloc_cnt;
12267			if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12268			    &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12269			    FC_SUCCESS) {
12270				caddr_t msg;
12271
12272				(void) fc_ulp_error(res, &msg);
12273
12274				FCP_TRACE(fcp_logq, pptr->port_instbuf,
12275				    fcp_trace, FCP_BUF_LEVEL_2, 0,
12276				    "resume failed getportmap: reason=0x%x",
12277				    res);
12278
12279				fcp_log(CE_WARN, pptr->port_dip,
12280				    "!failed to get port map : %s", msg);
12281				break;
12282			}
12283			if (max_cnt > alloc_cnt) {
12284				alloc_cnt = max_cnt;
12285			}
12286		}
12287
12288		/*
12289		 * do the SCSI device discovery and create
12290		 * the devinfos
12291		 */
12292		fcp_statec_callback(ulph, pptr->port_fp_handle,
12293		    pptr->port_phys_state, pptr->port_topology, tmp_list,
12294		    max_cnt, pptr->port_id);
12295
12296		res = DDI_SUCCESS;
12297		break;
12298
12299	default:
12300		fcp_log(CE_WARN, pptr->port_dip,
12301		    "!fcp%d: invalid port state at attach=0x%x",
12302		    instance, pptr->port_phys_state);
12303
12304		mutex_enter(&pptr->port_mutex);
12305		pptr->port_phys_state = FCP_STATE_OFFLINE;
12306		mutex_exit(&pptr->port_mutex);
12307		res = DDI_SUCCESS;
12308
12309		break;
12310	}
12311
12312	if (tmp_list != NULL) {
12313		kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12314	}
12315
12316	return (res);
12317}
12318
12319
12320static void
12321fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12322{
12323	pptr->port_fp_modlinkage = *pinfo->port_linkage;
12324	pptr->port_dip = pinfo->port_dip;
12325	pptr->port_fp_handle = pinfo->port_handle;
12326	if (pinfo->port_acc_attr != NULL) {
12327		/*
12328		 * FCA supports DMA
12329		 */
12330		pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12331		pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12332		pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12333		pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12334	}
12335	pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12336	pptr->port_max_exch = pinfo->port_fca_max_exch;
12337	pptr->port_phys_state = pinfo->port_state;
12338	pptr->port_topology = pinfo->port_flags;
12339	pptr->port_reset_action = pinfo->port_reset_action;
12340	pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12341	pptr->port_fcp_dma = pinfo->port_fcp_dma;
12342	bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12343	bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12344
12345	/* Clear FMA caps to avoid fm-capability ereport */
12346	if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12347		pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12348	if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12349		pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12350	if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12351		pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12352}
12353
12354/*
12355 * If the elements wait field is set to 1 then
12356 * another thread is waiting for the operation to complete. Once
12357 * it is complete, the waiting thread is signaled and the element is
12358 * freed by the waiting thread. If the elements wait field is set to 0
12359 * the element is freed.
12360 */
12361static void
12362fcp_process_elem(struct fcp_hp_elem *elem, int result)
12363{
12364	ASSERT(elem != NULL);
12365	mutex_enter(&elem->mutex);
12366	elem->result = result;
12367	if (elem->wait) {
12368		elem->wait = 0;
12369		cv_signal(&elem->cv);
12370		mutex_exit(&elem->mutex);
12371	} else {
12372		mutex_exit(&elem->mutex);
12373		cv_destroy(&elem->cv);
12374		mutex_destroy(&elem->mutex);
12375		kmem_free(elem, sizeof (struct fcp_hp_elem));
12376	}
12377}
12378
12379/*
12380 * This function is invoked from the taskq thread to allocate
12381 * devinfo nodes and to online/offline them.
12382 */
12383static void
12384fcp_hp_task(void *arg)
12385{
12386	struct fcp_hp_elem	*elem = (struct fcp_hp_elem *)arg;
12387	struct fcp_lun	*plun = elem->lun;
12388	struct fcp_port		*pptr = elem->port;
12389	int			result;
12390
12391	ASSERT(elem->what == FCP_ONLINE ||
12392	    elem->what == FCP_OFFLINE ||
12393	    elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12394	    elem->what == FCP_MPXIO_PATH_SET_BUSY);
12395
12396	mutex_enter(&pptr->port_mutex);
12397	mutex_enter(&plun->lun_mutex);
12398	if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12399	    plun->lun_event_count != elem->event_cnt) ||
12400	    pptr->port_state & (FCP_STATE_SUSPENDED |
12401	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12402		mutex_exit(&plun->lun_mutex);
12403		mutex_exit(&pptr->port_mutex);
12404		fcp_process_elem(elem, NDI_FAILURE);
12405		return;
12406	}
12407	mutex_exit(&plun->lun_mutex);
12408	mutex_exit(&pptr->port_mutex);
12409
12410	result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12411	    elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12412	fcp_process_elem(elem, result);
12413}
12414
12415
12416static child_info_t *
12417fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12418    int tcount)
12419{
12420	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12421
12422	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12423		struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12424
12425		ASSERT(MUTEX_HELD(&pptr->port_mutex));
12426		/*
12427		 * Child has not been created yet. Create the child device
12428		 * based on the per-Lun flags.
12429		 */
12430		if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12431			plun->lun_cip =
12432			    CIP(fcp_create_dip(plun, lcount, tcount));
12433			plun->lun_mpxio = 0;
12434		} else {
12435			plun->lun_cip =
12436			    CIP(fcp_create_pip(plun, lcount, tcount));
12437			plun->lun_mpxio = 1;
12438		}
12439	} else {
12440		plun->lun_cip = cip;
12441	}
12442
12443	return (plun->lun_cip);
12444}
12445
12446
12447static int
12448fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12449{
12450	int		rval = FC_FAILURE;
12451	dev_info_t	*pdip;
12452	struct dev_info	*dip;
12453	int		circular;
12454
12455	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12456
12457	pdip = plun->lun_tgt->tgt_port->port_dip;
12458
12459	if (plun->lun_cip == NULL) {
12460		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12461		    fcp_trace, FCP_BUF_LEVEL_3, 0,
12462		    "fcp_is_dip_present: plun->lun_cip is NULL: "
12463		    "plun: %p lun state: %x num: %d target state: %x",
12464		    plun, plun->lun_state, plun->lun_num,
12465		    plun->lun_tgt->tgt_port->port_state);
12466		return (rval);
12467	}
12468	ndi_devi_enter(pdip, &circular);
12469	dip = DEVI(pdip)->devi_child;
12470	while (dip) {
12471		if (dip == DEVI(cdip)) {
12472			rval = FC_SUCCESS;
12473			break;
12474		}
12475		dip = dip->devi_sibling;
12476	}
12477	ndi_devi_exit(pdip, circular);
12478	return (rval);
12479}
12480
12481static int
12482fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12483{
12484	int		rval = FC_FAILURE;
12485
12486	ASSERT(plun != NULL);
12487	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12488
12489	if (plun->lun_mpxio == 0) {
12490		rval = fcp_is_dip_present(plun, DIP(cip));
12491	} else {
12492		rval = fcp_is_pip_present(plun, PIP(cip));
12493	}
12494
12495	return (rval);
12496}
12497
12498/*
12499 *     Function: fcp_create_dip
12500 *
12501 *  Description: Creates a dev_info_t structure for the LUN specified by the
12502 *		 caller.
12503 *
12504 *     Argument: plun		Lun structure
12505 *		 link_cnt	Link state count.
12506 *		 tgt_cnt	Target state change count.
12507 *
12508 * Return Value: NULL if it failed
12509 *		 dev_info_t structure address if it succeeded
12510 *
12511 *	Context: Kernel context
12512 */
12513static dev_info_t *
12514fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12515{
12516	int			failure = 0;
12517	uint32_t		tgt_id;
12518	uint64_t		sam_lun;
12519	struct fcp_tgt	*ptgt = plun->lun_tgt;
12520	struct fcp_port	*pptr = ptgt->tgt_port;
12521	dev_info_t		*pdip = pptr->port_dip;
12522	dev_info_t		*cdip = NULL;
12523	dev_info_t		*old_dip = DIP(plun->lun_cip);
12524	char			*nname = NULL;
12525	char			**compatible = NULL;
12526	int			ncompatible;
12527	char			*scsi_binding_set;
12528	char			t_pwwn[17];
12529
12530	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12531	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12532
12533	/* get the 'scsi-binding-set' property */
12534	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12535	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12536	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
12537		scsi_binding_set = NULL;
12538	}
12539
12540	/* determine the node name and compatible */
12541	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12542	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12543	if (scsi_binding_set) {
12544		ddi_prop_free(scsi_binding_set);
12545	}
12546
12547	if (nname == NULL) {
12548#ifdef	DEBUG
12549		cmn_err(CE_WARN, "%s%d: no driver for "
12550		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12551		    "	 compatible: %s",
12552		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12553		    ptgt->tgt_port_wwn.raw_wwn[0],
12554		    ptgt->tgt_port_wwn.raw_wwn[1],
12555		    ptgt->tgt_port_wwn.raw_wwn[2],
12556		    ptgt->tgt_port_wwn.raw_wwn[3],
12557		    ptgt->tgt_port_wwn.raw_wwn[4],
12558		    ptgt->tgt_port_wwn.raw_wwn[5],
12559		    ptgt->tgt_port_wwn.raw_wwn[6],
12560		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12561		    *compatible);
12562#endif	/* DEBUG */
12563		failure++;
12564		goto end_of_fcp_create_dip;
12565	}
12566
12567	cdip = fcp_find_existing_dip(plun, pdip, nname);
12568
12569	/*
12570	 * if the old_dip does not match the cdip, that means there is
12571	 * some property change. since we'll be using the cdip, we need
12572	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12573	 * then the dtype for the device has been updated. Offline the
12574	 * the old device and create a new device with the new device type
12575	 * Refer to bug: 4764752
12576	 */
12577	if (old_dip && (cdip != old_dip ||
12578	    plun->lun_state & FCP_LUN_CHANGED)) {
12579		plun->lun_state &= ~(FCP_LUN_INIT);
12580		mutex_exit(&plun->lun_mutex);
12581		mutex_exit(&pptr->port_mutex);
12582
12583		mutex_enter(&ptgt->tgt_mutex);
12584		(void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12585		    link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12586		mutex_exit(&ptgt->tgt_mutex);
12587
12588#ifdef DEBUG
12589		if (cdip != NULL) {
12590			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12591			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12592			    "Old dip=%p; New dip=%p don't match", old_dip,
12593			    cdip);
12594		} else {
12595			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12596			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12597			    "Old dip=%p; New dip=NULL don't match", old_dip);
12598		}
12599#endif
12600
12601		mutex_enter(&pptr->port_mutex);
12602		mutex_enter(&plun->lun_mutex);
12603	}
12604
12605	if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12606		plun->lun_state &= ~(FCP_LUN_CHANGED);
12607		if (ndi_devi_alloc(pptr->port_dip, nname,
12608		    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12609			failure++;
12610			goto end_of_fcp_create_dip;
12611		}
12612	}
12613
12614	/*
12615	 * Previously all the properties for the devinfo were destroyed here
12616	 * with a call to ndi_prop_remove_all(). Since this may cause loss of
12617	 * the devid property (and other properties established by the target
12618	 * driver or framework) which the code does not always recreate, this
12619	 * call was removed.
12620	 * This opens a theoretical possibility that we may return with a
12621	 * stale devid on the node if the scsi entity behind the fibre channel
12622	 * lun has changed.
12623	 */
12624
12625	/* decorate the node with compatible */
12626	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12627	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12628		failure++;
12629		goto end_of_fcp_create_dip;
12630	}
12631
12632	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12633	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12634		failure++;
12635		goto end_of_fcp_create_dip;
12636	}
12637
12638	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12639	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12640		failure++;
12641		goto end_of_fcp_create_dip;
12642	}
12643
12644	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12645	t_pwwn[16] = '\0';
12646	if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12647	    != DDI_PROP_SUCCESS) {
12648		failure++;
12649		goto end_of_fcp_create_dip;
12650	}
12651
12652	/*
12653	 * If there is no hard address - We might have to deal with
12654	 * that by using WWN - Having said that it is important to
12655	 * recognize this problem early so ssd can be informed of
12656	 * the right interconnect type.
12657	 */
12658	if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12659		tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12660	} else {
12661		tgt_id = ptgt->tgt_d_id;
12662	}
12663
12664	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12665	    tgt_id) != DDI_PROP_SUCCESS) {
12666		failure++;
12667		goto end_of_fcp_create_dip;
12668	}
12669
12670	if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12671	    (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12672		failure++;
12673		goto end_of_fcp_create_dip;
12674	}
12675	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12676	if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12677	    sam_lun) != DDI_PROP_SUCCESS) {
12678		failure++;
12679		goto end_of_fcp_create_dip;
12680	}
12681
12682end_of_fcp_create_dip:
12683	scsi_hba_nodename_compatible_free(nname, compatible);
12684
12685	if (cdip != NULL && failure) {
12686		(void) ndi_prop_remove_all(cdip);
12687		(void) ndi_devi_free(cdip);
12688		cdip = NULL;
12689	}
12690
12691	return (cdip);
12692}
12693
12694/*
12695 *     Function: fcp_create_pip
12696 *
12697 *  Description: Creates a Path Id for the LUN specified by the caller.
12698 *
12699 *     Argument: plun		Lun structure
12700 *		 link_cnt	Link state count.
12701 *		 tgt_cnt	Target state count.
12702 *
12703 * Return Value: NULL if it failed
12704 *		 mdi_pathinfo_t structure address if it succeeded
12705 *
12706 *	Context: Kernel context
12707 */
12708static mdi_pathinfo_t *
12709fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12710{
12711	int			i;
12712	char			buf[MAXNAMELEN];
12713	char			uaddr[MAXNAMELEN];
12714	int			failure = 0;
12715	uint32_t		tgt_id;
12716	uint64_t		sam_lun;
12717	struct fcp_tgt	*ptgt = plun->lun_tgt;
12718	struct fcp_port	*pptr = ptgt->tgt_port;
12719	dev_info_t		*pdip = pptr->port_dip;
12720	mdi_pathinfo_t		*pip = NULL;
12721	mdi_pathinfo_t		*old_pip = PIP(plun->lun_cip);
12722	char			*nname = NULL;
12723	char			**compatible = NULL;
12724	int			ncompatible;
12725	char			*scsi_binding_set;
12726	char			t_pwwn[17];
12727
12728	ASSERT(MUTEX_HELD(&plun->lun_mutex));
12729	ASSERT(MUTEX_HELD(&pptr->port_mutex));
12730
12731	scsi_binding_set = "vhci";
12732
12733	/* determine the node name and compatible */
12734	scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12735	    plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12736
12737	if (nname == NULL) {
12738#ifdef	DEBUG
12739		cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12740		    "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12741		    "	 compatible: %s",
12742		    ddi_driver_name(pdip), ddi_get_instance(pdip),
12743		    ptgt->tgt_port_wwn.raw_wwn[0],
12744		    ptgt->tgt_port_wwn.raw_wwn[1],
12745		    ptgt->tgt_port_wwn.raw_wwn[2],
12746		    ptgt->tgt_port_wwn.raw_wwn[3],
12747		    ptgt->tgt_port_wwn.raw_wwn[4],
12748		    ptgt->tgt_port_wwn.raw_wwn[5],
12749		    ptgt->tgt_port_wwn.raw_wwn[6],
12750		    ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12751		    *compatible);
12752#endif	/* DEBUG */
12753		failure++;
12754		goto end_of_fcp_create_pip;
12755	}
12756
12757	pip = fcp_find_existing_pip(plun, pdip);
12758
12759	/*
12760	 * if the old_dip does not match the cdip, that means there is
12761	 * some property change. since we'll be using the cdip, we need
12762	 * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12763	 * then the dtype for the device has been updated. Offline the
12764	 * the old device and create a new device with the new device type
12765	 * Refer to bug: 4764752
12766	 */
12767	if (old_pip && (pip != old_pip ||
12768	    plun->lun_state & FCP_LUN_CHANGED)) {
12769		plun->lun_state &= ~(FCP_LUN_INIT);
12770		mutex_exit(&plun->lun_mutex);
12771		mutex_exit(&pptr->port_mutex);
12772
12773		mutex_enter(&ptgt->tgt_mutex);
12774		(void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12775		    FCP_OFFLINE, lcount, tcount,
12776		    NDI_DEVI_REMOVE, 0);
12777		mutex_exit(&ptgt->tgt_mutex);
12778
12779		if (pip != NULL) {
12780			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12781			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12782			    "Old pip=%p; New pip=%p don't match",
12783			    old_pip, pip);
12784		} else {
12785			FCP_TRACE(fcp_logq, pptr->port_instbuf,
12786			    fcp_trace, FCP_BUF_LEVEL_2, 0,
12787			    "Old pip=%p; New pip=NULL don't match",
12788			    old_pip);
12789		}
12790
12791		mutex_enter(&pptr->port_mutex);
12792		mutex_enter(&plun->lun_mutex);
12793	}
12794
12795	/*
12796	 * Since FC_WWN_SIZE is 8 bytes and its not like the
12797	 * lun_guid_size which is dependent on the target, I don't
12798	 * believe the same trancation happens here UNLESS the standards
12799	 * change the FC_WWN_SIZE value to something larger than
12800	 * MAXNAMELEN(currently 255 bytes).
12801	 */
12802
12803	for (i = 0; i < FC_WWN_SIZE; i++) {
12804		(void) sprintf(&buf[i << 1], "%02x",
12805		    ptgt->tgt_port_wwn.raw_wwn[i]);
12806	}
12807
12808	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12809	    buf, plun->lun_num);
12810
12811	if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12812		/*
12813		 * Release the locks before calling into
12814		 * mdi_pi_alloc_compatible() since this can result in a
12815		 * callback into fcp which can result in a deadlock
12816		 * (see bug # 4870272).
12817		 *
12818		 * Basically, what we are trying to avoid is the scenario where
12819		 * one thread does ndi_devi_enter() and tries to grab
12820		 * fcp_mutex and another does it the other way round.
12821		 *
12822		 * But before we do that, make sure that nobody releases the
12823		 * port in the meantime. We can do this by setting a flag.
12824		 */
12825		plun->lun_state &= ~(FCP_LUN_CHANGED);
12826		pptr->port_state |= FCP_STATE_IN_MDI;
12827		mutex_exit(&plun->lun_mutex);
12828		mutex_exit(&pptr->port_mutex);
12829		if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12830		    uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12831			fcp_log(CE_WARN, pptr->port_dip,
12832			    "!path alloc failed:0x%x", plun);
12833			mutex_enter(&pptr->port_mutex);
12834			mutex_enter(&plun->lun_mutex);
12835			pptr->port_state &= ~FCP_STATE_IN_MDI;
12836			failure++;
12837			goto end_of_fcp_create_pip;
12838		}
12839		mutex_enter(&pptr->port_mutex);
12840		mutex_enter(&plun->lun_mutex);
12841		pptr->port_state &= ~FCP_STATE_IN_MDI;
12842	} else {
12843		(void) mdi_prop_remove(pip, NULL);
12844	}
12845
12846	mdi_pi_set_phci_private(pip, (caddr_t)plun);
12847
12848	if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12849	    ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12850	    != DDI_PROP_SUCCESS) {
12851		failure++;
12852		goto end_of_fcp_create_pip;
12853	}
12854
12855	if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12856	    ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12857	    != DDI_PROP_SUCCESS) {
12858		failure++;
12859		goto end_of_fcp_create_pip;
12860	}
12861
12862	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12863	t_pwwn[16] = '\0';
12864	if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12865	    != DDI_PROP_SUCCESS) {
12866		failure++;
12867		goto end_of_fcp_create_pip;
12868	}
12869
12870	/*
12871	 * If there is no hard address - We might have to deal with
12872	 * that by using WWN - Having said that it is important to
12873	 * recognize this problem early so ssd can be informed of
12874	 * the right interconnect type.
12875	 */
12876	if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12877	    ptgt->tgt_hard_addr != 0) {
12878		tgt_id = (uint32_t)
12879		    fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12880	} else {
12881		tgt_id = ptgt->tgt_d_id;
12882	}
12883
12884	if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12885	    != DDI_PROP_SUCCESS) {
12886		failure++;
12887		goto end_of_fcp_create_pip;
12888	}
12889
12890	if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12891	    != DDI_PROP_SUCCESS) {
12892		failure++;
12893		goto end_of_fcp_create_pip;
12894	}
12895	bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12896	if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12897	    != DDI_PROP_SUCCESS) {
12898		failure++;
12899		goto end_of_fcp_create_pip;
12900	}
12901
12902end_of_fcp_create_pip:
12903	scsi_hba_nodename_compatible_free(nname, compatible);
12904
12905	if (pip != NULL && failure) {
12906		(void) mdi_prop_remove(pip, NULL);
12907		mutex_exit(&plun->lun_mutex);
12908		mutex_exit(&pptr->port_mutex);
12909		(void) mdi_pi_free(pip, 0);
12910		mutex_enter(&pptr->port_mutex);
12911		mutex_enter(&plun->lun_mutex);
12912		pip = NULL;
12913	}
12914
12915	return (pip);
12916}
12917
12918static dev_info_t *
12919fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12920{
12921	uint_t			nbytes;
12922	uchar_t			*bytes;
12923	uint_t			nwords;
12924	uint32_t		tgt_id;
12925	int			*words;
12926	dev_info_t		*cdip;
12927	dev_info_t		*ndip;
12928	struct fcp_tgt	*ptgt = plun->lun_tgt;
12929	struct fcp_port	*pptr = ptgt->tgt_port;
12930	int			circular;
12931
12932	ndi_devi_enter(pdip, &circular);
12933
12934	ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12935	while ((cdip = ndip) != NULL) {
12936		ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12937
12938		if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12939			continue;
12940		}
12941
12942		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12943		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12944		    &nbytes) != DDI_PROP_SUCCESS) {
12945			continue;
12946		}
12947
12948		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12949			if (bytes != NULL) {
12950				ddi_prop_free(bytes);
12951			}
12952			continue;
12953		}
12954		ASSERT(bytes != NULL);
12955
12956		if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12957			ddi_prop_free(bytes);
12958			continue;
12959		}
12960
12961		ddi_prop_free(bytes);
12962
12963		if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12964		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12965		    &nbytes) != DDI_PROP_SUCCESS) {
12966			continue;
12967		}
12968
12969		if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12970			if (bytes != NULL) {
12971				ddi_prop_free(bytes);
12972			}
12973			continue;
12974		}
12975		ASSERT(bytes != NULL);
12976
12977		if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12978			ddi_prop_free(bytes);
12979			continue;
12980		}
12981
12982		ddi_prop_free(bytes);
12983
12984		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12985		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12986		    &nwords) != DDI_PROP_SUCCESS) {
12987			continue;
12988		}
12989
12990		if (nwords != 1 || words == NULL) {
12991			if (words != NULL) {
12992				ddi_prop_free(words);
12993			}
12994			continue;
12995		}
12996		ASSERT(words != NULL);
12997
12998		/*
12999		 * If there is no hard address - We might have to deal with
13000		 * that by using WWN - Having said that it is important to
13001		 * recognize this problem early so ssd can be informed of
13002		 * the right interconnect type.
13003		 */
13004		if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13005		    ptgt->tgt_hard_addr != 0) {
13006			tgt_id =
13007			    (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13008		} else {
13009			tgt_id = ptgt->tgt_d_id;
13010		}
13011
13012		if (tgt_id != (uint32_t)*words) {
13013			ddi_prop_free(words);
13014			continue;
13015		}
13016		ddi_prop_free(words);
13017
13018		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13019		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13020		    &nwords) != DDI_PROP_SUCCESS) {
13021			continue;
13022		}
13023
13024		if (nwords != 1 || words == NULL) {
13025			if (words != NULL) {
13026				ddi_prop_free(words);
13027			}
13028			continue;
13029		}
13030		ASSERT(words != NULL);
13031
13032		if (plun->lun_num == (uint16_t)*words) {
13033			ddi_prop_free(words);
13034			break;
13035		}
13036		ddi_prop_free(words);
13037	}
13038	ndi_devi_exit(pdip, circular);
13039
13040	return (cdip);
13041}
13042
13043
13044static int
13045fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13046{
13047	dev_info_t	*pdip;
13048	char		buf[MAXNAMELEN];
13049	char		uaddr[MAXNAMELEN];
13050	int		rval = FC_FAILURE;
13051
13052	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13053
13054	pdip = plun->lun_tgt->tgt_port->port_dip;
13055
13056	/*
13057	 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13058	 * non-NULL even when the LUN is not there as in the case when a LUN is
13059	 * configured and then deleted on the device end (for T3/T4 case). In
13060	 * such cases, pip will be NULL.
13061	 *
13062	 * If the device generates an RSCN, it will end up getting offlined when
13063	 * it disappeared and a new LUN will get created when it is rediscovered
13064	 * on the device. If we check for lun_cip here, the LUN will not end
13065	 * up getting onlined since this function will end up returning a
13066	 * FC_SUCCESS.
13067	 *
13068	 * The behavior is different on other devices. For instance, on a HDS,
13069	 * there was no RSCN generated by the device but the next I/O generated
13070	 * a check condition and rediscovery got triggered that way. So, in
13071	 * such cases, this path will not be exercised
13072	 */
13073	if (pip == NULL) {
13074		FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13075		    fcp_trace, FCP_BUF_LEVEL_4, 0,
13076		    "fcp_is_pip_present: plun->lun_cip is NULL: "
13077		    "plun: %p lun state: %x num: %d target state: %x",
13078		    plun, plun->lun_state, plun->lun_num,
13079		    plun->lun_tgt->tgt_port->port_state);
13080		return (rval);
13081	}
13082
13083	fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13084
13085	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13086
13087	if (plun->lun_old_guid) {
13088		if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13089			rval = FC_SUCCESS;
13090		}
13091	} else {
13092		if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13093			rval = FC_SUCCESS;
13094		}
13095	}
13096	return (rval);
13097}
13098
13099static mdi_pathinfo_t *
13100fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13101{
13102	char			buf[MAXNAMELEN];
13103	char			uaddr[MAXNAMELEN];
13104	mdi_pathinfo_t		*pip;
13105	struct fcp_tgt	*ptgt = plun->lun_tgt;
13106	struct fcp_port	*pptr = ptgt->tgt_port;
13107
13108	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13109
13110	fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13111	(void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13112
13113	pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13114
13115	return (pip);
13116}
13117
13118
13119static int
13120fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13121    int tcount, int flags, int *circ)
13122{
13123	int			rval;
13124	struct fcp_port		*pptr = plun->lun_tgt->tgt_port;
13125	struct fcp_tgt	*ptgt = plun->lun_tgt;
13126	dev_info_t		*cdip = NULL;
13127
13128	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13129	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13130
13131	if (plun->lun_cip == NULL) {
13132		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13133		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13134		    "fcp_online_child: plun->lun_cip is NULL: "
13135		    "plun: %p state: %x num: %d target state: %x",
13136		    plun, plun->lun_state, plun->lun_num,
13137		    plun->lun_tgt->tgt_port->port_state);
13138		return (NDI_FAILURE);
13139	}
13140again:
13141	if (plun->lun_mpxio == 0) {
13142		cdip = DIP(cip);
13143		mutex_exit(&plun->lun_mutex);
13144		mutex_exit(&pptr->port_mutex);
13145
13146		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13147		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13148		    "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13149		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13150
13151		/*
13152		 * We could check for FCP_LUN_INIT here but chances
13153		 * of getting here when it's already in FCP_LUN_INIT
13154		 * is rare and a duplicate ndi_devi_online wouldn't
13155		 * hurt either (as the node would already have been
13156		 * in CF2)
13157		 */
13158		if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13159			rval = ndi_devi_bind_driver(cdip, flags);
13160			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13161			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13162			    "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13163		} else {
13164			rval = ndi_devi_online(cdip, flags);
13165		}
13166
13167		/*
13168		 * We log the message into trace buffer if the device
13169		 * is "ses" and into syslog for any other device
13170		 * type. This is to prevent the ndi_devi_online failure
13171		 * message that appears for V880/A5K ses devices.
13172		 */
13173		if (rval == NDI_SUCCESS) {
13174			mutex_enter(&ptgt->tgt_mutex);
13175			plun->lun_state |= FCP_LUN_INIT;
13176			mutex_exit(&ptgt->tgt_mutex);
13177		} else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13178			fcp_log(CE_NOTE, pptr->port_dip,
13179			    "!ndi_devi_online:"
13180			    " failed for %s: target=%x lun=%x %x",
13181			    ddi_get_name(cdip), ptgt->tgt_d_id,
13182			    plun->lun_num, rval);
13183		} else {
13184			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13185			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13186			    " !ndi_devi_online:"
13187			    " failed for %s: target=%x lun=%x %x",
13188			    ddi_get_name(cdip), ptgt->tgt_d_id,
13189			    plun->lun_num, rval);
13190		}
13191	} else {
13192		cdip = mdi_pi_get_client(PIP(cip));
13193		mutex_exit(&plun->lun_mutex);
13194		mutex_exit(&pptr->port_mutex);
13195
13196		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13197		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13198		    "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13199		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13200
13201		/*
13202		 * Hold path and exit phci to avoid deadlock with power
13203		 * management code during mdi_pi_online.
13204		 */
13205		mdi_hold_path(PIP(cip));
13206		mdi_devi_exit_phci(pptr->port_dip, *circ);
13207
13208		rval = mdi_pi_online(PIP(cip), flags);
13209
13210		mdi_devi_enter_phci(pptr->port_dip, circ);
13211		mdi_rele_path(PIP(cip));
13212
13213		if (rval == MDI_SUCCESS) {
13214			mutex_enter(&ptgt->tgt_mutex);
13215			plun->lun_state |= FCP_LUN_INIT;
13216			mutex_exit(&ptgt->tgt_mutex);
13217
13218			/*
13219			 * Clear MPxIO path permanent disable in case
13220			 * fcp hotplug dropped the offline event.
13221			 */
13222			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13223
13224		} else if (rval == MDI_NOT_SUPPORTED) {
13225			child_info_t	*old_cip = cip;
13226
13227			/*
13228			 * MPxIO does not support this device yet.
13229			 * Enumerate in legacy mode.
13230			 */
13231			mutex_enter(&pptr->port_mutex);
13232			mutex_enter(&plun->lun_mutex);
13233			plun->lun_mpxio = 0;
13234			plun->lun_cip = NULL;
13235			cdip = fcp_create_dip(plun, lcount, tcount);
13236			plun->lun_cip = cip = CIP(cdip);
13237			if (cip == NULL) {
13238				fcp_log(CE_WARN, pptr->port_dip,
13239				    "!fcp_online_child: "
13240				    "Create devinfo failed for LU=%p", plun);
13241				mutex_exit(&plun->lun_mutex);
13242
13243				mutex_enter(&ptgt->tgt_mutex);
13244				plun->lun_state |= FCP_LUN_OFFLINE;
13245				mutex_exit(&ptgt->tgt_mutex);
13246
13247				mutex_exit(&pptr->port_mutex);
13248
13249				/*
13250				 * free the mdi_pathinfo node
13251				 */
13252				(void) mdi_pi_free(PIP(old_cip), 0);
13253			} else {
13254				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13255				    fcp_trace, FCP_BUF_LEVEL_3, 0,
13256				    "fcp_online_child: creating devinfo "
13257				    "node 0x%p for plun 0x%p",
13258				    cip, plun);
13259				mutex_exit(&plun->lun_mutex);
13260				mutex_exit(&pptr->port_mutex);
13261				/*
13262				 * free the mdi_pathinfo node
13263				 */
13264				(void) mdi_pi_free(PIP(old_cip), 0);
13265				mutex_enter(&pptr->port_mutex);
13266				mutex_enter(&plun->lun_mutex);
13267				goto again;
13268			}
13269		} else {
13270			if (cdip) {
13271				fcp_log(CE_NOTE, pptr->port_dip,
13272				    "!fcp_online_child: mdi_pi_online:"
13273				    " failed for %s: target=%x lun=%x %x",
13274				    ddi_get_name(cdip), ptgt->tgt_d_id,
13275				    plun->lun_num, rval);
13276			}
13277		}
13278		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13279	}
13280
13281	if (rval == NDI_SUCCESS) {
13282		if (cdip) {
13283			(void) ndi_event_retrieve_cookie(
13284			    pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13285			    &fcp_insert_eid, NDI_EVENT_NOPASS);
13286			(void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13287			    cdip, fcp_insert_eid, NULL);
13288		}
13289	}
13290	mutex_enter(&pptr->port_mutex);
13291	mutex_enter(&plun->lun_mutex);
13292	return (rval);
13293}
13294
13295/* ARGSUSED */
13296static int
13297fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13298    int tcount, int flags, int *circ)
13299{
13300	int		rval;
13301	int		lun_mpxio;
13302	struct fcp_port	*pptr = plun->lun_tgt->tgt_port;
13303	struct fcp_tgt	*ptgt = plun->lun_tgt;
13304	dev_info_t	*cdip;
13305
13306	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13307	ASSERT(MUTEX_HELD(&pptr->port_mutex));
13308
13309	if (plun->lun_cip == NULL) {
13310		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13311		    fcp_trace, FCP_BUF_LEVEL_3, 0,
13312		    "fcp_offline_child: plun->lun_cip is NULL: "
13313		    "plun: %p lun state: %x num: %d target state: %x",
13314		    plun, plun->lun_state, plun->lun_num,
13315		    plun->lun_tgt->tgt_port->port_state);
13316		return (NDI_FAILURE);
13317	}
13318
13319	/*
13320	 * We will use this value twice. Make a copy to be sure we use
13321	 * the same value in both places.
13322	 */
13323	lun_mpxio = plun->lun_mpxio;
13324
13325	if (lun_mpxio == 0) {
13326		cdip = DIP(cip);
13327		mutex_exit(&plun->lun_mutex);
13328		mutex_exit(&pptr->port_mutex);
13329		rval = ndi_devi_offline(DIP(cip), flags);
13330		if (rval != NDI_SUCCESS) {
13331			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13332			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13333			    "fcp_offline_child: ndi_devi_offline failed "
13334			    "rval=%x cip=%p", rval, cip);
13335		}
13336	} else {
13337		cdip = mdi_pi_get_client(PIP(cip));
13338		mutex_exit(&plun->lun_mutex);
13339		mutex_exit(&pptr->port_mutex);
13340
13341		/*
13342		 * Exit phci to avoid deadlock with power management code
13343		 * during mdi_pi_offline
13344		 */
13345		mdi_hold_path(PIP(cip));
13346		mdi_devi_exit_phci(pptr->port_dip, *circ);
13347
13348		rval = mdi_pi_offline(PIP(cip), flags);
13349
13350		mdi_devi_enter_phci(pptr->port_dip, circ);
13351		mdi_rele_path(PIP(cip));
13352
13353		rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13354	}
13355
13356	mutex_enter(&ptgt->tgt_mutex);
13357	plun->lun_state &= ~FCP_LUN_INIT;
13358	mutex_exit(&ptgt->tgt_mutex);
13359
13360	if (rval == NDI_SUCCESS) {
13361		cdip = NULL;
13362		if (flags & NDI_DEVI_REMOVE) {
13363			mutex_enter(&plun->lun_mutex);
13364			/*
13365			 * If the guid of the LUN changes, lun_cip will not
13366			 * equal to cip, and after offlining the LUN with the
13367			 * old guid, we should keep lun_cip since it's the cip
13368			 * of the LUN with the new guid.
13369			 * Otherwise remove our reference to child node.
13370			 *
13371			 * This must be done before the child node is freed,
13372			 * otherwise other threads could see a stale lun_cip
13373			 * pointer.
13374			 */
13375			if (plun->lun_cip == cip) {
13376				plun->lun_cip = NULL;
13377			}
13378			if (plun->lun_old_guid) {
13379				kmem_free(plun->lun_old_guid,
13380				    plun->lun_old_guid_size);
13381				plun->lun_old_guid = NULL;
13382				plun->lun_old_guid_size = 0;
13383			}
13384			mutex_exit(&plun->lun_mutex);
13385		}
13386	}
13387
13388	if (lun_mpxio != 0) {
13389		if (rval == NDI_SUCCESS) {
13390			/*
13391			 * Clear MPxIO path permanent disable as the path is
13392			 * already offlined.
13393			 */
13394			(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13395
13396			if (flags & NDI_DEVI_REMOVE) {
13397				(void) mdi_pi_free(PIP(cip), 0);
13398			}
13399		} else {
13400			FCP_TRACE(fcp_logq, pptr->port_instbuf,
13401			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13402			    "fcp_offline_child: mdi_pi_offline failed "
13403			    "rval=%x cip=%p", rval, cip);
13404		}
13405	}
13406
13407	mutex_enter(&pptr->port_mutex);
13408	mutex_enter(&plun->lun_mutex);
13409
13410	if (cdip) {
13411		FCP_TRACE(fcp_logq, pptr->port_instbuf,
13412		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13413		    " target=%x lun=%x", "ndi_offline",
13414		    ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13415	}
13416
13417	return (rval);
13418}
13419
13420static void
13421fcp_remove_child(struct fcp_lun *plun)
13422{
13423	child_info_t *cip;
13424	int circ;
13425
13426	ASSERT(MUTEX_HELD(&plun->lun_mutex));
13427
13428	if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13429		if (plun->lun_mpxio == 0) {
13430			(void) ndi_prop_remove_all(DIP(plun->lun_cip));
13431			(void) ndi_devi_free(DIP(plun->lun_cip));
13432			plun->lun_cip = NULL;
13433		} else {
13434			/*
13435			 * Clear reference to the child node in the lun.
13436			 * This must be done before freeing it with mdi_pi_free
13437			 * and with lun_mutex held so that other threads always
13438			 * see either valid lun_cip or NULL when holding
13439			 * lun_mutex. We keep a copy in cip.
13440			 */
13441			cip = plun->lun_cip;
13442			plun->lun_cip = NULL;
13443
13444			mutex_exit(&plun->lun_mutex);
13445			mutex_exit(&plun->lun_tgt->tgt_mutex);
13446			mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13447
13448			mdi_devi_enter(
13449			    plun->lun_tgt->tgt_port->port_dip, &circ);
13450
13451			/*
13452			 * Exit phci to avoid deadlock with power management
13453			 * code during mdi_pi_offline
13454			 */
13455			mdi_hold_path(PIP(cip));
13456			mdi_devi_exit_phci(
13457			    plun->lun_tgt->tgt_port->port_dip, circ);
13458			(void) mdi_pi_offline(PIP(cip),
13459			    NDI_DEVI_REMOVE);
13460			mdi_devi_enter_phci(
13461			    plun->lun_tgt->tgt_port->port_dip, &circ);
13462			mdi_rele_path(PIP(cip));
13463
13464			mdi_devi_exit(
13465			    plun->lun_tgt->tgt_port->port_dip, circ);
13466
13467			FCP_TRACE(fcp_logq,
13468			    plun->lun_tgt->tgt_port->port_instbuf,
13469			    fcp_trace, FCP_BUF_LEVEL_3, 0,
13470			    "lun=%p pip freed %p", plun, cip);
13471
13472			(void) mdi_prop_remove(PIP(cip), NULL);
13473			(void) mdi_pi_free(PIP(cip), 0);
13474
13475			mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13476			mutex_enter(&plun->lun_tgt->tgt_mutex);
13477			mutex_enter(&plun->lun_mutex);
13478		}
13479	} else {
13480		plun->lun_cip = NULL;
13481	}
13482}
13483
13484/*
13485 * called when a timeout occurs
13486 *
13487 * can be scheduled during an attach or resume (if not already running)
13488 *
13489 * one timeout is set up for all ports
13490 *
13491 * acquires and releases the global mutex
13492 */
13493/*ARGSUSED*/
13494static void
13495fcp_watch(void *arg)
13496{
13497	struct fcp_port	*pptr;
13498	struct fcp_ipkt	*icmd;
13499	struct fcp_ipkt	*nicmd;
13500	struct fcp_pkt	*cmd;
13501	struct fcp_pkt	*ncmd;
13502	struct fcp_pkt	*tail;
13503	struct fcp_pkt	*pcmd;
13504	struct fcp_pkt	*save_head;
13505	struct fcp_port	*save_port;
13506
13507	/* increment global watchdog time */
13508	fcp_watchdog_time += fcp_watchdog_timeout;
13509
13510	mutex_enter(&fcp_global_mutex);
13511
13512	/* scan each port in our list */
13513	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13514		save_port = fcp_port_head;
13515		pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13516		mutex_exit(&fcp_global_mutex);
13517
13518		mutex_enter(&pptr->port_mutex);
13519		if (pptr->port_ipkt_list == NULL &&
13520		    (pptr->port_state & (FCP_STATE_SUSPENDED |
13521		    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13522			pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13523			mutex_exit(&pptr->port_mutex);
13524			mutex_enter(&fcp_global_mutex);
13525			goto end_of_watchdog;
13526		}
13527
13528		/*
13529		 * We check if a list of targets need to be offlined.
13530		 */
13531		if (pptr->port_offline_tgts) {
13532			fcp_scan_offline_tgts(pptr);
13533		}
13534
13535		/*
13536		 * We check if a list of luns need to be offlined.
13537		 */
13538		if (pptr->port_offline_luns) {
13539			fcp_scan_offline_luns(pptr);
13540		}
13541
13542		/*
13543		 * We check if a list of targets or luns need to be reset.
13544		 */
13545		if (pptr->port_reset_list) {
13546			fcp_check_reset_delay(pptr);
13547		}
13548
13549		mutex_exit(&pptr->port_mutex);
13550
13551		/*
13552		 * This is where the pending commands (pkt) are checked for
13553		 * timeout.
13554		 */
13555		mutex_enter(&pptr->port_pkt_mutex);
13556		tail = pptr->port_pkt_tail;
13557
13558		for (pcmd = NULL, cmd = pptr->port_pkt_head;
13559		    cmd != NULL; cmd = ncmd) {
13560			ncmd = cmd->cmd_next;
13561			/*
13562			 * If a command is in this queue the bit CFLAG_IN_QUEUE
13563			 * must be set.
13564			 */
13565			ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13566			/*
13567			 * FCP_INVALID_TIMEOUT will be set for those
13568			 * command that need to be failed. Mostly those
13569			 * cmds that could not be queued down for the
13570			 * "timeout" value. cmd->cmd_timeout is used
13571			 * to try and requeue the command regularly.
13572			 */
13573			if (cmd->cmd_timeout >= fcp_watchdog_time) {
13574				/*
13575				 * This command hasn't timed out yet.  Let's
13576				 * go to the next one.
13577				 */
13578				pcmd = cmd;
13579				goto end_of_loop;
13580			}
13581
13582			if (cmd == pptr->port_pkt_head) {
13583				ASSERT(pcmd == NULL);
13584				pptr->port_pkt_head = cmd->cmd_next;
13585			} else {
13586				ASSERT(pcmd != NULL);
13587				pcmd->cmd_next = cmd->cmd_next;
13588			}
13589
13590			if (cmd == pptr->port_pkt_tail) {
13591				ASSERT(cmd->cmd_next == NULL);
13592				pptr->port_pkt_tail = pcmd;
13593				if (pcmd) {
13594					pcmd->cmd_next = NULL;
13595				}
13596			}
13597			cmd->cmd_next = NULL;
13598
13599			/*
13600			 * save the current head before dropping the
13601			 * mutex - If the head doesn't remain the
13602			 * same after re acquiring the mutex, just
13603			 * bail out and revisit on next tick.
13604			 *
13605			 * PS: The tail pointer can change as the commands
13606			 * get requeued after failure to retransport
13607			 */
13608			save_head = pptr->port_pkt_head;
13609			mutex_exit(&pptr->port_pkt_mutex);
13610
13611			if (cmd->cmd_fp_pkt->pkt_timeout ==
13612			    FCP_INVALID_TIMEOUT) {
13613				struct scsi_pkt		*pkt = cmd->cmd_pkt;
13614				struct fcp_lun	*plun;
13615				struct fcp_tgt	*ptgt;
13616
13617				plun = ADDR2LUN(&pkt->pkt_address);
13618				ptgt = plun->lun_tgt;
13619
13620				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13621				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13622				    "SCSI cmd 0x%x to D_ID=%x timed out",
13623				    pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13624
13625				cmd->cmd_state == FCP_PKT_ABORTING ?
13626				    fcp_fail_cmd(cmd, CMD_RESET,
13627				    STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13628				    CMD_TIMEOUT, STAT_ABORTED);
13629			} else {
13630				fcp_retransport_cmd(pptr, cmd);
13631			}
13632			mutex_enter(&pptr->port_pkt_mutex);
13633			if (save_head && save_head != pptr->port_pkt_head) {
13634				/*
13635				 * Looks like linked list got changed (mostly
13636				 * happens when an an OFFLINE LUN code starts
13637				 * returning overflow queue commands in
13638				 * parallel. So bail out and revisit during
13639				 * next tick
13640				 */
13641				break;
13642			}
13643		end_of_loop:
13644			/*
13645			 * Scan only upto the previously known tail pointer
13646			 * to avoid excessive processing - lots of new packets
13647			 * could have been added to the tail or the old ones
13648			 * re-queued.
13649			 */
13650			if (cmd == tail) {
13651				break;
13652			}
13653		}
13654		mutex_exit(&pptr->port_pkt_mutex);
13655
13656		mutex_enter(&pptr->port_mutex);
13657		for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13658			struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13659
13660			nicmd = icmd->ipkt_next;
13661			if ((icmd->ipkt_restart != 0) &&
13662			    (icmd->ipkt_restart >= fcp_watchdog_time)) {
13663				/* packet has not timed out */
13664				continue;
13665			}
13666
13667			/* time for packet re-transport */
13668			if (icmd == pptr->port_ipkt_list) {
13669				pptr->port_ipkt_list = icmd->ipkt_next;
13670				if (pptr->port_ipkt_list) {
13671					pptr->port_ipkt_list->ipkt_prev =
13672					    NULL;
13673				}
13674			} else {
13675				icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13676				if (icmd->ipkt_next) {
13677					icmd->ipkt_next->ipkt_prev =
13678					    icmd->ipkt_prev;
13679				}
13680			}
13681			icmd->ipkt_next = NULL;
13682			icmd->ipkt_prev = NULL;
13683			mutex_exit(&pptr->port_mutex);
13684
13685			if (fcp_is_retryable(icmd)) {
13686				fc_ulp_rscn_info_t *rscnp =
13687				    (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13688				    pkt_ulp_rscn_infop;
13689
13690				FCP_TRACE(fcp_logq, pptr->port_instbuf,
13691				    fcp_trace, FCP_BUF_LEVEL_2, 0,
13692				    "%x to D_ID=%x Retrying..",
13693				    icmd->ipkt_opcode,
13694				    icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13695
13696				/*
13697				 * Update the RSCN count in the packet
13698				 * before resending.
13699				 */
13700
13701				if (rscnp != NULL) {
13702					rscnp->ulp_rscn_count =
13703					    fc_ulp_get_rscn_count(pptr->
13704					    port_fp_handle);
13705				}
13706
13707				mutex_enter(&pptr->port_mutex);
13708				mutex_enter(&ptgt->tgt_mutex);
13709				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13710					mutex_exit(&ptgt->tgt_mutex);
13711					mutex_exit(&pptr->port_mutex);
13712					switch (icmd->ipkt_opcode) {
13713						int rval;
13714					case LA_ELS_PLOGI:
13715						if ((rval = fc_ulp_login(
13716						    pptr->port_fp_handle,
13717						    &icmd->ipkt_fpkt, 1)) ==
13718						    FC_SUCCESS) {
13719							mutex_enter(
13720							    &pptr->port_mutex);
13721							continue;
13722						}
13723						if (fcp_handle_ipkt_errors(
13724						    pptr, ptgt, icmd, rval,
13725						    "PLOGI") == DDI_SUCCESS) {
13726							mutex_enter(
13727							    &pptr->port_mutex);
13728							continue;
13729						}
13730						break;
13731
13732					case LA_ELS_PRLI:
13733						if ((rval = fc_ulp_issue_els(
13734						    pptr->port_fp_handle,
13735						    icmd->ipkt_fpkt)) ==
13736						    FC_SUCCESS) {
13737							mutex_enter(
13738							    &pptr->port_mutex);
13739							continue;
13740						}
13741						if (fcp_handle_ipkt_errors(
13742						    pptr, ptgt, icmd, rval,
13743						    "PRLI") == DDI_SUCCESS) {
13744							mutex_enter(
13745							    &pptr->port_mutex);
13746							continue;
13747						}
13748						break;
13749
13750					default:
13751						if ((rval = fcp_transport(
13752						    pptr->port_fp_handle,
13753						    icmd->ipkt_fpkt, 1)) ==
13754						    FC_SUCCESS) {
13755							mutex_enter(
13756							    &pptr->port_mutex);
13757							continue;
13758						}
13759						if (fcp_handle_ipkt_errors(
13760						    pptr, ptgt, icmd, rval,
13761						    "PRLI") == DDI_SUCCESS) {
13762							mutex_enter(
13763							    &pptr->port_mutex);
13764							continue;
13765						}
13766						break;
13767					}
13768				} else {
13769					mutex_exit(&ptgt->tgt_mutex);
13770					mutex_exit(&pptr->port_mutex);
13771				}
13772			} else {
13773				fcp_print_error(icmd->ipkt_fpkt);
13774			}
13775
13776			(void) fcp_call_finish_init(pptr, ptgt,
13777			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13778			    icmd->ipkt_cause);
13779			fcp_icmd_free(pptr, icmd);
13780			mutex_enter(&pptr->port_mutex);
13781		}
13782
13783		pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13784		mutex_exit(&pptr->port_mutex);
13785		mutex_enter(&fcp_global_mutex);
13786
13787	end_of_watchdog:
13788		/*
13789		 * Bail out early before getting into trouble
13790		 */
13791		if (save_port != fcp_port_head) {
13792			break;
13793		}
13794	}
13795
13796	if (fcp_watchdog_init > 0) {
13797		/* reschedule timeout to go again */
13798		fcp_watchdog_id =
13799		    timeout(fcp_watch, NULL, fcp_watchdog_tick);
13800	}
13801	mutex_exit(&fcp_global_mutex);
13802}
13803
13804
13805static void
13806fcp_check_reset_delay(struct fcp_port *pptr)
13807{
13808	uint32_t		tgt_cnt;
13809	int			level;
13810	struct fcp_tgt	*ptgt;
13811	struct fcp_lun	*plun;
13812	struct fcp_reset_elem *cur = NULL;
13813	struct fcp_reset_elem *next = NULL;
13814	struct fcp_reset_elem *prev = NULL;
13815
13816	ASSERT(mutex_owned(&pptr->port_mutex));
13817
13818	next = pptr->port_reset_list;
13819	while ((cur = next) != NULL) {
13820		next = cur->next;
13821
13822		if (cur->timeout < fcp_watchdog_time) {
13823			prev = cur;
13824			continue;
13825		}
13826
13827		ptgt = cur->tgt;
13828		plun = cur->lun;
13829		tgt_cnt = cur->tgt_cnt;
13830
13831		if (ptgt) {
13832			level = RESET_TARGET;
13833		} else {
13834			ASSERT(plun != NULL);
13835			level = RESET_LUN;
13836			ptgt = plun->lun_tgt;
13837		}
13838		if (prev) {
13839			prev->next = next;
13840		} else {
13841			/*
13842			 * Because we drop port mutex while doing aborts for
13843			 * packets, we can't rely on reset_list pointing to
13844			 * our head
13845			 */
13846			if (cur == pptr->port_reset_list) {
13847				pptr->port_reset_list = next;
13848			} else {
13849				struct fcp_reset_elem *which;
13850
13851				which = pptr->port_reset_list;
13852				while (which && which->next != cur) {
13853					which = which->next;
13854				}
13855				ASSERT(which != NULL);
13856
13857				which->next = next;
13858				prev = which;
13859			}
13860		}
13861
13862		kmem_free(cur, sizeof (*cur));
13863
13864		if (tgt_cnt == ptgt->tgt_change_cnt) {
13865			mutex_enter(&ptgt->tgt_mutex);
13866			if (level == RESET_TARGET) {
13867				fcp_update_tgt_state(ptgt,
13868				    FCP_RESET, FCP_LUN_BUSY);
13869			} else {
13870				fcp_update_lun_state(plun,
13871				    FCP_RESET, FCP_LUN_BUSY);
13872			}
13873			mutex_exit(&ptgt->tgt_mutex);
13874
13875			mutex_exit(&pptr->port_mutex);
13876			fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13877			mutex_enter(&pptr->port_mutex);
13878		}
13879	}
13880}
13881
13882
13883static void
13884fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13885    struct fcp_lun *rlun, int tgt_cnt)
13886{
13887	int			rval;
13888	struct fcp_lun	*tlun, *nlun;
13889	struct fcp_pkt	*pcmd = NULL, *ncmd = NULL,
13890	    *cmd = NULL, *head = NULL,
13891	    *tail = NULL;
13892
13893	mutex_enter(&pptr->port_pkt_mutex);
13894	for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13895		struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13896		struct fcp_tgt *ptgt = plun->lun_tgt;
13897
13898		ncmd = cmd->cmd_next;
13899
13900		if (ptgt != ttgt && plun != rlun) {
13901			pcmd = cmd;
13902			continue;
13903		}
13904
13905		if (pcmd != NULL) {
13906			ASSERT(pptr->port_pkt_head != cmd);
13907			pcmd->cmd_next = ncmd;
13908		} else {
13909			ASSERT(cmd == pptr->port_pkt_head);
13910			pptr->port_pkt_head = ncmd;
13911		}
13912		if (pptr->port_pkt_tail == cmd) {
13913			ASSERT(cmd->cmd_next == NULL);
13914			pptr->port_pkt_tail = pcmd;
13915			if (pcmd != NULL) {
13916				pcmd->cmd_next = NULL;
13917			}
13918		}
13919
13920		if (head == NULL) {
13921			head = tail = cmd;
13922		} else {
13923			ASSERT(tail != NULL);
13924			tail->cmd_next = cmd;
13925			tail = cmd;
13926		}
13927		cmd->cmd_next = NULL;
13928	}
13929	mutex_exit(&pptr->port_pkt_mutex);
13930
13931	for (cmd = head; cmd != NULL; cmd = ncmd) {
13932		struct scsi_pkt *pkt = cmd->cmd_pkt;
13933
13934		ncmd = cmd->cmd_next;
13935		ASSERT(pkt != NULL);
13936
13937		mutex_enter(&pptr->port_mutex);
13938		if (ttgt->tgt_change_cnt == tgt_cnt) {
13939			mutex_exit(&pptr->port_mutex);
13940			cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13941			pkt->pkt_reason = CMD_RESET;
13942			pkt->pkt_statistics |= STAT_DEV_RESET;
13943			cmd->cmd_state = FCP_PKT_IDLE;
13944			fcp_post_callback(cmd);
13945		} else {
13946			mutex_exit(&pptr->port_mutex);
13947		}
13948	}
13949
13950	/*
13951	 * If the FCA will return all the commands in its queue then our
13952	 * work is easy, just return.
13953	 */
13954
13955	if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13956		return;
13957	}
13958
13959	/*
13960	 * For RESET_LUN get hold of target pointer
13961	 */
13962	if (ttgt == NULL) {
13963		ASSERT(rlun != NULL);
13964
13965		ttgt = rlun->lun_tgt;
13966
13967		ASSERT(ttgt != NULL);
13968	}
13969
13970	/*
13971	 * There are some severe race conditions here.
13972	 * While we are trying to abort the pkt, it might be completing
13973	 * so mark it aborted and if the abort does not succeed then
13974	 * handle it in the watch thread.
13975	 */
13976	mutex_enter(&ttgt->tgt_mutex);
13977	nlun = ttgt->tgt_lun;
13978	mutex_exit(&ttgt->tgt_mutex);
13979	while ((tlun = nlun) != NULL) {
13980		int restart = 0;
13981		if (rlun && rlun != tlun) {
13982			mutex_enter(&ttgt->tgt_mutex);
13983			nlun = tlun->lun_next;
13984			mutex_exit(&ttgt->tgt_mutex);
13985			continue;
13986		}
13987		mutex_enter(&tlun->lun_mutex);
13988		cmd = tlun->lun_pkt_head;
13989		while (cmd != NULL) {
13990			if (cmd->cmd_state == FCP_PKT_ISSUED) {
13991				struct scsi_pkt *pkt;
13992
13993				restart = 1;
13994				cmd->cmd_state = FCP_PKT_ABORTING;
13995				mutex_exit(&tlun->lun_mutex);
13996				rval = fc_ulp_abort(pptr->port_fp_handle,
13997				    cmd->cmd_fp_pkt, KM_SLEEP);
13998				if (rval == FC_SUCCESS) {
13999					pkt = cmd->cmd_pkt;
14000					pkt->pkt_reason = CMD_RESET;
14001					pkt->pkt_statistics |= STAT_DEV_RESET;
14002					cmd->cmd_state = FCP_PKT_IDLE;
14003					fcp_post_callback(cmd);
14004				} else {
14005					caddr_t msg;
14006
14007					(void) fc_ulp_error(rval, &msg);
14008
14009					/*
14010					 * This part is tricky. The abort
14011					 * failed and now the command could
14012					 * be completing.  The cmd_state ==
14013					 * FCP_PKT_ABORTING should save
14014					 * us in fcp_cmd_callback. If we
14015					 * are already aborting ignore the
14016					 * command in fcp_cmd_callback.
14017					 * Here we leave this packet for 20
14018					 * sec to be aborted in the
14019					 * fcp_watch thread.
14020					 */
14021					fcp_log(CE_WARN, pptr->port_dip,
14022					    "!Abort failed after reset %s",
14023					    msg);
14024
14025					cmd->cmd_timeout =
14026					    fcp_watchdog_time +
14027					    cmd->cmd_pkt->pkt_time +
14028					    FCP_FAILED_DELAY;
14029
14030					cmd->cmd_fp_pkt->pkt_timeout =
14031					    FCP_INVALID_TIMEOUT;
14032					/*
14033					 * This is a hack, cmd is put in the
14034					 * overflow queue so that it can be
14035					 * timed out finally
14036					 */
14037					cmd->cmd_flags |= CFLAG_IN_QUEUE;
14038
14039					mutex_enter(&pptr->port_pkt_mutex);
14040					if (pptr->port_pkt_head) {
14041						ASSERT(pptr->port_pkt_tail
14042						    != NULL);
14043						pptr->port_pkt_tail->cmd_next
14044						    = cmd;
14045						pptr->port_pkt_tail = cmd;
14046					} else {
14047						ASSERT(pptr->port_pkt_tail
14048						    == NULL);
14049						pptr->port_pkt_head =
14050						    pptr->port_pkt_tail
14051						    = cmd;
14052					}
14053					cmd->cmd_next = NULL;
14054					mutex_exit(&pptr->port_pkt_mutex);
14055				}
14056				mutex_enter(&tlun->lun_mutex);
14057				cmd = tlun->lun_pkt_head;
14058			} else {
14059				cmd = cmd->cmd_forw;
14060			}
14061		}
14062		mutex_exit(&tlun->lun_mutex);
14063
14064		mutex_enter(&ttgt->tgt_mutex);
14065		restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14066		mutex_exit(&ttgt->tgt_mutex);
14067
14068		mutex_enter(&pptr->port_mutex);
14069		if (tgt_cnt != ttgt->tgt_change_cnt) {
14070			mutex_exit(&pptr->port_mutex);
14071			return;
14072		} else {
14073			mutex_exit(&pptr->port_mutex);
14074		}
14075	}
14076}
14077
14078
14079/*
14080 * unlink the soft state, returning the soft state found (if any)
14081 *
14082 * acquires and releases the global mutex
14083 */
14084struct fcp_port *
14085fcp_soft_state_unlink(struct fcp_port *pptr)
14086{
14087	struct fcp_port	*hptr;		/* ptr index */
14088	struct fcp_port	*tptr;		/* prev hptr */
14089
14090	mutex_enter(&fcp_global_mutex);
14091	for (hptr = fcp_port_head, tptr = NULL;
14092	    hptr != NULL;
14093	    tptr = hptr, hptr = hptr->port_next) {
14094		if (hptr == pptr) {
14095			/* we found a match -- remove this item */
14096			if (tptr == NULL) {
14097				/* we're at the head of the list */
14098				fcp_port_head = hptr->port_next;
14099			} else {
14100				tptr->port_next = hptr->port_next;
14101			}
14102			break;			/* success */
14103		}
14104	}
14105	if (fcp_port_head == NULL) {
14106		fcp_cleanup_blacklist(&fcp_lun_blacklist);
14107	}
14108	mutex_exit(&fcp_global_mutex);
14109	return (hptr);
14110}
14111
14112
14113/*
14114 * called by fcp_scsi_hba_tgt_init to find a LUN given a
14115 * WWN and a LUN number
14116 */
14117/* ARGSUSED */
14118static struct fcp_lun *
14119fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14120{
14121	int hash;
14122	struct fcp_tgt *ptgt;
14123	struct fcp_lun *plun;
14124
14125	ASSERT(mutex_owned(&pptr->port_mutex));
14126
14127	hash = FCP_HASH(wwn);
14128	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14129	    ptgt = ptgt->tgt_next) {
14130		if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14131		    sizeof (ptgt->tgt_port_wwn)) == 0) {
14132			mutex_enter(&ptgt->tgt_mutex);
14133			for (plun = ptgt->tgt_lun;
14134			    plun != NULL;
14135			    plun = plun->lun_next) {
14136				if (plun->lun_num == lun) {
14137					mutex_exit(&ptgt->tgt_mutex);
14138					return (plun);
14139				}
14140			}
14141			mutex_exit(&ptgt->tgt_mutex);
14142			return (NULL);
14143		}
14144	}
14145	return (NULL);
14146}
14147
14148/*
14149 *     Function: fcp_prepare_pkt
14150 *
14151 *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14152 *		 for fcp_start(). It binds the data or partially maps it.
14153 *		 Builds the FCP header and starts the initialization of the
14154 *		 Fibre Channel header.
14155 *
14156 *     Argument: *pptr		FCP port.
14157 *		 *cmd		FCP packet.
14158 *		 *plun		LUN the command will be sent to.
14159 *
14160 *	Context: User, Kernel and Interrupt context.
14161 */
14162static void
14163fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14164    struct fcp_lun *plun)
14165{
14166	fc_packet_t		*fpkt = cmd->cmd_fp_pkt;
14167	struct fcp_tgt		*ptgt = plun->lun_tgt;
14168	struct fcp_cmd		*fcmd = &cmd->cmd_fcp_cmd;
14169
14170	ASSERT(cmd->cmd_pkt->pkt_comp ||
14171	    (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14172
14173	if (cmd->cmd_pkt->pkt_numcookies) {
14174		if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14175			fcmd->fcp_cntl.cntl_read_data = 1;
14176			fcmd->fcp_cntl.cntl_write_data = 0;
14177			fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14178		} else {
14179			fcmd->fcp_cntl.cntl_read_data = 0;
14180			fcmd->fcp_cntl.cntl_write_data = 1;
14181			fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14182		}
14183
14184		fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14185
14186		fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14187		ASSERT(fpkt->pkt_data_cookie_cnt <=
14188		    pptr->port_data_dma_attr.dma_attr_sgllen);
14189
14190		cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14191
14192		/* FCA needs pkt_datalen to be set */
14193		fpkt->pkt_datalen = cmd->cmd_dmacount;
14194		fcmd->fcp_data_len = cmd->cmd_dmacount;
14195	} else {
14196		fcmd->fcp_cntl.cntl_read_data = 0;
14197		fcmd->fcp_cntl.cntl_write_data = 0;
14198		fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14199		fpkt->pkt_datalen = 0;
14200		fcmd->fcp_data_len = 0;
14201	}
14202
14203	/* set up the Tagged Queuing type */
14204	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14205		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14206	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14207		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14208	} else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14209		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14210	} else {
14211		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14212	}
14213
14214	fcmd->fcp_ent_addr = plun->lun_addr;
14215
14216	if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14217		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14218		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14219	} else {
14220		ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14221	}
14222
14223	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14224	cmd->cmd_pkt->pkt_state = 0;
14225	cmd->cmd_pkt->pkt_statistics = 0;
14226	cmd->cmd_pkt->pkt_resid = 0;
14227
14228	cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14229
14230	if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14231		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14232		fpkt->pkt_comp = NULL;
14233	} else {
14234		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14235		if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14236			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14237		}
14238		fpkt->pkt_comp = fcp_cmd_callback;
14239	}
14240
14241	mutex_enter(&pptr->port_mutex);
14242	if (pptr->port_state & FCP_STATE_SUSPENDED) {
14243		fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14244	}
14245	mutex_exit(&pptr->port_mutex);
14246
14247	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14248	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14249
14250	/*
14251	 * Save a few kernel cycles here
14252	 */
14253#ifndef	__lock_lint
14254	fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14255#endif /* __lock_lint */
14256}
14257
14258static void
14259fcp_post_callback(struct fcp_pkt *cmd)
14260{
14261	scsi_hba_pkt_comp(cmd->cmd_pkt);
14262}
14263
14264
14265/*
14266 * called to do polled I/O by fcp_start()
14267 *
14268 * return a transport status value, i.e. TRAN_ACCECPT for success
14269 */
14270static int
14271fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14272{
14273	int	rval;
14274
14275#ifdef	DEBUG
14276	mutex_enter(&pptr->port_pkt_mutex);
14277	pptr->port_npkts++;
14278	mutex_exit(&pptr->port_pkt_mutex);
14279#endif /* DEBUG */
14280
14281	if (cmd->cmd_fp_pkt->pkt_timeout) {
14282		cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14283	} else {
14284		cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14285	}
14286
14287	ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14288
14289	cmd->cmd_state = FCP_PKT_ISSUED;
14290
14291	rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14292
14293#ifdef	DEBUG
14294	mutex_enter(&pptr->port_pkt_mutex);
14295	pptr->port_npkts--;
14296	mutex_exit(&pptr->port_pkt_mutex);
14297#endif /* DEBUG */
14298
14299	cmd->cmd_state = FCP_PKT_IDLE;
14300
14301	switch (rval) {
14302	case FC_SUCCESS:
14303		if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14304			fcp_complete_pkt(cmd->cmd_fp_pkt);
14305			rval = TRAN_ACCEPT;
14306		} else {
14307			rval = TRAN_FATAL_ERROR;
14308		}
14309		break;
14310
14311	case FC_TRAN_BUSY:
14312		rval = TRAN_BUSY;
14313		cmd->cmd_pkt->pkt_resid = 0;
14314		break;
14315
14316	case FC_BADPACKET:
14317		rval = TRAN_BADPKT;
14318		break;
14319
14320	default:
14321		rval = TRAN_FATAL_ERROR;
14322		break;
14323	}
14324
14325	return (rval);
14326}
14327
14328
14329/*
14330 * called by some of the following transport-called routines to convert
14331 * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14332 */
14333static struct fcp_port *
14334fcp_dip2port(dev_info_t *dip)
14335{
14336	int	instance;
14337
14338	instance = ddi_get_instance(dip);
14339	return (ddi_get_soft_state(fcp_softstate, instance));
14340}
14341
14342
14343/*
14344 * called internally to return a LUN given a dip
14345 */
14346struct fcp_lun *
14347fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14348{
14349	struct fcp_tgt *ptgt;
14350	struct fcp_lun *plun;
14351	int i;
14352
14353
14354	ASSERT(mutex_owned(&pptr->port_mutex));
14355
14356	for (i = 0; i < FCP_NUM_HASH; i++) {
14357		for (ptgt = pptr->port_tgt_hash_table[i];
14358		    ptgt != NULL;
14359		    ptgt = ptgt->tgt_next) {
14360			mutex_enter(&ptgt->tgt_mutex);
14361			for (plun = ptgt->tgt_lun; plun != NULL;
14362			    plun = plun->lun_next) {
14363				mutex_enter(&plun->lun_mutex);
14364				if (plun->lun_cip == cip) {
14365					mutex_exit(&plun->lun_mutex);
14366					mutex_exit(&ptgt->tgt_mutex);
14367					return (plun); /* match found */
14368				}
14369				mutex_exit(&plun->lun_mutex);
14370			}
14371			mutex_exit(&ptgt->tgt_mutex);
14372		}
14373	}
14374	return (NULL);				/* no LUN found */
14375}
14376
14377/*
14378 * pass an element to the hotplug list, kick the hotplug thread
14379 * and wait for the element to get processed by the hotplug thread.
14380 * on return the element is freed.
14381 *
14382 * return zero success and non-zero on failure
14383 *
14384 * acquires/releases the target mutex
14385 *
14386 */
14387static int
14388fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14389    child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14390{
14391	struct fcp_hp_elem	*elem;
14392	int			rval;
14393
14394	mutex_enter(&plun->lun_tgt->tgt_mutex);
14395	if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14396	    what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14397		mutex_exit(&plun->lun_tgt->tgt_mutex);
14398		fcp_log(CE_CONT, pptr->port_dip,
14399		    "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14400		    what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14401		return (NDI_FAILURE);
14402	}
14403	mutex_exit(&plun->lun_tgt->tgt_mutex);
14404	mutex_enter(&elem->mutex);
14405	if (elem->wait) {
14406		while (elem->wait) {
14407			cv_wait(&elem->cv, &elem->mutex);
14408		}
14409	}
14410	rval = (elem->result);
14411	mutex_exit(&elem->mutex);
14412	mutex_destroy(&elem->mutex);
14413	cv_destroy(&elem->cv);
14414	kmem_free(elem, sizeof (struct fcp_hp_elem));
14415	return (rval);
14416}
14417
14418/*
14419 * pass an element to the hotplug list, and then
14420 * kick the hotplug thread
14421 *
14422 * return Boolean success, i.e. non-zero if all goes well, else zero on error
14423 *
14424 * acquires/releases the hotplug mutex
14425 *
14426 * called with the target mutex owned
14427 *
14428 * memory acquired in NOSLEEP mode
14429 * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14430 *	 for the hp daemon to process the request and is responsible for
14431 *	 freeing the element
14432 */
14433static struct fcp_hp_elem *
14434fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14435    child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14436{
14437	struct fcp_hp_elem	*elem;
14438	dev_info_t *pdip;
14439
14440	ASSERT(pptr != NULL);
14441	ASSERT(plun != NULL);
14442	ASSERT(plun->lun_tgt != NULL);
14443	ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14444
14445	/* create space for a hotplug element */
14446	if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14447	    == NULL) {
14448		fcp_log(CE_WARN, NULL,
14449		    "!can't allocate memory for hotplug element");
14450		return (NULL);
14451	}
14452
14453	/* fill in hotplug element */
14454	elem->port = pptr;
14455	elem->lun = plun;
14456	elem->cip = cip;
14457	elem->old_lun_mpxio = plun->lun_mpxio;
14458	elem->what = what;
14459	elem->flags = flags;
14460	elem->link_cnt = link_cnt;
14461	elem->tgt_cnt = tgt_cnt;
14462	elem->wait = wait;
14463	mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14464	cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14465
14466	/* schedule the hotplug task */
14467	pdip = pptr->port_dip;
14468	mutex_enter(&plun->lun_mutex);
14469	if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14470		plun->lun_event_count++;
14471		elem->event_cnt = plun->lun_event_count;
14472	}
14473	mutex_exit(&plun->lun_mutex);
14474	if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14475	    (void *)elem, KM_NOSLEEP) == NULL) {
14476		mutex_enter(&plun->lun_mutex);
14477		if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14478			plun->lun_event_count--;
14479		}
14480		mutex_exit(&plun->lun_mutex);
14481		kmem_free(elem, sizeof (*elem));
14482		return (0);
14483	}
14484
14485	return (elem);
14486}
14487
14488
14489static void
14490fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14491{
14492	int			rval;
14493	struct scsi_address	*ap;
14494	struct fcp_lun	*plun;
14495	struct fcp_tgt	*ptgt;
14496	fc_packet_t	*fpkt;
14497
14498	ap = &cmd->cmd_pkt->pkt_address;
14499	plun = ADDR2LUN(ap);
14500	ptgt = plun->lun_tgt;
14501
14502	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14503
14504	cmd->cmd_state = FCP_PKT_IDLE;
14505
14506	mutex_enter(&pptr->port_mutex);
14507	mutex_enter(&ptgt->tgt_mutex);
14508	if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14509	    (!(pptr->port_state & FCP_STATE_ONLINING))) {
14510		fc_ulp_rscn_info_t *rscnp;
14511
14512		cmd->cmd_state = FCP_PKT_ISSUED;
14513
14514		/*
14515		 * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14516		 * originally NULL, hence we try to set it to the pd pointed
14517		 * to by the SCSI device we're trying to get to.
14518		 */
14519
14520		fpkt = cmd->cmd_fp_pkt;
14521		if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14522			fpkt->pkt_pd = ptgt->tgt_pd_handle;
14523			/*
14524			 * We need to notify the transport that we now have a
14525			 * reference to the remote port handle.
14526			 */
14527			fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14528		}
14529
14530		mutex_exit(&ptgt->tgt_mutex);
14531		mutex_exit(&pptr->port_mutex);
14532
14533		ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14534
14535		/* prepare the packet */
14536
14537		fcp_prepare_pkt(pptr, cmd, plun);
14538
14539		rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14540		    pkt_ulp_rscn_infop;
14541
14542		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14543		    fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14544
14545		if (rscnp != NULL) {
14546			rscnp->ulp_rscn_count =
14547			    fc_ulp_get_rscn_count(pptr->
14548			    port_fp_handle);
14549		}
14550
14551		rval = fcp_transport(pptr->port_fp_handle,
14552		    cmd->cmd_fp_pkt, 0);
14553
14554		if (rval == FC_SUCCESS) {
14555			return;
14556		}
14557		cmd->cmd_state &= ~FCP_PKT_ISSUED;
14558	} else {
14559		mutex_exit(&ptgt->tgt_mutex);
14560		mutex_exit(&pptr->port_mutex);
14561	}
14562
14563	fcp_queue_pkt(pptr, cmd);
14564}
14565
14566
14567static void
14568fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14569{
14570	ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14571
14572	cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14573	cmd->cmd_state = FCP_PKT_IDLE;
14574
14575	cmd->cmd_pkt->pkt_reason = reason;
14576	cmd->cmd_pkt->pkt_state = 0;
14577	cmd->cmd_pkt->pkt_statistics = statistics;
14578
14579	fcp_post_callback(cmd);
14580}
14581
14582/*
14583 *     Function: fcp_queue_pkt
14584 *
14585 *  Description: This function queues the packet passed by the caller into
14586 *		 the list of packets of the FCP port.
14587 *
14588 *     Argument: *pptr		FCP port.
14589 *		 *cmd		FCP packet to queue.
14590 *
14591 * Return Value: None
14592 *
14593 *	Context: User, Kernel and Interrupt context.
14594 */
14595static void
14596fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14597{
14598	ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14599
14600	mutex_enter(&pptr->port_pkt_mutex);
14601	cmd->cmd_flags |= CFLAG_IN_QUEUE;
14602	ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14603	cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14604
14605	/*
14606	 * zero pkt_time means hang around for ever
14607	 */
14608	if (cmd->cmd_pkt->pkt_time) {
14609		if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14610			cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14611		} else {
14612			/*
14613			 * Indicate the watch thread to fail the
14614			 * command by setting it to highest value
14615			 */
14616			cmd->cmd_timeout = fcp_watchdog_time;
14617			cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14618		}
14619	}
14620
14621	if (pptr->port_pkt_head) {
14622		ASSERT(pptr->port_pkt_tail != NULL);
14623
14624		pptr->port_pkt_tail->cmd_next = cmd;
14625		pptr->port_pkt_tail = cmd;
14626	} else {
14627		ASSERT(pptr->port_pkt_tail == NULL);
14628
14629		pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14630	}
14631	cmd->cmd_next = NULL;
14632	mutex_exit(&pptr->port_pkt_mutex);
14633}
14634
14635/*
14636 *     Function: fcp_update_targets
14637 *
14638 *  Description: This function applies the specified change of state to all
14639 *		 the targets listed.  The operation applied is 'set'.
14640 *
14641 *     Argument: *pptr		FCP port.
14642 *		 *dev_list	Array of fc_portmap_t structures.
14643 *		 count		Length of dev_list.
14644 *		 state		State bits to update.
14645 *		 cause		Reason for the update.
14646 *
14647 * Return Value: None
14648 *
14649 *	Context: User, Kernel and Interrupt context.
14650 *		 The mutex pptr->port_mutex must be held.
14651 */
14652static void
14653fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14654    uint32_t count, uint32_t state, int cause)
14655{
14656	fc_portmap_t		*map_entry;
14657	struct fcp_tgt	*ptgt;
14658
14659	ASSERT(MUTEX_HELD(&pptr->port_mutex));
14660
14661	while (count--) {
14662		map_entry = &(dev_list[count]);
14663		ptgt = fcp_lookup_target(pptr,
14664		    (uchar_t *)&(map_entry->map_pwwn));
14665		if (ptgt == NULL) {
14666			continue;
14667		}
14668
14669		mutex_enter(&ptgt->tgt_mutex);
14670		ptgt->tgt_trace = 0;
14671		ptgt->tgt_change_cnt++;
14672		ptgt->tgt_statec_cause = cause;
14673		ptgt->tgt_tmp_cnt = 1;
14674		fcp_update_tgt_state(ptgt, FCP_SET, state);
14675		mutex_exit(&ptgt->tgt_mutex);
14676	}
14677}
14678
14679static int
14680fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14681    int lcount, int tcount, int cause)
14682{
14683	int rval;
14684
14685	mutex_enter(&pptr->port_mutex);
14686	rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14687	mutex_exit(&pptr->port_mutex);
14688
14689	return (rval);
14690}
14691
14692
14693static int
14694fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14695    int lcount, int tcount, int cause)
14696{
14697	int	finish_init = 0;
14698	int	finish_tgt = 0;
14699	int	do_finish_init = 0;
14700	int	rval = FCP_NO_CHANGE;
14701
14702	if (cause == FCP_CAUSE_LINK_CHANGE ||
14703	    cause == FCP_CAUSE_LINK_DOWN) {
14704		do_finish_init = 1;
14705	}
14706
14707	if (ptgt != NULL) {
14708		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14709		    FCP_BUF_LEVEL_2, 0,
14710		    "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14711		    " cause = %d, d_id = 0x%x, tgt_done = %d",
14712		    pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14713		    pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14714		    ptgt->tgt_d_id, ptgt->tgt_done);
14715
14716		mutex_enter(&ptgt->tgt_mutex);
14717
14718		if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14719			rval = FCP_DEV_CHANGE;
14720			if (do_finish_init && ptgt->tgt_done == 0) {
14721				ptgt->tgt_done++;
14722				finish_init = 1;
14723			}
14724		} else {
14725			if (--ptgt->tgt_tmp_cnt <= 0) {
14726				ptgt->tgt_tmp_cnt = 0;
14727				finish_tgt = 1;
14728
14729				if (do_finish_init) {
14730					finish_init = 1;
14731				}
14732			}
14733		}
14734		mutex_exit(&ptgt->tgt_mutex);
14735	} else {
14736		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14737		    FCP_BUF_LEVEL_2, 0,
14738		    "Call Finish Init for NO target");
14739
14740		if (do_finish_init) {
14741			finish_init = 1;
14742		}
14743	}
14744
14745	if (finish_tgt) {
14746		ASSERT(ptgt != NULL);
14747
14748		mutex_enter(&ptgt->tgt_mutex);
14749#ifdef	DEBUG
14750		bzero(ptgt->tgt_tmp_cnt_stack,
14751		    sizeof (ptgt->tgt_tmp_cnt_stack));
14752
14753		ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14754		    FCP_STACK_DEPTH);
14755#endif /* DEBUG */
14756		mutex_exit(&ptgt->tgt_mutex);
14757
14758		(void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14759	}
14760
14761	if (finish_init && lcount == pptr->port_link_cnt) {
14762		ASSERT(pptr->port_tmp_cnt > 0);
14763		if (--pptr->port_tmp_cnt == 0) {
14764			fcp_finish_init(pptr);
14765		}
14766	} else if (lcount != pptr->port_link_cnt) {
14767		FCP_TRACE(fcp_logq, pptr->port_instbuf,
14768		    fcp_trace, FCP_BUF_LEVEL_2, 0,
14769		    "fcp_call_finish_init_held,1: state change occured"
14770		    " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14771	}
14772
14773	return (rval);
14774}
14775
14776static void
14777fcp_reconfigure_luns(void * tgt_handle)
14778{
14779	uint32_t		dev_cnt;
14780	fc_portmap_t		*devlist;
14781	struct fcp_tgt	*ptgt = (struct fcp_tgt *)tgt_handle;
14782	struct fcp_port		*pptr = ptgt->tgt_port;
14783
14784	/*
14785	 * If the timer that fires this off got canceled too late, the
14786	 * target could have been destroyed.
14787	 */
14788
14789	if (ptgt->tgt_tid == NULL) {
14790		return;
14791	}
14792
14793	devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14794	if (devlist == NULL) {
14795		fcp_log(CE_WARN, pptr->port_dip,
14796		    "!fcp%d: failed to allocate for portmap",
14797		    pptr->port_instance);
14798		return;
14799	}
14800
14801	dev_cnt = 1;
14802	devlist->map_pd = ptgt->tgt_pd_handle;
14803	devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14804	devlist->map_did.port_id = ptgt->tgt_d_id;
14805
14806	bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14807	bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14808
14809	devlist->map_state = PORT_DEVICE_LOGGED_IN;
14810	devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14811	devlist->map_flags = 0;
14812
14813	fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14814	    pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14815
14816	/*
14817	 * Clear the tgt_tid after no more references to
14818	 * the fcp_tgt
14819	 */
14820	mutex_enter(&ptgt->tgt_mutex);
14821	ptgt->tgt_tid = NULL;
14822	mutex_exit(&ptgt->tgt_mutex);
14823
14824	kmem_free(devlist, sizeof (*devlist));
14825}
14826
14827
14828static void
14829fcp_free_targets(struct fcp_port *pptr)
14830{
14831	int			i;
14832	struct fcp_tgt	*ptgt;
14833
14834	mutex_enter(&pptr->port_mutex);
14835	for (i = 0; i < FCP_NUM_HASH; i++) {
14836		ptgt = pptr->port_tgt_hash_table[i];
14837		while (ptgt != NULL) {
14838			struct fcp_tgt *next_tgt = ptgt->tgt_next;
14839
14840			fcp_free_target(ptgt);
14841			ptgt = next_tgt;
14842		}
14843	}
14844	mutex_exit(&pptr->port_mutex);
14845}
14846
14847
14848static void
14849fcp_free_target(struct fcp_tgt *ptgt)
14850{
14851	struct fcp_lun	*plun;
14852	timeout_id_t		tid;
14853
14854	mutex_enter(&ptgt->tgt_mutex);
14855	tid = ptgt->tgt_tid;
14856
14857	/*
14858	 * Cancel any pending timeouts for this target.
14859	 */
14860
14861	if (tid != NULL) {
14862		/*
14863		 * Set tgt_tid to NULL first to avoid a race in the callback.
14864		 * If tgt_tid is NULL, the callback will simply return.
14865		 */
14866		ptgt->tgt_tid = NULL;
14867		mutex_exit(&ptgt->tgt_mutex);
14868		(void) untimeout(tid);
14869		mutex_enter(&ptgt->tgt_mutex);
14870	}
14871
14872	plun = ptgt->tgt_lun;
14873	while (plun != NULL) {
14874		struct fcp_lun *next_lun = plun->lun_next;
14875
14876		fcp_dealloc_lun(plun);
14877		plun = next_lun;
14878	}
14879
14880	mutex_exit(&ptgt->tgt_mutex);
14881	fcp_dealloc_tgt(ptgt);
14882}
14883
14884/*
14885 *     Function: fcp_is_retryable
14886 *
14887 *  Description: Indicates if the internal packet is retryable.
14888 *
14889 *     Argument: *icmd		FCP internal packet.
14890 *
14891 * Return Value: 0	Not retryable
14892 *		 1	Retryable
14893 *
14894 *	Context: User, Kernel and Interrupt context
14895 */
14896static int
14897fcp_is_retryable(struct fcp_ipkt *icmd)
14898{
14899	if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14900	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14901		return (0);
14902	}
14903
14904	return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14905	    icmd->ipkt_port->port_deadline) ? 1 : 0);
14906}
14907
14908/*
14909 *     Function: fcp_create_on_demand
14910 *
14911 *     Argument: *pptr		FCP port.
14912 *		 *pwwn		Port WWN.
14913 *
14914 * Return Value: 0	Success
14915 *		 EIO
14916 *		 ENOMEM
14917 *		 EBUSY
14918 *		 EINVAL
14919 *
14920 *	Context: User and Kernel context
14921 */
14922static int
14923fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14924{
14925	int			wait_ms;
14926	int			tcount;
14927	int			lcount;
14928	int			ret;
14929	int			error;
14930	int			rval = EIO;
14931	int			ntries;
14932	fc_portmap_t		*devlist;
14933	opaque_t		pd;
14934	struct fcp_lun		*plun;
14935	struct fcp_tgt		*ptgt;
14936	int			old_manual = 0;
14937
14938	/* Allocates the fc_portmap_t structure. */
14939	devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14940
14941	/*
14942	 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14943	 * in the commented statement below:
14944	 *
14945	 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14946	 *
14947	 * Below, the deadline for the discovery process is set.
14948	 */
14949	mutex_enter(&pptr->port_mutex);
14950	pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14951	mutex_exit(&pptr->port_mutex);
14952
14953	/*
14954	 * We try to find the remote port based on the WWN provided by the
14955	 * caller.  We actually ask fp/fctl if it has it.
14956	 */
14957	pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14958	    (la_wwn_t *)pwwn, &error, 1);
14959
14960	if (pd == NULL) {
14961		kmem_free(devlist, sizeof (*devlist));
14962		return (rval);
14963	}
14964
14965	/*
14966	 * The remote port was found.  We ask fp/fctl to update our
14967	 * fc_portmap_t structure.
14968	 */
14969	ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14970	    (la_wwn_t *)pwwn, devlist);
14971	if (ret != FC_SUCCESS) {
14972		kmem_free(devlist, sizeof (*devlist));
14973		return (rval);
14974	}
14975
14976	/*
14977	 * The map flag field is set to indicates that the creation is being
14978	 * done at the user request (Ioclt probably luxadm or cfgadm).
14979	 */
14980	devlist->map_type = PORT_DEVICE_USER_CREATE;
14981
14982	mutex_enter(&pptr->port_mutex);
14983
14984	/*
14985	 * We check to see if fcp already has a target that describes the
14986	 * device being created.  If not it is created.
14987	 */
14988	ptgt = fcp_lookup_target(pptr, pwwn);
14989	if (ptgt == NULL) {
14990		lcount = pptr->port_link_cnt;
14991		mutex_exit(&pptr->port_mutex);
14992
14993		ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14994		if (ptgt == NULL) {
14995			fcp_log(CE_WARN, pptr->port_dip,
14996			    "!FC target allocation failed");
14997			return (ENOMEM);
14998		}
14999
15000		mutex_enter(&pptr->port_mutex);
15001	}
15002
15003	mutex_enter(&ptgt->tgt_mutex);
15004	ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15005	ptgt->tgt_tmp_cnt = 1;
15006	ptgt->tgt_device_created = 0;
15007	/*
15008	 * If fabric and auto config is set but the target was
15009	 * manually unconfigured then reset to the manual_config_only to
15010	 * 0 so the device will get configured.
15011	 */
15012	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15013	    fcp_enable_auto_configuration &&
15014	    ptgt->tgt_manual_config_only == 1) {
15015		old_manual = 1;
15016		ptgt->tgt_manual_config_only = 0;
15017	}
15018	mutex_exit(&ptgt->tgt_mutex);
15019
15020	fcp_update_targets(pptr, devlist, 1,
15021	    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15022
15023	lcount = pptr->port_link_cnt;
15024	tcount = ptgt->tgt_change_cnt;
15025
15026	if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15027	    tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15028		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15029		    fcp_enable_auto_configuration && old_manual) {
15030			mutex_enter(&ptgt->tgt_mutex);
15031			ptgt->tgt_manual_config_only = 1;
15032			mutex_exit(&ptgt->tgt_mutex);
15033		}
15034
15035		if (pptr->port_link_cnt != lcount ||
15036		    ptgt->tgt_change_cnt != tcount) {
15037			rval = EBUSY;
15038		}
15039		mutex_exit(&pptr->port_mutex);
15040
15041		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15042		    FCP_BUF_LEVEL_3, 0,
15043		    "fcp_create_on_demand: mapflags ptgt=%x, "
15044		    "lcount=%x::port_link_cnt=%x, "
15045		    "tcount=%x: tgt_change_cnt=%x, rval=%x",
15046		    ptgt, lcount, pptr->port_link_cnt,
15047		    tcount, ptgt->tgt_change_cnt, rval);
15048		return (rval);
15049	}
15050
15051	/*
15052	 * Due to lack of synchronization mechanisms, we perform
15053	 * periodic monitoring of our request; Because requests
15054	 * get dropped when another one supercedes (either because
15055	 * of a link change or a target change), it is difficult to
15056	 * provide a clean synchronization mechanism (such as a
15057	 * semaphore or a conditional variable) without exhaustively
15058	 * rewriting the mainline discovery code of this driver.
15059	 */
15060	wait_ms = 500;
15061
15062	ntries = fcp_max_target_retries;
15063
15064	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15065	    FCP_BUF_LEVEL_3, 0,
15066	    "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15067	    "lcount=%x::port_link_cnt=%x, "
15068	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15069	    "tgt_tmp_cnt =%x",
15070	    ntries, ptgt, lcount, pptr->port_link_cnt,
15071	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15072	    ptgt->tgt_tmp_cnt);
15073
15074	mutex_enter(&ptgt->tgt_mutex);
15075	while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15076	    ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15077		mutex_exit(&ptgt->tgt_mutex);
15078		mutex_exit(&pptr->port_mutex);
15079
15080		delay(drv_usectohz(wait_ms * 1000));
15081
15082		mutex_enter(&pptr->port_mutex);
15083		mutex_enter(&ptgt->tgt_mutex);
15084	}
15085
15086
15087	if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15088		rval = EBUSY;
15089	} else {
15090		if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15091		    FCP_TGT_NODE_PRESENT) {
15092			rval = 0;
15093		}
15094	}
15095
15096	FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15097	    FCP_BUF_LEVEL_3, 0,
15098	    "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15099	    "lcount=%x::port_link_cnt=%x, "
15100	    "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15101	    "tgt_tmp_cnt =%x",
15102	    ntries, ptgt, lcount, pptr->port_link_cnt,
15103	    tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15104	    ptgt->tgt_tmp_cnt);
15105
15106	if (rval) {
15107		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15108		    fcp_enable_auto_configuration && old_manual) {
15109			ptgt->tgt_manual_config_only = 1;
15110		}
15111		mutex_exit(&ptgt->tgt_mutex);
15112		mutex_exit(&pptr->port_mutex);
15113		kmem_free(devlist, sizeof (*devlist));
15114
15115		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15116		    FCP_BUF_LEVEL_3, 0,
15117		    "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15118		    "lcount=%x::port_link_cnt=%x, "
15119		    "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15120		    "tgt_device_created=%x, tgt D_ID=%x",
15121		    ntries, ptgt, lcount, pptr->port_link_cnt,
15122		    tcount, ptgt->tgt_change_cnt, rval,
15123		    ptgt->tgt_device_created, ptgt->tgt_d_id);
15124		return (rval);
15125	}
15126
15127	if ((plun = ptgt->tgt_lun) != NULL) {
15128		tcount = plun->lun_tgt->tgt_change_cnt;
15129	} else {
15130		rval = EINVAL;
15131	}
15132	lcount = pptr->port_link_cnt;
15133
15134	/*
15135	 * Configuring the target with no LUNs will fail. We
15136	 * should reset the node state so that it is not
15137	 * automatically configured when the LUNs are added
15138	 * to this target.
15139	 */
15140	if (ptgt->tgt_lun_cnt == 0) {
15141		ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15142	}
15143	mutex_exit(&ptgt->tgt_mutex);
15144	mutex_exit(&pptr->port_mutex);
15145
15146	while (plun) {
15147		child_info_t	*cip;
15148
15149		mutex_enter(&plun->lun_mutex);
15150		cip = plun->lun_cip;
15151		mutex_exit(&plun->lun_mutex);
15152
15153		mutex_enter(&ptgt->tgt_mutex);
15154		if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15155			mutex_exit(&ptgt->tgt_mutex);
15156
15157			rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15158			    FCP_ONLINE, lcount, tcount,
15159			    NDI_ONLINE_ATTACH);
15160			if (rval != NDI_SUCCESS) {
15161				FCP_TRACE(fcp_logq,
15162				    pptr->port_instbuf, fcp_trace,
15163				    FCP_BUF_LEVEL_3, 0,
15164				    "fcp_create_on_demand: "
15165				    "pass_to_hp_and_wait failed "
15166				    "rval=%x", rval);
15167				rval = EIO;
15168			} else {
15169				mutex_enter(&LUN_TGT->tgt_mutex);
15170				plun->lun_state &= ~(FCP_LUN_OFFLINE |
15171				    FCP_LUN_BUSY);
15172				mutex_exit(&LUN_TGT->tgt_mutex);
15173			}
15174			mutex_enter(&ptgt->tgt_mutex);
15175		}
15176
15177		plun = plun->lun_next;
15178		mutex_exit(&ptgt->tgt_mutex);
15179	}
15180
15181	kmem_free(devlist, sizeof (*devlist));
15182
15183	if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15184	    fcp_enable_auto_configuration && old_manual) {
15185		mutex_enter(&ptgt->tgt_mutex);
15186		/* if successful then set manual to 0 */
15187		if (rval == 0) {
15188			ptgt->tgt_manual_config_only = 0;
15189		} else {
15190			/* reset to 1 so the user has to do the config */
15191			ptgt->tgt_manual_config_only = 1;
15192		}
15193		mutex_exit(&ptgt->tgt_mutex);
15194	}
15195
15196	return (rval);
15197}
15198
15199
15200static void
15201fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15202{
15203	int		count;
15204	uchar_t		byte;
15205
15206	count = 0;
15207	while (*string) {
15208		byte = FCP_ATOB(*string); string++;
15209		byte = byte << 4 | FCP_ATOB(*string); string++;
15210		bytes[count++] = byte;
15211
15212		if (count >= byte_len) {
15213			break;
15214		}
15215	}
15216}
15217
15218static void
15219fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15220{
15221	int		i;
15222
15223	for (i = 0; i < FC_WWN_SIZE; i++) {
15224		(void) sprintf(string + (i * 2),
15225		    "%02x", wwn[i]);
15226	}
15227
15228}
15229
15230static void
15231fcp_print_error(fc_packet_t *fpkt)
15232{
15233	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
15234	    fpkt->pkt_ulp_private;
15235	struct fcp_port	*pptr;
15236	struct fcp_tgt	*ptgt;
15237	struct fcp_lun	*plun;
15238	caddr_t			buf;
15239	int			scsi_cmd = 0;
15240
15241	ptgt = icmd->ipkt_tgt;
15242	plun = icmd->ipkt_lun;
15243	pptr = ptgt->tgt_port;
15244
15245	buf = kmem_zalloc(256, KM_NOSLEEP);
15246	if (buf == NULL) {
15247		return;
15248	}
15249
15250	switch (icmd->ipkt_opcode) {
15251	case SCMD_REPORT_LUN:
15252		(void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15253		    " lun=0x%%x failed");
15254		scsi_cmd++;
15255		break;
15256
15257	case SCMD_INQUIRY_PAGE83:
15258		(void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15259		    " lun=0x%%x failed");
15260		scsi_cmd++;
15261		break;
15262
15263	case SCMD_INQUIRY:
15264		(void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15265		    " lun=0x%%x failed");
15266		scsi_cmd++;
15267		break;
15268
15269	case LA_ELS_PLOGI:
15270		(void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15271		break;
15272
15273	case LA_ELS_PRLI:
15274		(void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15275		break;
15276	}
15277
15278	if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15279		struct fcp_rsp		response, *rsp;
15280		uchar_t			asc, ascq;
15281		caddr_t			sense_key = NULL;
15282		struct fcp_rsp_info	fcp_rsp_err, *bep;
15283
15284		if (icmd->ipkt_nodma) {
15285			rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15286			bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15287			    sizeof (struct fcp_rsp));
15288		} else {
15289			rsp = &response;
15290			bep = &fcp_rsp_err;
15291
15292			FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15293			    sizeof (struct fcp_rsp));
15294
15295			FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15296			    bep, fpkt->pkt_resp_acc,
15297			    sizeof (struct fcp_rsp_info));
15298		}
15299
15300
15301		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15302			(void) sprintf(buf + strlen(buf),
15303			    " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15304			    " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15305			    " senselen=%%x. Giving up");
15306
15307			fcp_log(CE_WARN, pptr->port_dip, buf,
15308			    ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15309			    rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15310			    rsp->fcp_u.fcp_status.reserved_1,
15311			    rsp->fcp_response_len, rsp->fcp_sense_len);
15312
15313			kmem_free(buf, 256);
15314			return;
15315		}
15316
15317		if (rsp->fcp_u.fcp_status.rsp_len_set &&
15318		    bep->rsp_code != FCP_NO_FAILURE) {
15319			(void) sprintf(buf + strlen(buf),
15320			    " FCP Response code = 0x%x", bep->rsp_code);
15321		}
15322
15323		if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15324			struct scsi_extended_sense sense_info, *sense_ptr;
15325
15326			if (icmd->ipkt_nodma) {
15327				sense_ptr = (struct scsi_extended_sense *)
15328				    ((caddr_t)fpkt->pkt_resp +
15329				    sizeof (struct fcp_rsp) +
15330				    rsp->fcp_response_len);
15331			} else {
15332				sense_ptr = &sense_info;
15333
15334				FCP_CP_IN(fpkt->pkt_resp +
15335				    sizeof (struct fcp_rsp) +
15336				    rsp->fcp_response_len, &sense_info,
15337				    fpkt->pkt_resp_acc,
15338				    sizeof (struct scsi_extended_sense));
15339			}
15340
15341			if (sense_ptr->es_key < NUM_SENSE_KEYS +
15342			    NUM_IMPL_SENSE_KEYS) {
15343				sense_key = sense_keys[sense_ptr->es_key];
15344			} else {
15345				sense_key = "Undefined";
15346			}
15347
15348			asc = sense_ptr->es_add_code;
15349			ascq = sense_ptr->es_qual_code;
15350
15351			(void) sprintf(buf + strlen(buf),
15352			    ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15353			    " Giving up");
15354
15355			fcp_log(CE_WARN, pptr->port_dip, buf,
15356			    ptgt->tgt_d_id, plun->lun_num, sense_key,
15357			    asc, ascq);
15358		} else {
15359			(void) sprintf(buf + strlen(buf),
15360			    " : SCSI status=%%x. Giving up");
15361
15362			fcp_log(CE_WARN, pptr->port_dip, buf,
15363			    ptgt->tgt_d_id, plun->lun_num,
15364			    rsp->fcp_u.fcp_status.scsi_status);
15365		}
15366	} else {
15367		caddr_t state, reason, action, expln;
15368
15369		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
15370		    &action, &expln);
15371
15372		(void) sprintf(buf + strlen(buf), ": State:%%s,"
15373		    " Reason:%%s. Giving up");
15374
15375		if (scsi_cmd) {
15376			fcp_log(CE_WARN, pptr->port_dip, buf,
15377			    ptgt->tgt_d_id, plun->lun_num, state, reason);
15378		} else {
15379			fcp_log(CE_WARN, pptr->port_dip, buf,
15380			    ptgt->tgt_d_id, state, reason);
15381		}
15382	}
15383
15384	kmem_free(buf, 256);
15385}
15386
15387
15388static int
15389fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15390    struct fcp_ipkt *icmd, int rval, caddr_t op)
15391{
15392	int	ret = DDI_FAILURE;
15393	char	*error;
15394
15395	switch (rval) {
15396	case FC_DEVICE_BUSY_NEW_RSCN:
15397		/*
15398		 * This means that there was a new RSCN that the transport
15399		 * knows about (which the ULP *may* know about too) but the
15400		 * pkt that was sent down was related to an older RSCN. So, we
15401		 * are just going to reset the retry count and deadline and
15402		 * continue to retry. The idea is that transport is currently
15403		 * working on the new RSCN and will soon let the ULPs know
15404		 * about it and when it does the existing logic will kick in
15405		 * where it will change the tcount to indicate that something
15406		 * changed on the target. So, rediscovery will start and there
15407		 * will not be an infinite retry.
15408		 *
15409		 * For a full flow of how the RSCN info is transferred back and
15410		 * forth, see fp.c
15411		 */
15412		icmd->ipkt_retries = 0;
15413		icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15414		    FCP_ICMD_DEADLINE;
15415
15416		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15417		    FCP_BUF_LEVEL_3, 0,
15418		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15419		    rval, ptgt->tgt_d_id);
15420		/* FALLTHROUGH */
15421
15422	case FC_STATEC_BUSY:
15423	case FC_DEVICE_BUSY:
15424	case FC_PBUSY:
15425	case FC_FBUSY:
15426	case FC_TRAN_BUSY:
15427	case FC_OFFLINE:
15428		FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15429		    FCP_BUF_LEVEL_3, 0,
15430		    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15431		    rval, ptgt->tgt_d_id);
15432		if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15433		    fcp_is_retryable(icmd)) {
15434			fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15435			ret = DDI_SUCCESS;
15436		}
15437		break;
15438
15439	case FC_LOGINREQ:
15440		/*
15441		 * FC_LOGINREQ used to be handled just like all the cases
15442		 * above. It has been changed to handled a PRLI that fails
15443		 * with FC_LOGINREQ different than other ipkts that fail
15444		 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15445		 * a simple matter to turn it into a PLOGI instead, so that's
15446		 * exactly what we do here.
15447		 */
15448		if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15449			ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15450			    icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15451			    icmd->ipkt_change_cnt, icmd->ipkt_cause);
15452		} else {
15453			FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15454			    FCP_BUF_LEVEL_3, 0,
15455			    "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15456			    rval, ptgt->tgt_d_id);
15457			if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15458			    fcp_is_retryable(icmd)) {
15459				fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15460				ret = DDI_SUCCESS;
15461			}
15462		}
15463		break;
15464
15465	default:
15466		mutex_enter(&pptr->port_mutex);
15467		mutex_enter(&ptgt->tgt_mutex);
15468		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15469			mutex_exit(&ptgt->tgt_mutex);
15470			mutex_exit(&pptr->port_mutex);
15471
15472			(void) fc_ulp_error(rval, &error);
15473			fcp_log(CE_WARN, pptr->port_dip,
15474			    "!Failed to send %s to D_ID=%x error=%s",
15475			    op, ptgt->tgt_d_id, error);
15476		} else {
15477			FCP_TRACE(fcp_logq, pptr->port_instbuf,
15478			    fcp_trace, FCP_BUF_LEVEL_2, 0,
15479			    "fcp_handle_ipkt_errors,1: state change occured"
15480			    " for D_ID=0x%x", ptgt->tgt_d_id);
15481			mutex_exit(&ptgt->tgt_mutex);
15482			mutex_exit(&pptr->port_mutex);
15483		}
15484		break;
15485	}
15486
15487	return (ret);
15488}
15489
15490
15491/*
15492 * Check of outstanding commands on any LUN for this target
15493 */
15494static int
15495fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15496{
15497	struct	fcp_lun	*plun;
15498	struct	fcp_pkt	*cmd;
15499
15500	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15501		mutex_enter(&plun->lun_mutex);
15502		for (cmd = plun->lun_pkt_head; cmd != NULL;
15503		    cmd = cmd->cmd_forw) {
15504			if (cmd->cmd_state == FCP_PKT_ISSUED) {
15505				mutex_exit(&plun->lun_mutex);
15506				return (FC_SUCCESS);
15507			}
15508		}
15509		mutex_exit(&plun->lun_mutex);
15510	}
15511
15512	return (FC_FAILURE);
15513}
15514
15515static fc_portmap_t *
15516fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15517{
15518	int			i;
15519	fc_portmap_t		*devlist;
15520	fc_portmap_t		*devptr = NULL;
15521	struct fcp_tgt	*ptgt;
15522
15523	mutex_enter(&pptr->port_mutex);
15524	for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15525		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15526		    ptgt = ptgt->tgt_next) {
15527			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15528				++*dev_cnt;
15529			}
15530		}
15531	}
15532
15533	devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15534	    KM_NOSLEEP);
15535	if (devlist == NULL) {
15536		mutex_exit(&pptr->port_mutex);
15537		fcp_log(CE_WARN, pptr->port_dip,
15538		    "!fcp%d: failed to allocate for portmap for construct map",
15539		    pptr->port_instance);
15540		return (devptr);
15541	}
15542
15543	for (i = 0; i < FCP_NUM_HASH; i++) {
15544		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15545		    ptgt = ptgt->tgt_next) {
15546			if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15547				int ret;
15548
15549				ret = fc_ulp_pwwn_to_portmap(
15550				    pptr->port_fp_handle,
15551				    (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15552				    devlist);
15553
15554				if (ret == FC_SUCCESS) {
15555					devlist++;
15556					continue;
15557				}
15558
15559				devlist->map_pd = NULL;
15560				devlist->map_did.port_id = ptgt->tgt_d_id;
15561				devlist->map_hard_addr.hard_addr =
15562				    ptgt->tgt_hard_addr;
15563
15564				devlist->map_state = PORT_DEVICE_INVALID;
15565				devlist->map_type = PORT_DEVICE_OLD;
15566
15567				bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15568				    &devlist->map_nwwn, FC_WWN_SIZE);
15569
15570				bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15571				    &devlist->map_pwwn, FC_WWN_SIZE);
15572
15573				devlist++;
15574			}
15575		}
15576	}
15577
15578	mutex_exit(&pptr->port_mutex);
15579
15580	return (devptr);
15581}
15582/*
15583 * Inimate MPxIO that the lun is busy and cannot accept regular IO
15584 */
15585static void
15586fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15587{
15588	int i;
15589	struct fcp_tgt	*ptgt;
15590	struct fcp_lun	*plun;
15591
15592	for (i = 0; i < FCP_NUM_HASH; i++) {
15593		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15594		    ptgt = ptgt->tgt_next) {
15595			mutex_enter(&ptgt->tgt_mutex);
15596			for (plun = ptgt->tgt_lun; plun != NULL;
15597			    plun = plun->lun_next) {
15598				if (plun->lun_mpxio &&
15599				    plun->lun_state & FCP_LUN_BUSY) {
15600					if (!fcp_pass_to_hp(pptr, plun,
15601					    plun->lun_cip,
15602					    FCP_MPXIO_PATH_SET_BUSY,
15603					    pptr->port_link_cnt,
15604					    ptgt->tgt_change_cnt, 0, 0)) {
15605						FCP_TRACE(fcp_logq,
15606						    pptr->port_instbuf,
15607						    fcp_trace,
15608						    FCP_BUF_LEVEL_2, 0,
15609						    "path_verifybusy: "
15610						    "disable lun %p failed!",
15611						    plun);
15612					}
15613				}
15614			}
15615			mutex_exit(&ptgt->tgt_mutex);
15616		}
15617	}
15618}
15619
15620static int
15621fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15622{
15623	dev_info_t		*cdip = NULL;
15624	dev_info_t		*pdip = NULL;
15625
15626	ASSERT(plun);
15627
15628	mutex_enter(&plun->lun_mutex);
15629	if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15630		mutex_exit(&plun->lun_mutex);
15631		return (NDI_FAILURE);
15632	}
15633	mutex_exit(&plun->lun_mutex);
15634	cdip = mdi_pi_get_client(PIP(cip));
15635	pdip = mdi_pi_get_phci(PIP(cip));
15636
15637	ASSERT(cdip != NULL);
15638	ASSERT(pdip != NULL);
15639
15640	if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15641		/* LUN ready for IO */
15642		(void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15643	} else {
15644		/* LUN busy to accept IO */
15645		(void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15646	}
15647	return (NDI_SUCCESS);
15648}
15649
15650/*
15651 * Caller must free the returned string of MAXPATHLEN len
15652 * If the device is offline (-1 instance number) NULL
15653 * will be returned.
15654 */
15655static char *
15656fcp_get_lun_path(struct fcp_lun *plun) {
15657	dev_info_t	*dip = NULL;
15658	char		*path = NULL;
15659	mdi_pathinfo_t	*pip = NULL;
15660
15661	if (plun == NULL) {
15662		return (NULL);
15663	}
15664
15665	mutex_enter(&plun->lun_mutex);
15666	if (plun->lun_mpxio == 0) {
15667		dip = DIP(plun->lun_cip);
15668		mutex_exit(&plun->lun_mutex);
15669	} else {
15670		/*
15671		 * lun_cip must be accessed with lun_mutex held. Here
15672		 * plun->lun_cip either points to a valid node or it is NULL.
15673		 * Make a copy so that we can release lun_mutex.
15674		 */
15675		pip = PIP(plun->lun_cip);
15676
15677		/*
15678		 * Increase ref count on the path so that we can release
15679		 * lun_mutex and still be sure that the pathinfo node (and thus
15680		 * also the client) is not deallocated. If pip is NULL, this
15681		 * has no effect.
15682		 */
15683		mdi_hold_path(pip);
15684
15685		mutex_exit(&plun->lun_mutex);
15686
15687		/* Get the client. If pip is NULL, we get NULL. */
15688		dip = mdi_pi_get_client(pip);
15689	}
15690
15691	if (dip == NULL)
15692		goto out;
15693	if (ddi_get_instance(dip) < 0)
15694		goto out;
15695
15696	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15697	if (path == NULL)
15698		goto out;
15699
15700	(void) ddi_pathname(dip, path);
15701
15702	/* Clean up. */
15703out:
15704	if (pip != NULL)
15705		mdi_rele_path(pip);
15706
15707	/*
15708	 * In reality, the user wants a fully valid path (one they can open)
15709	 * but this string is lacking the mount point, and the minor node.
15710	 * It would be nice if we could "figure these out" somehow
15711	 * and fill them in.  Otherwise, the userland code has to understand
15712	 * driver specific details of which minor node is the "best" or
15713	 * "right" one to expose.  (Ex: which slice is the whole disk, or
15714	 * which tape doesn't rewind)
15715	 */
15716	return (path);
15717}
15718
15719static int
15720fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15721    ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15722{
15723	int64_t reset_delay;
15724	int rval, retry = 0;
15725	struct fcp_port *pptr = fcp_dip2port(parent);
15726
15727	reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15728	    (ddi_get_lbolt64() - pptr->port_attach_time);
15729	if (reset_delay < 0) {
15730		reset_delay = 0;
15731	}
15732
15733	if (fcp_bus_config_debug) {
15734		flag |= NDI_DEVI_DEBUG;
15735	}
15736
15737	switch (op) {
15738	case BUS_CONFIG_ONE:
15739		/*
15740		 * Retry the command since we need to ensure
15741		 * the fabric devices are available for root
15742		 */
15743		while (retry++ < fcp_max_bus_config_retries) {
15744			rval =	(ndi_busop_bus_config(parent,
15745			    flag | NDI_MDI_FALLBACK, op,
15746			    arg, childp, (clock_t)reset_delay));
15747			if (rval == 0) {
15748				return (rval);
15749			}
15750		}
15751
15752		/*
15753		 * drain taskq to make sure nodes are created and then
15754		 * try again.
15755		 */
15756		taskq_wait(DEVI(parent)->devi_taskq);
15757		return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15758		    op, arg, childp, 0));
15759
15760	case BUS_CONFIG_DRIVER:
15761	case BUS_CONFIG_ALL: {
15762		/*
15763		 * delay till all devices report in (port_tmp_cnt == 0)
15764		 * or FCP_INIT_WAIT_TIMEOUT
15765		 */
15766		mutex_enter(&pptr->port_mutex);
15767		while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15768			(void) cv_timedwait(&pptr->port_config_cv,
15769			    &pptr->port_mutex,
15770			    ddi_get_lbolt() + (clock_t)reset_delay);
15771			reset_delay =
15772			    (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15773			    (ddi_get_lbolt64() - pptr->port_attach_time);
15774		}
15775		mutex_exit(&pptr->port_mutex);
15776		/* drain taskq to make sure nodes are created */
15777		taskq_wait(DEVI(parent)->devi_taskq);
15778		return (ndi_busop_bus_config(parent, flag, op,
15779		    arg, childp, 0));
15780	}
15781
15782	default:
15783		return (NDI_FAILURE);
15784	}
15785	/*NOTREACHED*/
15786}
15787
15788static int
15789fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15790    ddi_bus_config_op_t op, void *arg)
15791{
15792	if (fcp_bus_config_debug) {
15793		flag |= NDI_DEVI_DEBUG;
15794	}
15795
15796	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15797}
15798
15799
15800/*
15801 * Routine to copy GUID into the lun structure.
15802 * returns 0 if copy was successful and 1 if encountered a
15803 * failure and did not copy the guid.
15804 */
15805static int
15806fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15807{
15808
15809	int retval = 0;
15810
15811	/* add one for the null terminator */
15812	const unsigned int len = strlen(guidp) + 1;
15813
15814	if ((guidp == NULL) || (plun == NULL)) {
15815		return (1);
15816	}
15817
15818	/*
15819	 * if the plun->lun_guid already has been allocated,
15820	 * then check the size. if the size is exact, reuse
15821	 * it....if not free it an allocate the required size.
15822	 * The reallocation should NOT typically happen
15823	 * unless the GUIDs reported changes between passes.
15824	 * We free up and alloc again even if the
15825	 * size was more than required. This is due to the
15826	 * fact that the field lun_guid_size - serves
15827	 * dual role of indicating the size of the wwn
15828	 * size and ALSO the allocation size.
15829	 */
15830	if (plun->lun_guid) {
15831		if (plun->lun_guid_size != len) {
15832			/*
15833			 * free the allocated memory and
15834			 * initialize the field
15835			 * lun_guid_size to 0.
15836			 */
15837			kmem_free(plun->lun_guid, plun->lun_guid_size);
15838			plun->lun_guid = NULL;
15839			plun->lun_guid_size = 0;
15840		}
15841	}
15842	/*
15843	 * alloc only if not already done.
15844	 */
15845	if (plun->lun_guid == NULL) {
15846		plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15847		if (plun->lun_guid == NULL) {
15848			cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15849			    "Unable to allocate"
15850			    "Memory for GUID!!! size %d", len);
15851			retval = 1;
15852		} else {
15853			plun->lun_guid_size = len;
15854		}
15855	}
15856	if (plun->lun_guid) {
15857		/*
15858		 * now copy the GUID
15859		 */
15860		bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15861	}
15862	return (retval);
15863}
15864
15865/*
15866 * fcp_reconfig_wait
15867 *
15868 * Wait for a rediscovery/reconfiguration to complete before continuing.
15869 */
15870
15871static void
15872fcp_reconfig_wait(struct fcp_port *pptr)
15873{
15874	clock_t		reconfig_start, wait_timeout;
15875
15876	/*
15877	 * Quick check.	 If pptr->port_tmp_cnt is 0, there is no
15878	 * reconfiguration in progress.
15879	 */
15880
15881	mutex_enter(&pptr->port_mutex);
15882	if (pptr->port_tmp_cnt == 0) {
15883		mutex_exit(&pptr->port_mutex);
15884		return;
15885	}
15886	mutex_exit(&pptr->port_mutex);
15887
15888	/*
15889	 * If we cause a reconfig by raising power, delay until all devices
15890	 * report in (port_tmp_cnt returns to 0)
15891	 */
15892
15893	reconfig_start = ddi_get_lbolt();
15894	wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15895
15896	mutex_enter(&pptr->port_mutex);
15897
15898	while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15899	    pptr->port_tmp_cnt) {
15900
15901		(void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15902		    reconfig_start + wait_timeout);
15903	}
15904
15905	mutex_exit(&pptr->port_mutex);
15906
15907	/*
15908	 * Even if fcp_tmp_count isn't 0, continue without error.  The port
15909	 * we want may still be ok.  If not, it will error out later
15910	 */
15911}
15912
15913/*
15914 * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15915 * We rely on the fcp_global_mutex to provide protection against changes to
15916 * the fcp_lun_blacklist.
15917 *
15918 * You can describe a list of target port WWNs and LUN numbers which will
15919 * not be configured. LUN numbers will be interpreted as decimal. White
15920 * spaces and ',' can be used in the list of LUN numbers.
15921 *
15922 * To prevent LUNs 1 and 2 from being configured for target
15923 * port 510000f010fd92a1 and target port 510000e012079df1, set:
15924 *
15925 * pwwn-lun-blacklist=
15926 * "510000f010fd92a1,1,2",
15927 * "510000e012079df1,1,2";
15928 */
15929static void
15930fcp_read_blacklist(dev_info_t *dip,
15931    struct fcp_black_list_entry **pplun_blacklist) {
15932	char **prop_array	= NULL;
15933	char *curr_pwwn		= NULL;
15934	char *curr_lun		= NULL;
15935	uint32_t prop_item	= 0;
15936	int idx			= 0;
15937	int len			= 0;
15938
15939	ASSERT(mutex_owned(&fcp_global_mutex));
15940	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15941	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15942	    LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15943		return;
15944	}
15945
15946	for (idx = 0; idx < prop_item; idx++) {
15947
15948		curr_pwwn = prop_array[idx];
15949		while (*curr_pwwn == ' ') {
15950			curr_pwwn++;
15951		}
15952		if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15953			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15954			    ", please check.", curr_pwwn);
15955			continue;
15956		}
15957		if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15958		    (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15959			fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15960			    ", please check.", curr_pwwn);
15961			continue;
15962		}
15963		for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15964			if (isxdigit(curr_pwwn[len]) != TRUE) {
15965				fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15966				    "blacklist, please check.", curr_pwwn);
15967				break;
15968			}
15969		}
15970		if (len != sizeof (la_wwn_t) * 2) {
15971			continue;
15972		}
15973
15974		curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15975		*(curr_lun - 1) = '\0';
15976		fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15977	}
15978
15979	ddi_prop_free(prop_array);
15980}
15981
15982/*
15983 * Get the masking info about one remote target port designated by wwn.
15984 * Lun ids could be separated by ',' or white spaces.
15985 */
15986static void
15987fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15988    struct fcp_black_list_entry **pplun_blacklist) {
15989	int		idx			= 0;
15990	uint32_t	offset			= 0;
15991	unsigned long	lun_id			= 0;
15992	char		lunid_buf[16];
15993	char		*pend			= NULL;
15994	int		illegal_digit		= 0;
15995
15996	while (offset < strlen(curr_lun)) {
15997		while ((curr_lun[offset + idx] != ',') &&
15998		    (curr_lun[offset + idx] != '\0') &&
15999		    (curr_lun[offset + idx] != ' ')) {
16000			if (isdigit(curr_lun[offset + idx]) == 0) {
16001				illegal_digit++;
16002			}
16003			idx++;
16004		}
16005		if (illegal_digit > 0) {
16006			offset += (idx+1);	/* To the start of next lun */
16007			idx = 0;
16008			illegal_digit = 0;
16009			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16010			    "the blacklist, please check digits.",
16011			    curr_lun, curr_pwwn);
16012			continue;
16013		}
16014		if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16015			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16016			    "the blacklist, please check the length of LUN#.",
16017			    curr_lun, curr_pwwn);
16018			break;
16019		}
16020		if (idx == 0) {	/* ignore ' ' or ',' or '\0' */
16021		    offset++;
16022		    continue;
16023		}
16024
16025		bcopy(curr_lun + offset, lunid_buf, idx);
16026		lunid_buf[idx] = '\0';
16027		if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16028			fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16029		} else {
16030			fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16031			    "the blacklist, please check %s.",
16032			    curr_lun, curr_pwwn, lunid_buf);
16033		}
16034		offset += (idx+1);	/* To the start of next lun */
16035		idx = 0;
16036	}
16037}
16038
16039/*
16040 * Add one masking record
16041 */
16042static void
16043fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16044    struct fcp_black_list_entry **pplun_blacklist) {
16045	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16046	struct fcp_black_list_entry	*new_entry	= NULL;
16047	la_wwn_t			wwn;
16048
16049	fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16050	while (tmp_entry) {
16051		if ((bcmp(&tmp_entry->wwn, &wwn,
16052		    sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16053			return;
16054		}
16055
16056		tmp_entry = tmp_entry->next;
16057	}
16058
16059	/* add to black list */
16060	new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16061	    (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16062	bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16063	new_entry->lun = lun_id;
16064	new_entry->masked = 0;
16065	new_entry->next = *pplun_blacklist;
16066	*pplun_blacklist = new_entry;
16067}
16068
16069/*
16070 * Check if we should mask the specified lun of this fcp_tgt
16071 */
16072static int
16073fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16074	struct fcp_black_list_entry *remote_port;
16075
16076	remote_port = fcp_lun_blacklist;
16077	while (remote_port != NULL) {
16078		if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16079			if (remote_port->lun == lun_id) {
16080				remote_port->masked++;
16081				if (remote_port->masked == 1) {
16082					fcp_log(CE_NOTE, NULL, "LUN %d of port "
16083					    "%02x%02x%02x%02x%02x%02x%02x%02x "
16084					    "is masked due to black listing.\n",
16085					    lun_id, wwn->raw_wwn[0],
16086					    wwn->raw_wwn[1], wwn->raw_wwn[2],
16087					    wwn->raw_wwn[3], wwn->raw_wwn[4],
16088					    wwn->raw_wwn[5], wwn->raw_wwn[6],
16089					    wwn->raw_wwn[7]);
16090				}
16091				return (TRUE);
16092			}
16093		}
16094		remote_port = remote_port->next;
16095	}
16096	return (FALSE);
16097}
16098
16099/*
16100 * Release all allocated resources
16101 */
16102static void
16103fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16104	struct fcp_black_list_entry	*tmp_entry	= *pplun_blacklist;
16105	struct fcp_black_list_entry	*current_entry	= NULL;
16106
16107	ASSERT(mutex_owned(&fcp_global_mutex));
16108	/*
16109	 * Traverse all luns
16110	 */
16111	while (tmp_entry) {
16112		current_entry = tmp_entry;
16113		tmp_entry = tmp_entry->next;
16114		kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16115	}
16116	*pplun_blacklist = NULL;
16117}
16118
16119/*
16120 * In fcp module,
16121 *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16122 */
16123static struct scsi_pkt *
16124fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16125    struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16126    int flags, int (*callback)(), caddr_t arg)
16127{
16128	fcp_port_t	*pptr = ADDR2FCP(ap);
16129	fcp_pkt_t	*cmd  = NULL;
16130	fc_frame_hdr_t	*hp;
16131
16132	/*
16133	 * First step: get the packet
16134	 */
16135	if (pkt == NULL) {
16136		pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16137		    tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16138		    callback, arg);
16139		if (pkt == NULL) {
16140			return (NULL);
16141		}
16142
16143		/*
16144		 * All fields in scsi_pkt will be initialized properly or
16145		 * set to zero. We need do nothing for scsi_pkt.
16146		 */
16147		/*
16148		 * But it's our responsibility to link other related data
16149		 * structures. Their initialization will be done, just
16150		 * before the scsi_pkt will be sent to FCA.
16151		 */
16152		cmd		= PKT2CMD(pkt);
16153		cmd->cmd_pkt	= pkt;
16154		cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16155		/*
16156		 * fc_packet_t
16157		 */
16158		cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16159		cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16160		    sizeof (struct fcp_pkt));
16161		cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16162		cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16163		cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16164		cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16165		/*
16166		 * Fill in the Fabric Channel Header
16167		 */
16168		hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16169		hp->r_ctl = R_CTL_COMMAND;
16170		hp->rsvd = 0;
16171		hp->type = FC_TYPE_SCSI_FCP;
16172		hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16173		hp->seq_id = 0;
16174		hp->df_ctl  = 0;
16175		hp->seq_cnt = 0;
16176		hp->ox_id = 0xffff;
16177		hp->rx_id = 0xffff;
16178		hp->ro = 0;
16179	} else {
16180		/*
16181		 * We need think if we should reset any elements in
16182		 * related data structures.
16183		 */
16184		FCP_TRACE(fcp_logq, pptr->port_instbuf,
16185		    fcp_trace, FCP_BUF_LEVEL_6, 0,
16186		    "reusing pkt, flags %d", flags);
16187		cmd = PKT2CMD(pkt);
16188		if (cmd->cmd_fp_pkt->pkt_pd) {
16189			cmd->cmd_fp_pkt->pkt_pd = NULL;
16190		}
16191	}
16192
16193	/*
16194	 * Second step:	 dma allocation/move
16195	 */
16196	if (bp && bp->b_bcount != 0) {
16197		/*
16198		 * Mark if it's read or write
16199		 */
16200		if (bp->b_flags & B_READ) {
16201			cmd->cmd_flags |= CFLAG_IS_READ;
16202		} else {
16203			cmd->cmd_flags &= ~CFLAG_IS_READ;
16204		}
16205
16206		bp_mapin(bp);
16207		cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16208		cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16209		cmd->cmd_fp_pkt->pkt_data_resid = 0;
16210	} else {
16211		/*
16212		 * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16213		 * to send zero-length read/write.
16214		 */
16215		cmd->cmd_fp_pkt->pkt_data = NULL;
16216		cmd->cmd_fp_pkt->pkt_datalen = 0;
16217	}
16218
16219	return (pkt);
16220}
16221
16222static void
16223fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16224{
16225	fcp_port_t	*pptr = ADDR2FCP(ap);
16226
16227	/*
16228	 * First we let FCA to uninitilize private part.
16229	 */
16230	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16231	    PKT2CMD(pkt)->cmd_fp_pkt);
16232
16233	/*
16234	 * Then we uninitialize fc_packet.
16235	 */
16236
16237	/*
16238	 * Thirdly, we uninitializae fcp_pkt.
16239	 */
16240
16241	/*
16242	 * In the end, we free scsi_pkt.
16243	 */
16244	scsi_hba_pkt_free(ap, pkt);
16245}
16246
16247static int
16248fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16249{
16250	fcp_port_t	*pptr = ADDR2FCP(ap);
16251	fcp_lun_t	*plun = ADDR2LUN(ap);
16252	fcp_tgt_t	*ptgt = plun->lun_tgt;
16253	fcp_pkt_t	*cmd  = PKT2CMD(pkt);
16254	fcp_cmd_t	*fcmd = &cmd->cmd_fcp_cmd;
16255	fc_packet_t	*fpkt = cmd->cmd_fp_pkt;
16256	int		 rval;
16257
16258	fpkt->pkt_pd = ptgt->tgt_pd_handle;
16259	(void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16260
16261	/*
16262	 * Firstly, we need initialize fcp_pkt_t
16263	 * Secondly, we need initialize fcp_cmd_t.
16264	 */
16265	bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16266	fcmd->fcp_data_len = fpkt->pkt_datalen;
16267	fcmd->fcp_ent_addr = plun->lun_addr;
16268	if (pkt->pkt_flags & FLAG_HTAG) {
16269		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16270	} else if (pkt->pkt_flags & FLAG_OTAG) {
16271		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16272	} else if (pkt->pkt_flags & FLAG_STAG) {
16273		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16274	} else {
16275		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16276	}
16277
16278	if (cmd->cmd_flags & CFLAG_IS_READ) {
16279		fcmd->fcp_cntl.cntl_read_data = 1;
16280		fcmd->fcp_cntl.cntl_write_data = 0;
16281	} else {
16282		fcmd->fcp_cntl.cntl_read_data = 0;
16283		fcmd->fcp_cntl.cntl_write_data = 1;
16284	}
16285
16286	/*
16287	 * Then we need initialize fc_packet_t too.
16288	 */
16289	fpkt->pkt_timeout = pkt->pkt_time + 2;
16290	fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16291	fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16292	if (cmd->cmd_flags & CFLAG_IS_READ) {
16293		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16294	} else {
16295		fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16296	}
16297
16298	if (pkt->pkt_flags & FLAG_NOINTR) {
16299		fpkt->pkt_comp = NULL;
16300		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16301	} else {
16302		fpkt->pkt_comp = fcp_cmd_callback;
16303		fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16304		if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16305			fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16306		}
16307	}
16308
16309	/*
16310	 * Lastly, we need initialize scsi_pkt
16311	 */
16312	pkt->pkt_reason = CMD_CMPLT;
16313	pkt->pkt_state = 0;
16314	pkt->pkt_statistics = 0;
16315	pkt->pkt_resid = 0;
16316
16317	/*
16318	 * if interrupts aren't allowed (e.g. at dump time) then we'll
16319	 * have to do polled I/O
16320	 */
16321	if (pkt->pkt_flags & FLAG_NOINTR) {
16322		return (fcp_dopoll(pptr, cmd));
16323	}
16324
16325	cmd->cmd_state = FCP_PKT_ISSUED;
16326	rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16327	if (rval == FC_SUCCESS) {
16328		return (TRAN_ACCEPT);
16329	}
16330
16331	/*
16332	 * Need more consideration
16333	 *
16334	 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16335	 */
16336	cmd->cmd_state = FCP_PKT_IDLE;
16337	if (rval == FC_TRAN_BUSY) {
16338		return (TRAN_BUSY);
16339	} else {
16340		return (TRAN_FATAL_ERROR);
16341	}
16342}
16343
16344/*
16345 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16346 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16347 */
16348static void
16349fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16350{
16351	FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16352	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16353}
16354
16355/*
16356 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16357 */
16358static void
16359fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16360{
16361	FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16362	    FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16363}
16364