Home | History | Annotate | Download | only in ulp
      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 2010 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  * Fibre Channel SCSI ULP Mapping driver
     26  */
     27 
     28 #include <sys/scsi/scsi.h>
     29 #include <sys/types.h>
     30 #include <sys/varargs.h>
     31 #include <sys/devctl.h>
     32 #include <sys/thread.h>
     33 #include <sys/thread.h>
     34 #include <sys/open.h>
     35 #include <sys/file.h>
     36 #include <sys/sunndi.h>
     37 #include <sys/console.h>
     38 #include <sys/proc.h>
     39 #include <sys/time.h>
     40 #include <sys/utsname.h>
     41 #include <sys/scsi/impl/scsi_reset_notify.h>
     42 #include <sys/ndi_impldefs.h>
     43 #include <sys/byteorder.h>
     44 #include <sys/fs/dv_node.h>
     45 #include <sys/ctype.h>
     46 #include <sys/sunmdi.h>
     47 
     48 #include <sys/fibre-channel/fc.h>
     49 #include <sys/fibre-channel/impl/fc_ulpif.h>
     50 #include <sys/fibre-channel/ulp/fcpvar.h>
     51 
     52 /*
     53  * Discovery Process
     54  * =================
     55  *
     56  *    The discovery process is a major function of FCP.	 In order to help
     57  * understand that function a flow diagram is given here.  This diagram
     58  * doesn't claim to cover all the cases and the events that can occur during
     59  * the discovery process nor the subtleties of the code.  The code paths shown
     60  * are simplified.  Its purpose is to help the reader (and potentially bug
     61  * fixer) have an overall view of the logic of the code.  For that reason the
     62  * diagram covers the simple case of the line coming up cleanly or of a new
     63  * port attaching to FCP the link being up.  The reader must keep in mind
     64  * that:
     65  *
     66  *	- There are special cases where bringing devices online and offline
     67  *	  is driven by Ioctl.
     68  *
     69  *	- The behavior of the discovery process can be modified through the
     70  *	  .conf file.
     71  *
     72  *	- The line can go down and come back up at any time during the
     73  *	  discovery process which explains some of the complexity of the code.
     74  *
     75  * ............................................................................
     76  *
     77  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
     78  *
     79  *
     80  *			+-------------------------+
     81  *   fp/fctl module --->|    fcp_port_attach	  |
     82  *			+-------------------------+
     83  *	   |			     |
     84  *	   |			     |
     85  *	   |			     v
     86  *	   |		+-------------------------+
     87  *	   |		| fcp_handle_port_attach  |
     88  *	   |		+-------------------------+
     89  *	   |				|
     90  *	   |				|
     91  *	   +--------------------+	|
     92  *				|	|
     93  *				v	v
     94  *			+-------------------------+
     95  *			|   fcp_statec_callback	  |
     96  *			+-------------------------+
     97  *				    |
     98  *				    |
     99  *				    v
    100  *			+-------------------------+
    101  *			|    fcp_handle_devices	  |
    102  *			+-------------------------+
    103  *				    |
    104  *				    |
    105  *				    v
    106  *			+-------------------------+
    107  *			|   fcp_handle_mapflags	  |
    108  *			+-------------------------+
    109  *				    |
    110  *				    |
    111  *				    v
    112  *			+-------------------------+
    113  *			|     fcp_send_els	  |
    114  *			|			  |
    115  *			| PLOGI or PRLI To all the|
    116  *			| reachable devices.	  |
    117  *			+-------------------------+
    118  *
    119  *
    120  * ............................................................................
    121  *
    122  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
    123  *	   STEP 1 are called (it is actually the same function).
    124  *
    125  *
    126  *			+-------------------------+
    127  *			|    fcp_icmd_callback	  |
    128  *   fp/fctl module --->|			  |
    129  *			| callback for PLOGI and  |
    130  *			| PRLI.			  |
    131  *			+-------------------------+
    132  *				     |
    133  *				     |
    134  *	    Received PLOGI Accept   /-\	  Received PRLI Accept
    135  *		       _ _ _ _ _ _ /   \_ _ _ _ _ _
    136  *		      |		   \   /	   |
    137  *		      |		    \-/		   |
    138  *		      |				   |
    139  *		      v				   v
    140  *	+-------------------------+	+-------------------------+
    141  *	|     fcp_send_els	  |	|     fcp_send_scsi	  |
    142  *	|			  |	|			  |
    143  *	|	  PRLI		  |	|	REPORT_LUN	  |
    144  *	+-------------------------+	+-------------------------+
    145  *
    146  * ............................................................................
    147  *
    148  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
    149  *	   (It is actually the same function).
    150  *
    151  *
    152  *			    +-------------------------+
    153  *   fp/fctl module ------->|	 fcp_scsi_callback    |
    154  *			    +-------------------------+
    155  *					|
    156  *					|
    157  *					|
    158  *	Receive REPORT_LUN reply       /-\	Receive INQUIRY PAGE83 reply
    159  *		  _ _ _ _ _ _ _ _ _ _ /	  \_ _ _ _ _ _ _ _ _ _ _ _
    160  *		 |		      \	  /			  |
    161  *		 |		       \-/			  |
    162  *		 |			|			  |
    163  *		 | Receive INQUIRY reply|			  |
    164  *		 |			|			  |
    165  *		 v			v			  v
    166  * +------------------------+ +----------------------+ +----------------------+
    167  * |  fcp_handle_reportlun  | |	 fcp_handle_inquiry  | |  fcp_handle_page83   |
    168  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
    169  * +------------------------+ +----------------------+ +----------------------+
    170  *		 |			|			  |
    171  *		 |			|			  |
    172  *		 |			|			  |
    173  *		 v			v			  |
    174  *     +-----------------+	+-----------------+		  |
    175  *     |  fcp_send_scsi	 |	|  fcp_send_scsi  |		  |
    176  *     |		 |	|		  |		  |
    177  *     |     INQUIRY	 |	| INQUIRY PAGE83  |		  |
    178  *     |  (To each LUN)	 |	+-----------------+		  |
    179  *     +-----------------+					  |
    180  *								  |
    181  *								  v
    182  *						      +------------------------+
    183  *						      |	 fcp_call_finish_init  |
    184  *						      +------------------------+
    185  *								  |
    186  *								  v
    187  *						 +-----------------------------+
    188  *						 |  fcp_call_finish_init_held  |
    189  *						 +-----------------------------+
    190  *								  |
    191  *								  |
    192  *			   All LUNs scanned			 /-\
    193  *			       _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
    194  *			      |					\   /
    195  *			      |					 \-/
    196  *			      v					  |
    197  *		     +------------------+			  |
    198  *		     |	fcp_finish_tgt	|			  |
    199  *		     +------------------+			  |
    200  *			      |	  Target Not Offline and	  |
    201  *  Target Not Offline and    |	  not marked and tgt_node_state	  |
    202  *  marked		     /-\  not FCP_TGT_NODE_ON_DEMAND	  |
    203  *		_ _ _ _ _ _ /	\_ _ _ _ _ _ _ _		  |
    204  *	       |	    \	/		|		  |
    205  *	       |	     \-/		|		  |
    206  *	       v				v		  |
    207  * +----------------------------+     +-------------------+	  |
    208  * |	 fcp_offline_target	|     |	 fcp_create_luns  |	  |
    209  * |				|     +-------------------+	  |
    210  * | A structure fcp_tgt_elem	|		|		  |
    211  * | is created and queued in	|		v		  |
    212  * | the FCP port list		|     +-------------------+	  |
    213  * | port_offline_tgts.	 It	|     |	 fcp_pass_to_hp	  |	  |
    214  * | will be unqueued by the	|     |			  |	  |
    215  * | watchdog timer.		|     | Called for each	  |	  |
    216  * +----------------------------+     | LUN. Dispatches	  |	  |
    217  *		  |		      | fcp_hp_task	  |	  |
    218  *		  |		      +-------------------+	  |
    219  *		  |				|		  |
    220  *		  |				|		  |
    221  *		  |				|		  |
    222  *		  |				+---------------->|
    223  *		  |						  |
    224  *		  +---------------------------------------------->|
    225  *								  |
    226  *								  |
    227  *		All the targets (devices) have been scanned	 /-\
    228  *				_ _ _ _	_ _ _ _	_ _ _ _ _ _ _ _ /   \
    229  *			       |				\   /
    230  *			       |				 \-/
    231  *	    +-------------------------------------+		  |
    232  *	    |		fcp_finish_init		  |		  |
    233  *	    |					  |		  |
    234  *	    | Signal broadcasts the condition	  |		  |
    235  *	    | variable port_config_cv of the FCP  |		  |
    236  *	    | port.  One potential code sequence  |		  |
    237  *	    | waiting on the condition variable	  |		  |
    238  *	    | the code sequence handling	  |		  |
    239  *	    | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|		  |
    240  *	    | The other is in the function	  |		  |
    241  *	    | fcp_reconfig_wait which is called	  |		  |
    242  *	    | in the transmit path preventing IOs |		  |
    243  *	    | from going through till the disco-  |		  |
    244  *	    | very process is over.		  |		  |
    245  *	    +-------------------------------------+		  |
    246  *			       |				  |
    247  *			       |				  |
    248  *			       +--------------------------------->|
    249  *								  |
    250  *								  v
    251  *								Return
    252  *
    253  * ............................................................................
    254  *
    255  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
    256  *
    257  *
    258  *			+-------------------------+
    259  *			|      fcp_hp_task	  |
    260  *			+-------------------------+
    261  *				     |
    262  *				     |
    263  *				     v
    264  *			+-------------------------+
    265  *			|     fcp_trigger_lun	  |
    266  *			+-------------------------+
    267  *				     |
    268  *				     |
    269  *				     v
    270  *		   Bring offline    /-\	 Bring online
    271  *		  _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
    272  *		 |		   \   /		   |
    273  *		 |		    \-/			   |
    274  *		 v					   v
    275  *    +---------------------+			+-----------------------+
    276  *    |	 fcp_offline_child  |			|      fcp_get_cip	|
    277  *    +---------------------+			|			|
    278  *						| Creates a dev_info_t	|
    279  *						| or a mdi_pathinfo_t	|
    280  *						| depending on whether	|
    281  *						| mpxio is on or off.	|
    282  *						+-----------------------+
    283  *							   |
    284  *							   |
    285  *							   v
    286  *						+-----------------------+
    287  *						|  fcp_online_child	|
    288  *						|			|
    289  *						| Set device online	|
    290  *						| using NDI or MDI.	|
    291  *						+-----------------------+
    292  *
    293  * ............................................................................
    294  *
    295  * STEP 5: The watchdog timer expires.	The watch dog timer does much more that
    296  *	   what is described here.  We only show the target offline path.
    297  *
    298  *
    299  *			 +--------------------------+
    300  *			 |	  fcp_watch	    |
    301  *			 +--------------------------+
    302  *				       |
    303  *				       |
    304  *				       v
    305  *			 +--------------------------+
    306  *			 |  fcp_scan_offline_tgts   |
    307  *			 +--------------------------+
    308  *				       |
    309  *				       |
    310  *				       v
    311  *			 +--------------------------+
    312  *			 |  fcp_offline_target_now  |
    313  *			 +--------------------------+
    314  *				       |
    315  *				       |
    316  *				       v
    317  *			 +--------------------------+
    318  *			 |   fcp_offline_tgt_luns   |
    319  *			 +--------------------------+
    320  *				       |
    321  *				       |
    322  *				       v
    323  *			 +--------------------------+
    324  *			 |     fcp_offline_lun	    |
    325  *			 +--------------------------+
    326  *				       |
    327  *				       |
    328  *				       v
    329  *		     +----------------------------------+
    330  *		     |	     fcp_offline_lun_now	|
    331  *		     |					|
    332  *		     | A request (or two if mpxio) is	|
    333  *		     | sent to the hot plug task using	|
    334  *		     | a fcp_hp_elem structure.		|
    335  *		     +----------------------------------+
    336  */
    337 
    338 /*
    339  * Functions registered with DDI framework
    340  */
    341 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
    342 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
    343 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
    344 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
    345 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
    346     cred_t *credp, int *rval);
    347 
    348 /*
    349  * Functions registered with FC Transport framework
    350  */
    351 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
    352     fc_attach_cmd_t cmd,  uint32_t s_id);
    353 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
    354     fc_detach_cmd_t cmd);
    355 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
    356     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
    357     uint32_t claimed);
    358 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
    359     fc_unsol_buf_t *buf, uint32_t claimed);
    360 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
    361     fc_unsol_buf_t *buf, uint32_t claimed);
    362 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
    363     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
    364     uint32_t  dev_cnt, uint32_t port_sid);
    365 
    366 /*
    367  * Functions registered with SCSA framework
    368  */
    369 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
    370     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
    371 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
    372     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
    373 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
    374     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
    375 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
    376 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
    377 static int fcp_scsi_reset(struct scsi_address *ap, int level);
    378 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
    379 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
    380     int whom);
    381 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
    382 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
    383     void (*callback)(caddr_t), caddr_t arg);
    384 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
    385     char *name, ddi_eventcookie_t *event_cookiep);
    386 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
    387     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
    388     ddi_callback_id_t *cb_id);
    389 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
    390     ddi_callback_id_t cb_id);
    391 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
    392     ddi_eventcookie_t eventid, void *impldata);
    393 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
    394     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
    395 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
    396     ddi_bus_config_op_t op, void *arg);
    397 
    398 /*
    399  * Internal functions
    400  */
    401 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
    402     int mode, int *rval);
    403 
    404 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
    405     int mode, int *rval);
    406 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
    407     struct fcp_scsi_cmd *fscsi, int mode);
    408 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
    409     caddr_t base_addr, int mode);
    410 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
    411 
    412 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
    413     la_wwn_t *pwwn, int	*ret_val, int *fc_status, int *fc_pkt_state,
    414     int *fc_pkt_reason, int *fc_pkt_action);
    415 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
    416     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
    417 static int fcp_tgt_send_prli(struct fcp_tgt	*ptgt, int *fc_status,
    418     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
    419 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
    420 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
    421 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
    422 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
    423 
    424 static void fcp_handle_devices(struct fcp_port *pptr,
    425     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
    426     fcp_map_tag_t *map_tag, int cause);
    427 static int fcp_handle_mapflags(struct fcp_port *pptr,
    428     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
    429     int tgt_cnt, int cause);
    430 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
    431 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
    432     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
    433 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
    434     int cause);
    435 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
    436     uint32_t state);
    437 static struct fcp_port *fcp_get_port(opaque_t port_handle);
    438 static void fcp_unsol_callback(fc_packet_t *fpkt);
    439 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
    440     uchar_t r_ctl, uchar_t type);
    441 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
    442 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
    443     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
    444     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
    445 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
    446 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
    447     int nodma, int flags);
    448 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
    449 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
    450     uchar_t *wwn);
    451 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
    452     uint32_t d_id);
    453 static void fcp_icmd_callback(fc_packet_t *fpkt);
    454 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
    455     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
    456 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
    457 static void fcp_scsi_callback(fc_packet_t *fpkt);
    458 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
    459 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
    460 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
    461 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
    462     uint16_t lun_num);
    463 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
    464     int link_cnt, int tgt_cnt, int cause);
    465 static void fcp_finish_init(struct fcp_port *pptr);
    466 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
    467     int tgt_cnt, int cause);
    468 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
    469     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
    470 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
    471     int link_cnt, int tgt_cnt, int nowait, int flags);
    472 static void fcp_offline_target_now(struct fcp_port *pptr,
    473     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
    474 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
    475     int tgt_cnt, int flags);
    476 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
    477     int nowait, int flags);
    478 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
    479     int tgt_cnt);
    480 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
    481     int tgt_cnt, int flags);
    482 static void fcp_scan_offline_luns(struct fcp_port *pptr);
    483 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
    484 static void fcp_update_offline_flags(struct fcp_lun *plun);
    485 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
    486 static void fcp_abort_commands(struct fcp_pkt *head, struct
    487     fcp_port *pptr);
    488 static void fcp_cmd_callback(fc_packet_t *fpkt);
    489 static void fcp_complete_pkt(fc_packet_t *fpkt);
    490 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
    491     struct fcp_port *pptr);
    492 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
    493     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
    494 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
    495 static void fcp_dealloc_lun(struct fcp_lun *plun);
    496 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
    497     fc_portmap_t *map_entry, int link_cnt);
    498 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
    499 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
    500 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
    501     int internal);
    502 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
    503 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
    504     uint32_t s_id, int instance);
    505 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
    506     int instance);
    507 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
    508 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
    509     int);
    510 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
    511 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
    512 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
    513     int flags);
    514 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
    515 static int fcp_reset_target(struct scsi_address *ap, int level);
    516 static int fcp_commoncap(struct scsi_address *ap, char *cap,
    517     int val, int tgtonly, int doset);
    518 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
    519 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
    520 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
    521     int sleep);
    522 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
    523     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
    524 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
    525 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
    526 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
    527     int lcount, int tcount);
    528 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
    529 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
    530 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
    531     int tgt_cnt);
    532 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
    533     dev_info_t *pdip, caddr_t name);
    534 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
    535     int lcount, int tcount, int flags, int *circ);
    536 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
    537     int lcount, int tcount, int flags, int *circ);
    538 static void fcp_remove_child(struct fcp_lun *plun);
    539 static void fcp_watch(void *arg);
    540 static void fcp_check_reset_delay(struct fcp_port *pptr);
    541 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
    542     struct fcp_lun *rlun, int tgt_cnt);
    543 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
    544 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
    545     uchar_t *wwn, uint16_t lun);
    546 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
    547     struct fcp_lun *plun);
    548 static void fcp_post_callback(struct fcp_pkt *cmd);
    549 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
    550 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
    551 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
    552     child_info_t *cip);
    553 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
    554     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
    555     int tgt_cnt, int flags);
    556 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
    557     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
    558     int tgt_cnt, int flags, int wait);
    559 static void fcp_retransport_cmd(struct fcp_port *pptr,
    560     struct fcp_pkt *cmd);
    561 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
    562     uint_t statistics);
    563 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
    564 static void fcp_update_targets(struct fcp_port *pptr,
    565     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
    566 static int fcp_call_finish_init(struct fcp_port *pptr,
    567     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
    568 static int fcp_call_finish_init_held(struct fcp_port *pptr,
    569     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
    570 static void fcp_reconfigure_luns(void * tgt_handle);
    571 static void fcp_free_targets(struct fcp_port *pptr);
    572 static void fcp_free_target(struct fcp_tgt *ptgt);
    573 static int fcp_is_retryable(struct fcp_ipkt *icmd);
    574 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
    575 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
    576 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
    577 static void fcp_print_error(fc_packet_t *fpkt);
    578 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
    579     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
    580 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
    581 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
    582     uint32_t *dev_cnt);
    583 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
    584 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
    585 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
    586     struct fcp_ioctl *, struct fcp_port **);
    587 static char *fcp_get_lun_path(struct fcp_lun *plun);
    588 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
    589     int *rval);
    590 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
    591 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
    592 static char *fcp_get_lun_path(struct fcp_lun *plun);
    593 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
    594     int *rval);
    595 static void fcp_reconfig_wait(struct fcp_port *pptr);
    596 
    597 /*
    598  * New functions added for mpxio support
    599  */
    600 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
    601     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
    602 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
    603     int tcount);
    604 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
    605     dev_info_t *pdip);
    606 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
    607 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
    608 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
    609 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
    610 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
    611     int what);
    612 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
    613     fc_packet_t *fpkt);
    614 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
    615 
    616 /*
    617  * New functions added for lun masking support
    618  */
    619 static void fcp_read_blacklist(dev_info_t *dip,
    620     struct fcp_black_list_entry **pplun_blacklist);
    621 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
    622     struct fcp_black_list_entry **pplun_blacklist);
    623 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
    624     struct fcp_black_list_entry **pplun_blacklist);
    625 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
    626 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
    627 
    628 /*
    629  * New functions to support software FCA (like fcoei)
    630  */
    631 static struct scsi_pkt *fcp_pseudo_init_pkt(
    632 	struct scsi_address *ap, struct scsi_pkt *pkt,
    633 	struct buf *bp, int cmdlen, int statuslen,
    634 	int tgtlen, int flags, int (*callback)(), caddr_t arg);
    635 static void fcp_pseudo_destroy_pkt(
    636 	struct scsi_address *ap, struct scsi_pkt *pkt);
    637 static void fcp_pseudo_sync_pkt(
    638 	struct scsi_address *ap, struct scsi_pkt *pkt);
    639 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
    640 static void fcp_pseudo_dmafree(
    641 	struct scsi_address *ap, struct scsi_pkt *pkt);
    642 
    643 extern struct mod_ops	mod_driverops;
    644 /*
    645  * This variable is defined in modctl.c and set to '1' after the root driver
    646  * and fs are loaded.  It serves as an indication that the root filesystem can
    647  * be used.
    648  */
    649 extern int		modrootloaded;
    650 /*
    651  * This table contains strings associated with the SCSI sense key codes.  It
    652  * is used by FCP to print a clear explanation of the code returned in the
    653  * sense information by a device.
    654  */
    655 extern char		*sense_keys[];
    656 /*
    657  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).	It is
    658  * under this device that the paths to a physical device are created when
    659  * MPxIO is used.
    660  */
    661 extern dev_info_t	*scsi_vhci_dip;
    662 
    663 /*
    664  * Report lun processing
    665  */
    666 #define	FCP_LUN_ADDRESSING		0x80
    667 #define	FCP_PD_ADDRESSING		0x00
    668 #define	FCP_VOLUME_ADDRESSING		0x40
    669 
    670 #define	FCP_SVE_THROTTLE		0x28 /* Vicom */
    671 #define	MAX_INT_DMA			0x7fffffff
    672 /*
    673  * Property definitions
    674  */
    675 #define	NODE_WWN_PROP	(char *)fcp_node_wwn_prop
    676 #define	PORT_WWN_PROP	(char *)fcp_port_wwn_prop
    677 #define	TARGET_PROP	(char *)fcp_target_prop
    678 #define	LUN_PROP	(char *)fcp_lun_prop
    679 #define	SAM_LUN_PROP	(char *)fcp_sam_lun_prop
    680 #define	CONF_WWN_PROP	(char *)fcp_conf_wwn_prop
    681 #define	OBP_BOOT_WWN	(char *)fcp_obp_boot_wwn
    682 #define	MANUAL_CFG_ONLY	(char *)fcp_manual_config_only
    683 #define	INIT_PORT_PROP	(char *)fcp_init_port_prop
    684 #define	TGT_PORT_PROP	(char *)fcp_tgt_port_prop
    685 #define	LUN_BLACKLIST_PROP	(char *)fcp_lun_blacklist_prop
    686 /*
    687  * Short hand macros.
    688  */
    689 #define	LUN_PORT	(plun->lun_tgt->tgt_port)
    690 #define	LUN_TGT		(plun->lun_tgt)
    691 
    692 /*
    693  * Driver private macros
    694  */
    695 #define	FCP_ATOB(x)	(((x) >= '0' && (x) <= '9') ? ((x) - '0') :	\
    696 			((x) >= 'a' && (x) <= 'f') ?			\
    697 			((x) - 'a' + 10) : ((x) - 'A' + 10))
    698 
    699 #define	FCP_MAX(a, b)	((a) > (b) ? (a) : (b))
    700 
    701 #define	FCP_N_NDI_EVENTS						\
    702 	(sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
    703 
    704 #define	FCP_LINK_STATE_CHANGED(p, c)			\
    705 	((p)->port_link_cnt != (c)->ipkt_link_cnt)
    706 
    707 #define	FCP_TGT_STATE_CHANGED(t, c)			\
    708 	((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
    709 
    710 #define	FCP_STATE_CHANGED(p, t, c)		\
    711 	(FCP_TGT_STATE_CHANGED(t, c))
    712 
    713 #define	FCP_MUST_RETRY(fpkt)				\
    714 	((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||	\
    715 	(fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||	\
    716 	(fpkt)->pkt_state == FC_PKT_TRAN_BSY ||	\
    717 	(fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||	\
    718 	(fpkt)->pkt_state == FC_PKT_NPORT_BSY ||	\
    719 	(fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||	\
    720 	(fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||	\
    721 	(fpkt)->pkt_reason == FC_REASON_OFFLINE)
    722 
    723 #define	FCP_SENSE_REPORTLUN_CHANGED(es)		\
    724 	((es)->es_key == KEY_UNIT_ATTENTION &&	\
    725 	(es)->es_add_code == 0x3f &&		\
    726 	(es)->es_qual_code == 0x0e)
    727 
    728 #define	FCP_SENSE_NO_LUN(es)			\
    729 	((es)->es_key == KEY_ILLEGAL_REQUEST &&	\
    730 	(es)->es_add_code == 0x25 &&		\
    731 	(es)->es_qual_code == 0x0)
    732 
    733 #define	FCP_VERSION		"20091208-1.192"
    734 #define	FCP_NAME_VERSION	"SunFC FCP v" FCP_VERSION
    735 
    736 #define	FCP_NUM_ELEMENTS(array)			\
    737 	(sizeof (array) / sizeof ((array)[0]))
    738 
    739 /*
    740  * Debugging, Error reporting, and tracing
    741  */
    742 #define	FCP_LOG_SIZE		1024 * 1024
    743 
    744 #define	FCP_LEVEL_1		0x00001		/* attach/detach PM CPR */
    745 #define	FCP_LEVEL_2		0x00002		/* failures/Invalid data */
    746 #define	FCP_LEVEL_3		0x00004		/* state change, discovery */
    747 #define	FCP_LEVEL_4		0x00008		/* ULP messages */
    748 #define	FCP_LEVEL_5		0x00010		/* ELS/SCSI cmds */
    749 #define	FCP_LEVEL_6		0x00020		/* Transport failures */
    750 #define	FCP_LEVEL_7		0x00040
    751 #define	FCP_LEVEL_8		0x00080		/* I/O tracing */
    752 #define	FCP_LEVEL_9		0x00100		/* I/O tracing */
    753 
    754 
    755 
    756 /*
    757  * Log contents to system messages file
    758  */
    759 #define	FCP_MSG_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
    760 #define	FCP_MSG_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
    761 #define	FCP_MSG_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
    762 #define	FCP_MSG_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
    763 #define	FCP_MSG_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
    764 #define	FCP_MSG_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
    765 #define	FCP_MSG_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
    766 #define	FCP_MSG_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
    767 #define	FCP_MSG_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
    768 
    769 
    770 /*
    771  * Log contents to trace buffer
    772  */
    773 #define	FCP_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
    774 #define	FCP_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
    775 #define	FCP_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
    776 #define	FCP_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
    777 #define	FCP_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
    778 #define	FCP_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
    779 #define	FCP_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
    780 #define	FCP_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
    781 #define	FCP_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
    782 
    783 
    784 /*
    785  * Log contents to both system messages file and trace buffer
    786  */
    787 #define	FCP_MSG_BUF_LEVEL_1	(FCP_LEVEL_1 | FC_TRACE_LOG_BUF |	\
    788 				FC_TRACE_LOG_MSG)
    789 #define	FCP_MSG_BUF_LEVEL_2	(FCP_LEVEL_2 | FC_TRACE_LOG_BUF |	\
    790 				FC_TRACE_LOG_MSG)
    791 #define	FCP_MSG_BUF_LEVEL_3	(FCP_LEVEL_3 | FC_TRACE_LOG_BUF |	\
    792 				FC_TRACE_LOG_MSG)
    793 #define	FCP_MSG_BUF_LEVEL_4	(FCP_LEVEL_4 | FC_TRACE_LOG_BUF |	\
    794 				FC_TRACE_LOG_MSG)
    795 #define	FCP_MSG_BUF_LEVEL_5	(FCP_LEVEL_5 | FC_TRACE_LOG_BUF |	\
    796 				FC_TRACE_LOG_MSG)
    797 #define	FCP_MSG_BUF_LEVEL_6	(FCP_LEVEL_6 | FC_TRACE_LOG_BUF |	\
    798 				FC_TRACE_LOG_MSG)
    799 #define	FCP_MSG_BUF_LEVEL_7	(FCP_LEVEL_7 | FC_TRACE_LOG_BUF |	\
    800 				FC_TRACE_LOG_MSG)
    801 #define	FCP_MSG_BUF_LEVEL_8	(FCP_LEVEL_8 | FC_TRACE_LOG_BUF |	\
    802 				FC_TRACE_LOG_MSG)
    803 #define	FCP_MSG_BUF_LEVEL_9	(FCP_LEVEL_9 | FC_TRACE_LOG_BUF |	\
    804 				FC_TRACE_LOG_MSG)
    805 #ifdef DEBUG
    806 #define	FCP_DTRACE	fc_trace_debug
    807 #else
    808 #define	FCP_DTRACE
    809 #endif
    810 
    811 #define	FCP_TRACE	fc_trace_debug
    812 
    813 static struct cb_ops fcp_cb_ops = {
    814 	fcp_open,			/* open */
    815 	fcp_close,			/* close */
    816 	nodev,				/* strategy */
    817 	nodev,				/* print */
    818 	nodev,				/* dump */
    819 	nodev,				/* read */
    820 	nodev,				/* write */
    821 	fcp_ioctl,			/* ioctl */
    822 	nodev,				/* devmap */
    823 	nodev,				/* mmap */
    824 	nodev,				/* segmap */
    825 	nochpoll,			/* chpoll */
    826 	ddi_prop_op,			/* cb_prop_op */
    827 	0,				/* streamtab */
    828 	D_NEW | D_MP | D_HOTPLUG,	/* cb_flag */
    829 	CB_REV,				/* rev */
    830 	nodev,				/* aread */
    831 	nodev				/* awrite */
    832 };
    833 
    834 
    835 static struct dev_ops fcp_ops = {
    836 	DEVO_REV,
    837 	0,
    838 	ddi_getinfo_1to1,
    839 	nulldev,		/* identify */
    840 	nulldev,		/* probe */
    841 	fcp_attach,		/* attach and detach are mandatory */
    842 	fcp_detach,
    843 	nodev,			/* reset */
    844 	&fcp_cb_ops,		/* cb_ops */
    845 	NULL,			/* bus_ops */
    846 	NULL,			/* power */
    847 };
    848 
    849 
    850 char *fcp_version = FCP_NAME_VERSION;
    851 
    852 static struct modldrv modldrv = {
    853 	&mod_driverops,
    854 	FCP_NAME_VERSION,
    855 	&fcp_ops
    856 };
    857 
    858 
    859 static struct modlinkage modlinkage = {
    860 	MODREV_1,
    861 	&modldrv,
    862 	NULL
    863 };
    864 
    865 
    866 static fc_ulp_modinfo_t fcp_modinfo = {
    867 	&fcp_modinfo,			/* ulp_handle */
    868 	FCTL_ULP_MODREV_4,		/* ulp_rev */
    869 	FC4_SCSI_FCP,			/* ulp_type */
    870 	"fcp",				/* ulp_name */
    871 	FCP_STATEC_MASK,		/* ulp_statec_mask */
    872 	fcp_port_attach,		/* ulp_port_attach */
    873 	fcp_port_detach,		/* ulp_port_detach */
    874 	fcp_port_ioctl,			/* ulp_port_ioctl */
    875 	fcp_els_callback,		/* ulp_els_callback */
    876 	fcp_data_callback,		/* ulp_data_callback */
    877 	fcp_statec_callback		/* ulp_statec_callback */
    878 };
    879 
    880 #ifdef	DEBUG
    881 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
    882 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
    883 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
    884 				FCP_LEVEL_6 | FCP_LEVEL_7)
    885 #else
    886 #define	FCP_TRACE_DEFAULT	(FC_TRACE_LOG_MASK | FCP_LEVEL_1 |	\
    887 				FCP_LEVEL_2 | FCP_LEVEL_3 |		\
    888 				FCP_LEVEL_4 | FCP_LEVEL_5 |		\
    889 				FCP_LEVEL_6 | FCP_LEVEL_7)
    890 #endif
    891 
    892 /* FCP global variables */
    893 int			fcp_bus_config_debug = 0;
    894 static int		fcp_log_size = FCP_LOG_SIZE;
    895 static int		fcp_trace = FCP_TRACE_DEFAULT;
    896 static fc_trace_logq_t	*fcp_logq = NULL;
    897 static struct fcp_black_list_entry	*fcp_lun_blacklist = NULL;
    898 /*
    899  * The auto-configuration is set by default.  The only way of disabling it is
    900  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
    901  */
    902 static int		fcp_enable_auto_configuration = 1;
    903 static int		fcp_max_bus_config_retries	= 4;
    904 static int		fcp_lun_ready_retry = 300;
    905 /*
    906  * The value assigned to the following variable has changed several times due
    907  * to a problem with the data underruns reporting of some firmware(s).	The
    908  * current value of 50 gives a timeout value of 25 seconds for a max number
    909  * of 256 LUNs.
    910  */
    911 static int		fcp_max_target_retries = 50;
    912 /*
    913  * Watchdog variables
    914  * ------------------
    915  *
    916  * fcp_watchdog_init
    917  *
    918  *	Indicates if the watchdog timer is running or not.  This is actually
    919  *	a counter of the number of Fibre Channel ports that attached.  When
    920  *	the first port attaches the watchdog is started.  When the last port
    921  *	detaches the watchdog timer is stopped.
    922  *
    923  * fcp_watchdog_time
    924  *
    925  *	This is the watchdog clock counter.  It is incremented by
    926  *	fcp_watchdog_time each time the watchdog timer expires.
    927  *
    928  * fcp_watchdog_timeout
    929  *
    930  *	Increment value of the variable fcp_watchdog_time as well as the
    931  *	the timeout value of the watchdog timer.  The unit is 1 second.	 It
    932  *	is strange that this is not a #define	but a variable since the code
    933  *	never changes this value.  The reason why it can be said that the
    934  *	unit is 1 second is because the number of ticks for the watchdog
    935  *	timer is determined like this:
    936  *
    937  *	    fcp_watchdog_tick = fcp_watchdog_timeout *
    938  *				  drv_usectohz(1000000);
    939  *
    940  *	The value 1000000 is hard coded in the code.
    941  *
    942  * fcp_watchdog_tick
    943  *
    944  *	Watchdog timer value in ticks.
    945  */
    946 static int		fcp_watchdog_init = 0;
    947 static int		fcp_watchdog_time = 0;
    948 static int		fcp_watchdog_timeout = 1;
    949 static int		fcp_watchdog_tick;
    950 
    951 /*
    952  * fcp_offline_delay is a global variable to enable customisation of
    953  * the timeout on link offlines or RSCNs. The default value is set
    954  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
    955  * specified in FCP4 Chapter 11 (see www.t10.org).
    956  *
    957  * The variable fcp_offline_delay is specified in SECONDS.
    958  *
    959  * If we made this a static var then the user would not be able to
    960  * change it. This variable is set in fcp_attach().
    961  */
    962 unsigned int		fcp_offline_delay = FCP_OFFLINE_DELAY;
    963 
    964 static void		*fcp_softstate = NULL; /* for soft state */
    965 static uchar_t		fcp_oflag = FCP_IDLE; /* open flag */
    966 static kmutex_t		fcp_global_mutex;
    967 static kmutex_t		fcp_ioctl_mutex;
    968 static dev_info_t	*fcp_global_dip = NULL;
    969 static timeout_id_t	fcp_watchdog_id;
    970 const char		*fcp_lun_prop = "lun";
    971 const char		*fcp_sam_lun_prop = "sam-lun";
    972 const char		*fcp_target_prop = "target";
    973 /*
    974  * NOTE: consumers of "node-wwn" property include stmsboot in ON
    975  * consolidation.
    976  */
    977 const char		*fcp_node_wwn_prop = "node-wwn";
    978 const char		*fcp_port_wwn_prop = "port-wwn";
    979 const char		*fcp_conf_wwn_prop = "fc-port-wwn";
    980 const char		*fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
    981 const char		*fcp_manual_config_only = "manual_configuration_only";
    982 const char		*fcp_init_port_prop = "initiator-port";
    983 const char		*fcp_tgt_port_prop = "target-port";
    984 const char		*fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
    985 
    986 static struct fcp_port	*fcp_port_head = NULL;
    987 static ddi_eventcookie_t	fcp_insert_eid;
    988 static ddi_eventcookie_t	fcp_remove_eid;
    989 
    990 static ndi_event_definition_t	fcp_ndi_event_defs[] = {
    991 	{ FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
    992 	{ FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
    993 };
    994 
    995 /*
    996  * List of valid commands for the scsi_ioctl call
    997  */
    998 static uint8_t scsi_ioctl_list[] = {
    999 	SCMD_INQUIRY,
   1000 	SCMD_REPORT_LUN,
   1001 	SCMD_READ_CAPACITY
   1002 };
   1003 
   1004 /*
   1005  * this is used to dummy up a report lun response for cases
   1006  * where the target doesn't support it
   1007  */
   1008 static uchar_t fcp_dummy_lun[] = {
   1009 	0x00,		/* MSB length (length = no of luns * 8) */
   1010 	0x00,
   1011 	0x00,
   1012 	0x08,		/* LSB length */
   1013 	0x00,		/* MSB reserved */
   1014 	0x00,
   1015 	0x00,
   1016 	0x00,		/* LSB reserved */
   1017 	FCP_PD_ADDRESSING,
   1018 	0x00,		/* LUN is ZERO at the first level */
   1019 	0x00,
   1020 	0x00,		/* second level is zero */
   1021 	0x00,
   1022 	0x00,		/* third level is zero */
   1023 	0x00,
   1024 	0x00		/* fourth level is zero */
   1025 };
   1026 
   1027 static uchar_t fcp_alpa_to_switch[] = {
   1028 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
   1029 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
   1030 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
   1031 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
   1032 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
   1033 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
   1034 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
   1035 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
   1036 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
   1037 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
   1038 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
   1039 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
   1040 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
   1041 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
   1042 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
   1043 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
   1044 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
   1045 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
   1046 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
   1047 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
   1048 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
   1049 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
   1050 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
   1051 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   1052 };
   1053 
   1054 static caddr_t pid = "SESS01	      ";
   1055 
   1056 #if	!defined(lint)
   1057 
   1058 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
   1059     fcp_port::fcp_next fcp_watchdog_id))
   1060 
   1061 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
   1062 
   1063 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
   1064     fcp_insert_eid
   1065     fcp_remove_eid
   1066     fcp_watchdog_time))
   1067 
   1068 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
   1069     fcp_cb_ops
   1070     fcp_ops
   1071     callb_cpr))
   1072 
   1073 #endif /* lint */
   1074 
   1075 /*
   1076  * This table is used to determine whether or not it's safe to copy in
   1077  * the target node name for a lun.  Since all luns behind the same target
   1078  * have the same wwnn, only tagets that do not support multiple luns are
   1079  * eligible to be enumerated under mpxio if they aren't page83 compliant.
   1080  */
   1081 
   1082 char *fcp_symmetric_disk_table[] = {
   1083 	"SEAGATE ST",
   1084 	"IBM	 DDYFT",
   1085 	"SUNW	 SUNWGS",	/* Daktari enclosure */
   1086 	"SUN	 SENA",		/* SES device */
   1087 	"SUN	 SESS01"	/* VICOM SVE box */
   1088 };
   1089 
   1090 int fcp_symmetric_disk_table_size =
   1091 	sizeof (fcp_symmetric_disk_table)/sizeof (char *);
   1092 
   1093 /*
   1094  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
   1095  * will panic if you don't pass this in to the routine, this information.
   1096  * Need to determine what the actual impact to the system is by providing
   1097  * this information if any. Since dma allocation is done in pkt_init it may
   1098  * not have any impact. These values are straight from the Writing Device
   1099  * Driver manual.
   1100  */
   1101 static ddi_dma_attr_t pseudo_fca_dma_attr = {
   1102 	DMA_ATTR_V0,	/* ddi_dma_attr version */
   1103 	0,		/* low address */
   1104 	0xffffffff,	/* high address */
   1105 	0x00ffffff,	/* counter upper bound */
   1106 	1,		/* alignment requirements */
   1107 	0x3f,		/* burst sizes */
   1108 	1,		/* minimum DMA access */
   1109 	0xffffffff,	/* maximum DMA access */
   1110 	(1 << 24) - 1,	/* segment boundary restrictions */
   1111 	1,		/* scater/gather list length */
   1112 	512,		/* device granularity */
   1113 	0		/* DMA flags */
   1114 };
   1115 
   1116 /*
   1117  * The _init(9e) return value should be that of mod_install(9f). Under
   1118  * some circumstances, a failure may not be related mod_install(9f) and
   1119  * one would then require a return value to indicate the failure. Looking
   1120  * at mod_install(9f), it is expected to return 0 for success and non-zero
   1121  * for failure. mod_install(9f) for device drivers, further goes down the
   1122  * calling chain and ends up in ddi_installdrv(), whose return values are
   1123  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
   1124  * calling chain of mod_install(9f) which return values like EINVAL and
   1125  * in some even return -1.
   1126  *
   1127  * To work around the vagaries of the mod_install() calling chain, return
   1128  * either 0 or ENODEV depending on the success or failure of mod_install()
   1129  */
   1130 int
   1131 _init(void)
   1132 {
   1133 	int rval;
   1134 
   1135 	/*
   1136 	 * Allocate soft state and prepare to do ddi_soft_state_zalloc()
   1137 	 * before registering with the transport first.
   1138 	 */
   1139 	if (ddi_soft_state_init(&fcp_softstate,
   1140 	    sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
   1141 		return (EINVAL);
   1142 	}
   1143 
   1144 	mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
   1145 	mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
   1146 
   1147 	if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
   1148 		cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
   1149 		mutex_destroy(&fcp_global_mutex);
   1150 		mutex_destroy(&fcp_ioctl_mutex);
   1151 		ddi_soft_state_fini(&fcp_softstate);
   1152 		return (ENODEV);
   1153 	}
   1154 
   1155 	fcp_logq = fc_trace_alloc_logq(fcp_log_size);
   1156 
   1157 	if ((rval = mod_install(&modlinkage)) != 0) {
   1158 		fc_trace_free_logq(fcp_logq);
   1159 		(void) fc_ulp_remove(&fcp_modinfo);
   1160 		mutex_destroy(&fcp_global_mutex);
   1161 		mutex_destroy(&fcp_ioctl_mutex);
   1162 		ddi_soft_state_fini(&fcp_softstate);
   1163 		rval = ENODEV;
   1164 	}
   1165 
   1166 	return (rval);
   1167 }
   1168 
   1169 
   1170 /*
   1171  * the system is done with us as a driver, so clean up
   1172  */
   1173 int
   1174 _fini(void)
   1175 {
   1176 	int rval;
   1177 
   1178 	/*
   1179 	 * don't start cleaning up until we know that the module remove
   1180 	 * has worked  -- if this works, then we know that each instance
   1181 	 * has successfully been DDI_DETACHed
   1182 	 */
   1183 	if ((rval = mod_remove(&modlinkage)) != 0) {
   1184 		return (rval);
   1185 	}
   1186 
   1187 	(void) fc_ulp_remove(&fcp_modinfo);
   1188 
   1189 	ddi_soft_state_fini(&fcp_softstate);
   1190 	mutex_destroy(&fcp_global_mutex);
   1191 	mutex_destroy(&fcp_ioctl_mutex);
   1192 	fc_trace_free_logq(fcp_logq);
   1193 
   1194 	return (rval);
   1195 }
   1196 
   1197 
   1198 int
   1199 _info(struct modinfo *modinfop)
   1200 {
   1201 	return (mod_info(&modlinkage, modinfop));
   1202 }
   1203 
   1204 
   1205 /*
   1206  * attach the module
   1207  */
   1208 static int
   1209 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
   1210 {
   1211 	int rval = DDI_SUCCESS;
   1212 
   1213 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
   1214 	    FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
   1215 
   1216 	if (cmd == DDI_ATTACH) {
   1217 		/* The FCP pseudo device is created here. */
   1218 		mutex_enter(&fcp_global_mutex);
   1219 		fcp_global_dip = devi;
   1220 		mutex_exit(&fcp_global_mutex);
   1221 
   1222 		if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
   1223 		    0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
   1224 			ddi_report_dev(fcp_global_dip);
   1225 		} else {
   1226 			cmn_err(CE_WARN, "FCP: Cannot create minor node");
   1227 			mutex_enter(&fcp_global_mutex);
   1228 			fcp_global_dip = NULL;
   1229 			mutex_exit(&fcp_global_mutex);
   1230 
   1231 			rval = DDI_FAILURE;
   1232 		}
   1233 		/*
   1234 		 * We check the fcp_offline_delay property at this
   1235 		 * point. This variable is global for the driver,
   1236 		 * not specific to an instance.
   1237 		 *
   1238 		 * We do not recommend setting the value to less
   1239 		 * than 10 seconds (RA_TOV_els), or greater than
   1240 		 * 60 seconds.
   1241 		 */
   1242 		fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
   1243 		    devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
   1244 		    "fcp_offline_delay", FCP_OFFLINE_DELAY);
   1245 		if ((fcp_offline_delay < 10) ||
   1246 		    (fcp_offline_delay > 60)) {
   1247 			cmn_err(CE_WARN, "Setting fcp_offline_delay "
   1248 			    "to %d second(s). This is outside the "
   1249 			    "recommended range of 10..60 seconds.",
   1250 			    fcp_offline_delay);
   1251 		}
   1252 	}
   1253 
   1254 	return (rval);
   1255 }
   1256 
   1257 
   1258 /*ARGSUSED*/
   1259 static int
   1260 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
   1261 {
   1262 	int	res = DDI_SUCCESS;
   1263 
   1264 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
   1265 	    FCP_BUF_LEVEL_8, 0,	 "module detach: cmd=0x%x", cmd);
   1266 
   1267 	if (cmd == DDI_DETACH) {
   1268 		/*
   1269 		 * Check if there are active ports/threads. If there
   1270 		 * are any, we will fail, else we will succeed (there
   1271 		 * should not be much to clean up)
   1272 		 */
   1273 		mutex_enter(&fcp_global_mutex);
   1274 		FCP_DTRACE(fcp_logq, "fcp",
   1275 		    fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
   1276 		    (void *) fcp_port_head);
   1277 
   1278 		if (fcp_port_head == NULL) {
   1279 			ddi_remove_minor_node(fcp_global_dip, NULL);
   1280 			fcp_global_dip = NULL;
   1281 			mutex_exit(&fcp_global_mutex);
   1282 		} else {
   1283 			mutex_exit(&fcp_global_mutex);
   1284 			res = DDI_FAILURE;
   1285 		}
   1286 	}
   1287 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
   1288 	    FCP_BUF_LEVEL_8, 0,	 "module detach returning %d", res);
   1289 
   1290 	return (res);
   1291 }
   1292 
   1293 
   1294 /* ARGSUSED */
   1295 static int
   1296 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
   1297 {
   1298 	if (otype != OTYP_CHR) {
   1299 		return (EINVAL);
   1300 	}
   1301 
   1302 	/*
   1303 	 * Allow only root to talk;
   1304 	 */
   1305 	if (drv_priv(credp)) {
   1306 		return (EPERM);
   1307 	}
   1308 
   1309 	mutex_enter(&fcp_global_mutex);
   1310 	if (fcp_oflag & FCP_EXCL) {
   1311 		mutex_exit(&fcp_global_mutex);
   1312 		return (EBUSY);
   1313 	}
   1314 
   1315 	if (flag & FEXCL) {
   1316 		if (fcp_oflag & FCP_OPEN) {
   1317 			mutex_exit(&fcp_global_mutex);
   1318 			return (EBUSY);
   1319 		}
   1320 		fcp_oflag |= FCP_EXCL;
   1321 	}
   1322 	fcp_oflag |= FCP_OPEN;
   1323 	mutex_exit(&fcp_global_mutex);
   1324 
   1325 	return (0);
   1326 }
   1327 
   1328 
   1329 /* ARGSUSED */
   1330 static int
   1331 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
   1332 {
   1333 	if (otype != OTYP_CHR) {
   1334 		return (EINVAL);
   1335 	}
   1336 
   1337 	mutex_enter(&fcp_global_mutex);
   1338 	if (!(fcp_oflag & FCP_OPEN)) {
   1339 		mutex_exit(&fcp_global_mutex);
   1340 		return (ENODEV);
   1341 	}
   1342 	fcp_oflag = FCP_IDLE;
   1343 	mutex_exit(&fcp_global_mutex);
   1344 
   1345 	return (0);
   1346 }
   1347 
   1348 
   1349 /*
   1350  * fcp_ioctl
   1351  *	Entry point for the FCP ioctls
   1352  *
   1353  * Input:
   1354  *	See ioctl(9E)
   1355  *
   1356  * Output:
   1357  *	See ioctl(9E)
   1358  *
   1359  * Returns:
   1360  *	See ioctl(9E)
   1361  *
   1362  * Context:
   1363  *	Kernel context.
   1364  */
   1365 /* ARGSUSED */
   1366 static int
   1367 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
   1368     int *rval)
   1369 {
   1370 	int			ret = 0;
   1371 
   1372 	mutex_enter(&fcp_global_mutex);
   1373 	if (!(fcp_oflag & FCP_OPEN)) {
   1374 		mutex_exit(&fcp_global_mutex);
   1375 		return (ENXIO);
   1376 	}
   1377 	mutex_exit(&fcp_global_mutex);
   1378 
   1379 	switch (cmd) {
   1380 	case FCP_TGT_INQUIRY:
   1381 	case FCP_TGT_CREATE:
   1382 	case FCP_TGT_DELETE:
   1383 		ret = fcp_setup_device_data_ioctl(cmd,
   1384 		    (struct fcp_ioctl *)data, mode, rval);
   1385 		break;
   1386 
   1387 	case FCP_TGT_SEND_SCSI:
   1388 		mutex_enter(&fcp_ioctl_mutex);
   1389 		ret = fcp_setup_scsi_ioctl(
   1390 		    (struct fcp_scsi_cmd *)data, mode, rval);
   1391 		mutex_exit(&fcp_ioctl_mutex);
   1392 		break;
   1393 
   1394 	case FCP_STATE_COUNT:
   1395 		ret = fcp_get_statec_count((struct fcp_ioctl *)data,
   1396 		    mode, rval);
   1397 		break;
   1398 	case FCP_GET_TARGET_MAPPINGS:
   1399 		ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
   1400 		    mode, rval);
   1401 		break;
   1402 	default:
   1403 		fcp_log(CE_WARN, NULL,
   1404 		    "!Invalid ioctl opcode = 0x%x", cmd);
   1405 		ret	= EINVAL;
   1406 	}
   1407 
   1408 	return (ret);
   1409 }
   1410 
   1411 
   1412 /*
   1413  * fcp_setup_device_data_ioctl
   1414  *	Setup handler for the "device data" style of
   1415  *	ioctl for FCP.	See "fcp_util.h" for data structure
   1416  *	definition.
   1417  *
   1418  * Input:
   1419  *	cmd	= FCP ioctl command
   1420  *	data	= ioctl data
   1421  *	mode	= See ioctl(9E)
   1422  *
   1423  * Output:
   1424  *	data	= ioctl data
   1425  *	rval	= return value - see ioctl(9E)
   1426  *
   1427  * Returns:
   1428  *	See ioctl(9E)
   1429  *
   1430  * Context:
   1431  *	Kernel context.
   1432  */
   1433 /* ARGSUSED */
   1434 static int
   1435 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
   1436     int *rval)
   1437 {
   1438 	struct fcp_port	*pptr;
   1439 	struct	device_data	*dev_data;
   1440 	uint32_t		link_cnt;
   1441 	la_wwn_t		*wwn_ptr = NULL;
   1442 	struct fcp_tgt		*ptgt = NULL;
   1443 	struct fcp_lun		*plun = NULL;
   1444 	int			i, error;
   1445 	struct fcp_ioctl	fioctl;
   1446 
   1447 #ifdef	_MULTI_DATAMODEL
   1448 	switch (ddi_model_convert_from(mode & FMODELS)) {
   1449 	case DDI_MODEL_ILP32: {
   1450 		struct fcp32_ioctl f32_ioctl;
   1451 
   1452 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
   1453 		    sizeof (struct fcp32_ioctl), mode)) {
   1454 			return (EFAULT);
   1455 		}
   1456 		fioctl.fp_minor = f32_ioctl.fp_minor;
   1457 		fioctl.listlen = f32_ioctl.listlen;
   1458 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
   1459 		break;
   1460 	}
   1461 	case DDI_MODEL_NONE:
   1462 		if (ddi_copyin((void *)data, (void *)&fioctl,
   1463 		    sizeof (struct fcp_ioctl), mode)) {
   1464 			return (EFAULT);
   1465 		}
   1466 		break;
   1467 	}
   1468 
   1469 #else	/* _MULTI_DATAMODEL */
   1470 	if (ddi_copyin((void *)data, (void *)&fioctl,
   1471 	    sizeof (struct fcp_ioctl), mode)) {
   1472 		return (EFAULT);
   1473 	}
   1474 #endif	/* _MULTI_DATAMODEL */
   1475 
   1476 	/*
   1477 	 * Right now we can assume that the minor number matches with
   1478 	 * this instance of fp. If this changes we will need to
   1479 	 * revisit this logic.
   1480 	 */
   1481 	mutex_enter(&fcp_global_mutex);
   1482 	pptr = fcp_port_head;
   1483 	while (pptr) {
   1484 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
   1485 			break;
   1486 		} else {
   1487 			pptr = pptr->port_next;
   1488 		}
   1489 	}
   1490 	mutex_exit(&fcp_global_mutex);
   1491 	if (pptr == NULL) {
   1492 		return (ENXIO);
   1493 	}
   1494 	mutex_enter(&pptr->port_mutex);
   1495 
   1496 
   1497 	if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
   1498 	    fioctl.listlen, KM_NOSLEEP)) == NULL) {
   1499 		mutex_exit(&pptr->port_mutex);
   1500 		return (ENOMEM);
   1501 	}
   1502 
   1503 	if (ddi_copyin(fioctl.list, dev_data,
   1504 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
   1505 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
   1506 		mutex_exit(&pptr->port_mutex);
   1507 		return (EFAULT);
   1508 	}
   1509 	link_cnt = pptr->port_link_cnt;
   1510 
   1511 	if (cmd == FCP_TGT_INQUIRY) {
   1512 		wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
   1513 		if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
   1514 		    sizeof (wwn_ptr->raw_wwn)) == 0) {
   1515 			/* This ioctl is requesting INQ info of local HBA */
   1516 			mutex_exit(&pptr->port_mutex);
   1517 			dev_data[0].dev0_type = DTYPE_UNKNOWN;
   1518 			dev_data[0].dev_status = 0;
   1519 			if (ddi_copyout(dev_data, fioctl.list,
   1520 			    (sizeof (struct device_data)) * fioctl.listlen,
   1521 			    mode)) {
   1522 				kmem_free(dev_data,
   1523 				    sizeof (*dev_data) * fioctl.listlen);
   1524 				return (EFAULT);
   1525 			}
   1526 			kmem_free(dev_data,
   1527 			    sizeof (*dev_data) * fioctl.listlen);
   1528 #ifdef	_MULTI_DATAMODEL
   1529 			switch (ddi_model_convert_from(mode & FMODELS)) {
   1530 			case DDI_MODEL_ILP32: {
   1531 				struct fcp32_ioctl f32_ioctl;
   1532 				f32_ioctl.fp_minor = fioctl.fp_minor;
   1533 				f32_ioctl.listlen = fioctl.listlen;
   1534 				f32_ioctl.list = (caddr32_t)(long)fioctl.list;
   1535 				if (ddi_copyout((void *)&f32_ioctl,
   1536 				    (void *)data,
   1537 				    sizeof (struct fcp32_ioctl), mode)) {
   1538 					return (EFAULT);
   1539 				}
   1540 				break;
   1541 			}
   1542 			case DDI_MODEL_NONE:
   1543 				if (ddi_copyout((void *)&fioctl, (void *)data,
   1544 				    sizeof (struct fcp_ioctl), mode)) {
   1545 					return (EFAULT);
   1546 				}
   1547 				break;
   1548 			}
   1549 #else	/* _MULTI_DATAMODEL */
   1550 			if (ddi_copyout((void *)&fioctl, (void *)data,
   1551 			    sizeof (struct fcp_ioctl), mode)) {
   1552 				return (EFAULT);
   1553 			}
   1554 #endif	/* _MULTI_DATAMODEL */
   1555 			return (0);
   1556 		}
   1557 	}
   1558 
   1559 	if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
   1560 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
   1561 		mutex_exit(&pptr->port_mutex);
   1562 		return (ENXIO);
   1563 	}
   1564 
   1565 	for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
   1566 	    i++) {
   1567 		wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
   1568 
   1569 		dev_data[i].dev0_type = DTYPE_UNKNOWN;
   1570 
   1571 
   1572 		dev_data[i].dev_status = ENXIO;
   1573 
   1574 		if ((ptgt = fcp_lookup_target(pptr,
   1575 		    (uchar_t *)wwn_ptr)) == NULL) {
   1576 			mutex_exit(&pptr->port_mutex);
   1577 			if (fc_ulp_get_remote_port(pptr->port_fp_handle,
   1578 			    wwn_ptr, &error, 0) == NULL) {
   1579 				dev_data[i].dev_status = ENODEV;
   1580 				mutex_enter(&pptr->port_mutex);
   1581 				continue;
   1582 			} else {
   1583 
   1584 				dev_data[i].dev_status = EAGAIN;
   1585 
   1586 				mutex_enter(&pptr->port_mutex);
   1587 				continue;
   1588 			}
   1589 		} else {
   1590 			mutex_enter(&ptgt->tgt_mutex);
   1591 			if (ptgt->tgt_state & (FCP_TGT_MARK |
   1592 			    FCP_TGT_BUSY)) {
   1593 				dev_data[i].dev_status = EAGAIN;
   1594 				mutex_exit(&ptgt->tgt_mutex);
   1595 				continue;
   1596 			}
   1597 
   1598 			if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
   1599 				if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
   1600 					dev_data[i].dev_status = ENOTSUP;
   1601 				} else {
   1602 					dev_data[i].dev_status = ENXIO;
   1603 				}
   1604 				mutex_exit(&ptgt->tgt_mutex);
   1605 				continue;
   1606 			}
   1607 
   1608 			switch (cmd) {
   1609 			case FCP_TGT_INQUIRY:
   1610 				/*
   1611 				 * The reason we give device type of
   1612 				 * lun 0 only even though in some
   1613 				 * cases(like maxstrat) lun 0 device
   1614 				 * type may be 0x3f(invalid) is that
   1615 				 * for bridge boxes target will appear
   1616 				 * as luns and the first lun could be
   1617 				 * a device that utility may not care
   1618 				 * about (like a tape device).
   1619 				 */
   1620 				dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
   1621 				dev_data[i].dev_status = 0;
   1622 				mutex_exit(&ptgt->tgt_mutex);
   1623 
   1624 				if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
   1625 					dev_data[i].dev0_type = DTYPE_UNKNOWN;
   1626 				} else {
   1627 					dev_data[i].dev0_type = plun->lun_type;
   1628 				}
   1629 				mutex_enter(&ptgt->tgt_mutex);
   1630 				break;
   1631 
   1632 			case FCP_TGT_CREATE:
   1633 				mutex_exit(&ptgt->tgt_mutex);
   1634 				mutex_exit(&pptr->port_mutex);
   1635 
   1636 				/*
   1637 				 * serialize state change call backs.
   1638 				 * only one call back will be handled
   1639 				 * at a time.
   1640 				 */
   1641 				mutex_enter(&fcp_global_mutex);
   1642 				if (fcp_oflag & FCP_BUSY) {
   1643 					mutex_exit(&fcp_global_mutex);
   1644 					if (dev_data) {
   1645 						kmem_free(dev_data,
   1646 						    sizeof (*dev_data) *
   1647 						    fioctl.listlen);
   1648 					}
   1649 					return (EBUSY);
   1650 				}
   1651 				fcp_oflag |= FCP_BUSY;
   1652 				mutex_exit(&fcp_global_mutex);
   1653 
   1654 				dev_data[i].dev_status =
   1655 				    fcp_create_on_demand(pptr,
   1656 				    wwn_ptr->raw_wwn);
   1657 
   1658 				if (dev_data[i].dev_status != 0) {
   1659 					char	buf[25];
   1660 
   1661 					for (i = 0; i < FC_WWN_SIZE; i++) {
   1662 						(void) sprintf(&buf[i << 1],
   1663 						    "%02x",
   1664 						    wwn_ptr->raw_wwn[i]);
   1665 					}
   1666 
   1667 					fcp_log(CE_WARN, pptr->port_dip,
   1668 					    "!Failed to create nodes for"
   1669 					    " pwwn=%s; error=%x", buf,
   1670 					    dev_data[i].dev_status);
   1671 				}
   1672 
   1673 				/* allow state change call backs again */
   1674 				mutex_enter(&fcp_global_mutex);
   1675 				fcp_oflag &= ~FCP_BUSY;
   1676 				mutex_exit(&fcp_global_mutex);
   1677 
   1678 				mutex_enter(&pptr->port_mutex);
   1679 				mutex_enter(&ptgt->tgt_mutex);
   1680 
   1681 				break;
   1682 
   1683 			case FCP_TGT_DELETE:
   1684 				break;
   1685 
   1686 			default:
   1687 				fcp_log(CE_WARN, pptr->port_dip,
   1688 				    "!Invalid device data ioctl "
   1689 				    "opcode = 0x%x", cmd);
   1690 			}
   1691 			mutex_exit(&ptgt->tgt_mutex);
   1692 		}
   1693 	}
   1694 	mutex_exit(&pptr->port_mutex);
   1695 
   1696 	if (ddi_copyout(dev_data, fioctl.list,
   1697 	    (sizeof (struct device_data)) * fioctl.listlen, mode)) {
   1698 		kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
   1699 		return (EFAULT);
   1700 	}
   1701 	kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
   1702 
   1703 #ifdef	_MULTI_DATAMODEL
   1704 	switch (ddi_model_convert_from(mode & FMODELS)) {
   1705 	case DDI_MODEL_ILP32: {
   1706 		struct fcp32_ioctl f32_ioctl;
   1707 
   1708 		f32_ioctl.fp_minor = fioctl.fp_minor;
   1709 		f32_ioctl.listlen = fioctl.listlen;
   1710 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
   1711 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
   1712 		    sizeof (struct fcp32_ioctl), mode)) {
   1713 			return (EFAULT);
   1714 		}
   1715 		break;
   1716 	}
   1717 	case DDI_MODEL_NONE:
   1718 		if (ddi_copyout((void *)&fioctl, (void *)data,
   1719 		    sizeof (struct fcp_ioctl), mode)) {
   1720 			return (EFAULT);
   1721 		}
   1722 		break;
   1723 	}
   1724 #else	/* _MULTI_DATAMODEL */
   1725 
   1726 	if (ddi_copyout((void *)&fioctl, (void *)data,
   1727 	    sizeof (struct fcp_ioctl), mode)) {
   1728 		return (EFAULT);
   1729 	}
   1730 #endif	/* _MULTI_DATAMODEL */
   1731 
   1732 	return (0);
   1733 }
   1734 
   1735 /*
   1736  * Fetch the target mappings (path, etc.) for all LUNs
   1737  * on this port.
   1738  */
   1739 /* ARGSUSED */
   1740 static int
   1741 fcp_get_target_mappings(struct fcp_ioctl *data,
   1742     int mode, int *rval)
   1743 {
   1744 	struct fcp_port	    *pptr;
   1745 	fc_hba_target_mappings_t    *mappings;
   1746 	fc_hba_mapping_entry_t	    *map;
   1747 	struct fcp_tgt	    *ptgt = NULL;
   1748 	struct fcp_lun	    *plun = NULL;
   1749 	int			    i, mapIndex, mappingSize;
   1750 	int			    listlen;
   1751 	struct fcp_ioctl	    fioctl;
   1752 	char			    *path;
   1753 	fcp_ent_addr_t		    sam_lun_addr;
   1754 
   1755 #ifdef	_MULTI_DATAMODEL
   1756 	switch (ddi_model_convert_from(mode & FMODELS)) {
   1757 	case DDI_MODEL_ILP32: {
   1758 		struct fcp32_ioctl f32_ioctl;
   1759 
   1760 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
   1761 		    sizeof (struct fcp32_ioctl), mode)) {
   1762 			return (EFAULT);
   1763 		}
   1764 		fioctl.fp_minor = f32_ioctl.fp_minor;
   1765 		fioctl.listlen = f32_ioctl.listlen;
   1766 		fioctl.list = (caddr_t)(long)f32_ioctl.list;
   1767 		break;
   1768 	}
   1769 	case DDI_MODEL_NONE:
   1770 		if (ddi_copyin((void *)data, (void *)&fioctl,
   1771 		    sizeof (struct fcp_ioctl), mode)) {
   1772 			return (EFAULT);
   1773 		}
   1774 		break;
   1775 	}
   1776 
   1777 #else	/* _MULTI_DATAMODEL */
   1778 	if (ddi_copyin((void *)data, (void *)&fioctl,
   1779 	    sizeof (struct fcp_ioctl), mode)) {
   1780 		return (EFAULT);
   1781 	}
   1782 #endif	/* _MULTI_DATAMODEL */
   1783 
   1784 	/*
   1785 	 * Right now we can assume that the minor number matches with
   1786 	 * this instance of fp. If this changes we will need to
   1787 	 * revisit this logic.
   1788 	 */
   1789 	mutex_enter(&fcp_global_mutex);
   1790 	pptr = fcp_port_head;
   1791 	while (pptr) {
   1792 		if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
   1793 			break;
   1794 		} else {
   1795 			pptr = pptr->port_next;
   1796 		}
   1797 	}
   1798 	mutex_exit(&fcp_global_mutex);
   1799 	if (pptr == NULL) {
   1800 		cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
   1801 		    fioctl.fp_minor);
   1802 		return (ENXIO);
   1803 	}
   1804 
   1805 
   1806 	/* We use listlen to show the total buffer size */
   1807 	mappingSize = fioctl.listlen;
   1808 
   1809 	/* Now calculate how many mapping entries will fit */
   1810 	listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
   1811 	    - sizeof (fc_hba_target_mappings_t);
   1812 	if (listlen <= 0) {
   1813 		cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
   1814 		return (ENXIO);
   1815 	}
   1816 	listlen = listlen / sizeof (fc_hba_mapping_entry_t);
   1817 
   1818 	if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
   1819 		return (ENOMEM);
   1820 	}
   1821 	mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
   1822 
   1823 	/* Now get to work */
   1824 	mapIndex = 0;
   1825 
   1826 	mutex_enter(&pptr->port_mutex);
   1827 	/* Loop through all targets on this port */
   1828 	for (i = 0; i < FCP_NUM_HASH; i++) {
   1829 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
   1830 		    ptgt = ptgt->tgt_next) {
   1831 
   1832 			mutex_enter(&ptgt->tgt_mutex);
   1833 
   1834 			/* Loop through all LUNs on this target */
   1835 			for (plun = ptgt->tgt_lun; plun != NULL;
   1836 			    plun = plun->lun_next) {
   1837 				if (plun->lun_state & FCP_LUN_OFFLINE) {
   1838 					continue;
   1839 				}
   1840 
   1841 				path = fcp_get_lun_path(plun);
   1842 				if (path == NULL) {
   1843 					continue;
   1844 				}
   1845 
   1846 				if (mapIndex >= listlen) {
   1847 					mapIndex ++;
   1848 					kmem_free(path, MAXPATHLEN);
   1849 					continue;
   1850 				}
   1851 				map = &mappings->entries[mapIndex++];
   1852 				bcopy(path, map->targetDriver,
   1853 				    sizeof (map->targetDriver));
   1854 				map->d_id = ptgt->tgt_d_id;
   1855 				map->busNumber = 0;
   1856 				map->targetNumber = ptgt->tgt_d_id;
   1857 				map->osLUN = plun->lun_num;
   1858 
   1859 				/*
   1860 				 * We had swapped lun when we stored it in
   1861 				 * lun_addr. We need to swap it back before
   1862 				 * returning it to user land
   1863 				 */
   1864 
   1865 				sam_lun_addr.ent_addr_0 =
   1866 				    BE_16(plun->lun_addr.ent_addr_0);
   1867 				sam_lun_addr.ent_addr_1 =
   1868 				    BE_16(plun->lun_addr.ent_addr_1);
   1869 				sam_lun_addr.ent_addr_2 =
   1870 				    BE_16(plun->lun_addr.ent_addr_2);
   1871 				sam_lun_addr.ent_addr_3 =
   1872 				    BE_16(plun->lun_addr.ent_addr_3);
   1873 
   1874 				bcopy(&sam_lun_addr, &map->samLUN,
   1875 				    FCP_LUN_SIZE);
   1876 				bcopy(ptgt->tgt_node_wwn.raw_wwn,
   1877 				    map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
   1878 				bcopy(ptgt->tgt_port_wwn.raw_wwn,
   1879 				    map->PortWWN.raw_wwn, sizeof (la_wwn_t));
   1880 
   1881 				if (plun->lun_guid) {
   1882 
   1883 					/* convert ascii wwn to bytes */
   1884 					fcp_ascii_to_wwn(plun->lun_guid,
   1885 					    map->guid, sizeof (map->guid));
   1886 
   1887 					if ((sizeof (map->guid)) <
   1888 					    plun->lun_guid_size / 2) {
   1889 						cmn_err(CE_WARN,
   1890 						    "fcp_get_target_mappings:"
   1891 						    "guid copy space "
   1892 						    "insufficient."
   1893 						    "Copy Truncation - "
   1894 						    "available %d; need %d",
   1895 						    (int)sizeof (map->guid),
   1896 						    (int)
   1897 						    plun->lun_guid_size / 2);
   1898 					}
   1899 				}
   1900 				kmem_free(path, MAXPATHLEN);
   1901 			}
   1902 			mutex_exit(&ptgt->tgt_mutex);
   1903 		}
   1904 	}
   1905 	mutex_exit(&pptr->port_mutex);
   1906 	mappings->numLuns = mapIndex;
   1907 
   1908 	if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
   1909 		kmem_free(mappings, mappingSize);
   1910 		return (EFAULT);
   1911 	}
   1912 	kmem_free(mappings, mappingSize);
   1913 
   1914 #ifdef	_MULTI_DATAMODEL
   1915 	switch (ddi_model_convert_from(mode & FMODELS)) {
   1916 	case DDI_MODEL_ILP32: {
   1917 		struct fcp32_ioctl f32_ioctl;
   1918 
   1919 		f32_ioctl.fp_minor = fioctl.fp_minor;
   1920 		f32_ioctl.listlen = fioctl.listlen;
   1921 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
   1922 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
   1923 		    sizeof (struct fcp32_ioctl), mode)) {
   1924 			return (EFAULT);
   1925 		}
   1926 		break;
   1927 	}
   1928 	case DDI_MODEL_NONE:
   1929 		if (ddi_copyout((void *)&fioctl, (void *)data,
   1930 		    sizeof (struct fcp_ioctl), mode)) {
   1931 			return (EFAULT);
   1932 		}
   1933 		break;
   1934 	}
   1935 #else	/* _MULTI_DATAMODEL */
   1936 
   1937 	if (ddi_copyout((void *)&fioctl, (void *)data,
   1938 	    sizeof (struct fcp_ioctl), mode)) {
   1939 		return (EFAULT);
   1940 	}
   1941 #endif	/* _MULTI_DATAMODEL */
   1942 
   1943 	return (0);
   1944 }
   1945 
   1946 /*
   1947  * fcp_setup_scsi_ioctl
   1948  *	Setup handler for the "scsi passthru" style of
   1949  *	ioctl for FCP.	See "fcp_util.h" for data structure
   1950  *	definition.
   1951  *
   1952  * Input:
   1953  *	u_fscsi	= ioctl data (user address space)
   1954  *	mode	= See ioctl(9E)
   1955  *
   1956  * Output:
   1957  *	u_fscsi	= ioctl data (user address space)
   1958  *	rval	= return value - see ioctl(9E)
   1959  *
   1960  * Returns:
   1961  *	0	= OK
   1962  *	EAGAIN	= See errno.h
   1963  *	EBUSY	= See errno.h
   1964  *	EFAULT	= See errno.h
   1965  *	EINTR	= See errno.h
   1966  *	EINVAL	= See errno.h
   1967  *	EIO	= See errno.h
   1968  *	ENOMEM	= See errno.h
   1969  *	ENXIO	= See errno.h
   1970  *
   1971  * Context:
   1972  *	Kernel context.
   1973  */
   1974 /* ARGSUSED */
   1975 static int
   1976 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
   1977     int mode, int *rval)
   1978 {
   1979 	int			ret		= 0;
   1980 	int			temp_ret;
   1981 	caddr_t			k_cdbbufaddr	= NULL;
   1982 	caddr_t			k_bufaddr	= NULL;
   1983 	caddr_t			k_rqbufaddr	= NULL;
   1984 	caddr_t			u_cdbbufaddr;
   1985 	caddr_t			u_bufaddr;
   1986 	caddr_t			u_rqbufaddr;
   1987 	struct fcp_scsi_cmd	k_fscsi;
   1988 
   1989 	/*
   1990 	 * Get fcp_scsi_cmd array element from user address space
   1991 	 */
   1992 	if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
   1993 	    != 0) {
   1994 		return (ret);
   1995 	}
   1996 
   1997 
   1998 	/*
   1999 	 * Even though kmem_alloc() checks the validity of the
   2000 	 * buffer length, this check is needed when the
   2001 	 * kmem_flags set and the zero buffer length is passed.
   2002 	 */
   2003 	if ((k_fscsi.scsi_cdblen <= 0) ||
   2004 	    (k_fscsi.scsi_buflen <= 0) ||
   2005 	    (k_fscsi.scsi_rqlen <= 0)) {
   2006 		return (EINVAL);
   2007 	}
   2008 
   2009 	/*
   2010 	 * Allocate data for fcp_scsi_cmd pointer fields
   2011 	 */
   2012 	if (ret == 0) {
   2013 		k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
   2014 		k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
   2015 		k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
   2016 
   2017 		if (k_cdbbufaddr == NULL ||
   2018 		    k_bufaddr	 == NULL ||
   2019 		    k_rqbufaddr	 == NULL) {
   2020 			ret = ENOMEM;
   2021 		}
   2022 	}
   2023 
   2024 	/*
   2025 	 * Get fcp_scsi_cmd pointer fields from user
   2026 	 * address space
   2027 	 */
   2028 	if (ret == 0) {
   2029 		u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
   2030 		u_bufaddr    = k_fscsi.scsi_bufaddr;
   2031 		u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
   2032 
   2033 		if (ddi_copyin(u_cdbbufaddr,
   2034 		    k_cdbbufaddr,
   2035 		    k_fscsi.scsi_cdblen,
   2036 		    mode)) {
   2037 			ret = EFAULT;
   2038 		} else if (ddi_copyin(u_bufaddr,
   2039 		    k_bufaddr,
   2040 		    k_fscsi.scsi_buflen,
   2041 		    mode)) {
   2042 			ret = EFAULT;
   2043 		} else if (ddi_copyin(u_rqbufaddr,
   2044 		    k_rqbufaddr,
   2045 		    k_fscsi.scsi_rqlen,
   2046 		    mode)) {
   2047 			ret = EFAULT;
   2048 		}
   2049 	}
   2050 
   2051 	/*
   2052 	 * Send scsi command (blocking)
   2053 	 */
   2054 	if (ret == 0) {
   2055 		/*
   2056 		 * Prior to sending the scsi command, the
   2057 		 * fcp_scsi_cmd data structure must contain kernel,
   2058 		 * not user, addresses.
   2059 		 */
   2060 		k_fscsi.scsi_cdbbufaddr	= k_cdbbufaddr;
   2061 		k_fscsi.scsi_bufaddr	= k_bufaddr;
   2062 		k_fscsi.scsi_rqbufaddr	= k_rqbufaddr;
   2063 
   2064 		ret = fcp_send_scsi_ioctl(&k_fscsi);
   2065 
   2066 		/*
   2067 		 * After sending the scsi command, the
   2068 		 * fcp_scsi_cmd data structure must contain user,
   2069 		 * not kernel, addresses.
   2070 		 */
   2071 		k_fscsi.scsi_cdbbufaddr	= u_cdbbufaddr;
   2072 		k_fscsi.scsi_bufaddr	= u_bufaddr;
   2073 		k_fscsi.scsi_rqbufaddr	= u_rqbufaddr;
   2074 	}
   2075 
   2076 	/*
   2077 	 * Put fcp_scsi_cmd pointer fields to user address space
   2078 	 */
   2079 	if (ret == 0) {
   2080 		if (ddi_copyout(k_cdbbufaddr,
   2081 		    u_cdbbufaddr,
   2082 		    k_fscsi.scsi_cdblen,
   2083 		    mode)) {
   2084 			ret = EFAULT;
   2085 		} else if (ddi_copyout(k_bufaddr,
   2086 		    u_bufaddr,
   2087 		    k_fscsi.scsi_buflen,
   2088 		    mode)) {
   2089 			ret = EFAULT;
   2090 		} else if (ddi_copyout(k_rqbufaddr,
   2091 		    u_rqbufaddr,
   2092 		    k_fscsi.scsi_rqlen,
   2093 		    mode)) {
   2094 			ret = EFAULT;
   2095 		}
   2096 	}
   2097 
   2098 	/*
   2099 	 * Free data for fcp_scsi_cmd pointer fields
   2100 	 */
   2101 	if (k_cdbbufaddr != NULL) {
   2102 		kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
   2103 	}
   2104 	if (k_bufaddr != NULL) {
   2105 		kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
   2106 	}
   2107 	if (k_rqbufaddr != NULL) {
   2108 		kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
   2109 	}
   2110 
   2111 	/*
   2112 	 * Put fcp_scsi_cmd array element to user address space
   2113 	 */
   2114 	temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
   2115 	if (temp_ret != 0) {
   2116 		ret = temp_ret;
   2117 	}
   2118 
   2119 	/*
   2120 	 * Return status
   2121 	 */
   2122 	return (ret);
   2123 }
   2124 
   2125 
   2126 /*
   2127  * fcp_copyin_scsi_cmd
   2128  *	Copy in fcp_scsi_cmd data structure from user address space.
   2129  *	The data may be in 32 bit or 64 bit modes.
   2130  *
   2131  * Input:
   2132  *	base_addr	= from address (user address space)
   2133  *	mode		= See ioctl(9E) and ddi_copyin(9F)
   2134  *
   2135  * Output:
   2136  *	fscsi		= to address (kernel address space)
   2137  *
   2138  * Returns:
   2139  *	0	= OK
   2140  *	EFAULT	= Error
   2141  *
   2142  * Context:
   2143  *	Kernel context.
   2144  */
   2145 static int
   2146 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
   2147 {
   2148 #ifdef	_MULTI_DATAMODEL
   2149 	struct fcp32_scsi_cmd	f32scsi;
   2150 
   2151 	switch (ddi_model_convert_from(mode & FMODELS)) {
   2152 	case DDI_MODEL_ILP32:
   2153 		/*
   2154 		 * Copy data from user address space
   2155 		 */
   2156 		if (ddi_copyin((void *)base_addr,
   2157 		    &f32scsi,
   2158 		    sizeof (struct fcp32_scsi_cmd),
   2159 		    mode)) {
   2160 			return (EFAULT);
   2161 		}
   2162 		/*
   2163 		 * Convert from 32 bit to 64 bit
   2164 		 */
   2165 		FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
   2166 		break;
   2167 	case DDI_MODEL_NONE:
   2168 		/*
   2169 		 * Copy data from user address space
   2170 		 */
   2171 		if (ddi_copyin((void *)base_addr,
   2172 		    fscsi,
   2173 		    sizeof (struct fcp_scsi_cmd),
   2174 		    mode)) {
   2175 			return (EFAULT);
   2176 		}
   2177 		break;
   2178 	}
   2179 #else	/* _MULTI_DATAMODEL */
   2180 	/*
   2181 	 * Copy data from user address space
   2182 	 */
   2183 	if (ddi_copyin((void *)base_addr,
   2184 	    fscsi,
   2185 	    sizeof (struct fcp_scsi_cmd),
   2186 	    mode)) {
   2187 		return (EFAULT);
   2188 	}
   2189 #endif	/* _MULTI_DATAMODEL */
   2190 
   2191 	return (0);
   2192 }
   2193 
   2194 
   2195 /*
   2196  * fcp_copyout_scsi_cmd
   2197  *	Copy out fcp_scsi_cmd data structure to user address space.
   2198  *	The data may be in 32 bit or 64 bit modes.
   2199  *
   2200  * Input:
   2201  *	fscsi		= to address (kernel address space)
   2202  *	mode		= See ioctl(9E) and ddi_copyin(9F)
   2203  *
   2204  * Output:
   2205  *	base_addr	= from address (user address space)
   2206  *
   2207  * Returns:
   2208  *	0	= OK
   2209  *	EFAULT	= Error
   2210  *
   2211  * Context:
   2212  *	Kernel context.
   2213  */
   2214 static int
   2215 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
   2216 {
   2217 #ifdef	_MULTI_DATAMODEL
   2218 	struct fcp32_scsi_cmd	f32scsi;
   2219 
   2220 	switch (ddi_model_convert_from(mode & FMODELS)) {
   2221 	case DDI_MODEL_ILP32:
   2222 		/*
   2223 		 * Convert from 64 bit to 32 bit
   2224 		 */
   2225 		FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
   2226 		/*
   2227 		 * Copy data to user address space
   2228 		 */
   2229 		if (ddi_copyout(&f32scsi,
   2230 		    (void *)base_addr,
   2231 		    sizeof (struct fcp32_scsi_cmd),
   2232 		    mode)) {
   2233 			return (EFAULT);
   2234 		}
   2235 		break;
   2236 	case DDI_MODEL_NONE:
   2237 		/*
   2238 		 * Copy data to user address space
   2239 		 */
   2240 		if (ddi_copyout(fscsi,
   2241 		    (void *)base_addr,
   2242 		    sizeof (struct fcp_scsi_cmd),
   2243 		    mode)) {
   2244 			return (EFAULT);
   2245 		}
   2246 		break;
   2247 	}
   2248 #else	/* _MULTI_DATAMODEL */
   2249 	/*
   2250 	 * Copy data to user address space
   2251 	 */
   2252 	if (ddi_copyout(fscsi,
   2253 	    (void *)base_addr,
   2254 	    sizeof (struct fcp_scsi_cmd),
   2255 	    mode)) {
   2256 		return (EFAULT);
   2257 	}
   2258 #endif	/* _MULTI_DATAMODEL */
   2259 
   2260 	return (0);
   2261 }
   2262 
   2263 
   2264 /*
   2265  * fcp_send_scsi_ioctl
   2266  *	Sends the SCSI command in blocking mode.
   2267  *
   2268  * Input:
   2269  *	fscsi		= SCSI command data structure
   2270  *
   2271  * Output:
   2272  *	fscsi		= SCSI command data structure
   2273  *
   2274  * Returns:
   2275  *	0	= OK
   2276  *	EAGAIN	= See errno.h
   2277  *	EBUSY	= See errno.h
   2278  *	EINTR	= See errno.h
   2279  *	EINVAL	= See errno.h
   2280  *	EIO	= See errno.h
   2281  *	ENOMEM	= See errno.h
   2282  *	ENXIO	= See errno.h
   2283  *
   2284  * Context:
   2285  *	Kernel context.
   2286  */
   2287 static int
   2288 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
   2289 {
   2290 	struct fcp_lun	*plun		= NULL;
   2291 	struct fcp_port	*pptr		= NULL;
   2292 	struct fcp_tgt	*ptgt		= NULL;
   2293 	fc_packet_t		*fpkt		= NULL;
   2294 	struct fcp_ipkt	*icmd		= NULL;
   2295 	int			target_created	= FALSE;
   2296 	fc_frame_hdr_t		*hp;
   2297 	struct fcp_cmd		fcp_cmd;
   2298 	struct fcp_cmd		*fcmd;
   2299 	union scsi_cdb		*scsi_cdb;
   2300 	la_wwn_t		*wwn_ptr;
   2301 	int			nodma;
   2302 	struct fcp_rsp		*rsp;
   2303 	struct fcp_rsp_info	*rsp_info;
   2304 	caddr_t			rsp_sense;
   2305 	int			buf_len;
   2306 	int			info_len;
   2307 	int			sense_len;
   2308 	struct scsi_extended_sense	*sense_to = NULL;
   2309 	timeout_id_t		tid;
   2310 	uint8_t			reconfig_lun = FALSE;
   2311 	uint8_t			reconfig_pending = FALSE;
   2312 	uint8_t			scsi_cmd;
   2313 	int			rsp_len;
   2314 	int			cmd_index;
   2315 	int			fc_status;
   2316 	int			pkt_state;
   2317 	int			pkt_action;
   2318 	int			pkt_reason;
   2319 	int			ret, xport_retval = ~FC_SUCCESS;
   2320 	int			lcount;
   2321 	int			tcount;
   2322 	int			reconfig_status;
   2323 	int			port_busy = FALSE;
   2324 	uchar_t			*lun_string;
   2325 
   2326 	/*
   2327 	 * Check valid SCSI command
   2328 	 */
   2329 	scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
   2330 	ret = EINVAL;
   2331 	for (cmd_index = 0;
   2332 	    cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
   2333 	    ret != 0;
   2334 	    cmd_index++) {
   2335 		/*
   2336 		 * First byte of CDB is the SCSI command
   2337 		 */
   2338 		if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
   2339 			ret = 0;
   2340 		}
   2341 	}
   2342 
   2343 	/*
   2344 	 * Check inputs
   2345 	 */
   2346 	if (fscsi->scsi_flags != FCP_SCSI_READ) {
   2347 		ret = EINVAL;
   2348 	} else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
   2349 		/* no larger than */
   2350 		ret = EINVAL;
   2351 	}
   2352 
   2353 
   2354 	/*
   2355 	 * Find FC port
   2356 	 */
   2357 	if (ret == 0) {
   2358 		/*
   2359 		 * Acquire global mutex
   2360 		 */
   2361 		mutex_enter(&fcp_global_mutex);
   2362 
   2363 		pptr = fcp_port_head;
   2364 		while (pptr) {
   2365 			if (pptr->port_instance ==
   2366 			    (uint32_t)fscsi->scsi_fc_port_num) {
   2367 				break;
   2368 			} else {
   2369 				pptr = pptr->port_next;
   2370 			}
   2371 		}
   2372 
   2373 		if (pptr == NULL) {
   2374 			ret = ENXIO;
   2375 		} else {
   2376 			/*
   2377 			 * fc_ulp_busy_port can raise power
   2378 			 *  so, we must not hold any mutexes involved in PM
   2379 			 */
   2380 			mutex_exit(&fcp_global_mutex);
   2381 			ret = fc_ulp_busy_port(pptr->port_fp_handle);
   2382 		}
   2383 
   2384 		if (ret == 0) {
   2385 
   2386 			/* remember port is busy, so we will release later */
   2387 			port_busy = TRUE;
   2388 
   2389 			/*
   2390 			 * If there is a reconfiguration in progress, wait
   2391 			 * for it to complete.
   2392 			 */
   2393 
   2394 			fcp_reconfig_wait(pptr);
   2395 
   2396 			/* reacquire mutexes in order */
   2397 			mutex_enter(&fcp_global_mutex);
   2398 			mutex_enter(&pptr->port_mutex);
   2399 
   2400 			/*
   2401 			 * Will port accept DMA?
   2402 			 */
   2403 			nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
   2404 			    ? 1 : 0;
   2405 
   2406 			/*
   2407 			 * If init or offline, device not known
   2408 			 *
   2409 			 * If we are discovering (onlining), we can
   2410 			 * NOT obviously provide reliable data about
   2411 			 * devices until it is complete
   2412 			 */
   2413 			if (pptr->port_state &	  (FCP_STATE_INIT |
   2414 			    FCP_STATE_OFFLINE)) {
   2415 				ret = ENXIO;
   2416 			} else if (pptr->port_state & FCP_STATE_ONLINING) {
   2417 				ret = EBUSY;
   2418 			} else {
   2419 				/*
   2420 				 * Find target from pwwn
   2421 				 *
   2422 				 * The wwn must be put into a local
   2423 				 * variable to ensure alignment.
   2424 				 */
   2425 				wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
   2426 				ptgt = fcp_lookup_target(pptr,
   2427 				    (uchar_t *)wwn_ptr);
   2428 
   2429 				/*
   2430 				 * If target not found,
   2431 				 */
   2432 				if (ptgt == NULL) {
   2433 					/*
   2434 					 * Note: Still have global &
   2435 					 * port mutexes
   2436 					 */
   2437 					mutex_exit(&pptr->port_mutex);
   2438 					ptgt = fcp_port_create_tgt(pptr,
   2439 					    wwn_ptr, &ret, &fc_status,
   2440 					    &pkt_state, &pkt_action,
   2441 					    &pkt_reason);
   2442 					mutex_enter(&pptr->port_mutex);
   2443 
   2444 					fscsi->scsi_fc_status  = fc_status;
   2445 					fscsi->scsi_pkt_state  =
   2446 					    (uchar_t)pkt_state;
   2447 					fscsi->scsi_pkt_reason = pkt_reason;
   2448 					fscsi->scsi_pkt_action =
   2449 					    (uchar_t)pkt_action;
   2450 
   2451 					if (ptgt != NULL) {
   2452 						target_created = TRUE;
   2453 					} else if (ret == 0) {
   2454 						ret = ENOMEM;
   2455 					}
   2456 				}
   2457 
   2458 				if (ret == 0) {
   2459 					/*
   2460 					 * Acquire target
   2461 					 */
   2462 					mutex_enter(&ptgt->tgt_mutex);
   2463 
   2464 					/*
   2465 					 * If target is mark or busy,
   2466 					 * then target can not be used
   2467 					 */
   2468 					if (ptgt->tgt_state &
   2469 					    (FCP_TGT_MARK |
   2470 					    FCP_TGT_BUSY)) {
   2471 						ret = EBUSY;
   2472 					} else {
   2473 						/*
   2474 						 * Mark target as busy
   2475 						 */
   2476 						ptgt->tgt_state |=
   2477 						    FCP_TGT_BUSY;
   2478 					}
   2479 
   2480 					/*
   2481 					 * Release target
   2482 					 */
   2483 					lcount = pptr->port_link_cnt;
   2484 					tcount = ptgt->tgt_change_cnt;
   2485 					mutex_exit(&ptgt->tgt_mutex);
   2486 				}
   2487 			}
   2488 
   2489 			/*
   2490 			 * Release port
   2491 			 */
   2492 			mutex_exit(&pptr->port_mutex);
   2493 		}
   2494 
   2495 		/*
   2496 		 * Release global mutex
   2497 		 */
   2498 		mutex_exit(&fcp_global_mutex);
   2499 	}
   2500 
   2501 	if (ret == 0) {
   2502 		uint64_t belun = BE_64(fscsi->scsi_lun);
   2503 
   2504 		/*
   2505 		 * If it's a target device, find lun from pwwn
   2506 		 * The wwn must be put into a local
   2507 		 * variable to ensure alignment.
   2508 		 */
   2509 		mutex_enter(&pptr->port_mutex);
   2510 		wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
   2511 		if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
   2512 			/* this is not a target */
   2513 			fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
   2514 			ret = ENXIO;
   2515 		} else if ((belun << 16) != 0) {
   2516 			/*
   2517 			 * Since fcp only support PD and LU addressing method
   2518 			 * so far, the last 6 bytes of a valid LUN are expected
   2519 			 * to be filled with 00h.
   2520 			 */
   2521 			fscsi->scsi_fc_status = FC_INVALID_LUN;
   2522 			cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
   2523 			    " method 0x%02x with LUN number 0x%016" PRIx64,
   2524 			    (uint8_t)(belun >> 62), belun);
   2525 			ret = ENXIO;
   2526 		} else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
   2527 		    (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
   2528 			/*
   2529 			 * This is a SCSI target, but no LUN at this
   2530 			 * address.
   2531 			 *
   2532 			 * In the future, we may want to send this to
   2533 			 * the target, and let it respond
   2534 			 * appropriately
   2535 			 */
   2536 			ret = ENXIO;
   2537 		}
   2538 		mutex_exit(&pptr->port_mutex);
   2539 	}
   2540 
   2541 	/*
   2542 	 * Finished grabbing external resources
   2543 	 * Allocate internal packet (icmd)
   2544 	 */
   2545 	if (ret == 0) {
   2546 		/*
   2547 		 * Calc rsp len assuming rsp info included
   2548 		 */
   2549 		rsp_len = sizeof (struct fcp_rsp) +
   2550 		    sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
   2551 
   2552 		icmd = fcp_icmd_alloc(pptr, ptgt,
   2553 		    sizeof (struct fcp_cmd),
   2554 		    rsp_len,
   2555 		    fscsi->scsi_buflen,
   2556 		    nodma,
   2557 		    lcount,			/* ipkt_link_cnt */
   2558 		    tcount,			/* ipkt_change_cnt */
   2559 		    0,				/* cause */
   2560 		    FC_INVALID_RSCN_COUNT);	/* invalidate the count */
   2561 
   2562 		if (icmd == NULL) {
   2563 			ret = ENOMEM;
   2564 		} else {
   2565 			/*
   2566 			 * Setup internal packet as sema sync
   2567 			 */
   2568 			fcp_ipkt_sema_init(icmd);
   2569 		}
   2570 	}
   2571 
   2572 	if (ret == 0) {
   2573 		/*
   2574 		 * Init fpkt pointer for use.
   2575 		 */
   2576 
   2577 		fpkt = icmd->ipkt_fpkt;
   2578 
   2579 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
   2580 		fpkt->pkt_tran_type	= FC_PKT_FCP_READ; /* only rd for now */
   2581 		fpkt->pkt_timeout	= fscsi->scsi_timeout;
   2582 
   2583 		/*
   2584 		 * Init fcmd pointer for use by SCSI command
   2585 		 */
   2586 
   2587 		if (nodma) {
   2588 			fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
   2589 		} else {
   2590 			fcmd = &fcp_cmd;
   2591 		}
   2592 		bzero(fcmd, sizeof (struct fcp_cmd));
   2593 		ptgt = plun->lun_tgt;
   2594 
   2595 		lun_string = (uchar_t *)&fscsi->scsi_lun;
   2596 
   2597 		fcmd->fcp_ent_addr.ent_addr_0 =
   2598 		    BE_16(*(uint16_t *)&(lun_string[0]));
   2599 		fcmd->fcp_ent_addr.ent_addr_1 =
   2600 		    BE_16(*(uint16_t *)&(lun_string[2]));
   2601 		fcmd->fcp_ent_addr.ent_addr_2 =
   2602 		    BE_16(*(uint16_t *)&(lun_string[4]));
   2603 		fcmd->fcp_ent_addr.ent_addr_3 =
   2604 		    BE_16(*(uint16_t *)&(lun_string[6]));
   2605 
   2606 		/*
   2607 		 * Setup internal packet(icmd)
   2608 		 */
   2609 		icmd->ipkt_lun		= plun;
   2610 		icmd->ipkt_restart	= 0;
   2611 		icmd->ipkt_retries	= 0;
   2612 		icmd->ipkt_opcode	= 0;
   2613 
   2614 		/*
   2615 		 * Init the frame HEADER Pointer for use
   2616 		 */
   2617 		hp = &fpkt->pkt_cmd_fhdr;
   2618 
   2619 		hp->s_id	= pptr->port_id;
   2620 		hp->d_id	= ptgt->tgt_d_id;
   2621 		hp->r_ctl	= R_CTL_COMMAND;
   2622 		hp->type	= FC_TYPE_SCSI_FCP;
   2623 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
   2624 		hp->rsvd	= 0;
   2625 		hp->seq_id	= 0;
   2626 		hp->seq_cnt	= 0;
   2627 		hp->ox_id	= 0xffff;
   2628 		hp->rx_id	= 0xffff;
   2629 		hp->ro		= 0;
   2630 
   2631 		fcmd->fcp_cntl.cntl_qtype	= FCP_QTYPE_SIMPLE;
   2632 		fcmd->fcp_cntl.cntl_read_data	= 1;	/* only rd for now */
   2633 		fcmd->fcp_cntl.cntl_write_data	= 0;
   2634 		fcmd->fcp_data_len	= fscsi->scsi_buflen;
   2635 
   2636 		scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
   2637 		bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
   2638 		    fscsi->scsi_cdblen);
   2639 
   2640 		if (!nodma) {
   2641 			FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
   2642 			    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
   2643 		}
   2644 
   2645 		/*
   2646 		 * Send SCSI command to FC transport
   2647 		 */
   2648 
   2649 		if (ret == 0) {
   2650 			mutex_enter(&ptgt->tgt_mutex);
   2651 
   2652 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   2653 				mutex_exit(&ptgt->tgt_mutex);
   2654 				fscsi->scsi_fc_status = xport_retval =
   2655 				    fc_ulp_transport(pptr->port_fp_handle,
   2656 				    fpkt);
   2657 				if (fscsi->scsi_fc_status != FC_SUCCESS) {
   2658 					ret = EIO;
   2659 				}
   2660 			} else {
   2661 				mutex_exit(&ptgt->tgt_mutex);
   2662 				ret = EBUSY;
   2663 			}
   2664 		}
   2665 	}
   2666 
   2667 	/*
   2668 	 * Wait for completion only if fc_ulp_transport was called and it
   2669 	 * returned a success. This is the only time callback will happen.
   2670 	 * Otherwise, there is no point in waiting
   2671 	 */
   2672 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
   2673 		ret = fcp_ipkt_sema_wait(icmd);
   2674 	}
   2675 
   2676 	/*
   2677 	 * Copy data to IOCTL data structures
   2678 	 */
   2679 	rsp = NULL;
   2680 	if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
   2681 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
   2682 
   2683 		if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
   2684 			fcp_log(CE_WARN, pptr->port_dip,
   2685 			    "!SCSI command to d_id=0x%x lun=0x%x"
   2686 			    " failed, Bad FCP response values:"
   2687 			    " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
   2688 			    " sts-rsvd2=%x, rsplen=%x, senselen=%x",
   2689 			    ptgt->tgt_d_id, plun->lun_num,
   2690 			    rsp->reserved_0, rsp->reserved_1,
   2691 			    rsp->fcp_u.fcp_status.reserved_0,
   2692 			    rsp->fcp_u.fcp_status.reserved_1,
   2693 			    rsp->fcp_response_len, rsp->fcp_sense_len);
   2694 
   2695 			ret = EIO;
   2696 		}
   2697 	}
   2698 
   2699 	if ((ret == 0) && (rsp != NULL)) {
   2700 		/*
   2701 		 * Calc response lengths
   2702 		 */
   2703 		sense_len = 0;
   2704 		info_len = 0;
   2705 
   2706 		if (rsp->fcp_u.fcp_status.rsp_len_set) {
   2707 			info_len = rsp->fcp_response_len;
   2708 		}
   2709 
   2710 		rsp_info   = (struct fcp_rsp_info *)
   2711 		    ((uint8_t *)rsp + sizeof (struct fcp_rsp));
   2712 
   2713 		/*
   2714 		 * Get SCSI status
   2715 		 */
   2716 		fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
   2717 		/*
   2718 		 * If a lun was just added or removed and the next command
   2719 		 * comes through this interface, we need to capture the check
   2720 		 * condition so we can discover the new topology.
   2721 		 */
   2722 		if (fscsi->scsi_bufstatus != STATUS_GOOD &&
   2723 		    rsp->fcp_u.fcp_status.sense_len_set) {
   2724 			sense_len = rsp->fcp_sense_len;
   2725 			rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
   2726 			sense_to = (struct scsi_extended_sense *)rsp_sense;
   2727 			if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
   2728 			    (FCP_SENSE_NO_LUN(sense_to))) {
   2729 				reconfig_lun = TRUE;
   2730 			}
   2731 		}
   2732 
   2733 		if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
   2734 		    (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
   2735 			if (reconfig_lun == FALSE) {
   2736 				reconfig_status =
   2737 				    fcp_is_reconfig_needed(ptgt, fpkt);
   2738 			}
   2739 
   2740 			if ((reconfig_lun == TRUE) ||
   2741 			    (reconfig_status == TRUE)) {
   2742 				mutex_enter(&ptgt->tgt_mutex);
   2743 				if (ptgt->tgt_tid == NULL) {
   2744 					/*
   2745 					 * Either we've been notified the
   2746 					 * REPORT_LUN data has changed, or
   2747 					 * we've determined on our own that
   2748 					 * we're out of date.  Kick off
   2749 					 * rediscovery.
   2750 					 */
   2751 					tid = timeout(fcp_reconfigure_luns,
   2752 					    (caddr_t)ptgt, drv_usectohz(1));
   2753 
   2754 					ptgt->tgt_tid = tid;
   2755 					ptgt->tgt_state |= FCP_TGT_BUSY;
   2756 					ret = EBUSY;
   2757 					reconfig_pending = TRUE;
   2758 				}
   2759 				mutex_exit(&ptgt->tgt_mutex);
   2760 			}
   2761 		}
   2762 
   2763 		/*
   2764 		 * Calc residuals and buffer lengths
   2765 		 */
   2766 
   2767 		if (ret == 0) {
   2768 			buf_len = fscsi->scsi_buflen;
   2769 			fscsi->scsi_bufresid	= 0;
   2770 			if (rsp->fcp_u.fcp_status.resid_under) {
   2771 				if (rsp->fcp_resid <= fscsi->scsi_buflen) {
   2772 					fscsi->scsi_bufresid = rsp->fcp_resid;
   2773 				} else {
   2774 					cmn_err(CE_WARN, "fcp: bad residue %x "
   2775 					    "for txfer len %x", rsp->fcp_resid,
   2776 					    fscsi->scsi_buflen);
   2777 					fscsi->scsi_bufresid =
   2778 					    fscsi->scsi_buflen;
   2779 				}
   2780 				buf_len -= fscsi->scsi_bufresid;
   2781 			}
   2782 			if (rsp->fcp_u.fcp_status.resid_over) {
   2783 				fscsi->scsi_bufresid = -rsp->fcp_resid;
   2784 			}
   2785 
   2786 			fscsi->scsi_rqresid	= fscsi->scsi_rqlen - sense_len;
   2787 			if (fscsi->scsi_rqlen < sense_len) {
   2788 				sense_len = fscsi->scsi_rqlen;
   2789 			}
   2790 
   2791 			fscsi->scsi_fc_rspcode	= 0;
   2792 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
   2793 				fscsi->scsi_fc_rspcode	= rsp_info->rsp_code;
   2794 			}
   2795 			fscsi->scsi_pkt_state	= fpkt->pkt_state;
   2796 			fscsi->scsi_pkt_action	= fpkt->pkt_action;
   2797 			fscsi->scsi_pkt_reason	= fpkt->pkt_reason;
   2798 
   2799 			/*
   2800 			 * Copy data and request sense
   2801 			 *
   2802 			 * Data must be copied by using the FCP_CP_IN macro.
   2803 			 * This will ensure the proper byte order since the data
   2804 			 * is being copied directly from the memory mapped
   2805 			 * device register.
   2806 			 *
   2807 			 * The response (and request sense) will be in the
   2808 			 * correct byte order.	No special copy is necessary.
   2809 			 */
   2810 
   2811 			if (buf_len) {
   2812 				FCP_CP_IN(fpkt->pkt_data,
   2813 				    fscsi->scsi_bufaddr,
   2814 				    fpkt->pkt_data_acc,
   2815 				    buf_len);
   2816 			}
   2817 			bcopy((void *)rsp_sense,
   2818 			    (void *)fscsi->scsi_rqbufaddr,
   2819 			    sense_len);
   2820 		}
   2821 	}
   2822 
   2823 	/*
   2824 	 * Cleanup transport data structures if icmd was alloc-ed
   2825 	 * So, cleanup happens in the same thread that icmd was alloc-ed
   2826 	 */
   2827 	if (icmd != NULL) {
   2828 		fcp_ipkt_sema_cleanup(icmd);
   2829 	}
   2830 
   2831 	/* restore pm busy/idle status */
   2832 	if (port_busy) {
   2833 		fc_ulp_idle_port(pptr->port_fp_handle);
   2834 	}
   2835 
   2836 	/*
   2837 	 * Cleanup target.  if a reconfig is pending, don't clear the BUSY
   2838 	 * flag, it'll be cleared when the reconfig is complete.
   2839 	 */
   2840 	if ((ptgt != NULL) && !reconfig_pending) {
   2841 		/*
   2842 		 * If target was created,
   2843 		 */
   2844 		if (target_created) {
   2845 			mutex_enter(&ptgt->tgt_mutex);
   2846 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
   2847 			mutex_exit(&ptgt->tgt_mutex);
   2848 		} else {
   2849 			/*
   2850 			 * De-mark target as busy
   2851 			 */
   2852 			mutex_enter(&ptgt->tgt_mutex);
   2853 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
   2854 			mutex_exit(&ptgt->tgt_mutex);
   2855 		}
   2856 	}
   2857 	return (ret);
   2858 }
   2859 
   2860 
   2861 static int
   2862 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
   2863     fc_packet_t	*fpkt)
   2864 {
   2865 	uchar_t			*lun_string;
   2866 	uint16_t		lun_num, i;
   2867 	int			num_luns;
   2868 	int			actual_luns;
   2869 	int			num_masked_luns;
   2870 	int			lun_buflen;
   2871 	struct fcp_lun	*plun	= NULL;
   2872 	struct fcp_reportlun_resp	*report_lun;
   2873 	uint8_t			reconfig_needed = FALSE;
   2874 	uint8_t			lun_exists = FALSE;
   2875 	fcp_port_t			*pptr		 = ptgt->tgt_port;
   2876 
   2877 	report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
   2878 
   2879 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
   2880 	    fpkt->pkt_datalen);
   2881 
   2882 	/* get number of luns (which is supplied as LUNS * 8) */
   2883 	num_luns = BE_32(report_lun->num_lun) >> 3;
   2884 
   2885 	/*
   2886 	 * Figure out exactly how many lun strings our response buffer
   2887 	 * can hold.
   2888 	 */
   2889 	lun_buflen = (fpkt->pkt_datalen -
   2890 	    2 * sizeof (uint32_t)) / sizeof (longlong_t);
   2891 
   2892 	/*
   2893 	 * Is our response buffer full or not? We don't want to
   2894 	 * potentially walk beyond the number of luns we have.
   2895 	 */
   2896 	if (num_luns <= lun_buflen) {
   2897 		actual_luns = num_luns;
   2898 	} else {
   2899 		actual_luns = lun_buflen;
   2900 	}
   2901 
   2902 	mutex_enter(&ptgt->tgt_mutex);
   2903 
   2904 	/* Scan each lun to see if we have masked it. */
   2905 	num_masked_luns = 0;
   2906 	if (fcp_lun_blacklist != NULL) {
   2907 		for (i = 0; i < actual_luns; i++) {
   2908 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
   2909 			switch (lun_string[0] & 0xC0) {
   2910 			case FCP_LUN_ADDRESSING:
   2911 			case FCP_PD_ADDRESSING:
   2912 			case FCP_VOLUME_ADDRESSING:
   2913 				lun_num = ((lun_string[0] & 0x3F) << 8)
   2914 				    | lun_string[1];
   2915 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
   2916 				    lun_num) == TRUE) {
   2917 					num_masked_luns++;
   2918 				}
   2919 				break;
   2920 			default:
   2921 				break;
   2922 			}
   2923 		}
   2924 	}
   2925 
   2926 	/*
   2927 	 * The quick and easy check.  If the number of LUNs reported
   2928 	 * doesn't match the number we currently know about, we need
   2929 	 * to reconfigure.
   2930 	 */
   2931 	if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
   2932 		mutex_exit(&ptgt->tgt_mutex);
   2933 		kmem_free(report_lun, fpkt->pkt_datalen);
   2934 		return (TRUE);
   2935 	}
   2936 
   2937 	/*
   2938 	 * If the quick and easy check doesn't turn up anything, we walk
   2939 	 * the list of luns from the REPORT_LUN response and look for
   2940 	 * any luns we don't know about.  If we find one, we know we need
   2941 	 * to reconfigure. We will skip LUNs that are masked because of the
   2942 	 * blacklist.
   2943 	 */
   2944 	for (i = 0; i < actual_luns; i++) {
   2945 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
   2946 		lun_exists = FALSE;
   2947 		switch (lun_string[0] & 0xC0) {
   2948 		case FCP_LUN_ADDRESSING:
   2949 		case FCP_PD_ADDRESSING:
   2950 		case FCP_VOLUME_ADDRESSING:
   2951 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
   2952 
   2953 			if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
   2954 			    &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
   2955 				lun_exists = TRUE;
   2956 				break;
   2957 			}
   2958 
   2959 			for (plun = ptgt->tgt_lun; plun;
   2960 			    plun = plun->lun_next) {
   2961 				if (plun->lun_num == lun_num) {
   2962 					lun_exists = TRUE;
   2963 					break;
   2964 				}
   2965 			}
   2966 			break;
   2967 		default:
   2968 			break;
   2969 		}
   2970 
   2971 		if (lun_exists == FALSE) {
   2972 			reconfig_needed = TRUE;
   2973 			break;
   2974 		}
   2975 	}
   2976 
   2977 	mutex_exit(&ptgt->tgt_mutex);
   2978 	kmem_free(report_lun, fpkt->pkt_datalen);
   2979 
   2980 	return (reconfig_needed);
   2981 }
   2982 
   2983 /*
   2984  * This function is called by fcp_handle_page83 and uses inquiry response data
   2985  * stored in plun->lun_inq to determine whether or not a device is a member of
   2986  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
   2987  * otherwise 1.
   2988  */
   2989 static int
   2990 fcp_symmetric_device_probe(struct fcp_lun *plun)
   2991 {
   2992 	struct scsi_inquiry	*stdinq = &plun->lun_inq;
   2993 	char			*devidptr;
   2994 	int			i, len;
   2995 
   2996 	for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
   2997 		devidptr = fcp_symmetric_disk_table[i];
   2998 		len = (int)strlen(devidptr);
   2999 
   3000 		if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
   3001 			return (0);
   3002 		}
   3003 	}
   3004 	return (1);
   3005 }
   3006 
   3007 
   3008 /*
   3009  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
   3010  * It basically returns the current count of # of state change callbacks
   3011  * i.e the value of tgt_change_cnt.
   3012  *
   3013  * INPUT:
   3014  *   fcp_ioctl.fp_minor -> The minor # of the fp port
   3015  *   fcp_ioctl.listlen	-> 1
   3016  *   fcp_ioctl.list	-> Pointer to a 32 bit integer
   3017  */
   3018 /*ARGSUSED2*/
   3019 static int
   3020 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
   3021 {
   3022 	int			ret;
   3023 	uint32_t		link_cnt;
   3024 	struct fcp_ioctl	fioctl;
   3025 	struct fcp_port	*pptr = NULL;
   3026 
   3027 	if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
   3028 	    &pptr)) != 0) {
   3029 		return (ret);
   3030 	}
   3031 
   3032 	ASSERT(pptr != NULL);
   3033 
   3034 	if (fioctl.listlen != 1) {
   3035 		return (EINVAL);
   3036 	}
   3037 
   3038 	mutex_enter(&pptr->port_mutex);
   3039 	if (pptr->port_state & FCP_STATE_OFFLINE) {
   3040 		mutex_exit(&pptr->port_mutex);
   3041 		return (ENXIO);
   3042 	}
   3043 
   3044 	/*
   3045 	 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
   3046 	 * When the fcp initially attaches to the port and there are nothing
   3047 	 * hanging out of the port or if there was a repeat offline state change
   3048 	 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
   3049 	 * In the latter case, port_tmp_cnt will be non-zero and that is how we
   3050 	 * will differentiate the 2 cases.
   3051 	 */
   3052 	if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
   3053 		mutex_exit(&pptr->port_mutex);
   3054 		return (ENXIO);
   3055 	}
   3056 
   3057 	link_cnt = pptr->port_link_cnt;
   3058 	mutex_exit(&pptr->port_mutex);
   3059 
   3060 	if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
   3061 		return (EFAULT);
   3062 	}
   3063 
   3064 #ifdef	_MULTI_DATAMODEL
   3065 	switch (ddi_model_convert_from(mode & FMODELS)) {
   3066 	case DDI_MODEL_ILP32: {
   3067 		struct fcp32_ioctl f32_ioctl;
   3068 
   3069 		f32_ioctl.fp_minor = fioctl.fp_minor;
   3070 		f32_ioctl.listlen = fioctl.listlen;
   3071 		f32_ioctl.list = (caddr32_t)(long)fioctl.list;
   3072 		if (ddi_copyout((void *)&f32_ioctl, (void *)data,
   3073 		    sizeof (struct fcp32_ioctl), mode)) {
   3074 			return (EFAULT);
   3075 		}
   3076 		break;
   3077 	}
   3078 	case DDI_MODEL_NONE:
   3079 		if (ddi_copyout((void *)&fioctl, (void *)data,
   3080 		    sizeof (struct fcp_ioctl), mode)) {
   3081 			return (EFAULT);
   3082 		}
   3083 		break;
   3084 	}
   3085 #else	/* _MULTI_DATAMODEL */
   3086 
   3087 	if (ddi_copyout((void *)&fioctl, (void *)data,
   3088 	    sizeof (struct fcp_ioctl), mode)) {
   3089 		return (EFAULT);
   3090 	}
   3091 #endif	/* _MULTI_DATAMODEL */
   3092 
   3093 	return (0);
   3094 }
   3095 
   3096 /*
   3097  * This function copies the fcp_ioctl structure passed in from user land
   3098  * into kernel land. Handles 32 bit applications.
   3099  */
   3100 /*ARGSUSED*/
   3101 static int
   3102 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
   3103     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
   3104 {
   3105 	struct fcp_port	*t_pptr;
   3106 
   3107 #ifdef	_MULTI_DATAMODEL
   3108 	switch (ddi_model_convert_from(mode & FMODELS)) {
   3109 	case DDI_MODEL_ILP32: {
   3110 		struct fcp32_ioctl f32_ioctl;
   3111 
   3112 		if (ddi_copyin((void *)data, (void *)&f32_ioctl,
   3113 		    sizeof (struct fcp32_ioctl), mode)) {
   3114 			return (EFAULT);
   3115 		}
   3116 		fioctl->fp_minor = f32_ioctl.fp_minor;
   3117 		fioctl->listlen = f32_ioctl.listlen;
   3118 		fioctl->list = (caddr_t)(long)f32_ioctl.list;
   3119 		break;
   3120 	}
   3121 	case DDI_MODEL_NONE:
   3122 		if (ddi_copyin((void *)data, (void *)fioctl,
   3123 		    sizeof (struct fcp_ioctl), mode)) {
   3124 			return (EFAULT);
   3125 		}
   3126 		break;
   3127 	}
   3128 
   3129 #else	/* _MULTI_DATAMODEL */
   3130 	if (ddi_copyin((void *)data, (void *)fioctl,
   3131 	    sizeof (struct fcp_ioctl), mode)) {
   3132 		return (EFAULT);
   3133 	}
   3134 #endif	/* _MULTI_DATAMODEL */
   3135 
   3136 	/*
   3137 	 * Right now we can assume that the minor number matches with
   3138 	 * this instance of fp. If this changes we will need to
   3139 	 * revisit this logic.
   3140 	 */
   3141 	mutex_enter(&fcp_global_mutex);
   3142 	t_pptr = fcp_port_head;
   3143 	while (t_pptr) {
   3144 		if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
   3145 			break;
   3146 		} else {
   3147 			t_pptr = t_pptr->port_next;
   3148 		}
   3149 	}
   3150 	*pptr = t_pptr;
   3151 	mutex_exit(&fcp_global_mutex);
   3152 	if (t_pptr == NULL) {
   3153 		return (ENXIO);
   3154 	}
   3155 
   3156 	return (0);
   3157 }
   3158 
   3159 /*
   3160  *     Function: fcp_port_create_tgt
   3161  *
   3162  *  Description: As the name suggest this function creates the target context
   3163  *		 specified by the the WWN provided by the caller.  If the
   3164  *		 creation goes well and the target is known by fp/fctl a PLOGI
   3165  *		 followed by a PRLI are issued.
   3166  *
   3167  *     Argument: pptr		fcp port structure
   3168  *		 pwwn		WWN of the target
   3169  *		 ret_val	Address of the return code.  It could be:
   3170  *				EIO, ENOMEM or 0.
   3171  *		 fc_status	PLOGI or PRLI status completion
   3172  *		 fc_pkt_state	PLOGI or PRLI state completion
   3173  *		 fc_pkt_reason	PLOGI or PRLI reason completion
   3174  *		 fc_pkt_action	PLOGI or PRLI action completion
   3175  *
   3176  * Return Value: NULL if it failed
   3177  *		 Target structure address if it succeeds
   3178  */
   3179 static struct fcp_tgt *
   3180 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
   3181     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
   3182 {
   3183 	struct fcp_tgt	*ptgt = NULL;
   3184 	fc_portmap_t		devlist;
   3185 	int			lcount;
   3186 	int			error;
   3187 
   3188 	*ret_val = 0;
   3189 
   3190 	/*
   3191 	 * Check FC port device & get port map
   3192 	 */
   3193 	if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
   3194 	    &error, 1) == NULL) {
   3195 		*ret_val = EIO;
   3196 	} else {
   3197 		if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
   3198 		    &devlist) != FC_SUCCESS) {
   3199 			*ret_val = EIO;
   3200 		}
   3201 	}
   3202 
   3203 	/* Set port map flags */
   3204 	devlist.map_type = PORT_DEVICE_USER_CREATE;
   3205 
   3206 	/* Allocate target */
   3207 	if (*ret_val == 0) {
   3208 		lcount = pptr->port_link_cnt;
   3209 		ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
   3210 		if (ptgt == NULL) {
   3211 			fcp_log(CE_WARN, pptr->port_dip,
   3212 			    "!FC target allocation failed");
   3213 			*ret_val = ENOMEM;
   3214 		} else {
   3215 			/* Setup target */
   3216 			mutex_enter(&ptgt->tgt_mutex);
   3217 
   3218 			ptgt->tgt_statec_cause	= FCP_CAUSE_TGT_CHANGE;
   3219 			ptgt->tgt_tmp_cnt	= 1;
   3220 			ptgt->tgt_d_id		= devlist.map_did.port_id;
   3221 			ptgt->tgt_hard_addr	=
   3222 			    devlist.map_hard_addr.hard_addr;
   3223 			ptgt->tgt_pd_handle	= devlist.map_pd;
   3224 			ptgt->tgt_fca_dev	= NULL;
   3225 
   3226 			bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
   3227 			    FC_WWN_SIZE);
   3228 			bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
   3229 			    FC_WWN_SIZE);
   3230 
   3231 			mutex_exit(&ptgt->tgt_mutex);
   3232 		}
   3233 	}
   3234 
   3235 	/* Release global mutex for PLOGI and PRLI */
   3236 	mutex_exit(&fcp_global_mutex);
   3237 
   3238 	/* Send PLOGI (If necessary) */
   3239 	if (*ret_val == 0) {
   3240 		*ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
   3241 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
   3242 	}
   3243 
   3244 	/* Send PRLI (If necessary) */
   3245 	if (*ret_val == 0) {
   3246 		*ret_val = fcp_tgt_send_prli(ptgt, fc_status,
   3247 		    fc_pkt_state, fc_pkt_reason, fc_pkt_action);
   3248 	}
   3249 
   3250 	mutex_enter(&fcp_global_mutex);
   3251 
   3252 	return (ptgt);
   3253 }
   3254 
   3255 /*
   3256  *     Function: fcp_tgt_send_plogi
   3257  *
   3258  *  Description: This function sends a PLOGI to the target specified by the
   3259  *		 caller and waits till it completes.
   3260  *
   3261  *     Argument: ptgt		Target to send the plogi to.
   3262  *		 fc_status	Status returned by fp/fctl in the PLOGI request.
   3263  *		 fc_pkt_state	State returned by fp/fctl in the PLOGI request.
   3264  *		 fc_pkt_reason	Reason returned by fp/fctl in the PLOGI request.
   3265  *		 fc_pkt_action	Action returned by fp/fctl in the PLOGI request.
   3266  *
   3267  * Return Value: 0
   3268  *		 ENOMEM
   3269  *		 EIO
   3270  *
   3271  *	Context: User context.
   3272  */
   3273 static int
   3274 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
   3275     int *fc_pkt_reason, int *fc_pkt_action)
   3276 {
   3277 	struct fcp_port	*pptr;
   3278 	struct fcp_ipkt	*icmd;
   3279 	struct fc_packet	*fpkt;
   3280 	fc_frame_hdr_t		*hp;
   3281 	struct la_els_logi	logi;
   3282 	int			tcount;
   3283 	int			lcount;
   3284 	int			ret, login_retval = ~FC_SUCCESS;
   3285 
   3286 	ret = 0;
   3287 
   3288 	pptr = ptgt->tgt_port;
   3289 
   3290 	lcount = pptr->port_link_cnt;
   3291 	tcount = ptgt->tgt_change_cnt;
   3292 
   3293 	/* Alloc internal packet */
   3294 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
   3295 	    sizeof (la_els_logi_t), 0,
   3296 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
   3297 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
   3298 
   3299 	if (icmd == NULL) {
   3300 		ret = ENOMEM;
   3301 	} else {
   3302 		/*
   3303 		 * Setup internal packet as sema sync
   3304 		 */
   3305 		fcp_ipkt_sema_init(icmd);
   3306 
   3307 		/*
   3308 		 * Setup internal packet (icmd)
   3309 		 */
   3310 		icmd->ipkt_lun		= NULL;
   3311 		icmd->ipkt_restart	= 0;
   3312 		icmd->ipkt_retries	= 0;
   3313 		icmd->ipkt_opcode	= LA_ELS_PLOGI;
   3314 
   3315 		/*
   3316 		 * Setup fc_packet
   3317 		 */
   3318 		fpkt = icmd->ipkt_fpkt;
   3319 
   3320 		fpkt->pkt_tran_flags	= FC_TRAN_CLASS3 | FC_TRAN_INTR;
   3321 		fpkt->pkt_tran_type	= FC_PKT_EXCHANGE;
   3322 		fpkt->pkt_timeout	= FCP_ELS_TIMEOUT;
   3323 
   3324 		/*
   3325 		 * Setup FC frame header
   3326 		 */
   3327 		hp = &fpkt->pkt_cmd_fhdr;
   3328 
   3329 		hp->s_id	= pptr->port_id;	/* source ID */
   3330 		hp->d_id	= ptgt->tgt_d_id;	/* dest ID */
   3331 		hp->r_ctl	= R_CTL_ELS_REQ;
   3332 		hp->type	= FC_TYPE_EXTENDED_LS;
   3333 		hp->f_ctl	= F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
   3334 		hp->seq_id	= 0;
   3335 		hp->rsvd	= 0;
   3336 		hp->df_ctl	= 0;
   3337 		hp->seq_cnt	= 0;
   3338 		hp->ox_id	= 0xffff;		/* i.e. none */
   3339 		hp->rx_id	= 0xffff;		/* i.e. none */
   3340 		hp->ro		= 0;
   3341 
   3342 		/*
   3343 		 * Setup PLOGI
   3344 		 */
   3345 		bzero(&logi, sizeof (struct la_els_logi));
   3346 		logi.ls_code.ls_code = LA_ELS_PLOGI;
   3347 
   3348 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
   3349 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
   3350 
   3351 		/*
   3352 		 * Send PLOGI
   3353 		 */
   3354 		*fc_status = login_retval =
   3355 		    fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
   3356 		if (*fc_status != FC_SUCCESS) {
   3357 			ret = EIO;
   3358 		}
   3359 	}
   3360 
   3361 	/*
   3362 	 * Wait for completion
   3363 	 */
   3364 	if ((ret == 0) && (login_retval == FC_SUCCESS)) {
   3365 		ret = fcp_ipkt_sema_wait(icmd);
   3366 
   3367 		*fc_pkt_state	= fpkt->pkt_state;
   3368 		*fc_pkt_reason	= fpkt->pkt_reason;
   3369 		*fc_pkt_action	= fpkt->pkt_action;
   3370 	}
   3371 
   3372 	/*
   3373 	 * Cleanup transport data structures if icmd was alloc-ed AND if there
   3374 	 * is going to be no callback (i.e if fc_ulp_login() failed).
   3375 	 * Otherwise, cleanup happens in callback routine.
   3376 	 */
   3377 	if (icmd != NULL) {
   3378 		fcp_ipkt_sema_cleanup(icmd);
   3379 	}
   3380 
   3381 	return (ret);
   3382 }
   3383 
   3384 /*
   3385  *     Function: fcp_tgt_send_prli
   3386  *
   3387  *  Description: Does nothing as of today.
   3388  *
   3389  *     Argument: ptgt		Target to send the prli to.
   3390  *		 fc_status	Status returned by fp/fctl in the PRLI request.
   3391  *		 fc_pkt_state	State returned by fp/fctl in the PRLI request.
   3392  *		 fc_pkt_reason	Reason returned by fp/fctl in the PRLI request.
   3393  *		 fc_pkt_action	Action returned by fp/fctl in the PRLI request.
   3394  *
   3395  * Return Value: 0
   3396  */
   3397 /*ARGSUSED*/
   3398 static int
   3399 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
   3400     int *fc_pkt_reason, int *fc_pkt_action)
   3401 {
   3402 	return (0);
   3403 }
   3404 
   3405 /*
   3406  *     Function: fcp_ipkt_sema_init
   3407  *
   3408  *  Description: Initializes the semaphore contained in the internal packet.
   3409  *
   3410  *     Argument: icmd	Internal packet the semaphore of which must be
   3411  *			initialized.
   3412  *
   3413  * Return Value: None
   3414  *
   3415  *	Context: User context only.
   3416  */
   3417 static void
   3418 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
   3419 {
   3420 	struct fc_packet	*fpkt;
   3421 
   3422 	fpkt = icmd->ipkt_fpkt;
   3423 
   3424 	/* Create semaphore for sync */
   3425 	sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
   3426 
   3427 	/* Setup the completion callback */
   3428 	fpkt->pkt_comp = fcp_ipkt_sema_callback;
   3429 }
   3430 
   3431 /*
   3432  *     Function: fcp_ipkt_sema_wait
   3433  *
   3434  *  Description: Wait on the semaphore embedded in the internal packet.	 The
   3435  *		 semaphore is released in the callback.
   3436  *
   3437  *     Argument: icmd	Internal packet to wait on for completion.
   3438  *
   3439  * Return Value: 0
   3440  *		 EIO
   3441  *		 EBUSY
   3442  *		 EAGAIN
   3443  *
   3444  *	Context: User context only.
   3445  *
   3446  * This function does a conversion between the field pkt_state of the fc_packet
   3447  * embedded in the internal packet (icmd) and the code it returns.
   3448  */
   3449 static int
   3450 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
   3451 {
   3452 	struct fc_packet	*fpkt;
   3453 	int	ret;
   3454 
   3455 	ret = EIO;
   3456 	fpkt = icmd->ipkt_fpkt;
   3457 
   3458 	/*
   3459 	 * Wait on semaphore
   3460 	 */
   3461 	sema_p(&(icmd->ipkt_sema));
   3462 
   3463 	/*
   3464 	 * Check the status of the FC packet
   3465 	 */
   3466 	switch (fpkt->pkt_state) {
   3467 	case FC_PKT_SUCCESS:
   3468 		ret = 0;
   3469 		break;
   3470 	case FC_PKT_LOCAL_RJT:
   3471 		switch (fpkt->pkt_reason) {
   3472 		case FC_REASON_SEQ_TIMEOUT:
   3473 		case FC_REASON_RX_BUF_TIMEOUT:
   3474 			ret = EAGAIN;
   3475 			break;
   3476 		case FC_REASON_PKT_BUSY:
   3477 			ret = EBUSY;
   3478 			break;
   3479 		}
   3480 		break;
   3481 	case FC_PKT_TIMEOUT:
   3482 		ret = EAGAIN;
   3483 		break;
   3484 	case FC_PKT_LOCAL_BSY:
   3485 	case FC_PKT_TRAN_BSY:
   3486 	case FC_PKT_NPORT_BSY:
   3487 	case FC_PKT_FABRIC_BSY:
   3488 		ret = EBUSY;
   3489 		break;
   3490 	case FC_PKT_LS_RJT:
   3491 	case FC_PKT_BA_RJT:
   3492 		switch (fpkt->pkt_reason) {
   3493 		case FC_REASON_LOGICAL_BSY:
   3494 			ret = EBUSY;
   3495 			break;
   3496 		}
   3497 		break;
   3498 	case FC_PKT_FS_RJT:
   3499 		switch (fpkt->pkt_reason) {
   3500 		case FC_REASON_FS_LOGICAL_BUSY:
   3501 			ret = EBUSY;
   3502 			break;
   3503 		}
   3504 		break;
   3505 	}
   3506 
   3507 	return (ret);
   3508 }
   3509 
   3510 /*
   3511  *     Function: fcp_ipkt_sema_callback
   3512  *
   3513  *  Description: Registered as the completion callback function for the FC
   3514  *		 transport when the ipkt semaphore is used for sync. This will
   3515  *		 cleanup the used data structures, if necessary and wake up
   3516  *		 the user thread to complete the transaction.
   3517  *
   3518  *     Argument: fpkt	FC packet (points to the icmd)
   3519  *
   3520  * Return Value: None
   3521  *
   3522  *	Context: User context only
   3523  */
   3524 static void
   3525 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
   3526 {
   3527 	struct fcp_ipkt	*icmd;
   3528 
   3529 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
   3530 
   3531 	/*
   3532 	 * Wake up user thread
   3533 	 */
   3534 	sema_v(&(icmd->ipkt_sema));
   3535 }
   3536 
   3537 /*
   3538  *     Function: fcp_ipkt_sema_cleanup
   3539  *
   3540  *  Description: Called to cleanup (if necessary) the data structures used
   3541  *		 when ipkt sema is used for sync.  This function will detect
   3542  *		 whether the caller is the last thread (via counter) and
   3543  *		 cleanup only if necessary.
   3544  *
   3545  *     Argument: icmd	Internal command packet
   3546  *
   3547  * Return Value: None
   3548  *
   3549  *	Context: User context only
   3550  */
   3551 static void
   3552 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
   3553 {
   3554 	struct fcp_tgt	*ptgt;
   3555 	struct fcp_port	*pptr;
   3556 
   3557 	ptgt = icmd->ipkt_tgt;
   3558 	pptr = icmd->ipkt_port;
   3559 
   3560 	/*
   3561 	 * Acquire data structure
   3562 	 */
   3563 	mutex_enter(&ptgt->tgt_mutex);
   3564 
   3565 	/*
   3566 	 * Destroy semaphore
   3567 	 */
   3568 	sema_destroy(&(icmd->ipkt_sema));
   3569 
   3570 	/*
   3571 	 * Cleanup internal packet
   3572 	 */
   3573 	mutex_exit(&ptgt->tgt_mutex);
   3574 	fcp_icmd_free(pptr, icmd);
   3575 }
   3576 
   3577 /*
   3578  *     Function: fcp_port_attach
   3579  *
   3580  *  Description: Called by the transport framework to resume, suspend or
   3581  *		 attach a new port.
   3582  *
   3583  *     Argument: ulph		Port handle
   3584  *		 *pinfo		Port information
   3585  *		 cmd		Command
   3586  *		 s_id		Port ID
   3587  *
   3588  * Return Value: FC_FAILURE or FC_SUCCESS
   3589  */
   3590 /*ARGSUSED*/
   3591 static int
   3592 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
   3593     fc_attach_cmd_t cmd, uint32_t s_id)
   3594 {
   3595 	int	instance;
   3596 	int	res = FC_FAILURE; /* default result */
   3597 
   3598 	ASSERT(pinfo != NULL);
   3599 
   3600 	instance = ddi_get_instance(pinfo->port_dip);
   3601 
   3602 	switch (cmd) {
   3603 	case FC_CMD_ATTACH:
   3604 		/*
   3605 		 * this port instance attaching for the first time (or after
   3606 		 * being detached before)
   3607 		 */
   3608 		if (fcp_handle_port_attach(ulph, pinfo, s_id,
   3609 		    instance) == DDI_SUCCESS) {
   3610 			res = FC_SUCCESS;
   3611 		} else {
   3612 			ASSERT(ddi_get_soft_state(fcp_softstate,
   3613 			    instance) == NULL);
   3614 		}
   3615 		break;
   3616 
   3617 	case FC_CMD_RESUME:
   3618 	case FC_CMD_POWER_UP:
   3619 		/*
   3620 		 * this port instance was attached and the suspended and
   3621 		 * will now be resumed
   3622 		 */
   3623 		if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
   3624 		    instance) == DDI_SUCCESS) {
   3625 			res = FC_SUCCESS;
   3626 		}
   3627 		break;
   3628 
   3629 	default:
   3630 		/* shouldn't happen */
   3631 		FCP_TRACE(fcp_logq, "fcp",
   3632 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   3633 		    "port_attach: unknown cmdcommand: %d", cmd);
   3634 		break;
   3635 	}
   3636 
   3637 	/* return result */
   3638 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
   3639 	    FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
   3640 
   3641 	return (res);
   3642 }
   3643 
   3644 
   3645 /*
   3646  * detach or suspend this port instance
   3647  *
   3648  * acquires and releases the global mutex
   3649  *
   3650  * acquires and releases the mutex for this port
   3651  *
   3652  * acquires and releases the hotplug mutex for this port
   3653  */
   3654 /*ARGSUSED*/
   3655 static int
   3656 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
   3657     fc_detach_cmd_t cmd)
   3658 {
   3659 	int			flag;
   3660 	int			instance;
   3661 	struct fcp_port		*pptr;
   3662 
   3663 	instance = ddi_get_instance(info->port_dip);
   3664 	pptr = ddi_get_soft_state(fcp_softstate, instance);
   3665 
   3666 	switch (cmd) {
   3667 	case FC_CMD_SUSPEND:
   3668 		FCP_DTRACE(fcp_logq, "fcp",
   3669 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
   3670 		    "port suspend called for port %d", instance);
   3671 		flag = FCP_STATE_SUSPENDED;
   3672 		break;
   3673 
   3674 	case FC_CMD_POWER_DOWN:
   3675 		FCP_DTRACE(fcp_logq, "fcp",
   3676 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
   3677 		    "port power down called for port %d", instance);
   3678 		flag = FCP_STATE_POWER_DOWN;
   3679 		break;
   3680 
   3681 	case FC_CMD_DETACH:
   3682 		FCP_DTRACE(fcp_logq, "fcp",
   3683 		    fcp_trace, FCP_BUF_LEVEL_8, 0,
   3684 		    "port detach called for port %d", instance);
   3685 		flag = FCP_STATE_DETACHING;
   3686 		break;
   3687 
   3688 	default:
   3689 		/* shouldn't happen */
   3690 		return (FC_FAILURE);
   3691 	}
   3692 	FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
   3693 	    FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
   3694 
   3695 	return (fcp_handle_port_detach(pptr, flag, instance));
   3696 }
   3697 
   3698 
   3699 /*
   3700  * called for ioctls on the transport's devctl interface, and the transport
   3701  * has passed it to us
   3702  *
   3703  * this will only be called for device control ioctls (i.e. hotplugging stuff)
   3704  *
   3705  * return FC_SUCCESS if we decide to claim the ioctl,
   3706  * else return FC_UNCLAIMED
   3707  *
   3708  * *rval is set iff we decide to claim the ioctl
   3709  */
   3710 /*ARGSUSED*/
   3711 static int
   3712 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
   3713     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
   3714 {
   3715 	int			retval = FC_UNCLAIMED;	/* return value */
   3716 	struct fcp_port		*pptr = NULL;		/* our soft state */
   3717 	struct devctl_iocdata	*dcp = NULL;		/* for devctl */
   3718 	dev_info_t		*cdip;
   3719 	mdi_pathinfo_t		*pip = NULL;
   3720 	char			*ndi_nm;		/* NDI name */
   3721 	char			*ndi_addr;		/* NDI addr */
   3722 	int			is_mpxio, circ;
   3723 	int			devi_entered = 0;
   3724 	time_t			end_time;
   3725 
   3726 	ASSERT(rval != NULL);
   3727 
   3728 	FCP_DTRACE(fcp_logq, "fcp",
   3729 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
   3730 	    "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
   3731 
   3732 	/* if already claimed then forget it */
   3733 	if (claimed) {
   3734 		/*
   3735 		 * for now, if this ioctl has already been claimed, then
   3736 		 * we just ignore it
   3737 		 */
   3738 		return (retval);
   3739 	}
   3740 
   3741 	/* get our port info */
   3742 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
   3743 		fcp_log(CE_WARN, NULL,
   3744 		    "!fcp:Invalid port handle handle in ioctl");
   3745 		*rval = ENXIO;
   3746 		return (retval);
   3747 	}
   3748 	is_mpxio = pptr->port_mpxio;
   3749 
   3750 	switch (cmd) {
   3751 	case DEVCTL_BUS_GETSTATE:
   3752 	case DEVCTL_BUS_QUIESCE:
   3753 	case DEVCTL_BUS_UNQUIESCE:
   3754 	case DEVCTL_BUS_RESET:
   3755 	case DEVCTL_BUS_RESETALL:
   3756 
   3757 	case DEVCTL_BUS_DEV_CREATE:
   3758 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
   3759 			return (retval);
   3760 		}
   3761 		break;
   3762 
   3763 	case DEVCTL_DEVICE_GETSTATE:
   3764 	case DEVCTL_DEVICE_OFFLINE:
   3765 	case DEVCTL_DEVICE_ONLINE:
   3766 	case DEVCTL_DEVICE_REMOVE:
   3767 	case DEVCTL_DEVICE_RESET:
   3768 		if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
   3769 			return (retval);
   3770 		}
   3771 
   3772 		ASSERT(dcp != NULL);
   3773 
   3774 		/* ensure we have a name and address */
   3775 		if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
   3776 		    ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
   3777 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   3778 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   3779 			    "ioctl: can't get name (%s) or addr (%s)",
   3780 			    ndi_nm ? ndi_nm : "<null ptr>",
   3781 			    ndi_addr ? ndi_addr : "<null ptr>");
   3782 			ndi_dc_freehdl(dcp);
   3783 			return (retval);
   3784 		}
   3785 
   3786 
   3787 		/* get our child's DIP */
   3788 		ASSERT(pptr != NULL);
   3789 		if (is_mpxio) {
   3790 			mdi_devi_enter(pptr->port_dip, &circ);
   3791 		} else {
   3792 			ndi_devi_enter(pptr->port_dip, &circ);
   3793 		}
   3794 		devi_entered = 1;
   3795 
   3796 		if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
   3797 		    ndi_addr)) == NULL) {
   3798 			/* Look for virtually enumerated devices. */
   3799 			pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
   3800 			if (pip == NULL ||
   3801 			    ((cdip = mdi_pi_get_client(pip)) == NULL)) {
   3802 				*rval = ENXIO;
   3803 				goto out;
   3804 			}
   3805 		}
   3806 		break;
   3807 
   3808 	default:
   3809 		*rval = ENOTTY;
   3810 		return (retval);
   3811 	}
   3812 
   3813 	/* this ioctl is ours -- process it */
   3814 
   3815 	retval = FC_SUCCESS;		/* just means we claim the ioctl */
   3816 
   3817 	/* we assume it will be a success; else we'll set error value */
   3818 	*rval = 0;
   3819 
   3820 
   3821 	FCP_DTRACE(fcp_logq, pptr->port_instbuf,
   3822 	    fcp_trace, FCP_BUF_LEVEL_8, 0,
   3823 	    "ioctl: claiming this one");
   3824 
   3825 	/* handle ioctls now */
   3826 	switch (cmd) {
   3827 	case DEVCTL_DEVICE_GETSTATE:
   3828 		ASSERT(cdip != NULL);
   3829 		ASSERT(dcp != NULL);
   3830 		if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
   3831 			*rval = EFAULT;
   3832 		}
   3833 		break;
   3834 
   3835 	case DEVCTL_DEVICE_REMOVE:
   3836 	case DEVCTL_DEVICE_OFFLINE: {
   3837 		int			flag = 0;
   3838 		int			lcount;
   3839 		int			tcount;
   3840 		struct fcp_pkt	*head = NULL;
   3841 		struct fcp_lun	*plun;
   3842 		child_info_t		*cip = CIP(cdip);
   3843 		int			all = 1;
   3844 		struct fcp_lun	*tplun;
   3845 		struct fcp_tgt	*ptgt;
   3846 
   3847 		ASSERT(pptr != NULL);
   3848 		ASSERT(cdip != NULL);
   3849 
   3850 		mutex_enter(&pptr->port_mutex);
   3851 		if (pip != NULL) {
   3852 			cip = CIP(pip);
   3853 		}
   3854 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
   3855 			mutex_exit(&pptr->port_mutex);
   3856 			*rval = ENXIO;
   3857 			break;
   3858 		}
   3859 
   3860 		head = fcp_scan_commands(plun);
   3861 		if (head != NULL) {
   3862 			fcp_abort_commands(head, LUN_PORT);
   3863 		}
   3864 		lcount = pptr->port_link_cnt;
   3865 		tcount = plun->lun_tgt->tgt_change_cnt;
   3866 		mutex_exit(&pptr->port_mutex);
   3867 
   3868 		if (cmd == DEVCTL_DEVICE_REMOVE) {
   3869 			flag = NDI_DEVI_REMOVE;
   3870 		}
   3871 
   3872 		if (is_mpxio) {
   3873 			mdi_devi_exit(pptr->port_dip, circ);
   3874 		} else {
   3875 			ndi_devi_exit(pptr->port_dip, circ);
   3876 		}
   3877 		devi_entered = 0;
   3878 
   3879 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
   3880 		    FCP_OFFLINE, lcount, tcount, flag);
   3881 
   3882 		if (*rval != NDI_SUCCESS) {
   3883 			*rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
   3884 			break;
   3885 		}
   3886 
   3887 		fcp_update_offline_flags(plun);
   3888 
   3889 		ptgt = plun->lun_tgt;
   3890 		mutex_enter(&ptgt->tgt_mutex);
   3891 		for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
   3892 		    tplun->lun_next) {
   3893 			mutex_enter(&tplun->lun_mutex);
   3894 			if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
   3895 				all = 0;
   3896 			}
   3897 			mutex_exit(&tplun->lun_mutex);
   3898 		}
   3899 
   3900 		if (all) {
   3901 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
   3902 			/*
   3903 			 * The user is unconfiguring/offlining the device.
   3904 			 * If fabric and the auto configuration is set
   3905 			 * then make sure the user is the only one who
   3906 			 * can reconfigure the device.
   3907 			 */
   3908 			if (FC_TOP_EXTERNAL(pptr->port_topology) &&
   3909 			    fcp_enable_auto_configuration) {
   3910 				ptgt->tgt_manual_config_only = 1;
   3911 			}
   3912 		}
   3913 		mutex_exit(&ptgt->tgt_mutex);
   3914 		break;
   3915 	}
   3916 
   3917 	case DEVCTL_DEVICE_ONLINE: {
   3918 		int			lcount;
   3919 		int			tcount;
   3920 		struct fcp_lun	*plun;
   3921 		child_info_t		*cip = CIP(cdip);
   3922 
   3923 		ASSERT(cdip != NULL);
   3924 		ASSERT(pptr != NULL);
   3925 
   3926 		mutex_enter(&pptr->port_mutex);
   3927 		if (pip != NULL) {
   3928 			cip = CIP(pip);
   3929 		}
   3930 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
   3931 			mutex_exit(&pptr->port_mutex);
   3932 			*rval = ENXIO;
   3933 			break;
   3934 		}
   3935 		lcount = pptr->port_link_cnt;
   3936 		tcount = plun->lun_tgt->tgt_change_cnt;
   3937 		mutex_exit(&pptr->port_mutex);
   3938 
   3939 		/*
   3940 		 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
   3941 		 * to allow the device attach to occur when the device is
   3942 		 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
   3943 		 * from the scsi_probe()).
   3944 		 */
   3945 		mutex_enter(&LUN_TGT->tgt_mutex);
   3946 		plun->lun_state |= FCP_LUN_ONLINING;
   3947 		mutex_exit(&LUN_TGT->tgt_mutex);
   3948 
   3949 		if (is_mpxio) {
   3950 			mdi_devi_exit(pptr->port_dip, circ);
   3951 		} else {
   3952 			ndi_devi_exit(pptr->port_dip, circ);
   3953 		}
   3954 		devi_entered = 0;
   3955 
   3956 		*rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
   3957 		    FCP_ONLINE, lcount, tcount, 0);
   3958 
   3959 		if (*rval != NDI_SUCCESS) {
   3960 			/* Reset the FCP_LUN_ONLINING bit */
   3961 			mutex_enter(&LUN_TGT->tgt_mutex);
   3962 			plun->lun_state &= ~FCP_LUN_ONLINING;
   3963 			mutex_exit(&LUN_TGT->tgt_mutex);
   3964 			*rval = EIO;
   3965 			break;
   3966 		}
   3967 		mutex_enter(&LUN_TGT->tgt_mutex);
   3968 		plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
   3969 		    FCP_LUN_ONLINING);
   3970 		mutex_exit(&LUN_TGT->tgt_mutex);
   3971 		break;
   3972 	}
   3973 
   3974 	case DEVCTL_BUS_DEV_CREATE: {
   3975 		uchar_t			*bytes = NULL;
   3976 		uint_t			nbytes;
   3977 		struct fcp_tgt		*ptgt = NULL;
   3978 		struct fcp_lun		*plun = NULL;
   3979 		dev_info_t		*useless_dip = NULL;
   3980 
   3981 		*rval = ndi_dc_devi_create(dcp, pptr->port_dip,
   3982 		    DEVCTL_CONSTRUCT, &useless_dip);
   3983 		if (*rval != 0 || useless_dip == NULL) {
   3984 			break;
   3985 		}
   3986 
   3987 		if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
   3988 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
   3989 		    &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
   3990 			*rval = EINVAL;
   3991 			(void) ndi_devi_free(useless_dip);
   3992 			if (bytes != NULL) {
   3993 				ddi_prop_free(bytes);
   3994 			}
   3995 			break;
   3996 		}
   3997 
   3998 		*rval = fcp_create_on_demand(pptr, bytes);
   3999 		if (*rval == 0) {
   4000 			mutex_enter(&pptr->port_mutex);
   4001 			ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
   4002 			if (ptgt) {
   4003 				/*
   4004 				 * We now have a pointer to the target that
   4005 				 * was created. Lets point to the first LUN on
   4006 				 * this new target.
   4007 				 */
   4008 				mutex_enter(&ptgt->tgt_mutex);
   4009 
   4010 				plun = ptgt->tgt_lun;
   4011 				/*
   4012 				 * There may be stale/offline LUN entries on
   4013 				 * this list (this is by design) and so we have
   4014 				 * to make sure we point to the first online
   4015 				 * LUN
   4016 				 */
   4017 				while (plun &&
   4018 				    plun->lun_state & FCP_LUN_OFFLINE) {
   4019 					plun = plun->lun_next;
   4020 				}
   4021 
   4022 				mutex_exit(&ptgt->tgt_mutex);
   4023 			}
   4024 			mutex_exit(&pptr->port_mutex);
   4025 		}
   4026 
   4027 		if (*rval == 0 && ptgt && plun) {
   4028 			mutex_enter(&plun->lun_mutex);
   4029 			/*
   4030 			 * Allow up to fcp_lun_ready_retry seconds to
   4031 			 * configure all the luns behind the target.
   4032 			 *
   4033 			 * The intent here is to allow targets with long
   4034 			 * reboot/reset-recovery times to become available
   4035 			 * while limiting the maximum wait time for an
   4036 			 * unresponsive target.
   4037 			 */
   4038 			end_time = ddi_get_lbolt() +
   4039 			    SEC_TO_TICK(fcp_lun_ready_retry);
   4040 
   4041 			while (ddi_get_lbolt() < end_time) {
   4042 				retval = FC_SUCCESS;
   4043 
   4044 				/*
   4045 				 * The new ndi interfaces for on-demand creation
   4046 				 * are inflexible, Do some more work to pass on
   4047 				 * a path name of some LUN (design is broken !)
   4048 				 */
   4049 				if (plun->lun_cip) {
   4050 					if (plun->lun_mpxio == 0) {
   4051 						cdip = DIP(plun->lun_cip);
   4052 					} else {
   4053 						cdip = mdi_pi_get_client(
   4054 						    PIP(plun->lun_cip));
   4055 					}
   4056 					if (cdip == NULL) {
   4057 						*rval = ENXIO;
   4058 						break;
   4059 					}
   4060 
   4061 					if (!i_ddi_devi_attached(cdip)) {
   4062 						mutex_exit(&plun->lun_mutex);
   4063 						delay(drv_usectohz(1000000));
   4064 						mutex_enter(&plun->lun_mutex);
   4065 					} else {
   4066 						/*
   4067 						 * This Lun is ready, lets
   4068 						 * check the next one.
   4069 						 */
   4070 						mutex_exit(&plun->lun_mutex);
   4071 						plun = plun->lun_next;
   4072 						while (plun && (plun->lun_state
   4073 						    & FCP_LUN_OFFLINE)) {
   4074 							plun = plun->lun_next;
   4075 						}
   4076 						if (!plun) {
   4077 							break;
   4078 						}
   4079 						mutex_enter(&plun->lun_mutex);
   4080 					}
   4081 				} else {
   4082 					/*
   4083 					 * lun_cip field for a valid lun
   4084 					 * should never be NULL. Fail the
   4085 					 * command.
   4086 					 */
   4087 					*rval = ENXIO;
   4088 					break;
   4089 				}
   4090 			}
   4091 			if (plun) {
   4092 				mutex_exit(&plun->lun_mutex);
   4093 			} else {
   4094 				char devnm[MAXNAMELEN];
   4095 				int nmlen;
   4096 
   4097 				nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
   4098 				    ddi_node_name(cdip),
   4099 				    ddi_get_name_addr(cdip));
   4100 
   4101 				if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
   4102 				    0) {
   4103 					*rval = EFAULT;
   4104 				}
   4105 			}
   4106 		} else {
   4107 			int	i;
   4108 			char	buf[25];
   4109 
   4110 			for (i = 0; i < FC_WWN_SIZE; i++) {
   4111 				(void) sprintf(&buf[i << 1], "%02x", bytes[i]);
   4112 			}
   4113 
   4114 			fcp_log(CE_WARN, pptr->port_dip,
   4115 			    "!Failed to create nodes for pwwn=%s; error=%x",
   4116 			    buf, *rval);
   4117 		}
   4118 
   4119 		(void) ndi_devi_free(useless_dip);
   4120 		ddi_prop_free(bytes);
   4121 		break;
   4122 	}
   4123 
   4124 	case DEVCTL_DEVICE_RESET: {
   4125 		struct fcp_lun		*plun;
   4126 		child_info_t		*cip = CIP(cdip);
   4127 
   4128 		ASSERT(cdip != NULL);
   4129 		ASSERT(pptr != NULL);
   4130 		mutex_enter(&pptr->port_mutex);
   4131 		if (pip != NULL) {
   4132 			cip = CIP(pip);
   4133 		}
   4134 		if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
   4135 			mutex_exit(&pptr->port_mutex);
   4136 			*rval = ENXIO;
   4137 			break;
   4138 		}
   4139 		mutex_exit(&pptr->port_mutex);
   4140 
   4141 		mutex_enter(&plun->lun_tgt->tgt_mutex);
   4142 		if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
   4143 			mutex_exit(&plun->lun_tgt->tgt_mutex);
   4144 
   4145 			*rval = ENXIO;
   4146 			break;
   4147 		}
   4148 
   4149 		if (plun->lun_sd == NULL) {
   4150 			mutex_exit(&plun->lun_tgt->tgt_mutex);
   4151 
   4152 			*rval = ENXIO;
   4153 			break;
   4154 		}
   4155 		mutex_exit(&plun->lun_tgt->tgt_mutex);
   4156 
   4157 		/*
   4158 		 * set up ap so that fcp_reset can figure out
   4159 		 * which target to reset
   4160 		 */
   4161 		if (fcp_scsi_reset(&plun->lun_sd->sd_address,
   4162 		    RESET_TARGET) == FALSE) {
   4163 			*rval = EIO;
   4164 		}
   4165 		break;
   4166 	}
   4167 
   4168 	case DEVCTL_BUS_GETSTATE:
   4169 		ASSERT(dcp != NULL);
   4170 		ASSERT(pptr != NULL);
   4171 		ASSERT(pptr->port_dip != NULL);
   4172 		if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
   4173 		    NDI_SUCCESS) {
   4174 			*rval = EFAULT;
   4175 		}
   4176 		break;
   4177 
   4178 	case DEVCTL_BUS_QUIESCE:
   4179 	case DEVCTL_BUS_UNQUIESCE:
   4180 		*rval = ENOTSUP;
   4181 		break;
   4182 
   4183 	case DEVCTL_BUS_RESET:
   4184 	case DEVCTL_BUS_RESETALL:
   4185 		ASSERT(pptr != NULL);
   4186 		(void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
   4187 		break;
   4188 
   4189 	default:
   4190 		ASSERT(dcp != NULL);
   4191 		*rval = ENOTTY;
   4192 		break;
   4193 	}
   4194 
   4195 	/* all done -- clean up and return */
   4196 out:	if (devi_entered) {
   4197 		if (is_mpxio) {
   4198 			mdi_devi_exit(pptr->port_dip, circ);
   4199 		} else {
   4200 			ndi_devi_exit(pptr->port_dip, circ);
   4201 		}
   4202 	}
   4203 
   4204 	if (dcp != NULL) {
   4205 		ndi_dc_freehdl(dcp);
   4206 	}
   4207 
   4208 	return (retval);
   4209 }
   4210 
   4211 
   4212 /*ARGSUSED*/
   4213 static int
   4214 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
   4215     uint32_t claimed)
   4216 {
   4217 	uchar_t			r_ctl;
   4218 	uchar_t			ls_code;
   4219 	struct fcp_port	*pptr;
   4220 
   4221 	if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
   4222 		return (FC_UNCLAIMED);
   4223 	}
   4224 
   4225 	mutex_enter(&pptr->port_mutex);
   4226 	if (pptr->port_state & (FCP_STATE_DETACHING |
   4227 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
   4228 		mutex_exit(&pptr->port_mutex);
   4229 		return (FC_UNCLAIMED);
   4230 	}
   4231 	mutex_exit(&pptr->port_mutex);
   4232 
   4233 	r_ctl = buf->ub_frame.r_ctl;
   4234 
   4235 	switch (r_ctl & R_CTL_ROUTING) {
   4236 	case R_CTL_EXTENDED_SVC:
   4237 		if (r_ctl == R_CTL_ELS_REQ) {
   4238 			ls_code = buf->ub_buffer[0];
   4239 
   4240 			switch (ls_code) {
   4241 			case LA_ELS_PRLI:
   4242 				/*
   4243 				 * We really don't care if something fails.
   4244 				 * If the PRLI was not sent out, then the
   4245 				 * other end will time it out.
   4246 				 */
   4247 				if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
   4248 					return (FC_SUCCESS);
   4249 				}
   4250 				return (FC_UNCLAIMED);
   4251 				/* NOTREACHED */
   4252 
   4253 			default:
   4254 				break;
   4255 			}
   4256 		}
   4257 		/* FALLTHROUGH */
   4258 
   4259 	default:
   4260 		return (FC_UNCLAIMED);
   4261 	}
   4262 }
   4263 
   4264 
   4265 /*ARGSUSED*/
   4266 static int
   4267 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
   4268     uint32_t claimed)
   4269 {
   4270 	return (FC_UNCLAIMED);
   4271 }
   4272 
   4273 /*
   4274  *     Function: fcp_statec_callback
   4275  *
   4276  *  Description: The purpose of this function is to handle a port state change.
   4277  *		 It is called from fp/fctl and, in a few instances, internally.
   4278  *
   4279  *     Argument: ulph		fp/fctl port handle
   4280  *		 port_handle	fcp_port structure
   4281  *		 port_state	Physical state of the port
   4282  *		 port_top	Topology
   4283  *		 *devlist	Pointer to the first entry of a table
   4284  *				containing the remote ports that can be
   4285  *				reached.
   4286  *		 dev_cnt	Number of entries pointed by devlist.
   4287  *		 port_sid	Port ID of the local port.
   4288  *
   4289  * Return Value: None
   4290  */
   4291 /*ARGSUSED*/
   4292 static void
   4293 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
   4294     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
   4295     uint32_t dev_cnt, uint32_t port_sid)
   4296 {
   4297 	uint32_t		link_count;
   4298 	int			map_len = 0;
   4299 	struct fcp_port	*pptr;
   4300 	fcp_map_tag_t		*map_tag = NULL;
   4301 
   4302 	if ((pptr = fcp_get_port(port_handle)) == NULL) {
   4303 		fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
   4304 		return;			/* nothing to work with! */
   4305 	}
   4306 
   4307 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4308 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
   4309 	    "fcp_statec_callback: port state/dev_cnt/top ="
   4310 	    "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
   4311 	    dev_cnt, port_top);
   4312 
   4313 	mutex_enter(&pptr->port_mutex);
   4314 
   4315 	/*
   4316 	 * If a thread is in detach, don't do anything.
   4317 	 */
   4318 	if (pptr->port_state & (FCP_STATE_DETACHING |
   4319 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
   4320 		mutex_exit(&pptr->port_mutex);
   4321 		return;
   4322 	}
   4323 
   4324 	/*
   4325 	 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
   4326 	 * init_pkt is called, it knows whether or not the target's status
   4327 	 * (or pd) might be changing.
   4328 	 */
   4329 
   4330 	if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
   4331 		pptr->port_state |= FCP_STATE_IN_CB_DEVC;
   4332 	}
   4333 
   4334 	/*
   4335 	 * the transport doesn't allocate or probe unless being
   4336 	 * asked to by either the applications or ULPs
   4337 	 *
   4338 	 * in cases where the port is OFFLINE at the time of port
   4339 	 * attach callback and the link comes ONLINE later, for
   4340 	 * easier automatic node creation (i.e. without you having to
   4341 	 * go out and run the utility to perform LOGINs) the
   4342 	 * following conditional is helpful
   4343 	 */
   4344 	pptr->port_phys_state = port_state;
   4345 
   4346 	if (dev_cnt) {
   4347 		mutex_exit(&pptr->port_mutex);
   4348 
   4349 		map_len = sizeof (*map_tag) * dev_cnt;
   4350 		map_tag = kmem_alloc(map_len, KM_NOSLEEP);
   4351 		if (map_tag == NULL) {
   4352 			fcp_log(CE_WARN, pptr->port_dip,
   4353 			    "!fcp%d: failed to allocate for map tags; "
   4354 			    " state change will not be processed",
   4355 			    pptr->port_instance);
   4356 
   4357 			mutex_enter(&pptr->port_mutex);
   4358 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
   4359 			mutex_exit(&pptr->port_mutex);
   4360 
   4361 			return;
   4362 		}
   4363 
   4364 		mutex_enter(&pptr->port_mutex);
   4365 	}
   4366 
   4367 	if (pptr->port_id != port_sid) {
   4368 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4369 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4370 		    "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
   4371 		    port_sid);
   4372 		/*
   4373 		 * The local port changed ID. It is the first time a port ID
   4374 		 * is assigned or something drastic happened.  We might have
   4375 		 * been unplugged and replugged on another loop or fabric port
   4376 		 * or somebody grabbed the AL_PA we had or somebody rezoned
   4377 		 * the fabric we were plugged into.
   4378 		 */
   4379 		pptr->port_id = port_sid;
   4380 	}
   4381 
   4382 	switch (FC_PORT_STATE_MASK(port_state)) {
   4383 	case FC_STATE_OFFLINE:
   4384 	case FC_STATE_RESET_REQUESTED:
   4385 		/*
   4386 		 * link has gone from online to offline -- just update the
   4387 		 * state of this port to BUSY and MARKed to go offline
   4388 		 */
   4389 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4390 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4391 		    "link went offline");
   4392 		if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
   4393 			/*
   4394 			 * We were offline a while ago and this one
   4395 			 * seems to indicate that the loop has gone
   4396 			 * dead forever.
   4397 			 */
   4398 			pptr->port_tmp_cnt += dev_cnt;
   4399 			pptr->port_state &= ~FCP_STATE_OFFLINE;
   4400 			pptr->port_state |= FCP_STATE_INIT;
   4401 			link_count = pptr->port_link_cnt;
   4402 			fcp_handle_devices(pptr, devlist, dev_cnt,
   4403 			    link_count, map_tag, FCP_CAUSE_LINK_DOWN);
   4404 		} else {
   4405 			pptr->port_link_cnt++;
   4406 			ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
   4407 			fcp_update_state(pptr, (FCP_LUN_BUSY |
   4408 			    FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
   4409 			if (pptr->port_mpxio) {
   4410 				fcp_update_mpxio_path_verifybusy(pptr);
   4411 			}
   4412 			pptr->port_state |= FCP_STATE_OFFLINE;
   4413 			pptr->port_state &=
   4414 			    ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
   4415 			pptr->port_tmp_cnt = 0;
   4416 		}
   4417 		mutex_exit(&pptr->port_mutex);
   4418 		break;
   4419 
   4420 	case FC_STATE_ONLINE:
   4421 	case FC_STATE_LIP:
   4422 	case FC_STATE_LIP_LBIT_SET:
   4423 		/*
   4424 		 * link has gone from offline to online
   4425 		 */
   4426 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4427 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4428 		    "link went online");
   4429 
   4430 		pptr->port_link_cnt++;
   4431 
   4432 		while (pptr->port_ipkt_cnt) {
   4433 			mutex_exit(&pptr->port_mutex);
   4434 			delay(drv_usectohz(1000000));
   4435 			mutex_enter(&pptr->port_mutex);
   4436 		}
   4437 
   4438 		pptr->port_topology = port_top;
   4439 
   4440 		/*
   4441 		 * The state of the targets and luns accessible through this
   4442 		 * port is updated.
   4443 		 */
   4444 		fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
   4445 		    FCP_CAUSE_LINK_CHANGE);
   4446 
   4447 		pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
   4448 		pptr->port_state |= FCP_STATE_ONLINING;
   4449 		pptr->port_tmp_cnt = dev_cnt;
   4450 		link_count = pptr->port_link_cnt;
   4451 
   4452 		pptr->port_deadline = fcp_watchdog_time +
   4453 		    FCP_ICMD_DEADLINE;
   4454 
   4455 		if (!dev_cnt) {
   4456 			/*
   4457 			 * We go directly to the online state if no remote
   4458 			 * ports were discovered.
   4459 			 */
   4460 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4461 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4462 			    "No remote ports discovered");
   4463 
   4464 			pptr->port_state &= ~FCP_STATE_ONLINING;
   4465 			pptr->port_state |= FCP_STATE_ONLINE;
   4466 		}
   4467 
   4468 		switch (port_top) {
   4469 		case FC_TOP_FABRIC:
   4470 		case FC_TOP_PUBLIC_LOOP:
   4471 		case FC_TOP_PRIVATE_LOOP:
   4472 		case FC_TOP_PT_PT:
   4473 
   4474 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
   4475 				fcp_retry_ns_registry(pptr, port_sid);
   4476 			}
   4477 
   4478 			fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
   4479 			    map_tag, FCP_CAUSE_LINK_CHANGE);
   4480 			break;
   4481 
   4482 		default:
   4483 			/*
   4484 			 * We got here because we were provided with an unknown
   4485 			 * topology.
   4486 			 */
   4487 			if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
   4488 				pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
   4489 			}
   4490 
   4491 			pptr->port_tmp_cnt -= dev_cnt;
   4492 			fcp_log(CE_WARN, pptr->port_dip,
   4493 			    "!unknown/unsupported topology (0x%x)", port_top);
   4494 			break;
   4495 		}
   4496 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4497 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4498 		    "Notify ssd of the reset to reinstate the reservations");
   4499 
   4500 		scsi_hba_reset_notify_callback(&pptr->port_mutex,
   4501 		    &pptr->port_reset_notify_listf);
   4502 
   4503 		mutex_exit(&pptr->port_mutex);
   4504 
   4505 		break;
   4506 
   4507 	case FC_STATE_RESET:
   4508 		ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
   4509 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4510 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4511 		    "RESET state, waiting for Offline/Online state_cb");
   4512 		mutex_exit(&pptr->port_mutex);
   4513 		break;
   4514 
   4515 	case FC_STATE_DEVICE_CHANGE:
   4516 		/*
   4517 		 * We come here when an application has requested
   4518 		 * Dynamic node creation/deletion in Fabric connectivity.
   4519 		 */
   4520 		if (pptr->port_state & (FCP_STATE_OFFLINE |
   4521 		    FCP_STATE_INIT)) {
   4522 			/*
   4523 			 * This case can happen when the FCTL is in the
   4524 			 * process of giving us on online and the host on
   4525 			 * the other side issues a PLOGI/PLOGO. Ideally
   4526 			 * the state changes should be serialized unless
   4527 			 * they are opposite (online-offline).
   4528 			 * The transport will give us a final state change
   4529 			 * so we can ignore this for the time being.
   4530 			 */
   4531 			pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
   4532 			mutex_exit(&pptr->port_mutex);
   4533 			break;
   4534 		}
   4535 
   4536 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
   4537 			fcp_retry_ns_registry(pptr, port_sid);
   4538 		}
   4539 
   4540 		/*
   4541 		 * Extend the deadline under steady state conditions
   4542 		 * to provide more time for the device-change-commands
   4543 		 */
   4544 		if (!pptr->port_ipkt_cnt) {
   4545 			pptr->port_deadline = fcp_watchdog_time +
   4546 			    FCP_ICMD_DEADLINE;
   4547 		}
   4548 
   4549 		/*
   4550 		 * There is another race condition here, where if we were
   4551 		 * in ONLINEING state and a devices in the map logs out,
   4552 		 * fp will give another state change as DEVICE_CHANGE
   4553 		 * and OLD. This will result in that target being offlined.
   4554 		 * The pd_handle is freed. If from the first statec callback
   4555 		 * we were going to fire a PLOGI/PRLI, the system will
   4556 		 * panic in fc_ulp_transport with invalid pd_handle.
   4557 		 * The fix is to check for the link_cnt before issuing
   4558 		 * any command down.
   4559 		 */
   4560 		fcp_update_targets(pptr, devlist, dev_cnt,
   4561 		    FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
   4562 
   4563 		link_count = pptr->port_link_cnt;
   4564 
   4565 		fcp_handle_devices(pptr, devlist, dev_cnt,
   4566 		    link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
   4567 
   4568 		pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
   4569 
   4570 		mutex_exit(&pptr->port_mutex);
   4571 		break;
   4572 
   4573 	case FC_STATE_TARGET_PORT_RESET:
   4574 		if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
   4575 			fcp_retry_ns_registry(pptr, port_sid);
   4576 		}
   4577 
   4578 		/* Do nothing else */
   4579 		mutex_exit(&pptr->port_mutex);
   4580 		break;
   4581 
   4582 	default:
   4583 		fcp_log(CE_WARN, pptr->port_dip,
   4584 		    "!Invalid state change=0x%x", port_state);
   4585 		mutex_exit(&pptr->port_mutex);
   4586 		break;
   4587 	}
   4588 
   4589 	if (map_tag) {
   4590 		kmem_free(map_tag, map_len);
   4591 	}
   4592 }
   4593 
   4594 /*
   4595  *     Function: fcp_handle_devices
   4596  *
   4597  *  Description: This function updates the devices currently known by
   4598  *		 walking the list provided by the caller.  The list passed
   4599  *		 by the caller is supposed to be the list of reachable
   4600  *		 devices.
   4601  *
   4602  *     Argument: *pptr		Fcp port structure.
   4603  *		 *devlist	Pointer to the first entry of a table
   4604  *				containing the remote ports that can be
   4605  *				reached.
   4606  *		 dev_cnt	Number of entries pointed by devlist.
   4607  *		 link_cnt	Link state count.
   4608  *		 *map_tag	Array of fcp_map_tag_t structures.
   4609  *		 cause		What caused this function to be called.
   4610  *
   4611  * Return Value: None
   4612  *
   4613  *	  Notes: The pptr->port_mutex must be held.
   4614  */
   4615 static void
   4616 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
   4617     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
   4618 {
   4619 	int			i;
   4620 	int			check_finish_init = 0;
   4621 	fc_portmap_t		*map_entry;
   4622 	struct fcp_tgt	*ptgt = NULL;
   4623 
   4624 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4625 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4626 	    "fcp_handle_devices: called for %d dev(s)", dev_cnt);
   4627 
   4628 	if (dev_cnt) {
   4629 		ASSERT(map_tag != NULL);
   4630 	}
   4631 
   4632 	/*
   4633 	 * The following code goes through the list of remote ports that are
   4634 	 * accessible through this (pptr) local port (The list walked is the
   4635 	 * one provided by the caller which is the list of the remote ports
   4636 	 * currently reachable).  It checks if any of them was already
   4637 	 * known by looking for the corresponding target structure based on
   4638 	 * the world wide name.	 If a target is part of the list it is tagged
   4639 	 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
   4640 	 *
   4641 	 * Old comment
   4642 	 * -----------
   4643 	 * Before we drop port mutex; we MUST get the tags updated; This
   4644 	 * two step process is somewhat slow, but more reliable.
   4645 	 */
   4646 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
   4647 		map_entry = &(devlist[i]);
   4648 
   4649 		/*
   4650 		 * get ptr to this map entry in our port's
   4651 		 * list (if any)
   4652 		 */
   4653 		ptgt = fcp_lookup_target(pptr,
   4654 		    (uchar_t *)&(map_entry->map_pwwn));
   4655 
   4656 		if (ptgt) {
   4657 			map_tag[i] = ptgt->tgt_change_cnt;
   4658 			if (cause == FCP_CAUSE_LINK_CHANGE) {
   4659 				ptgt->tgt_aux_state = FCP_TGT_TAGGED;
   4660 			}
   4661 		}
   4662 	}
   4663 
   4664 	/*
   4665 	 * At this point we know which devices of the new list were already
   4666 	 * known (The field tgt_aux_state of the target structure has been
   4667 	 * set to FCP_TGT_TAGGED).
   4668 	 *
   4669 	 * The following code goes through the list of targets currently known
   4670 	 * by the local port (the list is actually a hashing table).  If a
   4671 	 * target is found and is not tagged, it means the target cannot
   4672 	 * be reached anymore through the local port (pptr).  It is offlined.
   4673 	 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
   4674 	 */
   4675 	for (i = 0; i < FCP_NUM_HASH; i++) {
   4676 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
   4677 		    ptgt = ptgt->tgt_next) {
   4678 			mutex_enter(&ptgt->tgt_mutex);
   4679 			if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
   4680 			    (cause == FCP_CAUSE_LINK_CHANGE) &&
   4681 			    !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
   4682 				fcp_offline_target_now(pptr, ptgt,
   4683 				    link_cnt, ptgt->tgt_change_cnt, 0);
   4684 			}
   4685 			mutex_exit(&ptgt->tgt_mutex);
   4686 		}
   4687 	}
   4688 
   4689 	/*
   4690 	 * At this point, the devices that were known but cannot be reached
   4691 	 * anymore, have most likely been offlined.
   4692 	 *
   4693 	 * The following section of code seems to go through the list of
   4694 	 * remote ports that can now be reached.  For every single one it
   4695 	 * checks if it is already known or if it is a new port.
   4696 	 */
   4697 	for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
   4698 
   4699 		if (check_finish_init) {
   4700 			ASSERT(i > 0);
   4701 			(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
   4702 			    map_tag[i - 1], cause);
   4703 			check_finish_init = 0;
   4704 		}
   4705 
   4706 		/* get a pointer to this map entry */
   4707 		map_entry = &(devlist[i]);
   4708 
   4709 		/*
   4710 		 * Check for the duplicate map entry flag. If we have marked
   4711 		 * this entry as a duplicate we skip it since the correct
   4712 		 * (perhaps even same) state change will be encountered
   4713 		 * later in the list.
   4714 		 */
   4715 		if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
   4716 			continue;
   4717 		}
   4718 
   4719 		/* get ptr to this map entry in our port's list (if any) */
   4720 		ptgt = fcp_lookup_target(pptr,
   4721 		    (uchar_t *)&(map_entry->map_pwwn));
   4722 
   4723 		if (ptgt) {
   4724 			/*
   4725 			 * This device was already known.  The field
   4726 			 * tgt_aux_state is reset (was probably set to
   4727 			 * FCP_TGT_TAGGED previously in this routine).
   4728 			 */
   4729 			ptgt->tgt_aux_state = 0;
   4730 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4731 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
   4732 			    "handle_devices: map did/state/type/flags = "
   4733 			    "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
   4734 			    "tgt_state=%d",
   4735 			    map_entry->map_did.port_id, map_entry->map_state,
   4736 			    map_entry->map_type, map_entry->map_flags,
   4737 			    ptgt->tgt_d_id, ptgt->tgt_state);
   4738 		}
   4739 
   4740 		if (map_entry->map_type == PORT_DEVICE_OLD ||
   4741 		    map_entry->map_type == PORT_DEVICE_NEW ||
   4742 		    map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
   4743 		    map_entry->map_type == PORT_DEVICE_CHANGED) {
   4744 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4745 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   4746 			    "map_type=%x, did = %x",
   4747 			    map_entry->map_type,
   4748 			    map_entry->map_did.port_id);
   4749 		}
   4750 
   4751 		switch (map_entry->map_type) {
   4752 		case PORT_DEVICE_NOCHANGE:
   4753 		case PORT_DEVICE_USER_CREATE:
   4754 		case PORT_DEVICE_USER_LOGIN:
   4755 		case PORT_DEVICE_NEW:
   4756 		case PORT_DEVICE_REPORTLUN_CHANGED:
   4757 			FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
   4758 
   4759 			if (fcp_handle_mapflags(pptr, ptgt, map_entry,
   4760 			    link_cnt, (ptgt) ? map_tag[i] : 0,
   4761 			    cause) == TRUE) {
   4762 
   4763 				FCP_TGT_TRACE(ptgt, map_tag[i],
   4764 				    FCP_TGT_TRACE_2);
   4765 				check_finish_init++;
   4766 			}
   4767 			break;
   4768 
   4769 		case PORT_DEVICE_OLD:
   4770 			if (ptgt != NULL) {
   4771 				FCP_TGT_TRACE(ptgt, map_tag[i],
   4772 				    FCP_TGT_TRACE_3);
   4773 
   4774 				mutex_enter(&ptgt->tgt_mutex);
   4775 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
   4776 					/*
   4777 					 * Must do an in-line wait for I/Os
   4778 					 * to get drained
   4779 					 */
   4780 					mutex_exit(&ptgt->tgt_mutex);
   4781 					mutex_exit(&pptr->port_mutex);
   4782 
   4783 					mutex_enter(&ptgt->tgt_mutex);
   4784 					while (ptgt->tgt_ipkt_cnt ||
   4785 					    fcp_outstanding_lun_cmds(ptgt)
   4786 					    == FC_SUCCESS) {
   4787 						mutex_exit(&ptgt->tgt_mutex);
   4788 						delay(drv_usectohz(1000000));
   4789 						mutex_enter(&ptgt->tgt_mutex);
   4790 					}
   4791 					mutex_exit(&ptgt->tgt_mutex);
   4792 
   4793 					mutex_enter(&pptr->port_mutex);
   4794 					mutex_enter(&ptgt->tgt_mutex);
   4795 
   4796 					(void) fcp_offline_target(pptr, ptgt,
   4797 					    link_cnt, map_tag[i], 0, 0);
   4798 				}
   4799 				mutex_exit(&ptgt->tgt_mutex);
   4800 			}
   4801 			check_finish_init++;
   4802 			break;
   4803 
   4804 		case PORT_DEVICE_USER_DELETE:
   4805 		case PORT_DEVICE_USER_LOGOUT:
   4806 			if (ptgt != NULL) {
   4807 				FCP_TGT_TRACE(ptgt, map_tag[i],
   4808 				    FCP_TGT_TRACE_4);
   4809 
   4810 				mutex_enter(&ptgt->tgt_mutex);
   4811 				if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
   4812 					(void) fcp_offline_target(pptr, ptgt,
   4813 					    link_cnt, map_tag[i], 1, 0);
   4814 				}
   4815 				mutex_exit(&ptgt->tgt_mutex);
   4816 			}
   4817 			check_finish_init++;
   4818 			break;
   4819 
   4820 		case PORT_DEVICE_CHANGED:
   4821 			if (ptgt != NULL) {
   4822 				FCP_TGT_TRACE(ptgt, map_tag[i],
   4823 				    FCP_TGT_TRACE_5);
   4824 
   4825 				if (fcp_device_changed(pptr, ptgt,
   4826 				    map_entry, link_cnt, map_tag[i],
   4827 				    cause) == TRUE) {
   4828 					check_finish_init++;
   4829 				}
   4830 			} else {
   4831 				if (fcp_handle_mapflags(pptr, ptgt,
   4832 				    map_entry, link_cnt, 0, cause) == TRUE) {
   4833 					check_finish_init++;
   4834 				}
   4835 			}
   4836 			break;
   4837 
   4838 		default:
   4839 			fcp_log(CE_WARN, pptr->port_dip,
   4840 			    "!Invalid map_type=0x%x", map_entry->map_type);
   4841 			check_finish_init++;
   4842 			break;
   4843 		}
   4844 	}
   4845 
   4846 	if (check_finish_init && pptr->port_link_cnt == link_cnt) {
   4847 		ASSERT(i > 0);
   4848 		(void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
   4849 		    map_tag[i-1], cause);
   4850 	} else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
   4851 		fcp_offline_all(pptr, link_cnt, cause);
   4852 	}
   4853 }
   4854 
   4855 static int
   4856 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
   4857 {
   4858 	struct fcp_lun	*plun;
   4859 	struct fcp_port *pptr;
   4860 	int		 rscn_count;
   4861 	int		 lun0_newalloc;
   4862 	int		 ret  = TRUE;
   4863 
   4864 	ASSERT(ptgt);
   4865 	pptr = ptgt->tgt_port;
   4866 	lun0_newalloc = 0;
   4867 	if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
   4868 		/*
   4869 		 * no LUN struct for LUN 0 yet exists,
   4870 		 * so create one
   4871 		 */
   4872 		plun = fcp_alloc_lun(ptgt);
   4873 		if (plun == NULL) {
   4874 			fcp_log(CE_WARN, pptr->port_dip,
   4875 			    "!Failed to allocate lun 0 for"
   4876 			    " D_ID=%x", ptgt->tgt_d_id);
   4877 			return (ret);
   4878 		}
   4879 		lun0_newalloc = 1;
   4880 	}
   4881 
   4882 	mutex_enter(&ptgt->tgt_mutex);
   4883 	/*
   4884 	 * consider lun 0 as device not connected if it is
   4885 	 * offlined or newly allocated
   4886 	 */
   4887 	if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
   4888 		plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
   4889 	}
   4890 	plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
   4891 	plun->lun_state &= ~FCP_LUN_OFFLINE;
   4892 	ptgt->tgt_lun_cnt = 1;
   4893 	ptgt->tgt_report_lun_cnt = 0;
   4894 	mutex_exit(&ptgt->tgt_mutex);
   4895 
   4896 	rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
   4897 	if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
   4898 	    sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
   4899 	    ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
   4900 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   4901 		    fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
   4902 		    "to D_ID=%x", ptgt->tgt_d_id);
   4903 	} else {
   4904 		ret = FALSE;
   4905 	}
   4906 
   4907 	return (ret);
   4908 }
   4909 
   4910 /*
   4911  *     Function: fcp_handle_mapflags
   4912  *
   4913  *  Description: This function creates a target structure if the ptgt passed
   4914  *		 is NULL.  It also kicks off the PLOGI if we are not logged
   4915  *		 into the target yet or the PRLI if we are logged into the
   4916  *		 target already.  The rest of the treatment is done in the
   4917  *		 callbacks of the PLOGI or PRLI.
   4918  *
   4919  *     Argument: *pptr		FCP Port structure.
   4920  *		 *ptgt		Target structure.
   4921  *		 *map_entry	Array of fc_portmap_t structures.
   4922  *		 link_cnt	Link state count.
   4923  *		 tgt_cnt	Target state count.
   4924  *		 cause		What caused this function to be called.
   4925  *
   4926  * Return Value: TRUE	Failed
   4927  *		 FALSE	Succeeded
   4928  *
   4929  *	  Notes: pptr->port_mutex must be owned.
   4930  */
   4931 static int
   4932 fcp_handle_mapflags(struct fcp_port	*pptr, struct fcp_tgt	*ptgt,
   4933     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
   4934 {
   4935 	int			lcount;
   4936 	int			tcount;
   4937 	int			ret = TRUE;
   4938 	int			alloc;
   4939 	struct fcp_ipkt	*icmd;
   4940 	struct fcp_lun	*pseq_lun = NULL;
   4941 	uchar_t			opcode;
   4942 	int			valid_ptgt_was_passed = FALSE;
   4943 
   4944 	ASSERT(mutex_owned(&pptr->port_mutex));
   4945 
   4946 	/*
   4947 	 * This case is possible where the FCTL has come up and done discovery
   4948 	 * before FCP was loaded and attached. FCTL would have discovered the
   4949 	 * devices and later the ULP came online. In this case ULP's would get
   4950 	 * PORT_DEVICE_NOCHANGE but target would be NULL.
   4951 	 */
   4952 	if (ptgt == NULL) {
   4953 		/* don't already have a target */
   4954 		mutex_exit(&pptr->port_mutex);
   4955 		ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
   4956 		mutex_enter(&pptr->port_mutex);
   4957 
   4958 		if (ptgt == NULL) {
   4959 			fcp_log(CE_WARN, pptr->port_dip,
   4960 			    "!FC target allocation failed");
   4961 			return (ret);
   4962 		}
   4963 		mutex_enter(&ptgt->tgt_mutex);
   4964 		ptgt->tgt_statec_cause = cause;
   4965 		ptgt->tgt_tmp_cnt = 1;
   4966 		mutex_exit(&ptgt->tgt_mutex);
   4967 	} else {
   4968 		valid_ptgt_was_passed = TRUE;
   4969 	}
   4970 
   4971 	/*
   4972 	 * Copy in the target parameters
   4973 	 */
   4974 	mutex_enter(&ptgt->tgt_mutex);
   4975 	ptgt->tgt_d_id = map_entry->map_did.port_id;
   4976 	ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
   4977 	ptgt->tgt_pd_handle = map_entry->map_pd;
   4978 	ptgt->tgt_fca_dev = NULL;
   4979 
   4980 	/* Copy port and node WWNs */
   4981 	bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
   4982 	    FC_WWN_SIZE);
   4983 	bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
   4984 	    FC_WWN_SIZE);
   4985 
   4986 	if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
   4987 	    (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
   4988 	    (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
   4989 	    valid_ptgt_was_passed) {
   4990 		/*
   4991 		 * determine if there are any tape LUNs on this target
   4992 		 */
   4993 		for (pseq_lun = ptgt->tgt_lun;
   4994 		    pseq_lun != NULL;
   4995 		    pseq_lun = pseq_lun->lun_next) {
   4996 			if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
   4997 			    !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
   4998 				fcp_update_tgt_state(ptgt, FCP_RESET,
   4999 				    FCP_LUN_MARK);
   5000 				mutex_exit(&ptgt->tgt_mutex);
   5001 				return (ret);
   5002 			}
   5003 		}
   5004 	}
   5005 
   5006 	/*
   5007 	 * if UA'REPORT_LUN_CHANGED received,
   5008 	 * send out REPORT LUN promptly, skip PLOGI/PRLI process
   5009 	 */
   5010 	if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
   5011 		ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
   5012 		mutex_exit(&ptgt->tgt_mutex);
   5013 		mutex_exit(&pptr->port_mutex);
   5014 
   5015 		ret = fcp_handle_reportlun_changed(ptgt, cause);
   5016 
   5017 		mutex_enter(&pptr->port_mutex);
   5018 		return (ret);
   5019 	}
   5020 
   5021 	/*
   5022 	 * If ptgt was NULL when this function was entered, then tgt_node_state
   5023 	 * was never specifically initialized but zeroed out which means
   5024 	 * FCP_TGT_NODE_NONE.
   5025 	 */
   5026 	switch (ptgt->tgt_node_state) {
   5027 	case FCP_TGT_NODE_NONE:
   5028 	case FCP_TGT_NODE_ON_DEMAND:
   5029 		if (FC_TOP_EXTERNAL(pptr->port_topology) &&
   5030 		    !fcp_enable_auto_configuration &&
   5031 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
   5032 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
   5033 		} else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
   5034 		    fcp_enable_auto_configuration &&
   5035 		    (ptgt->tgt_manual_config_only == 1) &&
   5036 		    map_entry->map_type != PORT_DEVICE_USER_CREATE) {
   5037 			/*
   5038 			 * If auto configuration is set and
   5039 			 * the tgt_manual_config_only flag is set then
   5040 			 * we only want the user to be able to change
   5041 			 * the state through create_on_demand.
   5042 			 */
   5043 			ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
   5044 		} else {
   5045 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
   5046 		}
   5047 		break;
   5048 
   5049 	case FCP_TGT_NODE_PRESENT:
   5050 		break;
   5051 	}
   5052 	/*
   5053 	 * If we are booting from a fabric device, make sure we
   5054 	 * mark the node state appropriately for this target to be
   5055 	 * enumerated
   5056 	 */
   5057 	if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
   5058 		if (bcmp((caddr_t)pptr->port_boot_wwn,
   5059 		    (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
   5060 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
   5061 			ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
   5062 		}
   5063 	}
   5064 	mutex_exit(&ptgt->tgt_mutex);
   5065 
   5066 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5067 	    fcp_trace, FCP_BUF_LEVEL_3, 0,
   5068 	    "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
   5069 	    map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
   5070 	    map_entry->map_rscn_info.ulp_rscn_count);
   5071 
   5072 	mutex_enter(&ptgt->tgt_mutex);
   5073 
   5074 	/*
   5075 	 * Reset target OFFLINE state and mark the target BUSY
   5076 	 */
   5077 	ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
   5078 	ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
   5079 
   5080 	tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
   5081 	lcount = link_cnt;
   5082 
   5083 	mutex_exit(&ptgt->tgt_mutex);
   5084 	mutex_exit(&pptr->port_mutex);
   5085 
   5086 	/*
   5087 	 * if we are already logged in, then we do a PRLI, else
   5088 	 * we do a PLOGI first (to get logged in)
   5089 	 *
   5090 	 * We will not check if we are the PLOGI initiator
   5091 	 */
   5092 	opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
   5093 	    map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
   5094 
   5095 	alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
   5096 
   5097 	icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
   5098 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
   5099 	    cause, map_entry->map_rscn_info.ulp_rscn_count);
   5100 
   5101 	if (icmd == NULL) {
   5102 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
   5103 		/*
   5104 		 * We've exited port_mutex before calling fcp_icmd_alloc,
   5105 		 * we need to make sure we reacquire it before returning.
   5106 		 */
   5107 		mutex_enter(&pptr->port_mutex);
   5108 		return (FALSE);
   5109 	}
   5110 
   5111 	/* TRUE is only returned while target is intended skipped */
   5112 	ret = FALSE;
   5113 	/* discover info about this target */
   5114 	if ((fcp_send_els(pptr, ptgt, icmd, opcode,
   5115 	    lcount, tcount, cause)) == DDI_SUCCESS) {
   5116 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
   5117 	} else {
   5118 		fcp_icmd_free(pptr, icmd);
   5119 		ret = TRUE;
   5120 	}
   5121 	mutex_enter(&pptr->port_mutex);
   5122 
   5123 	return (ret);
   5124 }
   5125 
   5126 /*
   5127  *     Function: fcp_send_els
   5128  *
   5129  *  Description: Sends an ELS to the target specified by the caller.  Supports
   5130  *		 PLOGI and PRLI.
   5131  *
   5132  *     Argument: *pptr		Fcp port.
   5133  *		 *ptgt		Target to send the ELS to.
   5134  *		 *icmd		Internal packet
   5135  *		 opcode		ELS opcode
   5136  *		 lcount		Link state change counter
   5137  *		 tcount		Target state change counter
   5138  *		 cause		What caused the call
   5139  *
   5140  * Return Value: DDI_SUCCESS
   5141  *		 Others
   5142  */
   5143 static int
   5144 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
   5145     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
   5146 {
   5147 	fc_packet_t		*fpkt;
   5148 	fc_frame_hdr_t		*hp;
   5149 	int			internal = 0;
   5150 	int			alloc;
   5151 	int			cmd_len;
   5152 	int			resp_len;
   5153 	int			res = DDI_FAILURE; /* default result */
   5154 	int			rval = DDI_FAILURE;
   5155 
   5156 	ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
   5157 	ASSERT(ptgt->tgt_port == pptr);
   5158 
   5159 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5160 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   5161 	    "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
   5162 	    (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
   5163 
   5164 	if (opcode == LA_ELS_PLOGI) {
   5165 		cmd_len = sizeof (la_els_logi_t);
   5166 		resp_len = sizeof (la_els_logi_t);
   5167 	} else {
   5168 		ASSERT(opcode == LA_ELS_PRLI);
   5169 		cmd_len = sizeof (la_els_prli_t);
   5170 		resp_len = sizeof (la_els_prli_t);
   5171 	}
   5172 
   5173 	if (icmd == NULL) {
   5174 		alloc = FCP_MAX(sizeof (la_els_logi_t),
   5175 		    sizeof (la_els_prli_t));
   5176 		icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
   5177 		    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
   5178 		    lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
   5179 		if (icmd == NULL) {
   5180 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
   5181 			return (res);
   5182 		}
   5183 		internal++;
   5184 	}
   5185 	fpkt = icmd->ipkt_fpkt;
   5186 
   5187 	fpkt->pkt_cmdlen = cmd_len;
   5188 	fpkt->pkt_rsplen = resp_len;
   5189 	fpkt->pkt_datalen = 0;
   5190 	icmd->ipkt_retries = 0;
   5191 
   5192 	/* fill in fpkt info */
   5193 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
   5194 	fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
   5195 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
   5196 
   5197 	/* get ptr to frame hdr in fpkt */
   5198 	hp = &fpkt->pkt_cmd_fhdr;
   5199 
   5200 	/*
   5201 	 * fill in frame hdr
   5202 	 */
   5203 	hp->r_ctl = R_CTL_ELS_REQ;
   5204 	hp->s_id = pptr->port_id;	/* source ID */
   5205 	hp->d_id = ptgt->tgt_d_id;	/* dest ID */
   5206 	hp->type = FC_TYPE_EXTENDED_LS;
   5207 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
   5208 	hp->seq_id = 0;
   5209 	hp->rsvd = 0;
   5210 	hp->df_ctl  = 0;
   5211 	hp->seq_cnt = 0;
   5212 	hp->ox_id = 0xffff;		/* i.e. none */
   5213 	hp->rx_id = 0xffff;		/* i.e. none */
   5214 	hp->ro = 0;
   5215 
   5216 	/*
   5217 	 * at this point we have a filled in cmd pkt
   5218 	 *
   5219 	 * fill in the respective info, then use the transport to send
   5220 	 * the packet
   5221 	 *
   5222 	 * for a PLOGI call fc_ulp_login(), and
   5223 	 * for a PRLI call fc_ulp_issue_els()
   5224 	 */
   5225 	switch (opcode) {
   5226 	case LA_ELS_PLOGI: {
   5227 		struct la_els_logi logi;
   5228 
   5229 		bzero(&logi, sizeof (struct la_els_logi));
   5230 
   5231 		hp = &fpkt->pkt_cmd_fhdr;
   5232 		hp->r_ctl = R_CTL_ELS_REQ;
   5233 		logi.ls_code.ls_code = LA_ELS_PLOGI;
   5234 		logi.ls_code.mbz = 0;
   5235 
   5236 		FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
   5237 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
   5238 
   5239 		icmd->ipkt_opcode = LA_ELS_PLOGI;
   5240 
   5241 		mutex_enter(&pptr->port_mutex);
   5242 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   5243 
   5244 			mutex_exit(&pptr->port_mutex);
   5245 
   5246 			rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
   5247 			if (rval == FC_SUCCESS) {
   5248 				res = DDI_SUCCESS;
   5249 				break;
   5250 			}
   5251 
   5252 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
   5253 
   5254 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
   5255 			    rval, "PLOGI");
   5256 		} else {
   5257 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5258 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
   5259 			    "fcp_send_els1: state change occured"
   5260 			    " for D_ID=0x%x", ptgt->tgt_d_id);
   5261 			mutex_exit(&pptr->port_mutex);
   5262 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
   5263 		}
   5264 		break;
   5265 	}
   5266 
   5267 	case LA_ELS_PRLI: {
   5268 		struct la_els_prli	prli;
   5269 		struct fcp_prli		*fprli;
   5270 
   5271 		bzero(&prli, sizeof (struct la_els_prli));
   5272 
   5273 		hp = &fpkt->pkt_cmd_fhdr;
   5274 		hp->r_ctl = R_CTL_ELS_REQ;
   5275 
   5276 		/* fill in PRLI cmd ELS fields */
   5277 		prli.ls_code = LA_ELS_PRLI;
   5278 		prli.page_length = 0x10;	/* huh? */
   5279 		prli.payload_length = sizeof (struct la_els_prli);
   5280 
   5281 		icmd->ipkt_opcode = LA_ELS_PRLI;
   5282 
   5283 		/* get ptr to PRLI service params */
   5284 		fprli = (struct fcp_prli *)prli.service_params;
   5285 
   5286 		/* fill in service params */
   5287 		fprli->type = 0x08;
   5288 		fprli->resvd1 = 0;
   5289 		fprli->orig_process_assoc_valid = 0;
   5290 		fprli->resp_process_assoc_valid = 0;
   5291 		fprli->establish_image_pair = 1;
   5292 		fprli->resvd2 = 0;
   5293 		fprli->resvd3 = 0;
   5294 		fprli->obsolete_1 = 0;
   5295 		fprli->obsolete_2 = 0;
   5296 		fprli->data_overlay_allowed = 0;
   5297 		fprli->initiator_fn = 1;
   5298 		fprli->confirmed_compl_allowed = 1;
   5299 
   5300 		if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
   5301 			fprli->target_fn = 1;
   5302 		} else {
   5303 			fprli->target_fn = 0;
   5304 		}
   5305 
   5306 		fprli->retry = 1;
   5307 		fprli->read_xfer_rdy_disabled = 1;
   5308 		fprli->write_xfer_rdy_disabled = 0;
   5309 
   5310 		FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
   5311 		    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
   5312 
   5313 		/* issue the PRLI request */
   5314 
   5315 		mutex_enter(&pptr->port_mutex);
   5316 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   5317 
   5318 			mutex_exit(&pptr->port_mutex);
   5319 
   5320 			rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
   5321 			if (rval == FC_SUCCESS) {
   5322 				res = DDI_SUCCESS;
   5323 				break;
   5324 			}
   5325 
   5326 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
   5327 
   5328 			res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
   5329 			    rval, "PRLI");
   5330 		} else {
   5331 			mutex_exit(&pptr->port_mutex);
   5332 			FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
   5333 		}
   5334 		break;
   5335 	}
   5336 
   5337 	default:
   5338 		fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
   5339 		break;
   5340 	}
   5341 
   5342 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5343 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   5344 	    "fcp_send_els: returning %d", res);
   5345 
   5346 	if (res != DDI_SUCCESS) {
   5347 		if (internal) {
   5348 			fcp_icmd_free(pptr, icmd);
   5349 		}
   5350 	}
   5351 
   5352 	return (res);
   5353 }
   5354 
   5355 
   5356 /*
   5357  * called internally update the state of all of the tgts and each LUN
   5358  * for this port (i.e. each target  known to be attached to this port)
   5359  * if they are not already offline
   5360  *
   5361  * must be called with the port mutex owned
   5362  *
   5363  * acquires and releases the target mutexes for each target attached
   5364  * to this port
   5365  */
   5366 void
   5367 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
   5368 {
   5369 	int i;
   5370 	struct fcp_tgt *ptgt;
   5371 
   5372 	ASSERT(mutex_owned(&pptr->port_mutex));
   5373 
   5374 	for (i = 0; i < FCP_NUM_HASH; i++) {
   5375 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
   5376 		    ptgt = ptgt->tgt_next) {
   5377 			mutex_enter(&ptgt->tgt_mutex);
   5378 			fcp_update_tgt_state(ptgt, FCP_SET, state);
   5379 			ptgt->tgt_change_cnt++;
   5380 			ptgt->tgt_statec_cause = cause;
   5381 			ptgt->tgt_tmp_cnt = 1;
   5382 			ptgt->tgt_done = 0;
   5383 			mutex_exit(&ptgt->tgt_mutex);
   5384 		}
   5385 	}
   5386 }
   5387 
   5388 
   5389 static void
   5390 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
   5391 {
   5392 	int i;
   5393 	int ndevs;
   5394 	struct fcp_tgt *ptgt;
   5395 
   5396 	ASSERT(mutex_owned(&pptr->port_mutex));
   5397 
   5398 	for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
   5399 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
   5400 		    ptgt = ptgt->tgt_next) {
   5401 			ndevs++;
   5402 		}
   5403 	}
   5404 
   5405 	if (ndevs == 0) {
   5406 		return;
   5407 	}
   5408 	pptr->port_tmp_cnt = ndevs;
   5409 
   5410 	for (i = 0; i < FCP_NUM_HASH; i++) {
   5411 		for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
   5412 		    ptgt = ptgt->tgt_next) {
   5413 			(void) fcp_call_finish_init_held(pptr, ptgt,
   5414 			    lcount, ptgt->tgt_change_cnt, cause);
   5415 		}
   5416 	}
   5417 }
   5418 
   5419 /*
   5420  *     Function: fcp_update_tgt_state
   5421  *
   5422  *  Description: This function updates the field tgt_state of a target.	 That
   5423  *		 field is a bitmap and which bit can be set or reset
   5424  *		 individually.	The action applied to the target state is also
   5425  *		 applied to all the LUNs belonging to the target (provided the
   5426  *		 LUN is not offline).  A side effect of applying the state
   5427  *		 modification to the target and the LUNs is the field tgt_trace
   5428  *		 of the target and lun_trace of the LUNs is set to zero.
   5429  *
   5430  *
   5431  *     Argument: *ptgt	Target structure.
   5432  *		 flag	Flag indication what action to apply (set/reset).
   5433  *		 state	State bits to update.
   5434  *
   5435  * Return Value: None
   5436  *
   5437  *	Context: Interrupt, Kernel or User context.
   5438  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
   5439  *		 calling this function.
   5440  */
   5441 void
   5442 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
   5443 {
   5444 	struct fcp_lun *plun;
   5445 
   5446 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
   5447 
   5448 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
   5449 		/* The target is not offline. */
   5450 		if (flag == FCP_SET) {
   5451 			ptgt->tgt_state |= state;
   5452 			ptgt->tgt_trace = 0;
   5453 		} else {
   5454 			ptgt->tgt_state &= ~state;
   5455 		}
   5456 
   5457 		for (plun = ptgt->tgt_lun; plun != NULL;
   5458 		    plun = plun->lun_next) {
   5459 			if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
   5460 				/* The LUN is not offline. */
   5461 				if (flag == FCP_SET) {
   5462 					plun->lun_state |= state;
   5463 					plun->lun_trace = 0;
   5464 				} else {
   5465 					plun->lun_state &= ~state;
   5466 				}
   5467 			}
   5468 		}
   5469 	}
   5470 }
   5471 
   5472 /*
   5473  *     Function: fcp_update_tgt_state
   5474  *
   5475  *  Description: This function updates the field lun_state of a LUN.  That
   5476  *		 field is a bitmap and which bit can be set or reset
   5477  *		 individually.
   5478  *
   5479  *     Argument: *plun	LUN structure.
   5480  *		 flag	Flag indication what action to apply (set/reset).
   5481  *		 state	State bits to update.
   5482  *
   5483  * Return Value: None
   5484  *
   5485  *	Context: Interrupt, Kernel or User context.
   5486  *		 The mutex of the target (ptgt->tgt_mutex) must be owned when
   5487  *		 calling this function.
   5488  */
   5489 void
   5490 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
   5491 {
   5492 	struct fcp_tgt	*ptgt = plun->lun_tgt;
   5493 
   5494 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
   5495 
   5496 	if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
   5497 		if (flag == FCP_SET) {
   5498 			plun->lun_state |= state;
   5499 		} else {
   5500 			plun->lun_state &= ~state;
   5501 		}
   5502 	}
   5503 }
   5504 
   5505 /*
   5506  *     Function: fcp_get_port
   5507  *
   5508  *  Description: This function returns the fcp_port structure from the opaque
   5509  *		 handle passed by the caller.  That opaque handle is the handle
   5510  *		 used by fp/fctl to identify a particular local port.  That
   5511  *		 handle has been stored in the corresponding fcp_port
   5512  *		 structure.  This function is going to walk the global list of
   5513  *		 fcp_port structures till one has a port_fp_handle that matches
   5514  *		 the handle passed by the caller.  This function enters the
   5515  *		 mutex fcp_global_mutex while walking the global list and then
   5516  *		 releases it.
   5517  *
   5518  *     Argument: port_handle	Opaque handle that fp/fctl uses to identify a
   5519  *				particular port.
   5520  *
   5521  * Return Value: NULL		Not found.
   5522  *		 Not NULL	Pointer to the fcp_port structure.
   5523  *
   5524  *	Context: Interrupt, Kernel or User context.
   5525  */
   5526 static struct fcp_port *
   5527 fcp_get_port(opaque_t port_handle)
   5528 {
   5529 	struct fcp_port *pptr;
   5530 
   5531 	ASSERT(port_handle != NULL);
   5532 
   5533 	mutex_enter(&fcp_global_mutex);
   5534 	for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
   5535 		if (pptr->port_fp_handle == port_handle) {
   5536 			break;
   5537 		}
   5538 	}
   5539 	mutex_exit(&fcp_global_mutex);
   5540 
   5541 	return (pptr);
   5542 }
   5543 
   5544 
   5545 static void
   5546 fcp_unsol_callback(fc_packet_t *fpkt)
   5547 {
   5548 	struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
   5549 	struct fcp_port *pptr = icmd->ipkt_port;
   5550 
   5551 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
   5552 		caddr_t state, reason, action, expln;
   5553 
   5554 		(void) fc_ulp_pkt_error(fpkt, &state, &reason,
   5555 		    &action, &expln);
   5556 
   5557 		fcp_log(CE_WARN, pptr->port_dip,
   5558 		    "!couldn't post response to unsolicited request: "
   5559 		    " state=%s reason=%s rx_id=%x ox_id=%x",
   5560 		    state, reason, fpkt->pkt_cmd_fhdr.ox_id,
   5561 		    fpkt->pkt_cmd_fhdr.rx_id);
   5562 	}
   5563 	fcp_icmd_free(pptr, icmd);
   5564 }
   5565 
   5566 
   5567 /*
   5568  * Perform general purpose preparation of a response to an unsolicited request
   5569  */
   5570 static void
   5571 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
   5572     uchar_t r_ctl, uchar_t type)
   5573 {
   5574 	pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
   5575 	pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
   5576 	pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
   5577 	pkt->pkt_cmd_fhdr.type = type;
   5578 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
   5579 	pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
   5580 	pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
   5581 	pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
   5582 	pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
   5583 	pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
   5584 	pkt->pkt_cmd_fhdr.ro = 0;
   5585 	pkt->pkt_cmd_fhdr.rsvd = 0;
   5586 	pkt->pkt_comp = fcp_unsol_callback;
   5587 	pkt->pkt_pd = NULL;
   5588 	pkt->pkt_ub_resp_token = (opaque_t)buf;
   5589 }
   5590 
   5591 
   5592 /*ARGSUSED*/
   5593 static int
   5594 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
   5595 {
   5596 	fc_packet_t		*fpkt;
   5597 	struct la_els_prli	prli;
   5598 	struct fcp_prli		*fprli;
   5599 	struct fcp_ipkt	*icmd;
   5600 	struct la_els_prli	*from;
   5601 	struct fcp_prli		*orig;
   5602 	struct fcp_tgt	*ptgt;
   5603 	int			tcount = 0;
   5604 	int			lcount;
   5605 
   5606 	from = (struct la_els_prli *)buf->ub_buffer;
   5607 	orig = (struct fcp_prli *)from->service_params;
   5608 	if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
   5609 	    NULL) {
   5610 		mutex_enter(&ptgt->tgt_mutex);
   5611 		tcount = ptgt->tgt_change_cnt;
   5612 		mutex_exit(&ptgt->tgt_mutex);
   5613 	}
   5614 
   5615 	mutex_enter(&pptr->port_mutex);
   5616 	lcount = pptr->port_link_cnt;
   5617 	mutex_exit(&pptr->port_mutex);
   5618 
   5619 	if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
   5620 	    sizeof (la_els_prli_t), 0,
   5621 	    pptr->port_state & FCP_STATE_FCA_IS_NODMA,
   5622 	    lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
   5623 		return (FC_FAILURE);
   5624 	}
   5625 
   5626 	fpkt = icmd->ipkt_fpkt;
   5627 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
   5628 	fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
   5629 	fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
   5630 	fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
   5631 	fpkt->pkt_rsplen = 0;
   5632 	fpkt->pkt_datalen = 0;
   5633 
   5634 	icmd->ipkt_opcode = LA_ELS_PRLI;
   5635 
   5636 	bzero(&prli, sizeof (struct la_els_prli));
   5637 	fprli = (struct fcp_prli *)prli.service_params;
   5638 	prli.ls_code = LA_ELS_ACC;
   5639 	prli.page_length = 0x10;
   5640 	prli.payload_length = sizeof (struct la_els_prli);
   5641 
   5642 	/* fill in service params */
   5643 	fprli->type = 0x08;
   5644 	fprli->resvd1 = 0;
   5645 	fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
   5646 	fprli->orig_process_associator = orig->orig_process_associator;
   5647 	fprli->resp_process_assoc_valid = 0;
   5648 	fprli->establish_image_pair = 1;
   5649 	fprli->resvd2 = 0;
   5650 	fprli->resvd3 = 0;
   5651 	fprli->obsolete_1 = 0;
   5652 	fprli->obsolete_2 = 0;
   5653 	fprli->data_overlay_allowed = 0;
   5654 	fprli->initiator_fn = 1;
   5655 	fprli->confirmed_compl_allowed = 1;
   5656 
   5657 	if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
   5658 		fprli->target_fn = 1;
   5659 	} else {
   5660 		fprli->target_fn = 0;
   5661 	}
   5662 
   5663 	fprli->retry = 1;
   5664 	fprli->read_xfer_rdy_disabled = 1;
   5665 	fprli->write_xfer_rdy_disabled = 0;
   5666 
   5667 	/* save the unsol prli payload first */
   5668 	FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
   5669 	    fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
   5670 
   5671 	FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
   5672 	    fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
   5673 
   5674 	fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
   5675 
   5676 	mutex_enter(&pptr->port_mutex);
   5677 	if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
   5678 		int rval;
   5679 		mutex_exit(&pptr->port_mutex);
   5680 
   5681 		if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
   5682 		    FC_SUCCESS) {
   5683 			if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
   5684 			    ptgt != NULL) {
   5685 				fcp_queue_ipkt(pptr, fpkt);
   5686 				return (FC_SUCCESS);
   5687 			}
   5688 			/* Let it timeout */
   5689 			fcp_icmd_free(pptr, icmd);
   5690 			return (FC_FAILURE);
   5691 		}
   5692 	} else {
   5693 		mutex_exit(&pptr->port_mutex);
   5694 		fcp_icmd_free(pptr, icmd);
   5695 		return (FC_FAILURE);
   5696 	}
   5697 
   5698 	(void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
   5699 
   5700 	return (FC_SUCCESS);
   5701 }
   5702 
   5703 /*
   5704  *     Function: fcp_icmd_alloc
   5705  *
   5706  *  Description: This function allocated a fcp_ipkt structure.	The pkt_comp
   5707  *		 field is initialized to fcp_icmd_callback.  Sometimes it is
   5708  *		 modified by the caller (such as fcp_send_scsi).  The
   5709  *		 structure is also tied to the state of the line and of the
   5710  *		 target at a particular time.  That link is established by
   5711  *		 setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
   5712  *		 and tcount which came respectively from pptr->link_cnt and
   5713  *		 ptgt->tgt_change_cnt.
   5714  *
   5715  *     Argument: *pptr		Fcp port.
   5716  *		 *ptgt		Target (destination of the command).
   5717  *		 cmd_len	Length of the command.
   5718  *		 resp_len	Length of the expected response.
   5719  *		 data_len	Length of the data.
   5720  *		 nodma		Indicates weither the command and response.
   5721  *				will be transfer through DMA or not.
   5722  *		 lcount		Link state change counter.
   5723  *		 tcount		Target state change counter.
   5724  *		 cause		Reason that lead to this call.
   5725  *
   5726  * Return Value: NULL		Failed.
   5727  *		 Not NULL	Internal packet address.
   5728  */
   5729 static struct fcp_ipkt *
   5730 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
   5731     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
   5732     uint32_t rscn_count)
   5733 {
   5734 	int			dma_setup = 0;
   5735 	fc_packet_t		*fpkt;
   5736 	struct fcp_ipkt	*icmd = NULL;
   5737 
   5738 	icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
   5739 	    pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
   5740 	    KM_NOSLEEP);
   5741 	if (icmd == NULL) {
   5742 		fcp_log(CE_WARN, pptr->port_dip,
   5743 		    "!internal packet allocation failed");
   5744 		return (NULL);
   5745 	}
   5746 
   5747 	/*
   5748 	 * initialize the allocated packet
   5749 	 */
   5750 	icmd->ipkt_nodma = nodma;
   5751 	icmd->ipkt_next = icmd->ipkt_prev = NULL;
   5752 	icmd->ipkt_lun = NULL;
   5753 
   5754 	icmd->ipkt_link_cnt = lcount;
   5755 	icmd->ipkt_change_cnt = tcount;
   5756 	icmd->ipkt_cause = cause;
   5757 
   5758 	mutex_enter(&pptr->port_mutex);
   5759 	icmd->ipkt_port = pptr;
   5760 	mutex_exit(&pptr->port_mutex);
   5761 
   5762 	/* keep track of amt of data to be sent in pkt */
   5763 	icmd->ipkt_cmdlen = cmd_len;
   5764 	icmd->ipkt_resplen = resp_len;
   5765 	icmd->ipkt_datalen = data_len;
   5766 
   5767 	/* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
   5768 	icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
   5769 
   5770 	/* set pkt's private ptr to point to cmd pkt */
   5771 	icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
   5772 
   5773 	/* set FCA private ptr to memory just beyond */
   5774 	icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
   5775 	    ((char *)icmd + sizeof (struct fcp_ipkt) +
   5776 	    pptr->port_dmacookie_sz);
   5777 
   5778 	/* get ptr to fpkt substruct and fill it in */
   5779 	fpkt = icmd->ipkt_fpkt;
   5780 	fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
   5781 	    sizeof (struct fcp_ipkt));
   5782 
   5783 	if (ptgt != NULL) {
   5784 		icmd->ipkt_tgt = ptgt;
   5785 		fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
   5786 	}
   5787 
   5788 	fpkt->pkt_comp = fcp_icmd_callback;
   5789 	fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
   5790 	fpkt->pkt_cmdlen = cmd_len;
   5791 	fpkt->pkt_rsplen = resp_len;
   5792 	fpkt->pkt_datalen = data_len;
   5793 
   5794 	/*
   5795 	 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
   5796 	 * rscn_count as fcp knows down to the transport. If a valid count was
   5797 	 * passed into this function, we allocate memory to actually pass down
   5798 	 * this info.
   5799 	 *
   5800 	 * BTW, if the kmem_zalloc fails, we won't try too hard. This will
   5801 	 * basically mean that fcp will not be able to help transport
   5802 	 * distinguish if a new RSCN has come after fcp was last informed about
   5803 	 * it. In such cases, it might lead to the problem mentioned in CR/bug #
   5804 	 * 5068068 where the device might end up going offline in case of RSCN
   5805 	 * storms.
   5806 	 */
   5807 	fpkt->pkt_ulp_rscn_infop = NULL;
   5808 	if (rscn_count != FC_INVALID_RSCN_COUNT) {
   5809 		fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
   5810 		    sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
   5811 		if (fpkt->pkt_ulp_rscn_infop == NULL) {
   5812 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5813 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
   5814 			    "Failed to alloc memory to pass rscn info");
   5815 		}
   5816 	}
   5817 
   5818 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
   5819 		fc_ulp_rscn_info_t	*rscnp;
   5820 
   5821 		rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
   5822 		rscnp->ulp_rscn_count = rscn_count;
   5823 	}
   5824 
   5825 	if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
   5826 		goto fail;
   5827 	}
   5828 	dma_setup++;
   5829 
   5830 	/*
   5831 	 * Must hold target mutex across setting of pkt_pd and call to
   5832 	 * fc_ulp_init_packet to ensure the handle to the target doesn't go
   5833 	 * away while we're not looking.
   5834 	 */
   5835 	if (ptgt != NULL) {
   5836 		mutex_enter(&ptgt->tgt_mutex);
   5837 		fpkt->pkt_pd = ptgt->tgt_pd_handle;
   5838 
   5839 		/* ask transport to do its initialization on this pkt */
   5840 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
   5841 		    != FC_SUCCESS) {
   5842 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5843 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
   5844 			    "fc_ulp_init_packet failed");
   5845 			mutex_exit(&ptgt->tgt_mutex);
   5846 			goto fail;
   5847 		}
   5848 		mutex_exit(&ptgt->tgt_mutex);
   5849 	} else {
   5850 		if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
   5851 		    != FC_SUCCESS) {
   5852 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   5853 			    fcp_trace, FCP_BUF_LEVEL_6, 0,
   5854 			    "fc_ulp_init_packet failed");
   5855 			goto fail;
   5856 		}
   5857 	}
   5858 
   5859 	mutex_enter(&pptr->port_mutex);
   5860 	if (pptr->port_state & (FCP_STATE_DETACHING |
   5861 	    FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
   5862 		int rval;
   5863 
   5864 		mutex_exit(&pptr->port_mutex);
   5865 
   5866 		rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
   5867 		ASSERT(rval == FC_SUCCESS);
   5868 
   5869 		goto fail;
   5870 	}
   5871 
   5872 	if (ptgt != NULL) {
   5873 		mutex_enter(&ptgt->tgt_mutex);
   5874 		ptgt->tgt_ipkt_cnt++;
   5875 		mutex_exit(&ptgt->tgt_mutex);
   5876 	}
   5877 
   5878 	pptr->port_ipkt_cnt++;
   5879 
   5880 	mutex_exit(&pptr->port_mutex);
   5881 
   5882 	return (icmd);
   5883 
   5884 fail:
   5885 	if (fpkt->pkt_ulp_rscn_infop != NULL) {
   5886 		kmem_free(fpkt->pkt_ulp_rscn_infop,
   5887 		    sizeof (fc_ulp_rscn_info_t));
   5888 		fpkt->pkt_ulp_rscn_infop = NULL;
   5889 	}
   5890 
   5891 	if (dma_setup) {
   5892 		fcp_free_dma(pptr, icmd);
   5893 	}
   5894 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
   5895 	    (size_t)pptr->port_dmacookie_sz);
   5896 
   5897 	return (NULL);
   5898 }
   5899 
   5900 /*
   5901  *     Function: fcp_icmd_free
   5902  *
   5903  *  Description: Frees the internal command passed by the caller.
   5904  *
   5905  *     Argument: *pptr		Fcp port.
   5906  *		 *icmd		Internal packet to free.
   5907  *
   5908  * Return Value: None
   5909  */
   5910 static void
   5911 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
   5912 {
   5913 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
   5914 
   5915 	/* Let the underlying layers do their cleanup. */
   5916 	(void) fc_ulp_uninit_packet(pptr->port_fp_handle,
   5917 	    icmd->ipkt_fpkt);
   5918 
   5919 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
   5920 		kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
   5921 		    sizeof (fc_ulp_rscn_info_t));
   5922 	}
   5923 
   5924 	fcp_free_dma(pptr, icmd);
   5925 
   5926 	kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
   5927 	    (size_t)pptr->port_dmacookie_sz);
   5928 
   5929 	mutex_enter(&pptr->port_mutex);
   5930 
   5931 	if (ptgt) {
   5932 		mutex_enter(&ptgt->tgt_mutex);
   5933 		ptgt->tgt_ipkt_cnt--;
   5934 		mutex_exit(&ptgt->tgt_mutex);
   5935 	}
   5936 
   5937 	pptr->port_ipkt_cnt--;
   5938 	mutex_exit(&pptr->port_mutex);
   5939 }
   5940 
   5941 /*
   5942  *     Function: fcp_alloc_dma
   5943  *
   5944  *  Description: Allocated the DMA resources required for the internal
   5945  *		 packet.
   5946  *
   5947  *     Argument: *pptr	FCP port.
   5948  *		 *icmd	Internal FCP packet.
   5949  *		 nodma	Indicates if the Cmd and Resp will be DMAed.
   5950  *		 flags	Allocation flags (Sleep or NoSleep).
   5951  *
   5952  * Return Value: FC_SUCCESS
   5953  *		 FC_NOMEM
   5954  */
   5955 static int
   5956 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
   5957     int nodma, int flags)
   5958 {
   5959 	int		rval;
   5960 	size_t		real_size;
   5961 	uint_t		ccount;
   5962 	int		bound = 0;
   5963 	int		cmd_resp = 0;
   5964 	fc_packet_t	*fpkt;
   5965 	ddi_dma_cookie_t	pkt_data_cookie;
   5966 	ddi_dma_cookie_t	*cp;
   5967 	uint32_t		cnt;
   5968 
   5969 	fpkt = &icmd->ipkt_fc_packet;
   5970 
   5971 	ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
   5972 	    fpkt->pkt_resp_dma == NULL);
   5973 
   5974 	icmd->ipkt_nodma = nodma;
   5975 
   5976 	if (nodma) {
   5977 		fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
   5978 		if (fpkt->pkt_cmd == NULL) {
   5979 			goto fail;
   5980 		}
   5981 
   5982 		fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
   5983 		if (fpkt->pkt_resp == NULL) {
   5984 			goto fail;
   5985 		}
   5986 	} else {
   5987 		ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
   5988 
   5989 		rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
   5990 		if (rval == FC_FAILURE) {
   5991 			ASSERT(fpkt->pkt_cmd_dma == NULL &&
   5992 			    fpkt->pkt_resp_dma == NULL);
   5993 			goto fail;
   5994 		}
   5995 		cmd_resp++;
   5996 	}
   5997 
   5998 	if ((fpkt->pkt_datalen != 0) &&
   5999 	    !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
   6000 		/*
   6001 		 * set up DMA handle and memory for the data in this packet
   6002 		 */
   6003 		if (ddi_dma_alloc_handle(pptr->port_dip,
   6004 		    &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
   6005 		    NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
   6006 			goto fail;
   6007 		}
   6008 
   6009 		if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
   6010 		    &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
   6011 		    DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
   6012 		    &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
   6013 			goto fail;
   6014 		}
   6015 
   6016 		/* was DMA mem size gotten < size asked for/needed ?? */
   6017 		if (real_size < fpkt->pkt_datalen) {
   6018 			goto fail;
   6019 		}
   6020 
   6021 		/* bind DMA address and handle together */
   6022 		if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
   6023 		    NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
   6024 		    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
   6025 		    &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
   6026 			goto fail;
   6027 		}
   6028 		bound++;
   6029 
   6030 		if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
   6031 			goto fail;
   6032 		}
   6033 
   6034 		fpkt->pkt_data_cookie_cnt = ccount;
   6035 
   6036 		cp = fpkt->pkt_data_cookie;
   6037 		*cp = pkt_data_cookie;
   6038 		cp++;
   6039 
   6040 		for (cnt = 1; cnt < ccount; cnt++, cp++) {
   6041 			ddi_dma_nextcookie(fpkt->pkt_data_dma,
   6042 			    &pkt_data_cookie);
   6043 			*cp = pkt_data_cookie;
   6044 		}
   6045 
   6046 	} else if (fpkt->pkt_datalen != 0) {
   6047 		/*
   6048 		 * If it's a pseudo FCA, then it can't support DMA even in
   6049 		 * SCSI data phase.
   6050 		 */
   6051 		fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
   6052 		if (fpkt->pkt_data == NULL) {
   6053 			goto fail;
   6054 		}
   6055 
   6056 	}
   6057 
   6058 	return (FC_SUCCESS);
   6059 
   6060 fail:
   6061 	if (bound) {
   6062 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
   6063 	}
   6064 
   6065 	if (fpkt->pkt_data_dma) {
   6066 		if (fpkt->pkt_data) {
   6067 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
   6068 		}
   6069 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
   6070 	} else {
   6071 		if (fpkt->pkt_data) {
   6072 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
   6073 		}
   6074 	}
   6075 
   6076 	if (nodma) {
   6077 		if (fpkt->pkt_cmd) {
   6078 			kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
   6079 		}
   6080 		if (fpkt->pkt_resp) {
   6081 			kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
   6082 		}
   6083 	} else {
   6084 		if (cmd_resp) {
   6085 			fcp_free_cmd_resp(pptr, fpkt);
   6086 		}
   6087 	}
   6088 
   6089 	return (FC_NOMEM);
   6090 }
   6091 
   6092 
   6093 static void
   6094 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
   6095 {
   6096 	fc_packet_t *fpkt = icmd->ipkt_fpkt;
   6097 
   6098 	if (fpkt->pkt_data_dma) {
   6099 		(void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
   6100 		if (fpkt->pkt_data) {
   6101 			ddi_dma_mem_free(&fpkt->pkt_data_acc);
   6102 		}
   6103 		ddi_dma_free_handle(&fpkt->pkt_data_dma);
   6104 	} else {
   6105 		if (fpkt->pkt_data) {
   6106 			kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
   6107 		}
   6108 		/*
   6109 		 * Need we reset pkt_* to zero???
   6110 		 */
   6111 	}
   6112 
   6113 	if (icmd->ipkt_nodma) {
   6114 		if (fpkt->pkt_cmd) {
   6115 			kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
   6116 		}
   6117 		if (fpkt->pkt_resp) {
   6118 			kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
   6119 		}
   6120 	} else {
   6121 		ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
   6122 
   6123 		fcp_free_cmd_resp(pptr, fpkt);
   6124 	}
   6125 }
   6126 
   6127 /*
   6128  *     Function: fcp_lookup_target
   6129  *
   6130  *  Description: Finds a target given a WWN.
   6131  *
   6132  *     Argument: *pptr	FCP port.
   6133  *		 *wwn	World Wide Name of the device to look for.
   6134  *
   6135  * Return Value: NULL		No target found
   6136  *		 Not NULL	Target structure
   6137  *
   6138  *	Context: Interrupt context.
   6139  *		 The mutex pptr->port_mutex must be owned.
   6140  */
   6141 /* ARGSUSED */
   6142 static struct fcp_tgt *
   6143 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
   6144 {
   6145 	int			hash;
   6146 	struct fcp_tgt	*ptgt;
   6147 
   6148 	ASSERT(mutex_owned(&pptr->port_mutex));
   6149 
   6150 	hash = FCP_HASH(wwn);
   6151 
   6152 	for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
   6153 	    ptgt = ptgt->tgt_next) {
   6154 		if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
   6155 		    bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
   6156 		    sizeof (ptgt->tgt_port_wwn)) == 0) {
   6157 			break;
   6158 		}
   6159 	}
   6160 
   6161 	return (ptgt);
   6162 }
   6163 
   6164 
   6165 /*
   6166  * Find target structure given a port identifier
   6167  */
   6168 static struct fcp_tgt *
   6169 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
   6170 {
   6171 	fc_portid_t		port_id;
   6172 	la_wwn_t		pwwn;
   6173 	struct fcp_tgt	*ptgt = NULL;
   6174 
   6175 	port_id.priv_lilp_posit = 0;
   6176 	port_id.port_id = d_id;
   6177 	if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
   6178 	    &pwwn) == FC_SUCCESS) {
   6179 		mutex_enter(&pptr->port_mutex);
   6180 		ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
   6181 		mutex_exit(&pptr->port_mutex);
   6182 	}
   6183 
   6184 	return (ptgt);
   6185 }
   6186 
   6187 
   6188 /*
   6189  * the packet completion callback routine for info cmd pkts
   6190  *
   6191  * this means fpkt pts to a response to either a PLOGI or a PRLI
   6192  *
   6193  * if there is an error an attempt is made to call a routine to resend
   6194  * the command that failed
   6195  */
   6196 static void
   6197 fcp_icmd_callback(fc_packet_t *fpkt)
   6198 {
   6199 	struct fcp_ipkt	*icmd;
   6200 	struct fcp_port	*pptr;
   6201 	struct fcp_tgt	*ptgt;
   6202 	struct la_els_prli	*prli;
   6203 	struct la_els_prli	prli_s;
   6204 	struct fcp_prli		*fprli;
   6205 	struct fcp_lun	*plun;
   6206 	int		free_pkt = 1;
   6207 	int		rval;
   6208 	ls_code_t	resp;
   6209 	uchar_t		prli_acc = 0;
   6210 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
   6211 	int		lun0_newalloc;
   6212 
   6213 	icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
   6214 
   6215 	/* get ptrs to the port and target structs for the cmd */
   6216 	pptr = icmd->ipkt_port;
   6217 	ptgt = icmd->ipkt_tgt;
   6218 
   6219 	FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
   6220 
   6221 	if (icmd->ipkt_opcode == LA_ELS_PRLI) {
   6222 		FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
   6223 		    sizeof (prli_s));
   6224 		prli_acc = (prli_s.ls_code == LA_ELS_ACC);
   6225 	}
   6226 
   6227 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6228 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6229 	    "ELS (%x) callback state=0x%x reason=0x%x for %x",
   6230 	    icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
   6231 	    ptgt->tgt_d_id);
   6232 
   6233 	if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
   6234 	    ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
   6235 
   6236 		mutex_enter(&ptgt->tgt_mutex);
   6237 		if (ptgt->tgt_pd_handle == NULL) {
   6238 			/*
   6239 			 * in a fabric environment the port device handles
   6240 			 * get created only after successful LOGIN into the
   6241 			 * transport, so the transport makes this port
   6242 			 * device (pd) handle available in this packet, so
   6243 			 * save it now
   6244 			 */
   6245 			ASSERT(fpkt->pkt_pd != NULL);
   6246 			ptgt->tgt_pd_handle = fpkt->pkt_pd;
   6247 		}
   6248 		mutex_exit(&ptgt->tgt_mutex);
   6249 
   6250 		/* which ELS cmd is this response for ?? */
   6251 		switch (icmd->ipkt_opcode) {
   6252 		case LA_ELS_PLOGI:
   6253 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6254 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
   6255 			    "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
   6256 			    ptgt->tgt_d_id,
   6257 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
   6258 			    *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
   6259 
   6260 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6261 			    FCP_TGT_TRACE_15);
   6262 
   6263 			/* Note that we are not allocating a new icmd */
   6264 			if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
   6265 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   6266 			    icmd->ipkt_cause) != DDI_SUCCESS) {
   6267 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6268 				    FCP_TGT_TRACE_16);
   6269 				goto fail;
   6270 			}
   6271 			break;
   6272 
   6273 		case LA_ELS_PRLI:
   6274 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6275 			    fcp_trace, FCP_BUF_LEVEL_5, 0,
   6276 			    "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
   6277 
   6278 			FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6279 			    FCP_TGT_TRACE_17);
   6280 
   6281 			prli = &prli_s;
   6282 
   6283 			FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
   6284 			    sizeof (prli_s));
   6285 
   6286 			fprli = (struct fcp_prli *)prli->service_params;
   6287 
   6288 			mutex_enter(&ptgt->tgt_mutex);
   6289 			ptgt->tgt_icap = fprli->initiator_fn;
   6290 			ptgt->tgt_tcap = fprli->target_fn;
   6291 			mutex_exit(&ptgt->tgt_mutex);
   6292 
   6293 			if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
   6294 				/*
   6295 				 * this FCP device does not support target mode
   6296 				 */
   6297 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6298 				    FCP_TGT_TRACE_18);
   6299 				goto fail;
   6300 			}
   6301 			if (fprli->retry == 1) {
   6302 				fc_ulp_disable_relogin(pptr->port_fp_handle,
   6303 				    &ptgt->tgt_port_wwn);
   6304 			}
   6305 
   6306 			/* target is no longer offline */
   6307 			mutex_enter(&pptr->port_mutex);
   6308 			mutex_enter(&ptgt->tgt_mutex);
   6309 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   6310 				ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
   6311 				    FCP_TGT_MARK);
   6312 			} else {
   6313 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6314 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6315 				    "fcp_icmd_callback,1: state change "
   6316 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
   6317 				mutex_exit(&ptgt->tgt_mutex);
   6318 				mutex_exit(&pptr->port_mutex);
   6319 				goto fail;
   6320 			}
   6321 			mutex_exit(&ptgt->tgt_mutex);
   6322 			mutex_exit(&pptr->port_mutex);
   6323 
   6324 			/*
   6325 			 * lun 0 should always respond to inquiry, so
   6326 			 * get the LUN struct for LUN 0
   6327 			 *
   6328 			 * Currently we deal with first level of addressing.
   6329 			 * If / when we start supporting 0x device types
   6330 			 * (DTYPE_ARRAY_CTRL, i.e. array controllers)
   6331 			 * this logic will need revisiting.
   6332 			 */
   6333 			lun0_newalloc = 0;
   6334 			if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
   6335 				/*
   6336 				 * no LUN struct for LUN 0 yet exists,
   6337 				 * so create one
   6338 				 */
   6339 				plun = fcp_alloc_lun(ptgt);
   6340 				if (plun == NULL) {
   6341 					fcp_log(CE_WARN, pptr->port_dip,
   6342 					    "!Failed to allocate lun 0 for"
   6343 					    " D_ID=%x", ptgt->tgt_d_id);
   6344 					goto fail;
   6345 				}
   6346 				lun0_newalloc = 1;
   6347 			}
   6348 
   6349 			/* fill in LUN info */
   6350 			mutex_enter(&ptgt->tgt_mutex);
   6351 			/*
   6352 			 * consider lun 0 as device not connected if it is
   6353 			 * offlined or newly allocated
   6354 			 */
   6355 			if ((plun->lun_state & FCP_LUN_OFFLINE) ||
   6356 			    lun0_newalloc) {
   6357 				plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
   6358 			}
   6359 			plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
   6360 			plun->lun_state &= ~FCP_LUN_OFFLINE;
   6361 			ptgt->tgt_lun_cnt = 1;
   6362 			ptgt->tgt_report_lun_cnt = 0;
   6363 			mutex_exit(&ptgt->tgt_mutex);
   6364 
   6365 			/* Retrieve the rscn count (if a valid one exists) */
   6366 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
   6367 				rscn_count = ((fc_ulp_rscn_info_t *)
   6368 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
   6369 				    ->ulp_rscn_count;
   6370 			} else {
   6371 				rscn_count = FC_INVALID_RSCN_COUNT;
   6372 			}
   6373 
   6374 			/* send Report Lun request to target */
   6375 			if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
   6376 			    sizeof (struct fcp_reportlun_resp),
   6377 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   6378 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
   6379 				mutex_enter(&pptr->port_mutex);
   6380 				if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   6381 					fcp_log(CE_WARN, pptr->port_dip,
   6382 					    "!Failed to send REPORT LUN to"
   6383 					    "  D_ID=%x", ptgt->tgt_d_id);
   6384 				} else {
   6385 					FCP_TRACE(fcp_logq,
   6386 					    pptr->port_instbuf, fcp_trace,
   6387 					    FCP_BUF_LEVEL_5, 0,
   6388 					    "fcp_icmd_callback,2:state change"
   6389 					    " occured for D_ID=0x%x",
   6390 					    ptgt->tgt_d_id);
   6391 				}
   6392 				mutex_exit(&pptr->port_mutex);
   6393 
   6394 				FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6395 				    FCP_TGT_TRACE_19);
   6396 
   6397 				goto fail;
   6398 			} else {
   6399 				free_pkt = 0;
   6400 				fcp_icmd_free(pptr, icmd);
   6401 			}
   6402 			break;
   6403 
   6404 		default:
   6405 			fcp_log(CE_WARN, pptr->port_dip,
   6406 			    "!fcp_icmd_callback Invalid opcode");
   6407 			goto fail;
   6408 		}
   6409 
   6410 		return;
   6411 	}
   6412 
   6413 
   6414 	/*
   6415 	 * Other PLOGI failures are not retried as the
   6416 	 * transport does it already
   6417 	 */
   6418 	if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
   6419 		if (fcp_is_retryable(icmd) &&
   6420 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
   6421 
   6422 			if (FCP_MUST_RETRY(fpkt)) {
   6423 				fcp_queue_ipkt(pptr, fpkt);
   6424 				return;
   6425 			}
   6426 
   6427 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6428 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6429 			    "ELS PRLI is retried for d_id=0x%x, state=%x,"
   6430 			    " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
   6431 			    fpkt->pkt_reason);
   6432 
   6433 			/*
   6434 			 * Retry by recalling the routine that
   6435 			 * originally queued this packet
   6436 			 */
   6437 			mutex_enter(&pptr->port_mutex);
   6438 			if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   6439 				caddr_t msg;
   6440 
   6441 				mutex_exit(&pptr->port_mutex);
   6442 
   6443 				ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
   6444 
   6445 				if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
   6446 					fpkt->pkt_timeout +=
   6447 					    FCP_TIMEOUT_DELTA;
   6448 				}
   6449 
   6450 				rval = fc_ulp_issue_els(pptr->port_fp_handle,
   6451 				    fpkt);
   6452 				if (rval == FC_SUCCESS) {
   6453 					return;
   6454 				}
   6455 
   6456 				if (rval == FC_STATEC_BUSY ||
   6457 				    rval == FC_OFFLINE) {
   6458 					fcp_queue_ipkt(pptr, fpkt);
   6459 					return;
   6460 				}
   6461 				(void) fc_ulp_error(rval, &msg);
   6462 
   6463 				fcp_log(CE_NOTE, pptr->port_dip,
   6464 				    "!ELS 0x%x failed to d_id=0x%x;"
   6465 				    " %s", icmd->ipkt_opcode,
   6466 				    ptgt->tgt_d_id, msg);
   6467 			} else {
   6468 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6469 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6470 				    "fcp_icmd_callback,3: state change "
   6471 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
   6472 				mutex_exit(&pptr->port_mutex);
   6473 			}
   6474 		}
   6475 	} else {
   6476 		if (fcp_is_retryable(icmd) &&
   6477 		    icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
   6478 			if (FCP_MUST_RETRY(fpkt)) {
   6479 				fcp_queue_ipkt(pptr, fpkt);
   6480 				return;
   6481 			}
   6482 		}
   6483 		mutex_enter(&pptr->port_mutex);
   6484 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
   6485 		    fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
   6486 			mutex_exit(&pptr->port_mutex);
   6487 			fcp_print_error(fpkt);
   6488 		} else {
   6489 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6490 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6491 			    "fcp_icmd_callback,4: state change occured"
   6492 			    " for D_ID=0x%x", ptgt->tgt_d_id);
   6493 			mutex_exit(&pptr->port_mutex);
   6494 		}
   6495 	}
   6496 
   6497 fail:
   6498 	if (free_pkt) {
   6499 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   6500 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   6501 		fcp_icmd_free(pptr, icmd);
   6502 	}
   6503 }
   6504 
   6505 
   6506 /*
   6507  * called internally to send an info cmd using the transport
   6508  *
   6509  * sends either an INQ or a REPORT_LUN
   6510  *
   6511  * when the packet is completed fcp_scsi_callback is called
   6512  */
   6513 static int
   6514 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
   6515     int lcount, int tcount, int cause, uint32_t rscn_count)
   6516 {
   6517 	int			nodma;
   6518 	struct fcp_ipkt		*icmd;
   6519 	struct fcp_tgt		*ptgt;
   6520 	struct fcp_port		*pptr;
   6521 	fc_frame_hdr_t		*hp;
   6522 	fc_packet_t		*fpkt;
   6523 	struct fcp_cmd		fcp_cmd;
   6524 	struct fcp_cmd		*fcmd;
   6525 	union scsi_cdb		*scsi_cdb;
   6526 
   6527 	ASSERT(plun != NULL);
   6528 
   6529 	ptgt = plun->lun_tgt;
   6530 	ASSERT(ptgt != NULL);
   6531 
   6532 	pptr = ptgt->tgt_port;
   6533 	ASSERT(pptr != NULL);
   6534 
   6535 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6536 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   6537 	    "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
   6538 
   6539 	nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
   6540 	icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
   6541 	    FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
   6542 	    rscn_count);
   6543 
   6544 	if (icmd == NULL) {
   6545 		return (DDI_FAILURE);
   6546 	}
   6547 
   6548 	fpkt = icmd->ipkt_fpkt;
   6549 	fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
   6550 	icmd->ipkt_retries = 0;
   6551 	icmd->ipkt_opcode = opcode;
   6552 	icmd->ipkt_lun = plun;
   6553 
   6554 	if (nodma) {
   6555 		fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
   6556 	} else {
   6557 		fcmd = &fcp_cmd;
   6558 	}
   6559 	bzero(fcmd, sizeof (struct fcp_cmd));
   6560 
   6561 	fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
   6562 
   6563 	hp = &fpkt->pkt_cmd_fhdr;
   6564 
   6565 	hp->s_id = pptr->port_id;
   6566 	hp->d_id = ptgt->tgt_d_id;
   6567 	hp->r_ctl = R_CTL_COMMAND;
   6568 	hp->type = FC_TYPE_SCSI_FCP;
   6569 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
   6570 	hp->rsvd = 0;
   6571 	hp->seq_id = 0;
   6572 	hp->seq_cnt = 0;
   6573 	hp->ox_id = 0xffff;
   6574 	hp->rx_id = 0xffff;
   6575 	hp->ro = 0;
   6576 
   6577 	bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
   6578 
   6579 	/*
   6580 	 * Request SCSI target for expedited processing
   6581 	 */
   6582 
   6583 	/*
   6584 	 * Set up for untagged queuing because we do not
   6585 	 * know if the fibre device supports queuing.
   6586 	 */
   6587 	fcmd->fcp_cntl.cntl_reserved_0 = 0;
   6588 	fcmd->fcp_cntl.cntl_reserved_1 = 0;
   6589 	fcmd->fcp_cntl.cntl_reserved_2 = 0;
   6590 	fcmd->fcp_cntl.cntl_reserved_3 = 0;
   6591 	fcmd->fcp_cntl.cntl_reserved_4 = 0;
   6592 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
   6593 	scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
   6594 
   6595 	switch (opcode) {
   6596 	case SCMD_INQUIRY_PAGE83:
   6597 		/*
   6598 		 * Prepare to get the Inquiry VPD page 83 information
   6599 		 */
   6600 		fcmd->fcp_cntl.cntl_read_data = 1;
   6601 		fcmd->fcp_cntl.cntl_write_data = 0;
   6602 		fcmd->fcp_data_len = alloc_len;
   6603 
   6604 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
   6605 		fpkt->pkt_comp = fcp_scsi_callback;
   6606 
   6607 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
   6608 		scsi_cdb->g0_addr2 = 0x01;
   6609 		scsi_cdb->g0_addr1 = 0x83;
   6610 		scsi_cdb->g0_count0 = (uchar_t)alloc_len;
   6611 		break;
   6612 
   6613 	case SCMD_INQUIRY:
   6614 		fcmd->fcp_cntl.cntl_read_data = 1;
   6615 		fcmd->fcp_cntl.cntl_write_data = 0;
   6616 		fcmd->fcp_data_len = alloc_len;
   6617 
   6618 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
   6619 		fpkt->pkt_comp = fcp_scsi_callback;
   6620 
   6621 		scsi_cdb->scc_cmd = SCMD_INQUIRY;
   6622 		scsi_cdb->g0_count0 = SUN_INQSIZE;
   6623 		break;
   6624 
   6625 	case SCMD_REPORT_LUN: {
   6626 		fc_portid_t	d_id;
   6627 		opaque_t	fca_dev;
   6628 
   6629 		ASSERT(alloc_len >= 16);
   6630 
   6631 		d_id.priv_lilp_posit = 0;
   6632 		d_id.port_id = ptgt->tgt_d_id;
   6633 
   6634 		fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
   6635 
   6636 		mutex_enter(&ptgt->tgt_mutex);
   6637 		ptgt->tgt_fca_dev = fca_dev;
   6638 		mutex_exit(&ptgt->tgt_mutex);
   6639 
   6640 		fcmd->fcp_cntl.cntl_read_data = 1;
   6641 		fcmd->fcp_cntl.cntl_write_data = 0;
   6642 		fcmd->fcp_data_len = alloc_len;
   6643 
   6644 		fpkt->pkt_tran_type = FC_PKT_FCP_READ;
   6645 		fpkt->pkt_comp = fcp_scsi_callback;
   6646 
   6647 		scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
   6648 		scsi_cdb->scc5_count0 = alloc_len & 0xff;
   6649 		scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
   6650 		scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
   6651 		scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
   6652 		break;
   6653 	}
   6654 
   6655 	default:
   6656 		fcp_log(CE_WARN, pptr->port_dip,
   6657 		    "!fcp_send_scsi Invalid opcode");
   6658 		break;
   6659 	}
   6660 
   6661 	if (!nodma) {
   6662 		FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
   6663 		    fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
   6664 	}
   6665 
   6666 	mutex_enter(&pptr->port_mutex);
   6667 	if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   6668 
   6669 		mutex_exit(&pptr->port_mutex);
   6670 		if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
   6671 		    FC_SUCCESS) {
   6672 			fcp_icmd_free(pptr, icmd);
   6673 			return (DDI_FAILURE);
   6674 		}
   6675 		return (DDI_SUCCESS);
   6676 	} else {
   6677 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6678 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6679 		    "fcp_send_scsi,1: state change occured"
   6680 		    " for D_ID=0x%x", ptgt->tgt_d_id);
   6681 		mutex_exit(&pptr->port_mutex);
   6682 		fcp_icmd_free(pptr, icmd);
   6683 		return (DDI_FAILURE);
   6684 	}
   6685 }
   6686 
   6687 
   6688 /*
   6689  * called by fcp_scsi_callback to check to handle the case where
   6690  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
   6691  */
   6692 static int
   6693 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
   6694 {
   6695 	uchar_t				rqlen;
   6696 	int				rval = DDI_FAILURE;
   6697 	struct scsi_extended_sense	sense_info, *sense;
   6698 	struct fcp_ipkt		*icmd = (struct fcp_ipkt *)
   6699 	    fpkt->pkt_ulp_private;
   6700 	struct fcp_tgt		*ptgt = icmd->ipkt_tgt;
   6701 	struct fcp_port		*pptr = ptgt->tgt_port;
   6702 
   6703 	ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
   6704 
   6705 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
   6706 		/*
   6707 		 * SCSI-II Reserve Release support. Some older FC drives return
   6708 		 * Reservation conflict for Report Luns command.
   6709 		 */
   6710 		if (icmd->ipkt_nodma) {
   6711 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
   6712 			rsp->fcp_u.fcp_status.sense_len_set = 0;
   6713 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6714 		} else {
   6715 			fcp_rsp_t	new_resp;
   6716 
   6717 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
   6718 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6719 
   6720 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
   6721 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
   6722 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6723 
   6724 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
   6725 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6726 		}
   6727 
   6728 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
   6729 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
   6730 
   6731 		return (DDI_SUCCESS);
   6732 	}
   6733 
   6734 	sense = &sense_info;
   6735 	if (!rsp->fcp_u.fcp_status.sense_len_set) {
   6736 		/* no need to continue if sense length is not set */
   6737 		return (rval);
   6738 	}
   6739 
   6740 	/* casting 64-bit integer to 8-bit */
   6741 	rqlen = (uchar_t)min(rsp->fcp_sense_len,
   6742 	    sizeof (struct scsi_extended_sense));
   6743 
   6744 	if (rqlen < 14) {
   6745 		/* no need to continue if request length isn't long enough */
   6746 		return (rval);
   6747 	}
   6748 
   6749 	if (icmd->ipkt_nodma) {
   6750 		/*
   6751 		 * We can safely use fcp_response_len here since the
   6752 		 * only path that calls fcp_check_reportlun,
   6753 		 * fcp_scsi_callback, has already called
   6754 		 * fcp_validate_fcp_response.
   6755 		 */
   6756 		sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
   6757 		    sizeof (struct fcp_rsp) + rsp->fcp_response_len);
   6758 	} else {
   6759 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
   6760 		    rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
   6761 		    sizeof (struct scsi_extended_sense));
   6762 	}
   6763 
   6764 	if (!FCP_SENSE_NO_LUN(sense)) {
   6765 		mutex_enter(&ptgt->tgt_mutex);
   6766 		/* clear the flag if any */
   6767 		ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
   6768 		mutex_exit(&ptgt->tgt_mutex);
   6769 	}
   6770 
   6771 	if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
   6772 	    (sense->es_add_code == 0x20)) {
   6773 		if (icmd->ipkt_nodma) {
   6774 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
   6775 			rsp->fcp_u.fcp_status.sense_len_set = 0;
   6776 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6777 		} else {
   6778 			fcp_rsp_t	new_resp;
   6779 
   6780 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
   6781 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6782 
   6783 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
   6784 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
   6785 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6786 
   6787 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
   6788 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6789 		}
   6790 
   6791 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
   6792 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
   6793 
   6794 		return (DDI_SUCCESS);
   6795 	}
   6796 
   6797 	/*
   6798 	 * This is for the STK library which returns a check condition,
   6799 	 * to indicate device is not ready, manual assistance needed.
   6800 	 * This is to a report lun command when the door is open.
   6801 	 */
   6802 	if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
   6803 		if (icmd->ipkt_nodma) {
   6804 			rsp->fcp_u.fcp_status.rsp_len_set = 0;
   6805 			rsp->fcp_u.fcp_status.sense_len_set = 0;
   6806 			rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6807 		} else {
   6808 			fcp_rsp_t	new_resp;
   6809 
   6810 			FCP_CP_IN(fpkt->pkt_resp, &new_resp,
   6811 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6812 
   6813 			new_resp.fcp_u.fcp_status.rsp_len_set = 0;
   6814 			new_resp.fcp_u.fcp_status.sense_len_set = 0;
   6815 			new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
   6816 
   6817 			FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
   6818 			    fpkt->pkt_resp_acc, sizeof (new_resp));
   6819 		}
   6820 
   6821 		FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
   6822 		    fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
   6823 
   6824 		return (DDI_SUCCESS);
   6825 	}
   6826 
   6827 	if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
   6828 	    (FCP_SENSE_NO_LUN(sense))) {
   6829 		mutex_enter(&ptgt->tgt_mutex);
   6830 		if ((FCP_SENSE_NO_LUN(sense)) &&
   6831 		    (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
   6832 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
   6833 			mutex_exit(&ptgt->tgt_mutex);
   6834 			/*
   6835 			 * reconfig was triggred by ILLEGAL REQUEST but
   6836 			 * got ILLEGAL REQUEST again
   6837 			 */
   6838 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6839 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
   6840 			    "!FCP: Unable to obtain Report Lun data"
   6841 			    " target=%x", ptgt->tgt_d_id);
   6842 		} else {
   6843 			if (ptgt->tgt_tid == NULL) {
   6844 				timeout_id_t	tid;
   6845 				/*
   6846 				 * REPORT LUN data has changed.	 Kick off
   6847 				 * rediscovery
   6848 				 */
   6849 				tid = timeout(fcp_reconfigure_luns,
   6850 				    (caddr_t)ptgt, (clock_t)drv_usectohz(1));
   6851 
   6852 				ptgt->tgt_tid = tid;
   6853 				ptgt->tgt_state |= FCP_TGT_BUSY;
   6854 			}
   6855 			if (FCP_SENSE_NO_LUN(sense)) {
   6856 				ptgt->tgt_state |= FCP_TGT_ILLREQ;
   6857 			}
   6858 			mutex_exit(&ptgt->tgt_mutex);
   6859 			if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
   6860 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6861 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
   6862 				    "!FCP:Report Lun Has Changed"
   6863 				    " target=%x", ptgt->tgt_d_id);
   6864 			} else if (FCP_SENSE_NO_LUN(sense)) {
   6865 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6866 				    fcp_trace, FCP_BUF_LEVEL_3, 0,
   6867 				    "!FCP:LU Not Supported"
   6868 				    " target=%x", ptgt->tgt_d_id);
   6869 			}
   6870 		}
   6871 		rval = DDI_SUCCESS;
   6872 	}
   6873 
   6874 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6875 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   6876 	    "D_ID=%x, sense=%x, status=%x",
   6877 	    fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
   6878 	    rsp->fcp_u.fcp_status.scsi_status);
   6879 
   6880 	return (rval);
   6881 }
   6882 
   6883 /*
   6884  *     Function: fcp_scsi_callback
   6885  *
   6886  *  Description: This is the callback routine set by fcp_send_scsi() after
   6887  *		 it calls fcp_icmd_alloc().  The SCSI command completed here
   6888  *		 and autogenerated by FCP are:	REPORT_LUN, INQUIRY and
   6889  *		 INQUIRY_PAGE83.
   6890  *
   6891  *     Argument: *fpkt	 FC packet used to convey the command
   6892  *
   6893  * Return Value: None
   6894  */
   6895 static void
   6896 fcp_scsi_callback(fc_packet_t *fpkt)
   6897 {
   6898 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
   6899 	    fpkt->pkt_ulp_private;
   6900 	struct fcp_rsp_info	fcp_rsp_err, *bep;
   6901 	struct fcp_port	*pptr;
   6902 	struct fcp_tgt	*ptgt;
   6903 	struct fcp_lun	*plun;
   6904 	struct fcp_rsp		response, *rsp;
   6905 
   6906 	ptgt = icmd->ipkt_tgt;
   6907 	pptr = ptgt->tgt_port;
   6908 	plun = icmd->ipkt_lun;
   6909 
   6910 	if (icmd->ipkt_nodma) {
   6911 		rsp = (struct fcp_rsp *)fpkt->pkt_resp;
   6912 	} else {
   6913 		rsp = &response;
   6914 		FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
   6915 		    sizeof (struct fcp_rsp));
   6916 	}
   6917 
   6918 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6919 	    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6920 	    "SCSI callback state=0x%x for %x, op_code=0x%x, "
   6921 	    "status=%x, lun num=%x",
   6922 	    fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
   6923 	    rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
   6924 
   6925 	/*
   6926 	 * Pre-init LUN GUID with NWWN if it is not a device that
   6927 	 * supports multiple luns and we know it's not page83
   6928 	 * compliant.  Although using a NWWN is not lun unique,
   6929 	 * we will be fine since there is only one lun behind the taget
   6930 	 * in this case.
   6931 	 */
   6932 	if ((plun->lun_guid_size == 0) &&
   6933 	    (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
   6934 	    (fcp_symmetric_device_probe(plun) == 0)) {
   6935 
   6936 		char ascii_wwn[FC_WWN_SIZE*2+1];
   6937 		fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
   6938 		(void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
   6939 	}
   6940 
   6941 	/*
   6942 	 * Some old FC tapes and FC <-> SCSI bridge devices return overrun
   6943 	 * when thay have more data than what is asked in CDB. An overrun
   6944 	 * is really when FCP_DL is smaller than the data length in CDB.
   6945 	 * In the case here we know that REPORT LUN command we formed within
   6946 	 * this binary has correct FCP_DL. So this OVERRUN is due to bad device
   6947 	 * behavior. In reality this is FC_SUCCESS.
   6948 	 */
   6949 	if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
   6950 	    (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
   6951 	    (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
   6952 		fpkt->pkt_state = FC_PKT_SUCCESS;
   6953 	}
   6954 
   6955 	if (fpkt->pkt_state != FC_PKT_SUCCESS) {
   6956 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6957 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6958 		    "icmd failed with state=0x%x for %x", fpkt->pkt_state,
   6959 		    ptgt->tgt_d_id);
   6960 
   6961 		if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
   6962 			/*
   6963 			 * Inquiry VPD page command on A5K SES devices would
   6964 			 * result in data CRC errors.
   6965 			 */
   6966 			if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
   6967 				(void) fcp_handle_page83(fpkt, icmd, 1);
   6968 				return;
   6969 			}
   6970 		}
   6971 		if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
   6972 		    FCP_MUST_RETRY(fpkt)) {
   6973 			fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
   6974 			fcp_retry_scsi_cmd(fpkt);
   6975 			return;
   6976 		}
   6977 
   6978 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   6979 		    FCP_TGT_TRACE_20);
   6980 
   6981 		mutex_enter(&pptr->port_mutex);
   6982 		mutex_enter(&ptgt->tgt_mutex);
   6983 		if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
   6984 			mutex_exit(&ptgt->tgt_mutex);
   6985 			mutex_exit(&pptr->port_mutex);
   6986 			fcp_print_error(fpkt);
   6987 		} else {
   6988 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   6989 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   6990 			    "fcp_scsi_callback,1: state change occured"
   6991 			    " for D_ID=0x%x", ptgt->tgt_d_id);
   6992 			mutex_exit(&ptgt->tgt_mutex);
   6993 			mutex_exit(&pptr->port_mutex);
   6994 		}
   6995 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   6996 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   6997 		fcp_icmd_free(pptr, icmd);
   6998 		return;
   6999 	}
   7000 
   7001 	FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
   7002 
   7003 	mutex_enter(&pptr->port_mutex);
   7004 	mutex_enter(&ptgt->tgt_mutex);
   7005 	if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
   7006 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7007 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7008 		    "fcp_scsi_callback,2: state change occured"
   7009 		    " for D_ID=0x%x", ptgt->tgt_d_id);
   7010 		mutex_exit(&ptgt->tgt_mutex);
   7011 		mutex_exit(&pptr->port_mutex);
   7012 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7013 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7014 		fcp_icmd_free(pptr, icmd);
   7015 		return;
   7016 	}
   7017 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
   7018 
   7019 	mutex_exit(&ptgt->tgt_mutex);
   7020 	mutex_exit(&pptr->port_mutex);
   7021 
   7022 	if (icmd->ipkt_nodma) {
   7023 		bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
   7024 		    sizeof (struct fcp_rsp));
   7025 	} else {
   7026 		bep = &fcp_rsp_err;
   7027 		FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
   7028 		    fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
   7029 	}
   7030 
   7031 	if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
   7032 		fcp_retry_scsi_cmd(fpkt);
   7033 		return;
   7034 	}
   7035 
   7036 	if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
   7037 	    FCP_NO_FAILURE) {
   7038 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7039 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7040 		    "rsp_code=0x%x, rsp_len_set=0x%x",
   7041 		    bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
   7042 		fcp_retry_scsi_cmd(fpkt);
   7043 		return;
   7044 	}
   7045 
   7046 	if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
   7047 	    rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
   7048 		fcp_queue_ipkt(pptr, fpkt);
   7049 		return;
   7050 	}
   7051 
   7052 	/*
   7053 	 * Devices that do not support INQUIRY_PAGE83, return check condition
   7054 	 * with illegal request as per SCSI spec.
   7055 	 * Crossbridge is one such device and Daktari's SES node is another.
   7056 	 * We want to ideally enumerate these devices as a non-mpxio devices.
   7057 	 * SES nodes (Daktari only currently) are an exception to this.
   7058 	 */
   7059 	if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
   7060 	    (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
   7061 
   7062 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7063 		    fcp_trace, FCP_BUF_LEVEL_3, 0,
   7064 		    "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
   7065 		    "check condition. May enumerate as non-mpxio device",
   7066 		    ptgt->tgt_d_id, plun->lun_type);
   7067 
   7068 		/*
   7069 		 * If we let Daktari's SES be enumerated as a non-mpxio
   7070 		 * device, there will be a discrepency in that the other
   7071 		 * internal FC disks will get enumerated as mpxio devices.
   7072 		 * Applications like luxadm expect this to be consistent.
   7073 		 *
   7074 		 * So, we put in a hack here to check if this is an SES device
   7075 		 * and handle it here.
   7076 		 */
   7077 		if (plun->lun_type == DTYPE_ESI) {
   7078 			/*
   7079 			 * Since, pkt_state is actually FC_PKT_SUCCESS
   7080 			 * at this stage, we fake a failure here so that
   7081 			 * fcp_handle_page83 will create a device path using
   7082 			 * the WWN instead of the GUID which is not there anyway
   7083 			 */
   7084 			fpkt->pkt_state = FC_PKT_LOCAL_RJT;
   7085 			(void) fcp_handle_page83(fpkt, icmd, 1);
   7086 			return;
   7087 		}
   7088 
   7089 		mutex_enter(&ptgt->tgt_mutex);
   7090 		plun->lun_state &= ~(FCP_LUN_OFFLINE |
   7091 		    FCP_LUN_MARK | FCP_LUN_BUSY);
   7092 		mutex_exit(&ptgt->tgt_mutex);
   7093 
   7094 		(void) fcp_call_finish_init(pptr, ptgt,
   7095 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7096 		    icmd->ipkt_cause);
   7097 		fcp_icmd_free(pptr, icmd);
   7098 		return;
   7099 	}
   7100 
   7101 	if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
   7102 		int rval = DDI_FAILURE;
   7103 
   7104 		/*
   7105 		 * handle cases where report lun isn't supported
   7106 		 * by faking up our own REPORT_LUN response or
   7107 		 * UNIT ATTENTION
   7108 		 */
   7109 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
   7110 			rval = fcp_check_reportlun(rsp, fpkt);
   7111 
   7112 			/*
   7113 			 * fcp_check_reportlun might have modified the
   7114 			 * FCP response. Copy it in again to get an updated
   7115 			 * FCP response
   7116 			 */
   7117 			if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
   7118 				rsp = &response;
   7119 
   7120 				FCP_CP_IN(fpkt->pkt_resp, rsp,
   7121 				    fpkt->pkt_resp_acc,
   7122 				    sizeof (struct fcp_rsp));
   7123 			}
   7124 		}
   7125 
   7126 		if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
   7127 			if (rval == DDI_SUCCESS) {
   7128 				(void) fcp_call_finish_init(pptr, ptgt,
   7129 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7130 				    icmd->ipkt_cause);
   7131 				fcp_icmd_free(pptr, icmd);
   7132 			} else {
   7133 				fcp_retry_scsi_cmd(fpkt);
   7134 			}
   7135 
   7136 			return;
   7137 		}
   7138 	} else {
   7139 		if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
   7140 			mutex_enter(&ptgt->tgt_mutex);
   7141 			ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
   7142 			mutex_exit(&ptgt->tgt_mutex);
   7143 		}
   7144 	}
   7145 
   7146 	ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
   7147 	if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
   7148 		(void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
   7149 		    DDI_DMA_SYNC_FORCPU);
   7150 	}
   7151 
   7152 	switch (icmd->ipkt_opcode) {
   7153 	case SCMD_INQUIRY:
   7154 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
   7155 		fcp_handle_inquiry(fpkt, icmd);
   7156 		break;
   7157 
   7158 	case SCMD_REPORT_LUN:
   7159 		FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
   7160 		    FCP_TGT_TRACE_22);
   7161 		fcp_handle_reportlun(fpkt, icmd);
   7162 		break;
   7163 
   7164 	case SCMD_INQUIRY_PAGE83:
   7165 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
   7166 		(void) fcp_handle_page83(fpkt, icmd, 0);
   7167 		break;
   7168 
   7169 	default:
   7170 		fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
   7171 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7172 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7173 		fcp_icmd_free(pptr, icmd);
   7174 		break;
   7175 	}
   7176 }
   7177 
   7178 
   7179 static void
   7180 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
   7181 {
   7182 	struct fcp_ipkt	*icmd = (struct fcp_ipkt *)
   7183 	    fpkt->pkt_ulp_private;
   7184 	struct fcp_tgt	*ptgt = icmd->ipkt_tgt;
   7185 	struct fcp_port	*pptr = ptgt->tgt_port;
   7186 
   7187 	if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
   7188 	    fcp_is_retryable(icmd)) {
   7189 		mutex_enter(&pptr->port_mutex);
   7190 		if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   7191 			mutex_exit(&pptr->port_mutex);
   7192 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7193 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
   7194 			    "Retrying %s to %x; state=%x, reason=%x",
   7195 			    (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
   7196 			    "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
   7197 			    fpkt->pkt_state, fpkt->pkt_reason);
   7198 
   7199 			fcp_queue_ipkt(pptr, fpkt);
   7200 		} else {
   7201 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7202 			    fcp_trace, FCP_BUF_LEVEL_3, 0,
   7203 			    "fcp_retry_scsi_cmd,1: state change occured"
   7204 			    " for D_ID=0x%x", ptgt->tgt_d_id);
   7205 			mutex_exit(&pptr->port_mutex);
   7206 			(void) fcp_call_finish_init(pptr, ptgt,
   7207 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7208 			    icmd->ipkt_cause);
   7209 			fcp_icmd_free(pptr, icmd);
   7210 		}
   7211 	} else {
   7212 		fcp_print_error(fpkt);
   7213 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7214 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7215 		fcp_icmd_free(pptr, icmd);
   7216 	}
   7217 }
   7218 
   7219 /*
   7220  *     Function: fcp_handle_page83
   7221  *
   7222  *  Description: Treats the response to INQUIRY_PAGE83.
   7223  *
   7224  *     Argument: *fpkt	FC packet used to convey the command.
   7225  *		 *icmd	Original fcp_ipkt structure.
   7226  *		 ignore_page83_data
   7227  *			if it's 1, that means it's a special devices's
   7228  *			page83 response, it should be enumerated under mpxio
   7229  *
   7230  * Return Value: None
   7231  */
   7232 static void
   7233 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
   7234     int ignore_page83_data)
   7235 {
   7236 	struct fcp_port	*pptr;
   7237 	struct fcp_lun	*plun;
   7238 	struct fcp_tgt	*ptgt;
   7239 	uchar_t			dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
   7240 	int			fail = 0;
   7241 	ddi_devid_t		devid;
   7242 	char			*guid = NULL;
   7243 	int			ret;
   7244 
   7245 	ASSERT(icmd != NULL && fpkt != NULL);
   7246 
   7247 	pptr = icmd->ipkt_port;
   7248 	ptgt = icmd->ipkt_tgt;
   7249 	plun = icmd->ipkt_lun;
   7250 
   7251 	if (fpkt->pkt_state == FC_PKT_SUCCESS) {
   7252 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
   7253 
   7254 		FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
   7255 		    SCMD_MAX_INQUIRY_PAGE83_SIZE);
   7256 
   7257 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7258 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7259 		    "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
   7260 		    "dtype=0x%x, lun num=%x",
   7261 		    pptr->port_instance, ptgt->tgt_d_id,
   7262 		    dev_id_page[0], plun->lun_num);
   7263 
   7264 		ret = ddi_devid_scsi_encode(
   7265 		    DEVID_SCSI_ENCODE_VERSION_LATEST,
   7266 		    NULL,		/* driver name */
   7267 		    (unsigned char *) &plun->lun_inq, /* standard inquiry */
   7268 		    sizeof (plun->lun_inq), /* size of standard inquiry */
   7269 		    NULL,		/* page 80 data */
   7270 		    0,		/* page 80 len */
   7271 		    dev_id_page,	/* page 83 data */
   7272 		    SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
   7273 		    &devid);
   7274 
   7275 		if (ret == DDI_SUCCESS) {
   7276 
   7277 			guid = ddi_devid_to_guid(devid);
   7278 
   7279 			if (guid) {
   7280 				/*
   7281 				 * Check our current guid.  If it's non null
   7282 				 * and it has changed, we need to copy it into
   7283 				 * lun_old_guid since we might still need it.
   7284 				 */
   7285 				if (plun->lun_guid &&
   7286 				    strcmp(guid, plun->lun_guid)) {
   7287 					unsigned int len;
   7288 
   7289 					/*
   7290 					 * If the guid of the LUN changes,
   7291 					 * reconfiguration should be triggered
   7292 					 * to reflect the changes.
   7293 					 * i.e. we should offline the LUN with
   7294 					 * the old guid, and online the LUN with
   7295 					 * the new guid.
   7296 					 */
   7297 					plun->lun_state |= FCP_LUN_CHANGED;
   7298 
   7299 					if (plun->lun_old_guid) {
   7300 						kmem_free(plun->lun_old_guid,
   7301 						    plun->lun_old_guid_size);
   7302 					}
   7303 
   7304 					len = plun->lun_guid_size;
   7305 					plun->lun_old_guid_size = len;
   7306 
   7307 					plun->lun_old_guid = kmem_zalloc(len,
   7308 					    KM_NOSLEEP);
   7309 
   7310 					if (plun->lun_old_guid) {
   7311 						/*
   7312 						 * The alloc was successful then
   7313 						 * let's do the copy.
   7314 						 */
   7315 						bcopy(plun->lun_guid,
   7316 						    plun->lun_old_guid, len);
   7317 					} else {
   7318 						fail = 1;
   7319 						plun->lun_old_guid_size = 0;
   7320 					}
   7321 				}
   7322 				if (!fail) {
   7323 					if (fcp_copy_guid_2_lun_block(
   7324 					    plun, guid)) {
   7325 						fail = 1;
   7326 					}
   7327 				}
   7328 				ddi_devid_free_guid(guid);
   7329 
   7330 			} else {
   7331 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7332 				    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7333 				    "fcp_handle_page83: unable to create "
   7334 				    "GUID");
   7335 
   7336 				/* couldn't create good guid from devid */
   7337 				fail = 1;
   7338 			}
   7339 			ddi_devid_free(devid);
   7340 
   7341 		} else if (ret == DDI_NOT_WELL_FORMED) {
   7342 			/* NULL filled data for page 83 */
   7343 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7344 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7345 			    "fcp_handle_page83: retry GUID");
   7346 
   7347 			icmd->ipkt_retries = 0;
   7348 			fcp_retry_scsi_cmd(fpkt);
   7349 			return;
   7350 		} else {
   7351 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7352 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7353 			    "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
   7354 			    ret);
   7355 			/*
   7356 			 * Since the page83 validation
   7357 			 * introduced late, we are being
   7358 			 * tolerant to the existing devices
   7359 			 * that already found to be working
   7360 			 * under mpxio, like A5200's SES device,
   7361 			 * its page83 response will not be standard-compliant,
   7362 			 * but we still want it to be enumerated under mpxio.
   7363 			 */
   7364 			if (fcp_symmetric_device_probe(plun) != 0) {
   7365 				fail = 1;
   7366 			}
   7367 		}
   7368 
   7369 	} else {
   7370 		/* bad packet state */
   7371 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
   7372 
   7373 		/*
   7374 		 * For some special devices (A5K SES and Daktari's SES devices),
   7375 		 * they should be enumerated under mpxio
   7376 		 * or "luxadm dis" will fail
   7377 		 */
   7378 		if (ignore_page83_data) {
   7379 			fail = 0;
   7380 		} else {
   7381 			fail = 1;
   7382 		}
   7383 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7384 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7385 		    "!Devid page cmd failed. "
   7386 		    "fpkt_state: %x fpkt_reason: %x",
   7387 		    "ignore_page83: %d",
   7388 		    fpkt->pkt_state, fpkt->pkt_reason,
   7389 		    ignore_page83_data);
   7390 	}
   7391 
   7392 	mutex_enter(&pptr->port_mutex);
   7393 	mutex_enter(&plun->lun_mutex);
   7394 	/*
   7395 	 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
   7396 	 * mismatch between lun_cip and lun_mpxio.
   7397 	 */
   7398 	if (plun->lun_cip == NULL) {
   7399 		/*
   7400 		 * If we don't have a guid for this lun it's because we were
   7401 		 * unable to glean one from the page 83 response.  Set the
   7402 		 * control flag to 0 here to make sure that we don't attempt to
   7403 		 * enumerate it under mpxio.
   7404 		 */
   7405 		if (fail || pptr->port_mpxio == 0) {
   7406 			plun->lun_mpxio = 0;
   7407 		} else {
   7408 			plun->lun_mpxio = 1;
   7409 		}
   7410 	}
   7411 	mutex_exit(&plun->lun_mutex);
   7412 	mutex_exit(&pptr->port_mutex);
   7413 
   7414 	mutex_enter(&ptgt->tgt_mutex);
   7415 	plun->lun_state &=
   7416 	    ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
   7417 	mutex_exit(&ptgt->tgt_mutex);
   7418 
   7419 	(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7420 	    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7421 
   7422 	fcp_icmd_free(pptr, icmd);
   7423 }
   7424 
   7425 /*
   7426  *     Function: fcp_handle_inquiry
   7427  *
   7428  *  Description: Called by fcp_scsi_callback to handle the response to an
   7429  *		 INQUIRY request.
   7430  *
   7431  *     Argument: *fpkt	FC packet used to convey the command.
   7432  *		 *icmd	Original fcp_ipkt structure.
   7433  *
   7434  * Return Value: None
   7435  */
   7436 static void
   7437 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
   7438 {
   7439 	struct fcp_port	*pptr;
   7440 	struct fcp_lun	*plun;
   7441 	struct fcp_tgt	*ptgt;
   7442 	uchar_t		dtype;
   7443 	uchar_t		pqual;
   7444 	uint32_t	rscn_count = FC_INVALID_RSCN_COUNT;
   7445 
   7446 	ASSERT(icmd != NULL && fpkt != NULL);
   7447 
   7448 	pptr = icmd->ipkt_port;
   7449 	ptgt = icmd->ipkt_tgt;
   7450 	plun = icmd->ipkt_lun;
   7451 
   7452 	FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
   7453 	    sizeof (struct scsi_inquiry));
   7454 
   7455 	dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
   7456 	pqual = plun->lun_inq.inq_dtype >> 5;
   7457 
   7458 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7459 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7460 	    "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
   7461 	    "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
   7462 	    plun->lun_num, dtype, pqual);
   7463 
   7464 	if (pqual != 0) {
   7465 		/*
   7466 		 * Non-zero peripheral qualifier
   7467 		 */
   7468 		fcp_log(CE_CONT, pptr->port_dip,
   7469 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
   7470 		    "Device type=0x%x Peripheral qual=0x%x\n",
   7471 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
   7472 
   7473 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7474 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7475 		    "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
   7476 		    "Device type=0x%x Peripheral qual=0x%x\n",
   7477 		    ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
   7478 
   7479 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
   7480 
   7481 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7482 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7483 		fcp_icmd_free(pptr, icmd);
   7484 		return;
   7485 	}
   7486 
   7487 	/*
   7488 	 * If the device is already initialized, check the dtype
   7489 	 * for a change. If it has changed then update the flags
   7490 	 * so the create_luns will offline the old device and
   7491 	 * create the new device. Refer to bug: 4764752
   7492 	 */
   7493 	if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
   7494 		plun->lun_state |= FCP_LUN_CHANGED;
   7495 	}
   7496 	plun->lun_type = plun->lun_inq.inq_dtype;
   7497 
   7498 	/*
   7499 	 * This code is setting/initializing the throttling in the FCA
   7500 	 * driver.
   7501 	 */
   7502 	mutex_enter(&pptr->port_mutex);
   7503 	if (!pptr->port_notify) {
   7504 		if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
   7505 			uint32_t cmd = 0;
   7506 			cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
   7507 			    ((cmd & 0xFFFFFF00 >> 8) |
   7508 			    FCP_SVE_THROTTLE << 8));
   7509 			pptr->port_notify = 1;
   7510 			mutex_exit(&pptr->port_mutex);
   7511 			(void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
   7512 			mutex_enter(&pptr->port_mutex);
   7513 		}
   7514 	}
   7515 
   7516 	if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
   7517 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7518 		    fcp_trace, FCP_BUF_LEVEL_2, 0,
   7519 		    "fcp_handle_inquiry,1:state change occured"
   7520 		    " for D_ID=0x%x", ptgt->tgt_d_id);
   7521 		mutex_exit(&pptr->port_mutex);
   7522 
   7523 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
   7524 		(void) fcp_call_finish_init(pptr, ptgt,
   7525 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7526 		    icmd->ipkt_cause);
   7527 		fcp_icmd_free(pptr, icmd);
   7528 		return;
   7529 	}
   7530 	ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
   7531 	mutex_exit(&pptr->port_mutex);
   7532 
   7533 	/* Retrieve the rscn count (if a valid one exists) */
   7534 	if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
   7535 		rscn_count = ((fc_ulp_rscn_info_t *)
   7536 		    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
   7537 	} else {
   7538 		rscn_count = FC_INVALID_RSCN_COUNT;
   7539 	}
   7540 
   7541 	if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
   7542 	    SCMD_MAX_INQUIRY_PAGE83_SIZE,
   7543 	    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7544 	    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
   7545 		fcp_log(CE_WARN, NULL, "!failed to send page 83");
   7546 		FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
   7547 		(void) fcp_call_finish_init(pptr, ptgt,
   7548 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7549 		    icmd->ipkt_cause);
   7550 	}
   7551 
   7552 	/*
   7553 	 * Read Inquiry VPD Page 0x83 to uniquely
   7554 	 * identify this logical unit.
   7555 	 */
   7556 	fcp_icmd_free(pptr, icmd);
   7557 }
   7558 
   7559 /*
   7560  *     Function: fcp_handle_reportlun
   7561  *
   7562  *  Description: Called by fcp_scsi_callback to handle the response to a
   7563  *		 REPORT_LUN request.
   7564  *
   7565  *     Argument: *fpkt	FC packet used to convey the command.
   7566  *		 *icmd	Original fcp_ipkt structure.
   7567  *
   7568  * Return Value: None
   7569  */
   7570 static void
   7571 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
   7572 {
   7573 	int				i;
   7574 	int				nluns_claimed;
   7575 	int				nluns_bufmax;
   7576 	int				len;
   7577 	uint16_t			lun_num;
   7578 	uint32_t			rscn_count = FC_INVALID_RSCN_COUNT;
   7579 	struct fcp_port			*pptr;
   7580 	struct fcp_tgt			*ptgt;
   7581 	struct fcp_lun			*plun;
   7582 	struct fcp_reportlun_resp	*report_lun;
   7583 
   7584 	pptr = icmd->ipkt_port;
   7585 	ptgt = icmd->ipkt_tgt;
   7586 	len = fpkt->pkt_datalen;
   7587 
   7588 	if ((len < FCP_LUN_HEADER) ||
   7589 	    ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
   7590 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7591 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7592 		fcp_icmd_free(pptr, icmd);
   7593 		return;
   7594 	}
   7595 
   7596 	FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
   7597 	    fpkt->pkt_datalen);
   7598 
   7599 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7600 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7601 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
   7602 	    pptr->port_instance, ptgt->tgt_d_id);
   7603 
   7604 	/*
   7605 	 * Get the number of luns (which is supplied as LUNS * 8) the
   7606 	 * device claims it has.
   7607 	 */
   7608 	nluns_claimed = BE_32(report_lun->num_lun) >> 3;
   7609 
   7610 	/*
   7611 	 * Get the maximum number of luns the buffer submitted can hold.
   7612 	 */
   7613 	nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
   7614 
   7615 	/*
   7616 	 * Due to limitations of certain hardware, we support only 16 bit LUNs
   7617 	 */
   7618 	if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
   7619 		kmem_free(report_lun, len);
   7620 
   7621 		fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
   7622 		    " 0x%x number of LUNs for target=%x", nluns_claimed,
   7623 		    ptgt->tgt_d_id);
   7624 
   7625 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7626 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7627 		fcp_icmd_free(pptr, icmd);
   7628 		return;
   7629 	}
   7630 
   7631 	/*
   7632 	 * If there are more LUNs than we have allocated memory for,
   7633 	 * allocate more space and send down yet another report lun if
   7634 	 * the maximum number of attempts hasn't been reached.
   7635 	 */
   7636 	mutex_enter(&ptgt->tgt_mutex);
   7637 
   7638 	if ((nluns_claimed > nluns_bufmax) &&
   7639 	    (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
   7640 
   7641 		struct fcp_lun *plun;
   7642 
   7643 		ptgt->tgt_report_lun_cnt++;
   7644 		plun = ptgt->tgt_lun;
   7645 		ASSERT(plun != NULL);
   7646 		mutex_exit(&ptgt->tgt_mutex);
   7647 
   7648 		kmem_free(report_lun, len);
   7649 
   7650 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7651 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7652 		    "!Dynamically discovered %d LUNs for D_ID=%x",
   7653 		    nluns_claimed, ptgt->tgt_d_id);
   7654 
   7655 		/* Retrieve the rscn count (if a valid one exists) */
   7656 		if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
   7657 			rscn_count = ((fc_ulp_rscn_info_t *)
   7658 			    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
   7659 			    ulp_rscn_count;
   7660 		} else {
   7661 			rscn_count = FC_INVALID_RSCN_COUNT;
   7662 		}
   7663 
   7664 		if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
   7665 		    FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
   7666 		    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7667 		    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
   7668 			(void) fcp_call_finish_init(pptr, ptgt,
   7669 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7670 			    icmd->ipkt_cause);
   7671 		}
   7672 
   7673 		fcp_icmd_free(pptr, icmd);
   7674 		return;
   7675 	}
   7676 
   7677 	if (nluns_claimed > nluns_bufmax) {
   7678 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7679 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7680 		    "Target=%x:%x:%x:%x:%x:%x:%x:%x"
   7681 		    "	 Number of LUNs lost=%x",
   7682 		    ptgt->tgt_port_wwn.raw_wwn[0],
   7683 		    ptgt->tgt_port_wwn.raw_wwn[1],
   7684 		    ptgt->tgt_port_wwn.raw_wwn[2],
   7685 		    ptgt->tgt_port_wwn.raw_wwn[3],
   7686 		    ptgt->tgt_port_wwn.raw_wwn[4],
   7687 		    ptgt->tgt_port_wwn.raw_wwn[5],
   7688 		    ptgt->tgt_port_wwn.raw_wwn[6],
   7689 		    ptgt->tgt_port_wwn.raw_wwn[7],
   7690 		    nluns_claimed - nluns_bufmax);
   7691 
   7692 		nluns_claimed = nluns_bufmax;
   7693 	}
   7694 	ptgt->tgt_lun_cnt = nluns_claimed;
   7695 
   7696 	/*
   7697 	 * Identify missing LUNs and print warning messages
   7698 	 */
   7699 	for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
   7700 		int offline;
   7701 		int exists = 0;
   7702 
   7703 		offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
   7704 
   7705 		for (i = 0; i < nluns_claimed && exists == 0; i++) {
   7706 			uchar_t		*lun_string;
   7707 
   7708 			lun_string = (uchar_t *)&(report_lun->lun_string[i]);
   7709 
   7710 			switch (lun_string[0] & 0xC0) {
   7711 			case FCP_LUN_ADDRESSING:
   7712 			case FCP_PD_ADDRESSING:
   7713 			case FCP_VOLUME_ADDRESSING:
   7714 				lun_num = ((lun_string[0] & 0x3F) << 8) |
   7715 				    lun_string[1];
   7716 				if (plun->lun_num == lun_num) {
   7717 					exists++;
   7718 					break;
   7719 				}
   7720 				break;
   7721 
   7722 			default:
   7723 				break;
   7724 			}
   7725 		}
   7726 
   7727 		if (!exists && !offline) {
   7728 			mutex_exit(&ptgt->tgt_mutex);
   7729 
   7730 			mutex_enter(&pptr->port_mutex);
   7731 			mutex_enter(&ptgt->tgt_mutex);
   7732 			if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
   7733 				/*
   7734 				 * set disappear flag when device was connected
   7735 				 */
   7736 				if (!(plun->lun_state &
   7737 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
   7738 					plun->lun_state |= FCP_LUN_DISAPPEARED;
   7739 				}
   7740 				mutex_exit(&ptgt->tgt_mutex);
   7741 				mutex_exit(&pptr->port_mutex);
   7742 				if (!(plun->lun_state &
   7743 				    FCP_LUN_DEVICE_NOT_CONNECTED)) {
   7744 					fcp_log(CE_NOTE, pptr->port_dip,
   7745 					    "!Lun=%x for target=%x disappeared",
   7746 					    plun->lun_num, ptgt->tgt_d_id);
   7747 				}
   7748 				mutex_enter(&ptgt->tgt_mutex);
   7749 			} else {
   7750 				FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7751 				    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7752 				    "fcp_handle_reportlun,1: state change"
   7753 				    " occured for D_ID=0x%x", ptgt->tgt_d_id);
   7754 				mutex_exit(&ptgt->tgt_mutex);
   7755 				mutex_exit(&pptr->port_mutex);
   7756 				kmem_free(report_lun, len);
   7757 				(void) fcp_call_finish_init(pptr, ptgt,
   7758 				    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7759 				    icmd->ipkt_cause);
   7760 				fcp_icmd_free(pptr, icmd);
   7761 				return;
   7762 			}
   7763 		} else if (exists) {
   7764 			/*
   7765 			 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
   7766 			 * actually exists in REPORT_LUN response
   7767 			 */
   7768 			if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
   7769 				plun->lun_state &=
   7770 				    ~FCP_LUN_DEVICE_NOT_CONNECTED;
   7771 			}
   7772 			if (offline || plun->lun_num == 0) {
   7773 				if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
   7774 					plun->lun_state &= ~FCP_LUN_DISAPPEARED;
   7775 					mutex_exit(&ptgt->tgt_mutex);
   7776 					fcp_log(CE_NOTE, pptr->port_dip,
   7777 					    "!Lun=%x for target=%x reappeared",
   7778 					    plun->lun_num, ptgt->tgt_d_id);
   7779 					mutex_enter(&ptgt->tgt_mutex);
   7780 				}
   7781 			}
   7782 		}
   7783 	}
   7784 
   7785 	ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
   7786 	mutex_exit(&ptgt->tgt_mutex);
   7787 
   7788 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7789 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7790 	    "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
   7791 	    pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
   7792 
   7793 	/* scan each lun */
   7794 	for (i = 0; i < nluns_claimed; i++) {
   7795 		uchar_t	*lun_string;
   7796 
   7797 		lun_string = (uchar_t *)&(report_lun->lun_string[i]);
   7798 
   7799 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7800 		    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7801 		    "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
   7802 		    " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
   7803 		    lun_string[0]);
   7804 
   7805 		switch (lun_string[0] & 0xC0) {
   7806 		case FCP_LUN_ADDRESSING:
   7807 		case FCP_PD_ADDRESSING:
   7808 		case FCP_VOLUME_ADDRESSING:
   7809 			lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
   7810 
   7811 			/* We will skip masked LUNs because of the blacklist. */
   7812 			if (fcp_lun_blacklist != NULL) {
   7813 				mutex_enter(&ptgt->tgt_mutex);
   7814 				if (fcp_should_mask(&ptgt->tgt_port_wwn,
   7815 				    lun_num) == TRUE) {
   7816 					ptgt->tgt_lun_cnt--;
   7817 					mutex_exit(&ptgt->tgt_mutex);
   7818 					break;
   7819 				}
   7820 				mutex_exit(&ptgt->tgt_mutex);
   7821 			}
   7822 
   7823 			/* see if this LUN is already allocated */
   7824 			if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
   7825 				plun = fcp_alloc_lun(ptgt);
   7826 				if (plun == NULL) {
   7827 					fcp_log(CE_NOTE, pptr->port_dip,
   7828 					    "!Lun allocation failed"
   7829 					    " target=%x lun=%x",
   7830 					    ptgt->tgt_d_id, lun_num);
   7831 					break;
   7832 				}
   7833 			}
   7834 
   7835 			mutex_enter(&plun->lun_tgt->tgt_mutex);
   7836 			/* convert to LUN */
   7837 			plun->lun_addr.ent_addr_0 =
   7838 			    BE_16(*(uint16_t *)&(lun_string[0]));
   7839 			plun->lun_addr.ent_addr_1 =
   7840 			    BE_16(*(uint16_t *)&(lun_string[2]));
   7841 			plun->lun_addr.ent_addr_2 =
   7842 			    BE_16(*(uint16_t *)&(lun_string[4]));
   7843 			plun->lun_addr.ent_addr_3 =
   7844 			    BE_16(*(uint16_t *)&(lun_string[6]));
   7845 
   7846 			plun->lun_num = lun_num;
   7847 			plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
   7848 			plun->lun_state &= ~FCP_LUN_OFFLINE;
   7849 			mutex_exit(&plun->lun_tgt->tgt_mutex);
   7850 
   7851 			/* Retrieve the rscn count (if a valid one exists) */
   7852 			if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
   7853 				rscn_count = ((fc_ulp_rscn_info_t *)
   7854 				    (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
   7855 				    ulp_rscn_count;
   7856 			} else {
   7857 				rscn_count = FC_INVALID_RSCN_COUNT;
   7858 			}
   7859 
   7860 			if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
   7861 			    icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
   7862 			    icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
   7863 				mutex_enter(&pptr->port_mutex);
   7864 				mutex_enter(&plun->lun_tgt->tgt_mutex);
   7865 				if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
   7866 					fcp_log(CE_NOTE, pptr->port_dip,
   7867 					    "!failed to send INQUIRY"
   7868 					    " target=%x lun=%x",
   7869 					    ptgt->tgt_d_id, plun->lun_num);
   7870 				} else {
   7871 					FCP_TRACE(fcp_logq,
   7872 					    pptr->port_instbuf, fcp_trace,
   7873 					    FCP_BUF_LEVEL_5, 0,
   7874 					    "fcp_handle_reportlun,2: state"
   7875 					    " change occured for D_ID=0x%x",
   7876 					    ptgt->tgt_d_id);
   7877 				}
   7878 				mutex_exit(&plun->lun_tgt->tgt_mutex);
   7879 				mutex_exit(&pptr->port_mutex);
   7880 			} else {
   7881 				continue;
   7882 			}
   7883 			break;
   7884 
   7885 		default:
   7886 			fcp_log(CE_WARN, NULL,
   7887 			    "!Unsupported LUN Addressing method %x "
   7888 			    "in response to REPORT_LUN", lun_string[0]);
   7889 			break;
   7890 		}
   7891 
   7892 		/*
   7893 		 * each time through this loop we should decrement
   7894 		 * the tmp_cnt by one -- since we go through this loop
   7895 		 * one time for each LUN, the tmp_cnt should never be <=0
   7896 		 */
   7897 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7898 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7899 	}
   7900 
   7901 	if (i == 0) {
   7902 		fcp_log(CE_WARN, pptr->port_dip,
   7903 		    "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
   7904 		(void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
   7905 		    icmd->ipkt_change_cnt, icmd->ipkt_cause);
   7906 	}
   7907 
   7908 	kmem_free(report_lun, len);
   7909 	fcp_icmd_free(pptr, icmd);
   7910 }
   7911 
   7912 
   7913 /*
   7914  * called internally to return a LUN given a target and a LUN number
   7915  */
   7916 static struct fcp_lun *
   7917 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
   7918 {
   7919 	struct fcp_lun	*plun;
   7920 
   7921 	mutex_enter(&ptgt->tgt_mutex);
   7922 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
   7923 		if (plun->lun_num == lun_num) {
   7924 			mutex_exit(&ptgt->tgt_mutex);
   7925 			return (plun);
   7926 		}
   7927 	}
   7928 	mutex_exit(&ptgt->tgt_mutex);
   7929 
   7930 	return (NULL);
   7931 }
   7932 
   7933 
   7934 /*
   7935  * handle finishing one target for fcp_finish_init
   7936  *
   7937  * return true (non-zero) if we want finish_init to continue with the
   7938  * next target
   7939  *
   7940  * called with the port mutex held
   7941  */
   7942 /*ARGSUSED*/
   7943 static int
   7944 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
   7945     int link_cnt, int tgt_cnt, int cause)
   7946 {
   7947 	int	rval = 1;
   7948 	ASSERT(pptr != NULL);
   7949 	ASSERT(ptgt != NULL);
   7950 
   7951 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   7952 	    fcp_trace, FCP_BUF_LEVEL_5, 0,
   7953 	    "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
   7954 	    ptgt->tgt_state);
   7955 
   7956 	ASSERT(mutex_owned(&pptr->port_mutex));
   7957 
   7958 	if ((pptr->port_link_cnt != link_cnt) ||
   7959 	    (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
   7960 		/*
   7961 		 * oh oh -- another link reset or target change
   7962 		 * must have occurred while we are in here
   7963 		 */
   7964 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
   7965 
   7966 		return (0);
   7967 	} else {
   7968 		FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
   7969 	}
   7970 
   7971 	mutex_enter(&ptgt->tgt_mutex);
   7972 
   7973 	if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
   7974 		/*
   7975 		 * tgt is not offline -- is it marked (i.e. needs
   7976 		 * to be offlined) ??
   7977 		 */
   7978 		if (ptgt->tgt_state & FCP_TGT_MARK) {
   7979 			/*
   7980 			 * this target not offline *and*
   7981 			 * marked
   7982 			 */
   7983 			ptgt->tgt_state &= ~FCP_TGT_MARK;
   7984 			rval = fcp_offline_target(pptr, ptgt, link_cnt,
   7985 			    tgt_cnt, 0, 0);
   7986 		} else {
   7987 			ptgt->tgt_state &= ~FCP_TGT_BUSY;
   7988 
   7989 			/* create the LUNs */
   7990 			if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
   7991 				ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
   7992 				fcp_create_luns(ptgt, link_cnt, tgt_cnt,
   7993 				    cause);
   7994 				ptgt->tgt_device_created = 1;
   7995 			} else {
   7996 				fcp_update_tgt_state(ptgt, FCP_RESET,
   7997 				    FCP_LUN_BUSY);
   7998 			}
   7999 		}
   8000 	}
   8001 
   8002 	mutex_exit(&ptgt->tgt_mutex);
   8003 
   8004 	return (rval);
   8005 }
   8006 
   8007 
   8008 /*
   8009  * this routine is called to finish port initialization
   8010  *
   8011  * Each port has a "temp" counter -- when a state change happens (e.g.
   8012  * port online), the temp count is set to the number of devices in the map.
   8013  * Then, as each device gets "discovered", the temp counter is decremented
   8014  * by one.  When this count reaches zero we know that all of the devices
   8015  * in the map have been discovered (or an error has occurred), so we can
   8016  * then finish initialization -- which is done by this routine (well, this
   8017  * and fcp-finish_tgt())
   8018  *
   8019  * acquires and releases the global mutex
   8020  *
   8021  * called with the port mutex owned
   8022  */
   8023 static void
   8024 fcp_finish_init(struct fcp_port *pptr)
   8025 {
   8026 #ifdef	DEBUG
   8027 	bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
   8028 	pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
   8029 	    FCP_STACK_DEPTH);
   8030 #endif /* DEBUG */
   8031 
   8032 	ASSERT(mutex_owned(&pptr->port_mutex));
   8033 
   8034 	FCP_TRACE(fcp_logq, pptr->port_instbuf,
   8035 	    fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
   8036 	    " entering; ipkt count=%d", pptr->port_ipkt_cnt);
   8037 
   8038 	if ((pptr->port_state & FCP_STATE_ONLINING) &&
   8039 	    !(pptr->port_state & (FCP_STATE_SUSPENDED |
   8040 	    FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
   8041 		pptr->port_state &= ~FCP_STATE_ONLINING;
   8042 		pptr->port_state |= FCP_STATE_ONLINE;
   8043 	}
   8044 
   8045 	/* Wake up threads waiting on config done */
   8046 	cv_broadcast(&pptr->port_config_cv);
   8047 }
   8048 
   8049 
   8050 /*
   8051  * called from fcp_finish_init to create the LUNs for a target
   8052  *
   8053  * called with the port mutex owned
   8054  */
   8055 static void
   8056 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
   8057 {
   8058 	struct fcp_lun	*plun;
   8059 	struct fcp_port	*pptr;
   8060 	child_info_t		*cip = NULL;
   8061 
   8062 	ASSERT(ptgt != NULL);
   8063 	ASSERT(mutex_owned(&ptgt->tgt_mutex));
   8064 
   8065 	pptr = ptgt->tgt_port;
   8066 
   8067 	ASSERT(pptr != NULL);
   8068 
   8069 	/* scan all LUNs for this target */
   8070 	for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
   8071 		if (plun->lun_state & FCP_LUN_OFFLINE) {
   8072 			continue;
   8073 		}
   8074 
   8075 		if (plun->lun_state & FCP_LUN_MARK) {
   8076 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   8077 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   8078 			    "fcp_create_luns: offlining marked LUN!");
   8079 			fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
   8080 			continue;
   8081 		}
   8082 
   8083 		plun->lun_state &= ~FCP_LUN_BUSY;
   8084 
   8085 		/*
   8086 		 * There are conditions in which FCP_LUN_INIT flag is cleared
   8087 		 * but we have a valid plun->lun_cip. To cover this case also
   8088 		 * CLEAR_BUSY whenever we have a valid lun_cip.
   8089 		 */
   8090 		if (plun->lun_mpxio && plun->lun_cip &&
   8091 		    (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
   8092 		    FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
   8093 		    0, 0))) {
   8094 			FCP_TRACE(fcp_logq, pptr->port_instbuf,
   8095 			    fcp_trace, FCP_BUF_LEVEL_2, 0,
   8096 			    "fcp_create_luns: enable lun %p failed!",
   8097 			    plun);
   8098 		}
   8099 
   8100 		if (plun->lun_state & FCP_LUN_INIT &&
   8101 		    !(plun->lun_state & FCP_LUN_CHANGED)) {
   8102 			continue;
   8103 		}
   8104 
   8105 		if (cause == FCP_CAUSE_USER_CREATE) {
   8106 			continue;
   8107 		}
   8108 
   8109 		FCP_TRACE(fcp_logq, pptr->port_instbuf,
   8110 		    fcp_trace, FCP_BUF_LEVEL_6, 0,
   8111 		    "create_luns: passing ONLINE elem to HP thread");
   8112 
   8113 		/*
   8114 		 * If lun has changed, prepare for offlining the old path.
   8115 		 * Do not offline the old path right now, since it may be
   8116 		 * still opened.
   8117 		 */
   8118 		if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
   8119 			fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
   8120 		}
   8121 
   8122 		/* pass an ONLINE element to the hotplug thread */
   8123 		if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
   8124 		    link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
   8125 
   8126 			/*
   8127 			 * We can not synchronous attach (i.e pass
   8128 			 * NDI_ONLINE_ATTACH) here as we might be
   8129 			 * coming from an interrupt or callback
   8130 			 * thread.
   8131 			 */
   8132 			if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
   8133 			    link_cnt, tgt_cnt, 0, 0)) {
   8134 				fcp_log(CE_CONT, pptr->port_dip,
   8135 				    "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
   8136 				    plun->lun_tgt->tgt_d_id, plun->lun_num);
   8137 			}
   8138 		}
   8139 	}
   8140 }
   8141 
   8142 
   8143 /*
   8144  * function to online/offline devices
   8145  */
   8146 static int
   8147 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
   8148     int online, int lcount, int tcount, int flags)
   8149 {