xref: /illumos-gate/usr/src/uts/common/io/fibre-channel/ulp/fcip.c (revision 0250c53ad267726f2438e3c6556199a0bbf588a2)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright (c) 2016 by Delphix. All rights reserved.
25  */
26 
27 /*
28  * SunOS 5.x Multithreaded STREAMS DLPI FCIP Module
29  * This is a pseudo driver module to handle encapsulation of IP and ARP
30  * datagrams over FibreChannel interfaces. FCIP is a cloneable STREAMS
31  * driver module which interfaces with IP/ARP using DLPI. This module
32  * is a Style-2 DLS provider.
33  *
34  * The implementation of this module is based on RFC 2625 which gives
35  * details on the encapsulation of IP/ARP data over FibreChannel.
36  * The fcip module needs to resolve an IP address to a port address before
37  * sending data to a destination port. A FC device port has 2 addresses
38  * associated with it: A 8 byte World Wide unique Port Name and a 3 byte
39  * volatile Port number or Port_ID.
40  *
41  * The mapping between a IP address and the World Wide Port Name is handled
42  * by the ARP layer since the IP over FC draft requires the MAC address to
43  * be the least significant six bytes of the WorldWide Port Names. The
44  * fcip module however needs to identify the destination port uniquely when
45  * the destination FC device has multiple FC ports.
46  *
47  * The FC layer mapping between the World Wide Port Name and the Port_ID
48  * will be handled through the use of a fabric name server or through the
49  * use of the FARP ELS command as described in the draft. Since the Port_IDs
50  * are volatile, the mapping between the World Wide Port Name and Port_IDs
51  * must be maintained and validated before use each time a datagram
52  * needs to be sent to the destination ports. The FC transport module
53  * informs the fcip module of all changes to states of ports on the
54  * fabric through registered callbacks. This enables the fcip module
55  * to maintain the WW_PN to Port_ID mappings current.
56  *
57  * For details on how this module interfaces with the FibreChannel Transport
58  * modules, refer to PSARC/1997/385. Chapter 3 of the FibreChannel Transport
59  * Programming guide details the APIs between ULPs and the Transport.
60  *
61  * Now for some Caveats:
62  *
63  * RFC 2625 requires that a FibreChannel Port name (the Port WWN) have
64  * the NAA bits set to '0001' indicating a IEEE 48bit address which
65  * corresponds to a ULA (Universal LAN MAC address). But with FibreChannel
66  * adapters containing 2 or more ports, IEEE naming cannot identify the
67  * ports on an adapter uniquely so we will in the first implementation
68  * be operating only on Port 0 of each adapter.
69  */
70 
71 #include	<sys/types.h>
72 #include	<sys/errno.h>
73 #include	<sys/debug.h>
74 #include	<sys/time.h>
75 #include	<sys/sysmacros.h>
76 #include	<sys/systm.h>
77 #include	<sys/user.h>
78 #include	<sys/stropts.h>
79 #include	<sys/stream.h>
80 #include	<sys/strlog.h>
81 #include	<sys/strsubr.h>
82 #include	<sys/cmn_err.h>
83 #include	<sys/cpu.h>
84 #include	<sys/kmem.h>
85 #include	<sys/conf.h>
86 #include	<sys/ddi.h>
87 #include	<sys/sunddi.h>
88 #include	<sys/ksynch.h>
89 #include	<sys/stat.h>
90 #include	<sys/kstat.h>
91 #include	<sys/vtrace.h>
92 #include	<sys/strsun.h>
93 #include	<sys/varargs.h>
94 #include	<sys/modctl.h>
95 #include 	<sys/thread.h>
96 #include 	<sys/var.h>
97 #include 	<sys/proc.h>
98 #include	<inet/common.h>
99 #include	<netinet/ip6.h>
100 #include	<inet/ip.h>
101 #include	<inet/arp.h>
102 #include	<inet/mi.h>
103 #include	<inet/nd.h>
104 #include	<sys/dlpi.h>
105 #include	<sys/ethernet.h>
106 #include	<sys/file.h>
107 #include	<sys/syslog.h>
108 #include	<sys/disp.h>
109 #include	<sys/taskq.h>
110 
111 /*
112  * Leadville includes
113  */
114 
115 #include	<sys/fibre-channel/fc.h>
116 #include	<sys/fibre-channel/impl/fc_ulpif.h>
117 #include	<sys/fibre-channel/ulp/fcip.h>
118 
119 #define	FCIP_ESBALLOC
120 
121 /*
122  * Function prototypes
123  */
124 
125 /* standard loadable modules entry points */
126 static int	fcip_attach(dev_info_t *, ddi_attach_cmd_t);
127 static int 	fcip_detach(dev_info_t *, ddi_detach_cmd_t);
128 static void 	fcip_dodetach(struct fcipstr *slp);
129 static int fcip_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
130     void *arg, void **result);
131 
132 
133 /* streams specific */
134 static void fcip_setipq(struct fcip *fptr);
135 static int fcip_wput(queue_t *, mblk_t *);
136 static int fcip_wsrv(queue_t *);
137 static void fcip_proto(queue_t *, mblk_t *);
138 static void fcip_ioctl(queue_t *, mblk_t *);
139 static int fcip_open(queue_t *wq, dev_t *devp, int flag,
140 		int sflag, cred_t *credp);
141 static int fcip_close(queue_t *rq, int flag, cred_t *credp);
142 static int fcip_start(queue_t *wq, mblk_t *mp, struct fcip *fptr,
143     struct fcip_dest *fdestp, int flags);
144 static void fcip_sendup(struct fcip *fptr, mblk_t *mp,
145     struct fcipstr *(*acceptfunc)());
146 static struct fcipstr *fcip_accept(struct fcipstr *slp, struct fcip *fptr,
147     int type, la_wwn_t *dhostp);
148 static mblk_t *fcip_addudind(struct fcip *fptr, mblk_t *mp,
149     fcph_network_hdr_t *nhdr, int type);
150 static int fcip_setup_mac_addr(struct fcip *fptr);
151 static void fcip_kstat_init(struct fcip *fptr);
152 static int fcip_stat_update(kstat_t *, int);
153 
154 
155 /* dlpi specific */
156 static void fcip_spareq(queue_t *wq, mblk_t *mp);
157 static void fcip_pareq(queue_t *wq, mblk_t *mp);
158 static void fcip_ubreq(queue_t *wq, mblk_t *mp);
159 static void fcip_breq(queue_t *wq, mblk_t *mp);
160 static void fcip_dreq(queue_t *wq, mblk_t *mp);
161 static void fcip_areq(queue_t *wq, mblk_t *mp);
162 static void fcip_udreq(queue_t *wq, mblk_t *mp);
163 static void fcip_ireq(queue_t *wq, mblk_t *mp);
164 static void fcip_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp);
165 
166 
167 /* solaris sundry, DR/CPR etc */
168 static int fcip_cache_constructor(void *buf, void *arg, int size);
169 static void fcip_cache_destructor(void *buf, void *size);
170 static int fcip_handle_suspend(fcip_port_info_t *fport, fc_detach_cmd_t cmd);
171 static int fcip_handle_resume(fcip_port_info_t *fport,
172     fc_ulp_port_info_t *port_info, fc_attach_cmd_t cmd);
173 static fcip_port_info_t *fcip_softstate_free(fcip_port_info_t *fport);
174 static int fcip_port_attach_handler(struct fcip *fptr);
175 
176 
177 /*
178  * ulp - transport interface function prototypes
179  */
180 static int fcip_port_attach(opaque_t ulp_handle, fc_ulp_port_info_t *,
181     fc_attach_cmd_t cmd, uint32_t sid);
182 static int fcip_port_detach(opaque_t ulp_handle, fc_ulp_port_info_t *,
183     fc_detach_cmd_t cmd);
184 static int fcip_port_ioctl(opaque_t ulp_handle,  opaque_t port_handle,
185     dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
186     uint32_t claimed);
187 static void fcip_statec_cb(opaque_t ulp_handle, opaque_t phandle,
188     uint32_t port_state, uint32_t port_top, fc_portmap_t changelist[],
189     uint32_t listlen, uint32_t sid);
190 static int fcip_els_cb(opaque_t ulp_handle, opaque_t phandle,
191     fc_unsol_buf_t *buf, uint32_t claimed);
192 static int fcip_data_cb(opaque_t ulp_handle, opaque_t phandle,
193     fc_unsol_buf_t *payload, uint32_t claimed);
194 
195 
196 /* Routing table specific */
197 static void fcip_handle_topology(struct fcip *fptr);
198 static int fcip_init_port(struct fcip *fptr);
199 struct fcip_routing_table *fcip_lookup_rtable(struct fcip *fptr,
200     la_wwn_t *pwwn, int matchflag);
201 static void fcip_rt_update(struct fcip *fptr, fc_portmap_t *devlist,
202     uint32_t listlen);
203 static void fcip_rt_flush(struct fcip *fptr);
204 static void fcip_rte_remove_deferred(void *arg);
205 static int fcip_do_plogi(struct fcip *fptr, struct fcip_routing_table *frp);
206 
207 
208 /* dest table specific */
209 static struct fcip_dest *fcip_get_dest(struct fcip *fptr,
210     la_wwn_t *dlphys);
211 static struct fcip_dest *fcip_add_dest(struct fcip *fptr,
212     struct fcip_routing_table *frp);
213 static int fcip_dest_add_broadcast_entry(struct fcip *fptr, int new_flag);
214 static uint32_t fcip_get_broadcast_did(struct fcip *fptr);
215 static void fcip_cleanup_dest(struct fcip *fptr);
216 
217 
218 /* helper functions */
219 static fcip_port_info_t *fcip_get_port(opaque_t phandle);
220 static int fcip_wwn_compare(la_wwn_t *wwn1, la_wwn_t *wwn2, int flag);
221 static void fcip_ether_to_str(struct ether_addr *e, caddr_t s);
222 static int fcip_port_get_num_pkts(struct fcip *fptr);
223 static int fcip_check_port_busy(struct fcip *fptr);
224 static void fcip_check_remove_minor_node(void);
225 static int fcip_set_wwn(la_wwn_t *pwwn);
226 static int fcip_plogi_in_progress(struct fcip *fptr);
227 static int fcip_check_port_exists(struct fcip *fptr);
228 static int fcip_is_supported_fc_topology(int fc_topology);
229 
230 
231 /* pkt specific */
232 static fcip_pkt_t *fcip_pkt_alloc(struct fcip *fptr, mblk_t *bp,
233     int flags, int datalen);
234 static void fcip_pkt_free(struct fcip_pkt *fcip_pkt, int flags);
235 static fcip_pkt_t *fcip_ipkt_alloc(struct fcip *fptr, int cmdlen,
236     int resplen, opaque_t pd, int flags);
237 static void fcip_ipkt_free(fcip_pkt_t *fcip_pkt);
238 static void fcip_ipkt_callback(fc_packet_t *fc_pkt);
239 static void fcip_free_pkt_dma(fcip_pkt_t *fcip_pkt);
240 static void fcip_pkt_callback(fc_packet_t *fc_pkt);
241 static void fcip_init_unicast_pkt(fcip_pkt_t *fcip_pkt, fc_portid_t sid,
242     fc_portid_t did, void (*comp) ());
243 static int fcip_transport(fcip_pkt_t *fcip_pkt);
244 static void fcip_pkt_timeout(void *arg);
245 static void fcip_timeout(void *arg);
246 static void fcip_fdestp_enqueue_pkt(struct fcip_dest *fdestp,
247     fcip_pkt_t *fcip_pkt);
248 static int fcip_fdestp_dequeue_pkt(struct fcip_dest *fdestp,
249     fcip_pkt_t *fcip_pkt);
250 static int fcip_sendup_constructor(void *buf, void *arg, int flags);
251 static void fcip_sendup_thr(void *arg);
252 static int fcip_sendup_alloc_enque(struct fcip *ftpr, mblk_t *mp,
253     struct fcipstr *(*f)());
254 
255 /*
256  * zero copy inbound data handling
257  */
258 #ifdef FCIP_ESBALLOC
259 static void fcip_ubfree(char *arg);
260 #endif /* FCIP_ESBALLOC */
261 
262 #if !defined(FCIP_ESBALLOC)
263 static void *fcip_allocb(size_t size, uint_t pri);
264 #endif
265 
266 
267 /* FCIP FARP support functions */
268 static struct fcip_dest *fcip_do_farp(struct fcip *fptr, la_wwn_t *pwwn,
269     char *ip_addr, size_t ip_addr_len, int flags);
270 static void fcip_init_broadcast_pkt(fcip_pkt_t *fcip_pkt, void (*comp) (),
271     int is_els);
272 static int fcip_handle_farp_request(struct fcip *fptr, la_els_farp_t *fcmd);
273 static int fcip_handle_farp_response(struct fcip *fptr, la_els_farp_t *fcmd);
274 static void fcip_cache_arp_broadcast(struct fcip *ftpr, fc_unsol_buf_t *buf);
275 static void fcip_port_ns(void *arg);
276 
277 #ifdef DEBUG
278 
279 #include <sys/debug.h>
280 
281 #define	FCIP_DEBUG_DEFAULT	0x1
282 #define	FCIP_DEBUG_ATTACH	0x2
283 #define	FCIP_DEBUG_INIT		0x4
284 #define	FCIP_DEBUG_DETACH	0x8
285 #define	FCIP_DEBUG_DLPI		0x10
286 #define	FCIP_DEBUG_ELS		0x20
287 #define	FCIP_DEBUG_DOWNSTREAM	0x40
288 #define	FCIP_DEBUG_UPSTREAM	0x80
289 #define	FCIP_DEBUG_MISC		0x100
290 
291 #define	FCIP_DEBUG_STARTUP	(FCIP_DEBUG_ATTACH|FCIP_DEBUG_INIT)
292 #define	FCIP_DEBUG_DATAOUT	(FCIP_DEBUG_DLPI|FCIP_DEBUG_DOWNSTREAM)
293 #define	FCIP_DEBUG_DATAIN	(FCIP_DEBUG_ELS|FCIP_DEBUG_UPSTREAM)
294 
295 static int fcip_debug = FCIP_DEBUG_DEFAULT;
296 
297 #define	FCIP_DEBUG(level, args)	\
298 	if (fcip_debug & (level))	cmn_err args;
299 
300 #else	/* DEBUG */
301 
302 #define	FCIP_DEBUG(level, args)		/* do nothing */
303 
304 #endif	/* DEBUG */
305 
306 #define	KIOIP	KSTAT_INTR_PTR(fcip->fcip_intrstats)
307 
308 /*
309  * Endian independent ethernet to WWN copy
310  */
311 #define	ether_to_wwn(E, W)	\
312 	bzero((void *)(W), sizeof (la_wwn_t)); \
313 	bcopy((void *)(E), (void *)&((W)->raw_wwn[2]), ETHERADDRL); \
314 	(W)->raw_wwn[0] |= 0x10
315 
316 /*
317  * wwn_to_ether : Endian independent, copies a WWN to struct ether_addr.
318  * The args to the macro are pointers to WWN and ether_addr structures
319  */
320 #define	wwn_to_ether(W, E)	\
321 	bcopy((void *)&((W)->raw_wwn[2]), (void *)E, ETHERADDRL)
322 
323 /*
324  * The module_info structure contains identification and limit values.
325  * All queues associated with a certain driver share the same module_info
326  * structures. This structure defines the characteristics of that driver/
327  * module's queues. The module name must be unique. The max and min packet
328  * sizes limit the no. of characters in M_DATA messages. The Hi and Lo
329  * water marks are for flow control when a module has a service procedure.
330  */
331 static struct module_info	fcipminfo = {
332 	FCIPIDNUM,	/* mi_idnum : Module ID num */
333 	FCIPNAME, 	/* mi_idname: Module Name */
334 	FCIPMINPSZ,	/* mi_minpsz: Min packet size */
335 	FCIPMAXPSZ,	/* mi_maxpsz: Max packet size */
336 	FCIPHIWAT,	/* mi_hiwat : High water mark */
337 	FCIPLOWAT	/* mi_lowat : Low water mark */
338 };
339 
340 /*
341  * The qinit structres contain the module put, service. open and close
342  * procedure pointers. All modules and drivers with the same streamtab
343  * file (i.e same fmodsw or cdevsw entry points) point to the same
344  * upstream (read) and downstream (write) qinit structs.
345  */
346 static struct qinit	fcip_rinit = {
347 	NULL,		/* qi_putp */
348 	NULL,		/* qi_srvp */
349 	fcip_open,	/* qi_qopen */
350 	fcip_close,	/* qi_qclose */
351 	NULL,		/* qi_qadmin */
352 	&fcipminfo,	/* qi_minfo */
353 	NULL		/* qi_mstat */
354 };
355 
356 static struct qinit	fcip_winit = {
357 	fcip_wput,	/* qi_putp */
358 	fcip_wsrv,	/* qi_srvp */
359 	NULL,		/* qi_qopen */
360 	NULL,		/* qi_qclose */
361 	NULL,		/* qi_qadmin */
362 	&fcipminfo,	/* qi_minfo */
363 	NULL		/* qi_mstat */
364 };
365 
366 /*
367  * streamtab contains pointers to the read and write qinit structures
368  */
369 
370 static struct streamtab fcip_info = {
371 	&fcip_rinit,	/* st_rdinit */
372 	&fcip_winit,	/* st_wrinit */
373 	NULL,		/* st_muxrinit */
374 	NULL,		/* st_muxwrinit */
375 };
376 
377 static struct cb_ops  fcip_cb_ops = {
378 	nodev,				/* open */
379 	nodev,				/* close */
380 	nodev,				/* strategy */
381 	nodev,				/* print */
382 	nodev,				/* dump */
383 	nodev,				/* read */
384 	nodev,				/* write */
385 	nodev,				/* ioctl */
386 	nodev,				/* devmap */
387 	nodev,				/* mmap */
388 	nodev,				/* segmap */
389 	nochpoll,			/* poll */
390 	ddi_prop_op,			/* cb_prop_op */
391 	&fcip_info,			/* streamtab  */
392 	D_MP | D_HOTPLUG,		/* Driver compatibility flag */
393 	CB_REV,				/* rev */
394 	nodev,				/* int (*cb_aread)() */
395 	nodev				/* int (*cb_awrite)() */
396 };
397 
398 /*
399  * autoconfiguration routines.
400  */
401 static struct dev_ops fcip_ops = {
402 	DEVO_REV,		/* devo_rev, */
403 	0,			/* refcnt  */
404 	fcip_getinfo,		/* info */
405 	nulldev,		/* identify */
406 	nulldev,		/* probe */
407 	fcip_attach,		/* attach */
408 	fcip_detach,		/* detach */
409 	nodev,			/* RESET */
410 	&fcip_cb_ops,		/* driver operations */
411 	NULL,			/* bus operations */
412 	ddi_power		/* power management */
413 };
414 
415 #define	FCIP_VERSION	"1.61"
416 #define	FCIP_NAME	"SunFC FCIP v" FCIP_VERSION
417 
418 #define	PORT_DRIVER	"fp"
419 
420 #define	GETSTRUCT(struct, number)	\
421 	((struct *)kmem_zalloc((size_t)(sizeof (struct) * (number)), \
422 		KM_SLEEP))
423 
424 static struct modldrv modldrv = {
425 	&mod_driverops,			/* Type of module - driver */
426 	FCIP_NAME,			/* Name of module */
427 	&fcip_ops,			/* driver ops */
428 };
429 
430 static struct modlinkage modlinkage = {
431 	MODREV_1, (void *)&modldrv, NULL
432 };
433 
434 
435 /*
436  * Now for some global statics
437  */
438 static uint32_t	fcip_ub_nbufs = FCIP_UB_NBUFS;
439 static uint32_t fcip_ub_size = FCIP_UB_SIZE;
440 static int fcip_pkt_ttl_ticks = FCIP_PKT_TTL;
441 static int fcip_tick_incr = 1;
442 static int fcip_wait_cmds = FCIP_WAIT_CMDS;
443 static int fcip_num_attaching = 0;
444 static int fcip_port_attach_pending = 0;
445 static int fcip_create_nodes_on_demand = 1;	/* keep it similar to fcp */
446 static int fcip_cache_on_arp_broadcast = 0;
447 static int fcip_farp_supported = 0;
448 static int fcip_minor_node_created = 0;
449 
450 /*
451  * Supported FCAs
452  */
453 #define	QLC_PORT_1_ID_BITS		0x100
454 #define	QLC_PORT_2_ID_BITS		0x101
455 #define	QLC_PORT_NAA			0x2
456 #define	QLC_MODULE_NAME			"qlc"
457 #define	IS_QLC_PORT(port_dip)		\
458 			(strcmp(ddi_driver_name(ddi_get_parent((port_dip))),\
459 			QLC_MODULE_NAME) == 0)
460 
461 
462 /*
463  * fcip softstate structures head.
464  */
465 
466 static void *fcip_softp = NULL;
467 
468 /*
469  * linked list of active (inuse) driver streams
470  */
471 
472 static int fcip_num_instances = 0;
473 static dev_info_t *fcip_module_dip = (dev_info_t *)0;
474 
475 
476 /*
477  * Ethernet broadcast address: Broadcast addressing in IP over fibre
478  * channel should be the IEEE ULA (also the low 6 bytes of the Port WWN).
479  *
480  * The broadcast addressing varies for differing topologies a node may be in:
481  *	- On a private loop the ARP broadcast is a class 3 sequence sent
482  *	  using OPNfr (Open Broadcast Replicate primitive) followed by
483  *	  the ARP frame to D_ID 0xFFFFFF
484  *
485  *	- On a public Loop the broadcast sequence is sent to AL_PA 0x00
486  *	  (no OPNfr primitive).
487  *
488  *	- For direct attach and point to point topologies we just send
489  *	  the frame to D_ID 0xFFFFFF
490  *
491  * For public loop the handling would probably be different - for now
492  * I'll just declare this struct - It can be deleted if not necessary.
493  *
494  */
495 
496 
497 /*
498  * DL_INFO_ACK template for the fcip module. The dl_info_ack_t structure is
499  * returned as a part of an  DL_INFO_ACK message which is a M_PCPROTO message
500  * returned in response to a DL_INFO_REQ message sent to us from a DLS user
501  * Let us fake an ether header as much as possible.
502  *
503  * dl_addr_length is the Provider's DLSAP addr which is SAP addr +
504  *                Physical addr of the provider. We set this to
505  *                ushort_t + sizeof (la_wwn_t) for Fibre Channel ports.
506  * dl_mac_type    Lets just use DL_ETHER - we can try using DL_IPFC, a new
507  *		  dlpi.h define later.
508  * dl_sap_length  -2 indicating the SAP address follows the Physical addr
509  *		  component in the DLSAP addr.
510  * dl_service_mode: DLCLDS - connectionless data link service.
511  *
512  */
513 
514 static dl_info_ack_t fcip_infoack = {
515 	DL_INFO_ACK,				/* dl_primitive */
516 	FCIPMTU,				/* dl_max_sdu */
517 	0,					/* dl_min_sdu */
518 	FCIPADDRL,				/* dl_addr_length */
519 	DL_ETHER,				/* dl_mac_type */
520 	0,					/* dl_reserved */
521 	0,					/* dl_current_state */
522 	-2,					/* dl_sap_length */
523 	DL_CLDLS,				/* dl_service_mode */
524 	0,					/* dl_qos_length */
525 	0,					/* dl_qos_offset */
526 	0,					/* dl_range_length */
527 	0,					/* dl_range_offset */
528 	DL_STYLE2,				/* dl_provider_style */
529 	sizeof (dl_info_ack_t),			/* dl_addr_offset */
530 	DL_VERSION_2,				/* dl_version */
531 	ETHERADDRL,				/* dl_brdcst_addr_length */
532 	sizeof (dl_info_ack_t) + FCIPADDRL,	/* dl_brdcst_addr_offset */
533 	0					/* dl_growth */
534 };
535 
536 /*
537  * FCIP broadcast address definition.
538  */
539 static	struct ether_addr	fcipnhbroadcastaddr = {
540 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
541 };
542 
543 /*
544  * RFC2625 requires the broadcast ARP address in the ARP data payload to
545  * be set to 0x00 00 00 00 00 00 for ARP broadcast packets
546  */
547 static	struct ether_addr	fcip_arpbroadcast_addr = {
548 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
549 };
550 
551 
552 #define	ether_bcopy(src, dest)	bcopy((src), (dest), ETHERADDRL);
553 
554 /*
555  * global kernel locks
556  */
557 static kcondvar_t	fcip_global_cv;
558 static kmutex_t		fcip_global_mutex;
559 
560 /*
561  * fctl external defines
562  */
563 extern int fc_ulp_add(fc_ulp_modinfo_t *);
564 
565 /*
566  * fctl data structures
567  */
568 
569 #define	FCIP_REV	0x07
570 
571 /* linked list of port info structures */
572 static fcip_port_info_t *fcip_port_head = NULL;
573 
574 /* linked list of fcip structures */
575 static struct fcipstr	*fcipstrup = NULL;
576 static krwlock_t	fcipstruplock;
577 
578 
579 /*
580  * Module information structure. This structure gives the FC Transport modules
581  * information about an ULP that registers with it.
582  */
583 static fc_ulp_modinfo_t	fcip_modinfo = {
584 	0,			/* for xref checks? */
585 	FCTL_ULP_MODREV_4,	/* FCIP revision */
586 	FC_TYPE_IS8802_SNAP,	/* type 5 for SNAP encapsulated datagrams */
587 	FCIP_NAME,		/* module name as in the modldrv struct */
588 	0x0,			/* get all statec callbacks for now */
589 	fcip_port_attach,	/* port attach callback */
590 	fcip_port_detach,	/* port detach callback */
591 	fcip_port_ioctl,	/* port ioctl callback */
592 	fcip_els_cb,		/* els callback */
593 	fcip_data_cb,		/* data callback */
594 	fcip_statec_cb		/* state change callback */
595 };
596 
597 
598 /*
599  * Solaris 9 and up, the /kernel/drv/fp.conf file will have the following entry
600  *
601  * ddi-forceattach=1;
602  *
603  * This will ensure that fp is loaded at bootup. No additional checks are needed
604  */
605 int
606 _init(void)
607 {
608 	int	rval;
609 
610 	/*
611 	 * Initialize the mutexs used by port attach and other callbacks.
612 	 * The transport can call back into our port_attach_callback
613 	 * routine even before _init() completes and bad things can happen.
614 	 */
615 	mutex_init(&fcip_global_mutex, NULL, MUTEX_DRIVER, NULL);
616 	cv_init(&fcip_global_cv, NULL, CV_DRIVER, NULL);
617 	rw_init(&fcipstruplock, NULL, RW_DRIVER, NULL);
618 
619 	mutex_enter(&fcip_global_mutex);
620 	fcip_port_attach_pending = 1;
621 	mutex_exit(&fcip_global_mutex);
622 
623 	/*
624 	 * Now attempt to register fcip with the transport.
625 	 * If fc_ulp_add fails, fcip module will not be loaded.
626 	 */
627 	rval = fc_ulp_add(&fcip_modinfo);
628 	if (rval != FC_SUCCESS) {
629 		mutex_destroy(&fcip_global_mutex);
630 		cv_destroy(&fcip_global_cv);
631 		rw_destroy(&fcipstruplock);
632 		switch (rval) {
633 		case FC_ULP_SAMEMODULE:
634 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
635 			    "!fcip: module is already registered with"
636 			    " transport"));
637 			rval = EEXIST;
638 			break;
639 		case FC_ULP_SAMETYPE:
640 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
641 			    "!fcip: Another module of the same ULP type 0x%x"
642 			    " is already registered with the transport",
643 			    fcip_modinfo.ulp_type));
644 			rval = EEXIST;
645 			break;
646 		case FC_BADULP:
647 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
648 			    "!fcip: Current fcip version 0x%x does not match"
649 			    " fctl version",
650 			    fcip_modinfo.ulp_rev));
651 			rval = ENODEV;
652 			break;
653 		default:
654 			FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
655 			    "!fcip: fc_ulp_add failed with status 0x%x", rval));
656 			rval = ENODEV;
657 			break;
658 		}
659 		return (rval);
660 	}
661 
662 	if ((rval = ddi_soft_state_init(&fcip_softp, sizeof (struct fcip),
663 			FCIP_NUM_INSTANCES)) != 0) {
664 		mutex_destroy(&fcip_global_mutex);
665 		cv_destroy(&fcip_global_cv);
666 		rw_destroy(&fcipstruplock);
667 		(void) fc_ulp_remove(&fcip_modinfo);
668 		return (rval);
669 	}
670 
671 	if ((rval = mod_install(&modlinkage)) != 0) {
672 		(void) fc_ulp_remove(&fcip_modinfo);
673 		mutex_destroy(&fcip_global_mutex);
674 		cv_destroy(&fcip_global_cv);
675 		rw_destroy(&fcipstruplock);
676 		ddi_soft_state_fini(&fcip_softp);
677 	}
678 	return (rval);
679 }
680 
681 /*
682  * Unload the port driver if this was the only ULP loaded and then
683  * deregister with the transport.
684  */
685 int
686 _fini(void)
687 {
688 	int	rval;
689 	int	rval1;
690 
691 	/*
692 	 * Do not permit the module to be unloaded before a port
693 	 * attach callback has happened.
694 	 */
695 	mutex_enter(&fcip_global_mutex);
696 	if (fcip_num_attaching || fcip_port_attach_pending) {
697 		mutex_exit(&fcip_global_mutex);
698 		return (EBUSY);
699 	}
700 	mutex_exit(&fcip_global_mutex);
701 
702 	if ((rval = mod_remove(&modlinkage)) != 0) {
703 		return (rval);
704 	}
705 
706 	/*
707 	 * unregister with the transport layer
708 	 */
709 	rval1 = fc_ulp_remove(&fcip_modinfo);
710 
711 	/*
712 	 * If the ULP was not registered with the transport, init should
713 	 * have failed. If transport has no knowledge of our existence
714 	 * we should simply bail out and succeed
715 	 */
716 #ifdef DEBUG
717 	if (rval1 == FC_BADULP) {
718 		FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
719 		"fcip: ULP was never registered with the transport"));
720 		rval = ENODEV;
721 	} else if (rval1 == FC_BADTYPE) {
722 		FCIP_DEBUG(FCIP_DEBUG_DEFAULT, (CE_WARN,
723 			"fcip: No ULP of this type 0x%x was registered with "
724 			"transport", fcip_modinfo.ulp_type));
725 		rval = ENODEV;
726 	}
727 #endif /* DEBUG */
728 
729 	mutex_destroy(&fcip_global_mutex);
730 	rw_destroy(&fcipstruplock);
731 	cv_destroy(&fcip_global_cv);
732 	ddi_soft_state_fini(&fcip_softp);
733 
734 	return (rval);
735 }
736 
737 /*
738  * Info about this loadable module
739  */
740 int
741 _info(struct modinfo *modinfop)
742 {
743 	return (mod_info(&modlinkage, modinfop));
744 }
745 
746 /*
747  * The port attach callback is invoked by the port driver when a FCA
748  * port comes online and binds with the transport layer. The transport
749  * then callsback into all ULP modules registered with it. The Port attach
750  * call back will also provide the ULP module with the Port's WWN and S_ID
751  */
752 /* ARGSUSED */
753 static int
754 fcip_port_attach(opaque_t ulp_handle, fc_ulp_port_info_t *port_info,
755     fc_attach_cmd_t cmd, uint32_t sid)
756 {
757 	int 			rval = FC_FAILURE;
758 	int 			instance;
759 	struct fcip		*fptr;
760 	fcip_port_info_t	*fport = NULL;
761 	fcip_port_info_t	*cur_fport;
762 	fc_portid_t		src_id;
763 
764 	switch (cmd) {
765 	case FC_CMD_ATTACH: {
766 		la_wwn_t	*ww_pn = NULL;
767 		/*
768 		 * It was determined that, as per spec, the lower 48 bits of
769 		 * the port-WWN will always be unique. This will make the MAC
770 		 * address (i.e the lower 48 bits of the WWN), that IP/ARP
771 		 * depend on, unique too. Hence we should be able to remove the
772 		 * restriction of attaching to only one of the ports of
773 		 * multi port FCAs.
774 		 *
775 		 * Earlier, fcip used to attach only to qlc module and fail
776 		 * silently for attach failures resulting from unknown FCAs or
777 		 * unsupported FCA ports. Now, we'll do no such checks.
778 		 */
779 		ww_pn = &port_info->port_pwwn;
780 
781 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
782 		    "port id bits: 0x%x", ww_pn->w.nport_id));
783 		/*
784 		 * A port has come online
785 		 */
786 		mutex_enter(&fcip_global_mutex);
787 		fcip_num_instances++;
788 		fcip_num_attaching++;
789 
790 		if (fcip_port_head == NULL) {
791 			/* OK to sleep here ? */
792 			fport = kmem_zalloc(sizeof (fcip_port_info_t),
793 						KM_NOSLEEP);
794 			if (fport == NULL) {
795 				fcip_num_instances--;
796 				fcip_num_attaching--;
797 				ASSERT(fcip_num_attaching >= 0);
798 				mutex_exit(&fcip_global_mutex);
799 				rval = FC_FAILURE;
800 				cmn_err(CE_WARN, "!fcip(%d): port attach "
801 				    "failed: alloc failed",
802 				    ddi_get_instance(port_info->port_dip));
803 				goto done;
804 			}
805 			fcip_port_head = fport;
806 		} else {
807 			/*
808 			 * traverse the port list and also check for
809 			 * duplicate port attaches - Nothing wrong in being
810 			 * paranoid Heh Heh.
811 			 */
812 			cur_fport = fcip_port_head;
813 			while (cur_fport != NULL) {
814 				if (cur_fport->fcipp_handle ==
815 				    port_info->port_handle) {
816 					fcip_num_instances--;
817 					fcip_num_attaching--;
818 					ASSERT(fcip_num_attaching >= 0);
819 					mutex_exit(&fcip_global_mutex);
820 					FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
821 					    "!fcip(%d): port already "
822 					    "attached!!", ddi_get_instance(
823 					    port_info->port_dip)));
824 					rval = FC_FAILURE;
825 					goto done;
826 				}
827 				cur_fport = cur_fport->fcipp_next;
828 			}
829 			fport = kmem_zalloc(sizeof (fcip_port_info_t),
830 						KM_NOSLEEP);
831 			if (fport == NULL) {
832 				rval = FC_FAILURE;
833 				fcip_num_instances--;
834 				fcip_num_attaching--;
835 				ASSERT(fcip_num_attaching >= 0);
836 				mutex_exit(&fcip_global_mutex);
837 				cmn_err(CE_WARN, "!fcip(%d): port attach "
838 				    "failed: alloc failed",
839 				    ddi_get_instance(port_info->port_dip));
840 				goto done;
841 			}
842 			fport->fcipp_next = fcip_port_head;
843 			fcip_port_head = fport;
844 		}
845 
846 		mutex_exit(&fcip_global_mutex);
847 
848 		/*
849 		 * now fill in the details about the port itself
850 		 */
851 		fport->fcipp_linkage = *port_info->port_linkage;
852 		fport->fcipp_handle = port_info->port_handle;
853 		fport->fcipp_dip = port_info->port_dip;
854 		fport->fcipp_topology = port_info->port_flags;
855 		fport->fcipp_pstate = port_info->port_state;
856 		fport->fcipp_naa = port_info->port_pwwn.w.naa_id;
857 		bcopy(&port_info->port_pwwn, &fport->fcipp_pwwn,
858 		    sizeof (la_wwn_t));
859 		bcopy(&port_info->port_nwwn, &fport->fcipp_nwwn,
860 		    sizeof (la_wwn_t));
861 		fport->fcipp_fca_pkt_size = port_info->port_fca_pkt_size;
862 		fport->fcipp_cmd_dma_attr = *port_info->port_cmd_dma_attr;
863 		fport->fcipp_resp_dma_attr = *port_info->port_resp_dma_attr;
864 		fport->fcipp_fca_acc_attr = *port_info->port_acc_attr;
865 		src_id.port_id = sid;
866 		src_id.priv_lilp_posit = 0;
867 		fport->fcipp_sid = src_id;
868 
869 		/*
870 		 * allocate soft state for this instance
871 		 */
872 		instance = ddi_get_instance(fport->fcipp_dip);
873 		if (ddi_soft_state_zalloc(fcip_softp,
874 		    instance) != DDI_SUCCESS) {
875 			rval = FC_FAILURE;
876 			cmn_err(CE_WARN, "!fcip(%d): port attach failed: "
877 			    "soft state alloc failed", instance);
878 			goto failure;
879 		}
880 
881 		fptr = ddi_get_soft_state(fcip_softp, instance);
882 
883 		if (fptr == NULL) {
884 			rval = FC_FAILURE;
885 			cmn_err(CE_WARN, "!fcip(%d): port attach failed: "
886 			    "failure to get soft state", instance);
887 			goto failure;
888 		}
889 
890 		/*
891 		 * initialize all mutexes and locks required for this module
892 		 */
893 		mutex_init(&fptr->fcip_mutex, NULL, MUTEX_DRIVER, NULL);
894 		mutex_init(&fptr->fcip_ub_mutex, NULL, MUTEX_DRIVER, NULL);
895 		mutex_init(&fptr->fcip_rt_mutex, NULL, MUTEX_DRIVER, NULL);
896 		mutex_init(&fptr->fcip_dest_mutex, NULL, MUTEX_DRIVER, NULL);
897 		mutex_init(&fptr->fcip_sendup_mutex, NULL, MUTEX_DRIVER, NULL);
898 		cv_init(&fptr->fcip_farp_cv, NULL, CV_DRIVER, NULL);
899 		cv_init(&fptr->fcip_sendup_cv, NULL, CV_DRIVER, NULL);
900 		cv_init(&fptr->fcip_ub_cv, NULL, CV_DRIVER, NULL);
901 
902 		mutex_enter(&fptr->fcip_mutex);
903 
904 		fptr->fcip_dip = fport->fcipp_dip;	/* parent's dip */
905 		fptr->fcip_instance = instance;
906 		fptr->fcip_ub_upstream = 0;
907 
908 		if (FC_PORT_STATE_MASK(port_info->port_state) ==
909 		    FC_STATE_ONLINE) {
910 			fptr->fcip_port_state = FCIP_PORT_ONLINE;
911 			if (fptr->fcip_flags & FCIP_LINK_DOWN) {
912 				fptr->fcip_flags &= ~FCIP_LINK_DOWN;
913 			}
914 		} else {
915 			fptr->fcip_port_state = FCIP_PORT_OFFLINE;
916 		}
917 
918 		fptr->fcip_flags |= FCIP_ATTACHING;
919 		fptr->fcip_port_info = fport;
920 
921 		/*
922 		 * Extract our MAC addr from our port's WWN. The lower 48
923 		 * bits will be our MAC address
924 		 */
925 		wwn_to_ether(&fport->fcipp_nwwn, &fptr->fcip_macaddr);
926 
927 		fport->fcipp_fcip = fptr;
928 
929 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
930 		    (CE_NOTE, "fcipdest : 0x%lx, rtable : 0x%lx",
931 		    (long)(sizeof (fptr->fcip_dest)),
932 		    (long)(sizeof (fptr->fcip_rtable))));
933 
934 		bzero(fptr->fcip_dest, sizeof (fptr->fcip_dest));
935 		bzero(fptr->fcip_rtable, sizeof (fptr->fcip_rtable));
936 
937 		/*
938 		 * create a taskq to handle sundry jobs for the driver
939 		 * This way we can have jobs run in parallel
940 		 */
941 		fptr->fcip_tq = taskq_create("fcip_tasks",
942 		    FCIP_NUM_THREADS, MINCLSYSPRI, FCIP_MIN_TASKS,
943 		    FCIP_MAX_TASKS, TASKQ_PREPOPULATE);
944 
945 		mutex_exit(&fptr->fcip_mutex);
946 
947 		/*
948 		 * create a separate thread to handle all unsolicited
949 		 * callback handling. This is because unsolicited_callback
950 		 * can happen from an interrupt context and the upstream
951 		 * modules can put new messages right back in the same
952 		 * thread context. This usually works fine, but sometimes
953 		 * we may have to block to obtain the dest struct entries
954 		 * for some remote ports.
955 		 */
956 		mutex_enter(&fptr->fcip_sendup_mutex);
957 		if (thread_create(NULL, DEFAULTSTKSZ,
958 		    (void (*)())fcip_sendup_thr, (caddr_t)fptr, 0, &p0,
959 		    TS_RUN, minclsyspri) == NULL) {
960 			mutex_exit(&fptr->fcip_sendup_mutex);
961 			cmn_err(CE_WARN,
962 			    "!unable to create fcip sendup thread for "
963 			    " instance: 0x%x", instance);
964 			rval = FC_FAILURE;
965 			goto done;
966 		}
967 		fptr->fcip_sendup_thr_initted = 1;
968 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = NULL;
969 		mutex_exit(&fptr->fcip_sendup_mutex);
970 
971 
972 		/* Let the attach handler do the rest */
973 		if (fcip_port_attach_handler(fptr) != FC_SUCCESS) {
974 			/*
975 			 * We have already cleaned up so return
976 			 */
977 			rval = FC_FAILURE;
978 			cmn_err(CE_WARN, "!fcip(%d): port attach failed",
979 			    instance);
980 			goto done;
981 		}
982 
983 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_CONT,
984 		    "!fcip attach for port instance (0x%x) successful",
985 		    instance));
986 
987 		rval = FC_SUCCESS;
988 		goto done;
989 	}
990 	case FC_CMD_POWER_UP:
991 	/* FALLTHROUGH */
992 	case FC_CMD_RESUME:
993 		mutex_enter(&fcip_global_mutex);
994 		fport = fcip_port_head;
995 		while (fport != NULL) {
996 			if (fport->fcipp_handle == port_info->port_handle) {
997 				break;
998 			}
999 			fport = fport->fcipp_next;
1000 		}
1001 		if (fport == NULL) {
1002 			rval = FC_SUCCESS;
1003 			mutex_exit(&fcip_global_mutex);
1004 			goto done;
1005 		}
1006 		rval = fcip_handle_resume(fport, port_info, cmd);
1007 		mutex_exit(&fcip_global_mutex);
1008 		goto done;
1009 
1010 	default:
1011 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
1012 		    "unknown cmd type 0x%x in port_attach", cmd));
1013 		rval = FC_FAILURE;
1014 		goto done;
1015 	}
1016 
1017 failure:
1018 	if (fport) {
1019 		mutex_enter(&fcip_global_mutex);
1020 		fcip_num_attaching--;
1021 		ASSERT(fcip_num_attaching >= 0);
1022 		(void) fcip_softstate_free(fport);
1023 		fcip_port_attach_pending = 0;
1024 		mutex_exit(&fcip_global_mutex);
1025 	}
1026 	return (rval);
1027 
1028 done:
1029 	mutex_enter(&fcip_global_mutex);
1030 	fcip_port_attach_pending = 0;
1031 	mutex_exit(&fcip_global_mutex);
1032 	return (rval);
1033 }
1034 
1035 /*
1036  * fcip_port_attach_handler : Completes the port attach operation after
1037  * the ulp_port_attach routine has completed its ground work. The job
1038  * of this function among other things is to obtain and handle topology
1039  * specifics, initialize a port, setup broadcast address entries in
1040  * the fcip tables etc. This routine cleans up behind itself on failures.
1041  * Returns FC_SUCCESS or FC_FAILURE.
1042  */
1043 static int
1044 fcip_port_attach_handler(struct fcip *fptr)
1045 {
1046 	fcip_port_info_t		*fport = fptr->fcip_port_info;
1047 	int				rval = FC_FAILURE;
1048 
1049 	ASSERT(fport != NULL);
1050 
1051 	mutex_enter(&fcip_global_mutex);
1052 
1053 	FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
1054 	    "fcip module dip: %p instance: %d",
1055 	    (void *)fcip_module_dip, ddi_get_instance(fptr->fcip_dip)));
1056 
1057 	if (fcip_module_dip == NULL) {
1058 		clock_t		fcip_lbolt;
1059 
1060 		fcip_lbolt = ddi_get_lbolt();
1061 		/*
1062 		 * we need to use the fcip devinfo for creating
1063 		 * the clone device node, but the fcip attach
1064 		 * (from its conf file entry claiming to be a
1065 		 * child of pseudo) may not have happened yet.
1066 		 * wait here for 10 seconds and fail port attach
1067 		 * if the fcip devinfo is not attached yet
1068 		 */
1069 		fcip_lbolt += drv_usectohz(FCIP_INIT_DELAY);
1070 
1071 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1072 		    (CE_WARN, "cv_timedwait lbolt %lx", fcip_lbolt));
1073 
1074 		(void) cv_timedwait(&fcip_global_cv, &fcip_global_mutex,
1075 		    fcip_lbolt);
1076 
1077 		if (fcip_module_dip == NULL) {
1078 			mutex_exit(&fcip_global_mutex);
1079 
1080 			FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
1081 				"fcip attach did not happen"));
1082 			goto port_attach_cleanup;
1083 		}
1084 	}
1085 
1086 	if ((!fcip_minor_node_created) &&
1087 	    fcip_is_supported_fc_topology(fport->fcipp_topology)) {
1088 		/*
1089 		 * Checking for same topologies which are considered valid
1090 		 * by fcip_handle_topology(). Dont create a minor node if
1091 		 * nothing is hanging off the FC port.
1092 		 */
1093 		if (ddi_create_minor_node(fcip_module_dip, "fcip", S_IFCHR,
1094 		    ddi_get_instance(fptr->fcip_dip), DDI_PSEUDO,
1095 		    CLONE_DEV) == DDI_FAILURE) {
1096 			mutex_exit(&fcip_global_mutex);
1097 			FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_WARN,
1098 			    "failed to create minor node for fcip(%d)",
1099 			    ddi_get_instance(fptr->fcip_dip)));
1100 			goto port_attach_cleanup;
1101 		}
1102 		fcip_minor_node_created++;
1103 	}
1104 	mutex_exit(&fcip_global_mutex);
1105 
1106 	/*
1107 	 * initialize port for traffic
1108 	 */
1109 	if (fcip_init_port(fptr) != FC_SUCCESS) {
1110 		/* fcip_init_port has already cleaned up its stuff */
1111 
1112 		mutex_enter(&fcip_global_mutex);
1113 
1114 		if ((fcip_num_instances == 1) &&
1115 		    (fcip_minor_node_created == 1)) {
1116 			/* Remove minor node iff this is the last instance */
1117 			ddi_remove_minor_node(fcip_module_dip, NULL);
1118 		}
1119 
1120 		mutex_exit(&fcip_global_mutex);
1121 
1122 		goto port_attach_cleanup;
1123 	}
1124 
1125 	mutex_enter(&fptr->fcip_mutex);
1126 	fptr->fcip_flags &= ~FCIP_ATTACHING;
1127 	fptr->fcip_flags |= FCIP_INITED;
1128 	fptr->fcip_timeout_ticks = 0;
1129 
1130 	/*
1131 	 * start the timeout threads
1132 	 */
1133 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
1134 	    drv_usectohz(1000000));
1135 
1136 	mutex_exit(&fptr->fcip_mutex);
1137 	mutex_enter(&fcip_global_mutex);
1138 	fcip_num_attaching--;
1139 	ASSERT(fcip_num_attaching >= 0);
1140 	mutex_exit(&fcip_global_mutex);
1141 	rval = FC_SUCCESS;
1142 	return (rval);
1143 
1144 port_attach_cleanup:
1145 	mutex_enter(&fcip_global_mutex);
1146 	(void) fcip_softstate_free(fport);
1147 	fcip_num_attaching--;
1148 	ASSERT(fcip_num_attaching >= 0);
1149 	mutex_exit(&fcip_global_mutex);
1150 	rval = FC_FAILURE;
1151 	return (rval);
1152 }
1153 
1154 
1155 /*
1156  * Handler for DDI_RESUME operations. Port must be ready to restart IP
1157  * traffic on resume
1158  */
1159 static int
1160 fcip_handle_resume(fcip_port_info_t *fport, fc_ulp_port_info_t *port_info,
1161     fc_attach_cmd_t cmd)
1162 {
1163 	int 		rval = FC_SUCCESS;
1164 	struct fcip	*fptr = fport->fcipp_fcip;
1165 	struct fcipstr	*tslp;
1166 	int		index;
1167 
1168 
1169 	ASSERT(fptr != NULL);
1170 
1171 	mutex_enter(&fptr->fcip_mutex);
1172 
1173 	if (cmd == FC_CMD_POWER_UP) {
1174 		fptr->fcip_flags &= ~(FCIP_POWER_DOWN);
1175 		if (fptr->fcip_flags & FCIP_SUSPENDED) {
1176 			mutex_exit(&fptr->fcip_mutex);
1177 			return (FC_SUCCESS);
1178 		}
1179 	} else if (cmd == FC_CMD_RESUME) {
1180 		fptr->fcip_flags &= ~(FCIP_SUSPENDED);
1181 	} else {
1182 		mutex_exit(&fptr->fcip_mutex);
1183 		return (FC_FAILURE);
1184 	}
1185 
1186 	/*
1187 	 * set the current port state and topology
1188 	 */
1189 	fport->fcipp_topology = port_info->port_flags;
1190 	fport->fcipp_pstate = port_info->port_state;
1191 
1192 	rw_enter(&fcipstruplock, RW_READER);
1193 	for (tslp = fcipstrup; tslp; tslp = tslp->sl_nextp) {
1194 		if (tslp->sl_fcip == fptr) {
1195 			break;
1196 		}
1197 	}
1198 	rw_exit(&fcipstruplock);
1199 
1200 	/*
1201 	 * No active streams on this port
1202 	 */
1203 	if (tslp == NULL) {
1204 		rval = FC_SUCCESS;
1205 		goto done;
1206 	}
1207 
1208 	mutex_enter(&fptr->fcip_rt_mutex);
1209 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
1210 		struct fcip_routing_table 	*frp;
1211 
1212 		frp = fptr->fcip_rtable[index];
1213 		while (frp) {
1214 			uint32_t		did;
1215 			/*
1216 			 * Mark the broadcast RTE available again. It
1217 			 * was marked SUSPENDED during SUSPEND.
1218 			 */
1219 			did = fcip_get_broadcast_did(fptr);
1220 			if (frp->fcipr_d_id.port_id == did) {
1221 				frp->fcipr_state = 0;
1222 				index = FCIP_RT_HASH_ELEMS;
1223 				break;
1224 			}
1225 			frp = frp->fcipr_next;
1226 		}
1227 	}
1228 	mutex_exit(&fptr->fcip_rt_mutex);
1229 
1230 	/*
1231 	 * fcip_handle_topology will update the port entries in the
1232 	 * routing table.
1233 	 * fcip_handle_topology also takes care of resetting the
1234 	 * fcipr_state field in the routing table structure. The entries
1235 	 * were set to RT_INVALID during suspend.
1236 	 */
1237 	fcip_handle_topology(fptr);
1238 
1239 done:
1240 	/*
1241 	 * Restart the timeout thread
1242 	 */
1243 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
1244 	    drv_usectohz(1000000));
1245 	mutex_exit(&fptr->fcip_mutex);
1246 	return (rval);
1247 }
1248 
1249 
1250 /*
1251  * Insert a destination port entry into the routing table for
1252  * this port
1253  */
1254 static void
1255 fcip_rt_update(struct fcip *fptr, fc_portmap_t *devlist, uint32_t listlen)
1256 {
1257 	struct fcip_routing_table	*frp;
1258 	fcip_port_info_t		*fport = fptr->fcip_port_info;
1259 	int				hash_bucket, i;
1260 	fc_portmap_t			*pmap;
1261 	char				wwn_buf[20];
1262 
1263 	ASSERT(!mutex_owned(&fptr->fcip_mutex));
1264 	mutex_enter(&fptr->fcip_rt_mutex);
1265 
1266 	for (i = 0; i < listlen; i++) {
1267 		pmap = &(devlist[i]);
1268 
1269 		frp = fcip_lookup_rtable(fptr, &(pmap->map_pwwn),
1270 		    FCIP_COMPARE_PWWN);
1271 		/*
1272 		 * If an entry for a port in the devlist exists in the
1273 		 * in the per port routing table, make sure the data
1274 		 * is current. We need to do this irrespective of the
1275 		 * underlying port topology.
1276 		 */
1277 		switch (pmap->map_type) {
1278 		/* FALLTHROUGH */
1279 		case PORT_DEVICE_NOCHANGE:
1280 		/* FALLTHROUGH */
1281 		case PORT_DEVICE_USER_LOGIN:
1282 		/* FALLTHROUGH */
1283 		case PORT_DEVICE_CHANGED:
1284 		/* FALLTHROUGH */
1285 		case PORT_DEVICE_NEW:
1286 			if (frp == NULL) {
1287 				goto add_new_entry;
1288 			} else if (frp) {
1289 				goto update_entry;
1290 			} else {
1291 				continue;
1292 			}
1293 
1294 		case PORT_DEVICE_OLD:
1295 		/* FALLTHROUGH */
1296 		case PORT_DEVICE_USER_LOGOUT:
1297 			/*
1298 			 * Mark entry for removal from Routing Table if
1299 			 * one exists. Let the timeout thread actually
1300 			 * remove the entry after we've given up hopes
1301 			 * of the port ever showing up.
1302 			 */
1303 			if (frp) {
1304 				uint32_t		did;
1305 
1306 				/*
1307 				 * Mark the routing table as invalid to bail
1308 				 * the packets early that are in transit
1309 				 */
1310 				did = fptr->fcip_broadcast_did;
1311 				if (frp->fcipr_d_id.port_id != did) {
1312 					frp->fcipr_pd = NULL;
1313 					frp->fcipr_state = FCIP_RT_INVALID;
1314 					frp->fcipr_invalid_timeout =
1315 					    fptr->fcip_timeout_ticks +
1316 					    FCIP_RTE_TIMEOUT;
1317 				}
1318 			}
1319 			continue;
1320 
1321 		default:
1322 			FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN,
1323 			    "unknown map flags in rt_update"));
1324 			continue;
1325 		}
1326 add_new_entry:
1327 		ASSERT(frp == NULL);
1328 		hash_bucket = FCIP_RT_HASH(pmap->map_pwwn.raw_wwn);
1329 
1330 		ASSERT(hash_bucket < FCIP_RT_HASH_ELEMS);
1331 
1332 		frp = (struct fcip_routing_table *)
1333 		    kmem_zalloc(sizeof (struct fcip_routing_table), KM_SLEEP);
1334 		/* insert at beginning of hash bucket */
1335 		frp->fcipr_next = fptr->fcip_rtable[hash_bucket];
1336 		fptr->fcip_rtable[hash_bucket] = frp;
1337 		fc_wwn_to_str(&pmap->map_pwwn, wwn_buf);
1338 		FCIP_DEBUG(FCIP_DEBUG_ATTACH, (CE_NOTE,
1339 		    "added entry for pwwn %s and d_id 0x%x",
1340 		    wwn_buf, pmap->map_did.port_id));
1341 update_entry:
1342 		bcopy((void *)&pmap->map_pwwn,
1343 		    (void *)&frp->fcipr_pwwn, sizeof (la_wwn_t));
1344 		bcopy((void *)&pmap->map_nwwn, (void *)&frp->fcipr_nwwn,
1345 		    sizeof (la_wwn_t));
1346 		frp->fcipr_d_id = pmap->map_did;
1347 		frp->fcipr_state = pmap->map_state;
1348 		frp->fcipr_pd = pmap->map_pd;
1349 
1350 		/*
1351 		 * If there is no pd for a destination port that is not
1352 		 * a broadcast entry, the port is pretty much unusable - so
1353 		 * mark the port for removal so we can try adding back the
1354 		 * entry again.
1355 		 */
1356 		if ((frp->fcipr_pd == NULL) &&
1357 		    (frp->fcipr_d_id.port_id != fptr->fcip_broadcast_did)) {
1358 			frp->fcipr_state = PORT_DEVICE_INVALID;
1359 			frp->fcipr_invalid_timeout = fptr->fcip_timeout_ticks +
1360 			    (FCIP_RTE_TIMEOUT / 2);
1361 		}
1362 		frp->fcipr_fca_dev =
1363 		    fc_ulp_get_fca_device(fport->fcipp_handle, pmap->map_did);
1364 
1365 		/*
1366 		 * login to the remote port. Don't worry about
1367 		 * plogi failures for now
1368 		 */
1369 		if (pmap->map_pd != NULL) {
1370 			(void) fcip_do_plogi(fptr, frp);
1371 		} else if (FC_TOP_EXTERNAL(fport->fcipp_topology)) {
1372 			fc_wwn_to_str(&frp->fcipr_pwwn, wwn_buf);
1373 			FCIP_DEBUG(FCIP_DEBUG_MISC, (CE_NOTE,
1374 			    "logging into pwwn %s, d_id 0x%x",
1375 			    wwn_buf, frp->fcipr_d_id.port_id));
1376 			(void) fcip_do_plogi(fptr, frp);
1377 		}
1378 
1379 	}
1380 	mutex_exit(&fptr->fcip_rt_mutex);
1381 }
1382 
1383 
1384 /*
1385  * return a matching routing table entry for a given fcip instance
1386  */
1387 struct fcip_routing_table *
1388 fcip_lookup_rtable(struct fcip *fptr, la_wwn_t *wwn, int matchflag)
1389 {
1390 	struct fcip_routing_table	*frp = NULL;
1391 	int				hash_bucket;
1392 
1393 	ASSERT(mutex_owned(&fptr->fcip_rt_mutex));
1394 
1395 	hash_bucket = FCIP_RT_HASH(wwn->raw_wwn);
1396 	frp = fptr->fcip_rtable[hash_bucket];
1397 	while (frp != NULL) {
1398 
1399 		if (fcip_wwn_compare(&frp->fcipr_pwwn, wwn, matchflag) == 0) {
1400 			break;
1401 		}
1402 
1403 		frp = frp->fcipr_next;
1404 	}
1405 	return (frp);
1406 }
1407 
1408 /*
1409  * Attach of fcip under pseudo. The actual setup of the interface
1410  * actually happens in fcip_port_attach on a callback from the
1411  * transport. The port_attach callback however can proceed only
1412  * after the devinfo for fcip has been created under pseudo
1413  */
1414 static int
1415 fcip_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1416 {
1417 	switch ((int)cmd) {
1418 
1419 	case DDI_ATTACH: {
1420 		ASSERT(fcip_module_dip == NULL);
1421 		fcip_module_dip = dip;
1422 
1423 		/*
1424 		 * this call originates as a result of fcip's conf
1425 		 * file entry and will result in a fcip instance being
1426 		 * a child of pseudo. We should ensure here that the port
1427 		 * driver (fp) has been loaded and initted since we would
1428 		 * never get a port attach callback without fp being loaded.
1429 		 * If we are unable to succesfully load and initalize fp -
1430 		 * just fail this attach.
1431 		 */
1432 		mutex_enter(&fcip_global_mutex);
1433 
1434 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1435 		    (CE_WARN, "global cv - signaling"));
1436 
1437 		cv_signal(&fcip_global_cv);
1438 
1439 		FCIP_DEBUG(FCIP_DEBUG_ATTACH,
1440 		    (CE_WARN, "global cv - signaled"));
1441 		mutex_exit(&fcip_global_mutex);
1442 		return (DDI_SUCCESS);
1443 	}
1444 	case DDI_RESUME:
1445 		/*
1446 		 * Resume appears trickier
1447 		 */
1448 		return (DDI_SUCCESS);
1449 	default:
1450 		return (DDI_FAILURE);
1451 	}
1452 }
1453 
1454 
1455 /*
1456  * The detach entry point to permit unloading fcip. We make sure
1457  * there are no active streams before we proceed with the detach
1458  */
1459 /* ARGSUSED */
1460 static int
1461 fcip_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1462 {
1463 	struct fcip		*fptr;
1464 	fcip_port_info_t	*fport;
1465 	int			detached;
1466 
1467 	switch (cmd) {
1468 	case DDI_DETACH: {
1469 		/*
1470 		 * If we got here, any active streams should have been
1471 		 * unplumbed but check anyway
1472 		 */
1473 		mutex_enter(&fcip_global_mutex);
1474 		if (fcipstrup != NULL) {
1475 			mutex_exit(&fcip_global_mutex);
1476 			return (DDI_FAILURE);
1477 		}
1478 
1479 		if (fcip_port_head != NULL) {
1480 			/*
1481 			 * Check to see if we have unattached/unbound
1482 			 * ports. If all the ports are unattached/unbound go
1483 			 * ahead and unregister with the transport
1484 			 */
1485 			fport = fcip_port_head;
1486 			while (fport != NULL) {
1487 				fptr = fport->fcipp_fcip;
1488 				if (fptr == NULL) {
1489 					continue;
1490 				}
1491 				mutex_enter(&fptr->fcip_mutex);
1492 				fptr->fcip_flags |= FCIP_DETACHING;
1493 				if (fptr->fcip_ipq ||
1494 				    fptr->fcip_flags & (FCIP_IN_TIMEOUT |
1495 				    FCIP_IN_CALLBACK | FCIP_ATTACHING |
1496 				    FCIP_SUSPENDED | FCIP_POWER_DOWN |
1497 				    FCIP_REG_INPROGRESS)) {
1498 					mutex_exit(&fptr->fcip_mutex);
1499 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1500 					    "fcip instance busy"));
1501 					break;
1502 				}
1503 				/*
1504 				 * Check for any outstanding pkts. If yes
1505 				 * fail the detach
1506 				 */
1507 				mutex_enter(&fptr->fcip_dest_mutex);
1508 				if (fcip_port_get_num_pkts(fptr) > 0) {
1509 					mutex_exit(&fptr->fcip_dest_mutex);
1510 					mutex_exit(&fptr->fcip_mutex);
1511 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1512 					    "fcip instance busy - pkts "
1513 					    "pending"));
1514 					break;
1515 				}
1516 				mutex_exit(&fptr->fcip_dest_mutex);
1517 
1518 				mutex_enter(&fptr->fcip_rt_mutex);
1519 				if (fcip_plogi_in_progress(fptr)) {
1520 					mutex_exit(&fptr->fcip_rt_mutex);
1521 					mutex_exit(&fptr->fcip_mutex);
1522 					FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
1523 					    "fcip instance busy - plogi in "
1524 					    "progress"));
1525 					break;
1526 				}
1527 				mutex_exit(&fptr->fcip_rt_mutex);
1528 
1529 				mutex_exit(&fptr->fcip_mutex);
1530 				fport = fport->fcipp_next;
1531 			}
1532 			/*
1533 			 * if fport is non NULL - we have active ports
1534 			 */
1535 			if (fport != NULL) {
1536 				/*
1537 				 * Remove the DETACHING flags on the ports
1538 				 */
1539 				fport = fcip_port_head;
1540 				while (fport != NULL) {
1541 					fptr = fport->fcipp_fcip;
1542 					mutex_enter(&fptr->fcip_mutex);
1543 					fptr->fcip_flags &= ~(FCIP_DETACHING);
1544 					mutex_exit(&fptr->fcip_mutex);
1545 					fport = fport->fcipp_next;
1546 				}
1547 				mutex_exit(&fcip_global_mutex);
1548 				return (DDI_FAILURE);
1549 			}
1550 		}
1551 
1552 		/*
1553 		 * free up all softstate structures
1554 		 */
1555 		fport = fcip_port_head;
1556 		while (fport != NULL) {
1557 			detached = 1;
1558 
1559 			fptr = fport->fcipp_fcip;
1560 			if (fptr) {
1561 				mutex_enter(&fptr->fcip_mutex);
1562 				/*
1563 				 * Check to see if somebody beat us to the
1564 				 * punch
1565 				 */
1566 				detached = fptr->fcip_flags & FCIP_DETACHED;
1567 				fptr->fcip_flags &= ~(FCIP_DETACHING);
1568 				fptr->fcip_flags |= FCIP_DETACHED;
1569 				mutex_exit(&fptr->fcip_mutex);
1570 			}
1571 
1572 			if (!detached) {
1573 				fport = fcip_softstate_free(fport);
1574 			} else {
1575 				/*
1576 				 * If the port was marked as detached
1577 				 * but it was still in the list, that
1578 				 * means another thread has marked it
1579 				 * but we got in while it released the
1580 				 * fcip_global_mutex in softstate_free.
1581 				 * Given that, we're still safe to use
1582 				 * fport->fcipp_next to find out what
1583 				 * the next port on the list is.
1584 				 */
1585 				fport = fport->fcipp_next;
1586 			}
1587 
1588 			FCIP_DEBUG(FCIP_DEBUG_DETACH,
1589 			    (CE_NOTE, "detaching port"));
1590 		}
1591 
1592 		/*
1593 		 * If we haven't removed all the port structures, we
1594 		 * aren't yet ready to be detached.
1595 		 */
1596 		if (fcip_port_head != NULL) {
1597 			mutex_exit(&fcip_global_mutex);
1598 			return (DDI_FAILURE);
1599 		}
1600 
1601 		fcip_num_instances = 0;
1602 		mutex_exit(&fcip_global_mutex);
1603 		fcip_module_dip = NULL;
1604 		return (DDI_SUCCESS);
1605 	}
1606 	case DDI_SUSPEND:
1607 		return (DDI_SUCCESS);
1608 	default:
1609 		return (DDI_FAILURE);
1610 	}
1611 }
1612 
1613 /*
1614  * The port_detach callback is called from the transport when a
1615  * FC port is being removed from the transport's control. This routine
1616  * provides fcip with an opportunity to cleanup all activities and
1617  * structures on the port marked for removal.
1618  */
1619 /* ARGSUSED */
1620 static int
1621 fcip_port_detach(opaque_t ulp_handle, fc_ulp_port_info_t *port_info,
1622     fc_detach_cmd_t cmd)
1623 {
1624 	int 			rval = FC_FAILURE;
1625 	fcip_port_info_t	*fport;
1626 	struct fcip		*fptr;
1627 	struct fcipstr		*strp;
1628 
1629 	switch (cmd) {
1630 	case FC_CMD_DETACH: {
1631 		mutex_enter(&fcip_global_mutex);
1632 
1633 		if (fcip_port_head == NULL) {
1634 			/*
1635 			 * we are all done but our fini has not been
1636 			 * called yet!! Let's hope we have no active
1637 			 * fcip instances here. - strange secnario but
1638 			 * no harm in having this return a success.
1639 			 */
1640 			fcip_check_remove_minor_node();
1641 
1642 			mutex_exit(&fcip_global_mutex);
1643 			return (FC_SUCCESS);
1644 		} else {
1645 			/*
1646 			 * traverse the port list
1647 			 */
1648 			fport = fcip_port_head;
1649 			while (fport != NULL) {
1650 				if (fport->fcipp_handle ==
1651 				    port_info->port_handle) {
1652 					fptr = fport->fcipp_fcip;
1653 
1654 					/*
1655 					 * Fail the port detach if there is
1656 					 * still an attached, bound stream on
1657 					 * this interface.
1658 					 */
1659 
1660 					rw_enter(&fcipstruplock, RW_READER);
1661 
1662 					for (strp = fcipstrup; strp != NULL;
1663 					    strp = strp->sl_nextp) {
1664 						if (strp->sl_fcip == fptr) {
1665 							rw_exit(&fcipstruplock);
1666 							mutex_exit(
1667 							    &fcip_global_mutex);
1668 							return (FC_FAILURE);
1669 						}
1670 					}
1671 
1672 					rw_exit(&fcipstruplock);
1673 
1674 					/*
1675 					 * fail port detach if we are in
1676 					 * the middle of a deferred port attach
1677 					 * or if the port has outstanding pkts
1678 					 */
1679 					if (fptr != NULL) {
1680 						mutex_enter(&fptr->fcip_mutex);
1681 						if (fcip_check_port_busy
1682 						    (fptr) ||
1683 						    (fptr->fcip_flags &
1684 						    FCIP_DETACHED)) {
1685 							mutex_exit(
1686 							    &fptr->fcip_mutex);
1687 							mutex_exit(
1688 							    &fcip_global_mutex);
1689 							return (FC_FAILURE);
1690 						}
1691 
1692 						fptr->fcip_flags |=
1693 						    FCIP_DETACHED;
1694 						mutex_exit(&fptr->fcip_mutex);
1695 					}
1696 					(void) fcip_softstate_free(fport);
1697 
1698 					fcip_check_remove_minor_node();
1699 					mutex_exit(&fcip_global_mutex);
1700 					return (FC_SUCCESS);
1701 				}
1702 				fport = fport->fcipp_next;
1703 			}
1704 			ASSERT(fport == NULL);
1705 		}
1706 		mutex_exit(&fcip_global_mutex);
1707 		break;
1708 	}
1709 	case FC_CMD_POWER_DOWN:
1710 	/* FALLTHROUGH */
1711 	case FC_CMD_SUSPEND:
1712 		mutex_enter(&fcip_global_mutex);
1713 		fport = fcip_port_head;
1714 		while (fport != NULL) {
1715 			if (fport->fcipp_handle == port_info->port_handle) {
1716 				break;
1717 			}
1718 			fport = fport->fcipp_next;
1719 		}
1720 		if (fport == NULL) {
1721 			mutex_exit(&fcip_global_mutex);
1722 			break;
1723 		}
1724 		rval = fcip_handle_suspend(fport, cmd);
1725 		mutex_exit(&fcip_global_mutex);
1726 		break;
1727 	default:
1728 		FCIP_DEBUG(FCIP_DEBUG_DETACH,
1729 		    (CE_WARN, "unknown port detach command!!"));
1730 		break;
1731 	}
1732 	return (rval);
1733 }
1734 
1735 
1736 /*
1737  * Returns 0 if the port is not busy, else returns non zero.
1738  */
1739 static int
1740 fcip_check_port_busy(struct fcip *fptr)
1741 {
1742 	int rval = 0, num_pkts = 0;
1743 
1744 	ASSERT(fptr != NULL);
1745 	ASSERT(MUTEX_HELD(&fptr->fcip_mutex));
1746 
1747 	mutex_enter(&fptr->fcip_dest_mutex);
1748 
1749 	if (fptr->fcip_flags & FCIP_PORT_BUSY ||
1750 	    ((num_pkts = fcip_port_get_num_pkts(fptr)) > 0) ||
1751 	    fptr->fcip_num_ipkts_pending) {
1752 		rval = 1;
1753 		FCIP_DEBUG(FCIP_DEBUG_DETACH,
1754 		    (CE_NOTE, "!fcip_check_port_busy: port is busy "
1755 		    "fcip_flags: 0x%x, num_pkts: 0x%x, ipkts_pending: 0x%lx!",
1756 		    fptr->fcip_flags, num_pkts, fptr->fcip_num_ipkts_pending));
1757 	}
1758 
1759 	mutex_exit(&fptr->fcip_dest_mutex);
1760 	return (rval);
1761 }
1762 
1763 /*
1764  * Helper routine to remove fcip's minor node
1765  * There is one minor node per system and it should be removed if there are no
1766  * other fcip instances (which has a 1:1 mapping for fp instances) present
1767  */
1768 static void
1769 fcip_check_remove_minor_node(void)
1770 {
1771 	ASSERT(MUTEX_HELD(&fcip_global_mutex));
1772 
1773 	/*
1774 	 * If there are no more fcip (fp) instances, remove the
1775 	 * minor node for fcip.
1776 	 * Reset fcip_minor_node_created to invalidate it.
1777 	 */
1778 	if (fcip_num_instances == 0 && (fcip_module_dip != NULL)) {
1779 		ddi_remove_minor_node(fcip_module_dip, NULL);
1780 		fcip_minor_node_created = 0;
1781 	}
1782 }
1783 
1784 /*
1785  * This routine permits the suspend operation during a CPR/System
1786  * power management operation. The routine basically quiesces I/Os
1787  * on all active interfaces
1788  */
1789 static int
1790 fcip_handle_suspend(fcip_port_info_t *fport, fc_detach_cmd_t cmd)
1791 {
1792 	struct fcip	*fptr = fport->fcipp_fcip;
1793 	timeout_id_t	tid;
1794 	int 		index;
1795 	int		tryagain = 0;
1796 	int		count;
1797 	struct fcipstr	*tslp;
1798 
1799 
1800 	ASSERT(fptr != NULL);
1801 	mutex_enter(&fptr->fcip_mutex);
1802 
1803 	/*
1804 	 * Fail if we are in the middle of a callback. Don't use delay during
1805 	 * suspend since clock intrs are not available so busy wait
1806 	 */
1807 	count = 0;
1808 	while (count++ < 15 &&
1809 	    ((fptr->fcip_flags & FCIP_IN_CALLBACK) ||
1810 	    (fptr->fcip_flags & FCIP_IN_TIMEOUT))) {
1811 		mutex_exit(&fptr->fcip_mutex);
1812 		drv_usecwait(1000000);
1813 		mutex_enter(&fptr->fcip_mutex);
1814 	}
1815 
1816 	if (fptr->fcip_flags & FCIP_IN_CALLBACK ||
1817 	    fptr->fcip_flags & FCIP_IN_TIMEOUT) {
1818 		mutex_exit(&fptr->fcip_mutex);
1819 		return (FC_FAILURE);
1820 	}
1821 
1822 	if (cmd == FC_CMD_POWER_DOWN) {
1823 		if (fptr->fcip_flags & FCIP_SUSPENDED) {
1824 			fptr->fcip_flags |= FCIP_POWER_DOWN;
1825 			mutex_exit(&fptr->fcip_mutex);
1826 			goto success;
1827 		} else {
1828 			fptr->fcip_flags |= FCIP_POWER_DOWN;
1829 		}
1830 	} else if (cmd == FC_CMD_SUSPEND) {
1831 		fptr->fcip_flags |= FCIP_SUSPENDED;
1832 	} else {
1833 		mutex_exit(&fptr->fcip_mutex);
1834 		return (FC_FAILURE);
1835 	}
1836 
1837 	mutex_exit(&fptr->fcip_mutex);
1838 	/*
1839 	 * If no streams are plumbed - its the easiest case - Just
1840 	 * bail out without having to do much
1841 	 */
1842 
1843 	rw_enter(&fcipstruplock, RW_READER);
1844 	for (tslp = fcipstrup; tslp; tslp = tslp->sl_nextp) {
1845 		if (tslp->sl_fcip == fptr) {
1846 			break;
1847 		}
1848 	}
1849 	rw_exit(&fcipstruplock);
1850 
1851 	/*
1852 	 * No active streams on this port
1853 	 */
1854 	if (tslp == NULL) {
1855 		goto success;
1856 	}
1857 
1858 	/*
1859 	 * Walk through each Routing table structure and check if
1860 	 * the destination table has any outstanding commands. If yes
1861 	 * wait for the commands to drain. Since we go through each
1862 	 * routing table entry in succession, it may be wise to wait
1863 	 * only a few seconds for each entry.
1864 	 */
1865 	mutex_enter(&fptr->fcip_rt_mutex);
1866 	while (!tryagain) {
1867 
1868 		tryagain = 0;
1869 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
1870 			struct fcip_routing_table 	*frp;
1871 			struct fcip_dest 		*fdestp;
1872 			la_wwn_t			*pwwn;
1873 			int				hash_bucket;
1874 
1875 			frp = fptr->fcip_rtable[index];
1876 			while (frp) {
1877 				/*
1878 				 * Mark the routing table as SUSPENDED. Even
1879 				 * mark the broadcast entry SUSPENDED to
1880 				 * prevent any ARP or other broadcasts. We
1881 				 * can reset the state of the broadcast
1882 				 * RTE when we resume.
1883 				 */
1884 				frp->fcipr_state = FCIP_RT_SUSPENDED;
1885 				pwwn = &frp->fcipr_pwwn;
1886 
1887 				/*
1888 				 * Get hold of destination pointer
1889 				 */
1890 				mutex_enter(&fptr->fcip_dest_mutex);
1891 
1892 				hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
1893 				ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
1894 
1895 				fdestp = fptr->fcip_dest[hash_bucket];
1896 				while (fdestp != NULL) {
1897 					mutex_enter(&fdestp->fcipd_mutex);
1898 					if (fdestp->fcipd_rtable) {
1899 						if (fcip_wwn_compare(pwwn,
1900 						    &fdestp->fcipd_pwwn,
1901 						    FCIP_COMPARE_PWWN) == 0) {
1902 							mutex_exit(
1903 							&fdestp->fcipd_mutex);
1904 							break;
1905 						}
1906 					}
1907 					mutex_exit(&fdestp->fcipd_mutex);
1908 					fdestp = fdestp->fcipd_next;
1909 				}
1910 
1911 				mutex_exit(&fptr->fcip_dest_mutex);
1912 				if (fdestp == NULL) {
1913 					frp = frp->fcipr_next;
1914 					continue;
1915 				}
1916 
1917 				/*
1918 				 * Wait for fcip_wait_cmds seconds for
1919 				 * the commands to drain.
1920 				 */
1921 				count = 0;
1922 				mutex_enter(&fdestp->fcipd_mutex);
1923 				while (fdestp->fcipd_ncmds &&
1924 				    count < fcip_wait_cmds) {
1925 					mutex_exit(&fdestp->fcipd_mutex);
1926 					mutex_exit(&fptr->fcip_rt_mutex);
1927 					drv_usecwait(1000000);
1928 					mutex_enter(&fptr->fcip_rt_mutex);
1929 					mutex_enter(&fdestp->fcipd_mutex);
1930 					count++;
1931 				}
1932 				/*
1933 				 * Check if we were able to drain all cmds
1934 				 * successfully. Else continue with other
1935 				 * ports and try during the second pass
1936 				 */
1937 				if (fdestp->fcipd_ncmds) {
1938 					tryagain++;
1939 				}
1940 				mutex_exit(&fdestp->fcipd_mutex);
1941 
1942 				frp = frp->fcipr_next;
1943 			}
1944 		}
1945 		if (tryagain == 0) {
1946 			break;
1947 		}
1948 	}
1949 	mutex_exit(&fptr->fcip_rt_mutex);
1950 
1951 	if (tryagain) {
1952 		mutex_enter(&fptr->fcip_mutex);
1953 		fptr->fcip_flags &= ~(FCIP_SUSPENDED | FCIP_POWER_DOWN);
1954 		mutex_exit(&fptr->fcip_mutex);
1955 		return (FC_FAILURE);
1956 	}
1957 
1958 success:
1959 	mutex_enter(&fptr->fcip_mutex);
1960 	tid = fptr->fcip_timeout_id;
1961 	fptr->fcip_timeout_id = NULL;
1962 	mutex_exit(&fptr->fcip_mutex);
1963 
1964 	(void) untimeout(tid);
1965 
1966 	return (FC_SUCCESS);
1967 }
1968 
1969 /*
1970  * the getinfo(9E) entry point
1971  */
1972 /* ARGSUSED */
1973 static int
1974 fcip_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
1975 {
1976 	int rval = DDI_FAILURE;
1977 
1978 	switch (cmd) {
1979 	case DDI_INFO_DEVT2DEVINFO:
1980 		*result = fcip_module_dip;
1981 		if (*result)
1982 			rval = DDI_SUCCESS;
1983 		break;
1984 
1985 	case DDI_INFO_DEVT2INSTANCE:
1986 		*result = (void *)0;
1987 		rval = DDI_SUCCESS;
1988 		break;
1989 	default:
1990 		break;
1991 	}
1992 
1993 	return (rval);
1994 }
1995 
1996 /*
1997  * called from fcip_attach to initialize kstats for the link
1998  */
1999 /* ARGSUSED */
2000 static void
2001 fcip_kstat_init(struct fcip *fptr)
2002 {
2003 	int instance;
2004 	char buf[16];
2005 	struct fcipstat	*fcipstatp;
2006 
2007 	ASSERT(mutex_owned(&fptr->fcip_mutex));
2008 
2009 	instance = ddi_get_instance(fptr->fcip_dip);
2010 	(void) sprintf(buf, "fcip%d", instance);
2011 
2012 #ifdef	kstat
2013 	fptr->fcip_kstatp = kstat_create("fcip", instance, buf, "net",
2014 	    KSTAT_TYPE_NAMED,
2015 	    (sizeof (struct fcipstat)/ sizeof (kstat_named_t)),
2016 	    KSTAT_FLAG_PERSISTENT);
2017 #else
2018 	fptr->fcip_kstatp = kstat_create("fcip", instance, buf, "net",
2019 	    KSTAT_TYPE_NAMED,
2020 	    (sizeof (struct fcipstat)/ sizeof (kstat_named_t)), 0);
2021 #endif
2022 	if (fptr->fcip_kstatp == NULL) {
2023 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN, "kstat created failed"));
2024 		return;
2025 	}
2026 
2027 	fcipstatp = (struct  fcipstat *)fptr->fcip_kstatp->ks_data;
2028 	kstat_named_init(&fcipstatp->fcips_ipackets,	"ipackets",
2029 		KSTAT_DATA_ULONG);
2030 	kstat_named_init(&fcipstatp->fcips_ierrors,	"ierrors",
2031 		KSTAT_DATA_ULONG);
2032 	kstat_named_init(&fcipstatp->fcips_opackets,	"opackets",
2033 		KSTAT_DATA_ULONG);
2034 	kstat_named_init(&fcipstatp->fcips_oerrors,	"oerrors",
2035 		KSTAT_DATA_ULONG);
2036 	kstat_named_init(&fcipstatp->fcips_collisions,	"collisions",
2037 		KSTAT_DATA_ULONG);
2038 	kstat_named_init(&fcipstatp->fcips_nocanput,	"nocanput",
2039 		KSTAT_DATA_ULONG);
2040 	kstat_named_init(&fcipstatp->fcips_allocbfail,	"allocbfail",
2041 		KSTAT_DATA_ULONG);
2042 
2043 	kstat_named_init(&fcipstatp->fcips_defer, "defer",
2044 		KSTAT_DATA_ULONG);
2045 	kstat_named_init(&fcipstatp->fcips_fram, "fram",
2046 		KSTAT_DATA_ULONG);
2047 	kstat_named_init(&fcipstatp->fcips_crc, "crc",
2048 		KSTAT_DATA_ULONG);
2049 	kstat_named_init(&fcipstatp->fcips_oflo, "oflo",
2050 		KSTAT_DATA_ULONG);
2051 	kstat_named_init(&fcipstatp->fcips_uflo, "uflo",
2052 		KSTAT_DATA_ULONG);
2053 	kstat_named_init(&fcipstatp->fcips_missed, "missed",
2054 		KSTAT_DATA_ULONG);
2055 	kstat_named_init(&fcipstatp->fcips_tlcol, "tlcol",
2056 		KSTAT_DATA_ULONG);
2057 	kstat_named_init(&fcipstatp->fcips_trtry, "trtry",
2058 		KSTAT_DATA_ULONG);
2059 	kstat_named_init(&fcipstatp->fcips_tnocar, "tnocar",
2060 		KSTAT_DATA_ULONG);
2061 	kstat_named_init(&fcipstatp->fcips_inits, "inits",
2062 		KSTAT_DATA_ULONG);
2063 	kstat_named_init(&fcipstatp->fcips_notbufs, "notbufs",
2064 		KSTAT_DATA_ULONG);
2065 	kstat_named_init(&fcipstatp->fcips_norbufs, "norbufs",
2066 		KSTAT_DATA_ULONG);
2067 	kstat_named_init(&fcipstatp->fcips_allocbfail, "allocbfail",
2068 		KSTAT_DATA_ULONG);
2069 
2070 	/*
2071 	 * required by kstat for MIB II objects(RFC 1213)
2072 	 */
2073 	kstat_named_init(&fcipstatp->fcips_rcvbytes, "fcips_rcvbytes",
2074 		KSTAT_DATA_ULONG);	/* # octets received */
2075 					/* MIB - ifInOctets */
2076 	kstat_named_init(&fcipstatp->fcips_xmtbytes, "fcips_xmtbytes",
2077 		KSTAT_DATA_ULONG);	/* # octets xmitted */
2078 					/* MIB - ifOutOctets */
2079 	kstat_named_init(&fcipstatp->fcips_multircv,	"fcips_multircv",
2080 		KSTAT_DATA_ULONG);	/* # multicast packets */
2081 					/* delivered to upper layer */
2082 					/* MIB - ifInNUcastPkts */
2083 	kstat_named_init(&fcipstatp->fcips_multixmt,	"fcips_multixmt",
2084 		KSTAT_DATA_ULONG);	/* # multicast packets */
2085 					/* requested to be sent */
2086 					/* MIB - ifOutNUcastPkts */
2087 	kstat_named_init(&fcipstatp->fcips_brdcstrcv, "fcips_brdcstrcv",
2088 		KSTAT_DATA_ULONG); /* # broadcast packets */
2089 					/* delivered to upper layer */
2090 					/* MIB - ifInNUcastPkts */
2091 	kstat_named_init(&fcipstatp->fcips_brdcstxmt, "fcips_brdcstxmt",
2092 		KSTAT_DATA_ULONG);	/* # broadcast packets */
2093 					/* requested to be sent */
2094 					/* MIB - ifOutNUcastPkts */
2095 	kstat_named_init(&fcipstatp->fcips_norcvbuf,	"fcips_norcvbuf",
2096 		KSTAT_DATA_ULONG);	/* # rcv packets discarded */
2097 					/* MIB - ifInDiscards */
2098 	kstat_named_init(&fcipstatp->fcips_noxmtbuf,	"fcips_noxmtbuf",
2099 		KSTAT_DATA_ULONG);	/* # xmt packets discarded */
2100 
2101 	fptr->fcip_kstatp->ks_update = fcip_stat_update;
2102 	fptr->fcip_kstatp->ks_private = (void *) fptr;
2103 	kstat_install(fptr->fcip_kstatp);
2104 }
2105 
2106 /*
2107  * Update the defined kstats for netstat et al to use
2108  */
2109 /* ARGSUSED */
2110 static int
2111 fcip_stat_update(kstat_t *fcip_statp, int val)
2112 {
2113 	struct fcipstat	*fcipstatp;
2114 	struct fcip	*fptr;
2115 
2116 	fptr = (struct fcip *)fcip_statp->ks_private;
2117 	fcipstatp = (struct fcipstat *)fcip_statp->ks_data;
2118 
2119 	if (val == KSTAT_WRITE) {
2120 		fptr->fcip_ipackets	= fcipstatp->fcips_ipackets.value.ul;
2121 		fptr->fcip_ierrors	= fcipstatp->fcips_ierrors.value.ul;
2122 		fptr->fcip_opackets	= fcipstatp->fcips_opackets.value.ul;
2123 		fptr->fcip_oerrors	= fcipstatp->fcips_oerrors.value.ul;
2124 		fptr->fcip_collisions	= fcipstatp->fcips_collisions.value.ul;
2125 		fptr->fcip_defer	= fcipstatp->fcips_defer.value.ul;
2126 		fptr->fcip_fram	= fcipstatp->fcips_fram.value.ul;
2127 		fptr->fcip_crc	= fcipstatp->fcips_crc.value.ul;
2128 		fptr->fcip_oflo	= fcipstatp->fcips_oflo.value.ul;
2129 		fptr->fcip_uflo	= fcipstatp->fcips_uflo.value.ul;
2130 		fptr->fcip_missed	= fcipstatp->fcips_missed.value.ul;
2131 		fptr->fcip_tlcol	= fcipstatp->fcips_tlcol.value.ul;
2132 		fptr->fcip_trtry	= fcipstatp->fcips_trtry.value.ul;
2133 		fptr->fcip_tnocar	= fcipstatp->fcips_tnocar.value.ul;
2134 		fptr->fcip_inits	= fcipstatp->fcips_inits.value.ul;
2135 		fptr->fcip_notbufs	= fcipstatp->fcips_notbufs.value.ul;
2136 		fptr->fcip_norbufs	= fcipstatp->fcips_norbufs.value.ul;
2137 		fptr->fcip_nocanput	= fcipstatp->fcips_nocanput.value.ul;
2138 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2139 		fptr->fcip_rcvbytes	= fcipstatp->fcips_rcvbytes.value.ul;
2140 		fptr->fcip_xmtbytes	= fcipstatp->fcips_xmtbytes.value.ul;
2141 		fptr->fcip_multircv	= fcipstatp->fcips_multircv.value.ul;
2142 		fptr->fcip_multixmt	= fcipstatp->fcips_multixmt.value.ul;
2143 		fptr->fcip_brdcstrcv	= fcipstatp->fcips_brdcstrcv.value.ul;
2144 		fptr->fcip_norcvbuf	= fcipstatp->fcips_norcvbuf.value.ul;
2145 		fptr->fcip_noxmtbuf	= fcipstatp->fcips_noxmtbuf.value.ul;
2146 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2147 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2148 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2149 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2150 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2151 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2152 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2153 		fptr->fcip_allocbfail	= fcipstatp->fcips_allocbfail.value.ul;
2154 
2155 	} else {
2156 		fcipstatp->fcips_ipackets.value.ul	= fptr->fcip_ipackets;
2157 		fcipstatp->fcips_ierrors.value.ul	= fptr->fcip_ierrors;
2158 		fcipstatp->fcips_opackets.value.ul	= fptr->fcip_opackets;
2159 		fcipstatp->fcips_oerrors.value.ul	= fptr->fcip_oerrors;
2160 		fcipstatp->fcips_collisions.value.ul	= fptr->fcip_collisions;
2161 		fcipstatp->fcips_nocanput.value.ul	= fptr->fcip_nocanput;
2162 		fcipstatp->fcips_allocbfail.value.ul	= fptr->fcip_allocbfail;
2163 		fcipstatp->fcips_defer.value.ul	= fptr->fcip_defer;
2164 		fcipstatp->fcips_fram.value.ul	= fptr->fcip_fram;
2165 		fcipstatp->fcips_crc.value.ul	= fptr->fcip_crc;
2166 		fcipstatp->fcips_oflo.value.ul	= fptr->fcip_oflo;
2167 		fcipstatp->fcips_uflo.value.ul	= fptr->fcip_uflo;
2168 		fcipstatp->fcips_missed.value.ul	= fptr->fcip_missed;
2169 		fcipstatp->fcips_tlcol.value.ul	= fptr->fcip_tlcol;
2170 		fcipstatp->fcips_trtry.value.ul	= fptr->fcip_trtry;
2171 		fcipstatp->fcips_tnocar.value.ul	= fptr->fcip_tnocar;
2172 		fcipstatp->fcips_inits.value.ul	= fptr->fcip_inits;
2173 		fcipstatp->fcips_norbufs.value.ul	= fptr->fcip_norbufs;
2174 		fcipstatp->fcips_notbufs.value.ul	= fptr->fcip_notbufs;
2175 		fcipstatp->fcips_rcvbytes.value.ul	= fptr->fcip_rcvbytes;
2176 		fcipstatp->fcips_xmtbytes.value.ul	= fptr->fcip_xmtbytes;
2177 		fcipstatp->fcips_multircv.value.ul	= fptr->fcip_multircv;
2178 		fcipstatp->fcips_multixmt.value.ul	= fptr->fcip_multixmt;
2179 		fcipstatp->fcips_brdcstrcv.value.ul	= fptr->fcip_brdcstrcv;
2180 		fcipstatp->fcips_brdcstxmt.value.ul	= fptr->fcip_brdcstxmt;
2181 		fcipstatp->fcips_norcvbuf.value.ul	= fptr->fcip_norcvbuf;
2182 		fcipstatp->fcips_noxmtbuf.value.ul	= fptr->fcip_noxmtbuf;
2183 
2184 	}
2185 	return (0);
2186 }
2187 
2188 
2189 /*
2190  * fcip_statec_cb: handles all required state change callback notifications
2191  * it receives from the transport
2192  */
2193 /* ARGSUSED */
2194 static void
2195 fcip_statec_cb(opaque_t ulp_handle, opaque_t phandle,
2196     uint32_t port_state, uint32_t port_top, fc_portmap_t changelist[],
2197     uint32_t listlen, uint32_t sid)
2198 {
2199 	fcip_port_info_t	*fport;
2200 	struct fcip 		*fptr;
2201 	struct fcipstr		*slp;
2202 	queue_t			*wrq;
2203 	int			instance;
2204 	int 			index;
2205 	struct fcip_routing_table 	*frtp;
2206 
2207 	fport = fcip_get_port(phandle);
2208 
2209 	if (fport == NULL) {
2210 		return;
2211 	}
2212 
2213 	fptr = fport->fcipp_fcip;
2214 	ASSERT(fptr != NULL);
2215 
2216 	if (fptr == NULL) {
2217 		return;
2218 	}
2219 
2220 	instance = ddi_get_instance(fport->fcipp_dip);
2221 
2222 	FCIP_DEBUG(FCIP_DEBUG_ELS,
2223 	    (CE_NOTE, "fcip%d, state change callback: state:0x%x, "
2224 	    "S_ID:0x%x, count:0x%x", instance, port_state, sid, listlen));
2225 
2226 	mutex_enter(&fptr->fcip_mutex);
2227 
2228 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2229 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2230 		mutex_exit(&fptr->fcip_mutex);
2231 		return;
2232 	}
2233 
2234 	/*
2235 	 * set fcip flags to indicate we are in the middle of a
2236 	 * state change callback so we can wait till the statechange
2237 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2238 	 */
2239 	fptr->fcip_flags |= FCIP_IN_SC_CB;
2240 
2241 	fport->fcipp_pstate = port_state;
2242 
2243 	/*
2244 	 * Check if topology changed. If Yes - Modify the broadcast
2245 	 * RTE entries to understand the new broadcast D_IDs
2246 	 */
2247 	if (fport->fcipp_topology != port_top &&
2248 	    (port_top != FC_TOP_UNKNOWN)) {
2249 		/* REMOVE later */
2250 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2251 		    "topology changed: Old topology: 0x%x New topology 0x%x",
2252 		    fport->fcipp_topology, port_top));
2253 		/*
2254 		 * If topology changed - attempt a rediscovery of
2255 		 * devices. Helps specially in Fabric/Public loops
2256 		 * and if on_demand_node_creation is disabled
2257 		 */
2258 		fport->fcipp_topology = port_top;
2259 		fcip_handle_topology(fptr);
2260 	}
2261 
2262 	mutex_exit(&fptr->fcip_mutex);
2263 
2264 	switch (FC_PORT_STATE_MASK(port_state)) {
2265 	case FC_STATE_ONLINE:
2266 	/* FALLTHROUGH */
2267 	case FC_STATE_LIP:
2268 	/* FALLTHROUGH */
2269 	case FC_STATE_LIP_LBIT_SET:
2270 
2271 		/*
2272 		 * nothing to do here actually other than if we
2273 		 * were actually logged onto a port in the devlist
2274 		 * (which indicates active communication between
2275 		 * the host port and the port in the changelist).
2276 		 * If however we are in a private loop or point to
2277 		 * point mode, we need to check for any IP capable
2278 		 * ports and update our routing table.
2279 		 */
2280 		switch (port_top) {
2281 		case FC_TOP_FABRIC:
2282 			/*
2283 			 * This indicates a fabric port with a NameServer.
2284 			 * Check the devlist to see if we are in active
2285 			 * communication with a port on the devlist.
2286 			 */
2287 			FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2288 			    "Statec_cb: fabric topology"));
2289 			fcip_rt_update(fptr, changelist, listlen);
2290 			break;
2291 		case FC_TOP_NO_NS:
2292 			/*
2293 			 * No nameserver - so treat it like a Private loop
2294 			 * or point to point topology and get a map of
2295 			 * devices on the link and get IP capable ports to
2296 			 * to update the routing table.
2297 			 */
2298 			FCIP_DEBUG(FCIP_DEBUG_ELS,
2299 			    (CE_NOTE, "Statec_cb: NO_NS topology"));
2300 		/* FALLTHROUGH */
2301 		case FC_TOP_PRIVATE_LOOP:
2302 			FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2303 			    "Statec_cb: Pvt_Loop topology"));
2304 		/* FALLTHROUGH */
2305 		case FC_TOP_PT_PT:
2306 			/*
2307 			 * call get_port_map() and update routing table
2308 			 */
2309 			fcip_rt_update(fptr, changelist, listlen);
2310 			break;
2311 		default:
2312 			FCIP_DEBUG(FCIP_DEBUG_ELS,
2313 			    (CE_NOTE, "Statec_cb: Unknown topology"));
2314 		}
2315 
2316 		/*
2317 		 * We should now enable the Queues and permit I/Os
2318 		 * to flow through downstream. The update of routing
2319 		 * table should have flushed out any port entries that
2320 		 * don't exist or are not available after the state change
2321 		 */
2322 		mutex_enter(&fptr->fcip_mutex);
2323 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
2324 		if (fptr->fcip_flags & FCIP_LINK_DOWN) {
2325 			fptr->fcip_flags &= ~FCIP_LINK_DOWN;
2326 		}
2327 		mutex_exit(&fptr->fcip_mutex);
2328 
2329 		/*
2330 		 * Enable write queues
2331 		 */
2332 		rw_enter(&fcipstruplock, RW_READER);
2333 		for (slp = fcipstrup; slp != NULL; slp = slp->sl_nextp) {
2334 			if (slp && slp->sl_fcip == fptr) {
2335 				wrq = WR(slp->sl_rq);
2336 				if (wrq->q_flag & QFULL) {
2337 					qenable(wrq);
2338 				}
2339 			}
2340 		}
2341 		rw_exit(&fcipstruplock);
2342 		break;
2343 	case FC_STATE_OFFLINE:
2344 		/*
2345 		 * mark the port_state OFFLINE and wait for it to
2346 		 * become online. Any new messages in this state will
2347 		 * simply be queued back up. If the port does not
2348 		 * come online in a short while, we can begin failing
2349 		 * messages and flush the routing table
2350 		 */
2351 		mutex_enter(&fptr->fcip_mutex);
2352 		fptr->fcip_mark_offline = fptr->fcip_timeout_ticks +
2353 		    FCIP_OFFLINE_TIMEOUT;
2354 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
2355 		mutex_exit(&fptr->fcip_mutex);
2356 
2357 		/*
2358 		 * Mark all Routing table entries as invalid to prevent
2359 		 * any commands from trickling through to ports that
2360 		 * have disappeared from under us
2361 		 */
2362 		mutex_enter(&fptr->fcip_rt_mutex);
2363 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
2364 			frtp = fptr->fcip_rtable[index];
2365 			while (frtp) {
2366 				frtp->fcipr_state = PORT_DEVICE_INVALID;
2367 				frtp = frtp->fcipr_next;
2368 			}
2369 		}
2370 		mutex_exit(&fptr->fcip_rt_mutex);
2371 
2372 		break;
2373 
2374 	case FC_STATE_RESET_REQUESTED:
2375 		/*
2376 		 * Release all Unsolicited buffers back to transport/FCA.
2377 		 * This also means the port state is marked offline - so
2378 		 * we may have to do what OFFLINE state requires us to do.
2379 		 * Care must be taken to wait for any active unsolicited
2380 		 * buffer with the other Streams modules - so wait for
2381 		 * a freeb if the unsolicited buffer is passed back all
2382 		 * the way upstream.
2383 		 */
2384 		mutex_enter(&fptr->fcip_mutex);
2385 
2386 #ifdef FCIP_ESBALLOC
2387 		while (fptr->fcip_ub_upstream) {
2388 			cv_wait(&fptr->fcip_ub_cv, &fptr->fcip_mutex);
2389 		}
2390 #endif	/* FCIP_ESBALLOC */
2391 
2392 		fptr->fcip_mark_offline = fptr->fcip_timeout_ticks +
2393 		    FCIP_OFFLINE_TIMEOUT;
2394 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
2395 		mutex_exit(&fptr->fcip_mutex);
2396 		break;
2397 
2398 	case FC_STATE_DEVICE_CHANGE:
2399 		if (listlen) {
2400 			fcip_rt_update(fptr, changelist, listlen);
2401 		}
2402 		break;
2403 	case FC_STATE_RESET:
2404 		/*
2405 		 * Not much to do I guess - wait for port to become
2406 		 * ONLINE. If the port doesn't become online in a short
2407 		 * while, the upper layers abort any request themselves.
2408 		 * We can just putback the messages in the streams queues
2409 		 * if the link is offline
2410 		 */
2411 		break;
2412 	}
2413 	mutex_enter(&fptr->fcip_mutex);
2414 	fptr->fcip_flags &= ~(FCIP_IN_SC_CB);
2415 	mutex_exit(&fptr->fcip_mutex);
2416 }
2417 
2418 /*
2419  * Given a port handle, return the fcip_port_info structure corresponding
2420  * to that port handle. The transport allocates and communicates with
2421  * ULPs using port handles
2422  */
2423 static fcip_port_info_t *
2424 fcip_get_port(opaque_t phandle)
2425 {
2426 	fcip_port_info_t *fport;
2427 
2428 	ASSERT(phandle != NULL);
2429 
2430 	mutex_enter(&fcip_global_mutex);
2431 	fport = fcip_port_head;
2432 
2433 	while (fport != NULL) {
2434 		if (fport->fcipp_handle == phandle) {
2435 			/* found */
2436 			break;
2437 		}
2438 		fport = fport->fcipp_next;
2439 	}
2440 
2441 	mutex_exit(&fcip_global_mutex);
2442 
2443 	return (fport);
2444 }
2445 
2446 /*
2447  * Handle inbound ELS requests received by the transport. We are only
2448  * intereseted in FARP/InARP mostly.
2449  */
2450 /* ARGSUSED */
2451 static int
2452 fcip_els_cb(opaque_t ulp_handle, opaque_t phandle,
2453     fc_unsol_buf_t *buf, uint32_t claimed)
2454 {
2455 	fcip_port_info_t	*fport;
2456 	struct fcip 		*fptr;
2457 	int			instance;
2458 	uchar_t			r_ctl;
2459 	uchar_t			ls_code;
2460 	la_els_farp_t		farp_cmd;
2461 	la_els_farp_t		*fcmd;
2462 	int			rval = FC_UNCLAIMED;
2463 
2464 	fport = fcip_get_port(phandle);
2465 	if (fport == NULL) {
2466 		return (FC_UNCLAIMED);
2467 	}
2468 
2469 	fptr = fport->fcipp_fcip;
2470 	ASSERT(fptr != NULL);
2471 	if (fptr == NULL) {
2472 		return (FC_UNCLAIMED);
2473 	}
2474 
2475 	instance = ddi_get_instance(fport->fcipp_dip);
2476 
2477 	mutex_enter(&fptr->fcip_mutex);
2478 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2479 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2480 		mutex_exit(&fptr->fcip_mutex);
2481 		return (FC_UNCLAIMED);
2482 	}
2483 
2484 	/*
2485 	 * set fcip flags to indicate we are in the middle of a
2486 	 * ELS callback so we can wait till the statechange
2487 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2488 	 */
2489 	fptr->fcip_flags |= FCIP_IN_ELS_CB;
2490 	mutex_exit(&fptr->fcip_mutex);
2491 
2492 	FCIP_DEBUG(FCIP_DEBUG_ELS,
2493 	    (CE_NOTE, "fcip%d, ELS callback , ", instance));
2494 
2495 	r_ctl = buf->ub_frame.r_ctl;
2496 	switch (r_ctl & R_CTL_ROUTING) {
2497 	case R_CTL_EXTENDED_SVC:
2498 		if (r_ctl == R_CTL_ELS_REQ) {
2499 			ls_code = buf->ub_buffer[0];
2500 			if (ls_code == LA_ELS_FARP_REQ) {
2501 				/*
2502 				 * Inbound FARP broadcast request
2503 				 */
2504 				if (buf->ub_bufsize != sizeof (la_els_farp_t)) {
2505 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2506 					    "Invalid FARP req buffer size "
2507 					    "expected 0x%lx, got 0x%x",
2508 					    (long)(sizeof (la_els_farp_t)),
2509 					    buf->ub_bufsize));
2510 					rval = FC_UNCLAIMED;
2511 					goto els_cb_done;
2512 				}
2513 				fcmd = (la_els_farp_t *)buf;
2514 				if (fcip_wwn_compare(&fcmd->resp_nwwn,
2515 				    &fport->fcipp_nwwn,
2516 				    FCIP_COMPARE_NWWN) != 0) {
2517 					rval = FC_UNCLAIMED;
2518 					goto els_cb_done;
2519 				}
2520 				/*
2521 				 * copy the FARP request and release the
2522 				 * unsolicited buffer
2523 				 */
2524 				fcmd = &farp_cmd;
2525 				bcopy((void *)buf, (void *)fcmd,
2526 				    sizeof (la_els_farp_t));
2527 				(void) fc_ulp_ubrelease(fport->fcipp_handle, 1,
2528 				    &buf->ub_token);
2529 
2530 				if (fcip_farp_supported &&
2531 				    fcip_handle_farp_request(fptr, fcmd) ==
2532 				    FC_SUCCESS) {
2533 					/*
2534 					 * We successfully sent out a FARP
2535 					 * reply to the requesting port
2536 					 */
2537 					rval = FC_SUCCESS;
2538 					goto els_cb_done;
2539 				} else {
2540 					rval = FC_UNCLAIMED;
2541 					goto els_cb_done;
2542 				}
2543 			}
2544 		} else if (r_ctl == R_CTL_ELS_RSP) {
2545 			ls_code = buf->ub_buffer[0];
2546 			if (ls_code == LA_ELS_FARP_REPLY) {
2547 				/*
2548 				 * We received a REPLY to our FARP request
2549 				 */
2550 				if (buf->ub_bufsize != sizeof (la_els_farp_t)) {
2551 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2552 					    "Invalid FARP req buffer size "
2553 					    "expected 0x%lx, got 0x%x",
2554 					    (long)(sizeof (la_els_farp_t)),
2555 					    buf->ub_bufsize));
2556 					rval = FC_UNCLAIMED;
2557 					goto els_cb_done;
2558 				}
2559 				fcmd = &farp_cmd;
2560 				bcopy((void *)buf, (void *)fcmd,
2561 				    sizeof (la_els_farp_t));
2562 				(void) fc_ulp_ubrelease(fport->fcipp_handle, 1,
2563 				    &buf->ub_token);
2564 				if (fcip_farp_supported &&
2565 				    fcip_handle_farp_response(fptr, fcmd) ==
2566 				    FC_SUCCESS) {
2567 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_NOTE,
2568 					    "Successfully recevied a FARP "
2569 					    "response"));
2570 					mutex_enter(&fptr->fcip_mutex);
2571 					fptr->fcip_farp_rsp_flag = 1;
2572 					cv_signal(&fptr->fcip_farp_cv);
2573 					mutex_exit(&fptr->fcip_mutex);
2574 					rval = FC_SUCCESS;
2575 					goto els_cb_done;
2576 				} else {
2577 					FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2578 					    "Unable to handle a FARP response "
2579 					    "receive"));
2580 					rval = FC_UNCLAIMED;
2581 					goto els_cb_done;
2582 				}
2583 			}
2584 		}
2585 		break;
2586 	default:
2587 		break;
2588 	}
2589 els_cb_done:
2590 	mutex_enter(&fptr->fcip_mutex);
2591 	fptr->fcip_flags &= ~(FCIP_IN_ELS_CB);
2592 	mutex_exit(&fptr->fcip_mutex);
2593 	return (rval);
2594 }
2595 
2596 
2597 /*
2598  * Handle inbound FARP requests
2599  */
2600 static int
2601 fcip_handle_farp_request(struct fcip *fptr, la_els_farp_t *fcmd)
2602 {
2603 	fcip_pkt_t		*fcip_pkt;
2604 	fc_packet_t		*fc_pkt;
2605 	fcip_port_info_t	*fport = fptr->fcip_port_info;
2606 	int			rval = FC_FAILURE;
2607 	opaque_t		fca_dev;
2608 	fc_portmap_t 		map;
2609 	struct fcip_routing_table *frp;
2610 	struct fcip_dest *fdestp;
2611 
2612 	/*
2613 	 * Add an entry for the remote port into our routing and destination
2614 	 * tables.
2615 	 */
2616 	map.map_did = fcmd->req_id;
2617 	map.map_hard_addr.hard_addr = fcmd->req_id.port_id;
2618 	map.map_state = PORT_DEVICE_VALID;
2619 	map.map_type = PORT_DEVICE_NEW;
2620 	map.map_flags = 0;
2621 	map.map_pd = NULL;
2622 	bcopy((void *)&fcmd->req_pwwn, (void *)&map.map_pwwn,
2623 	    sizeof (la_wwn_t));
2624 	bcopy((void *)&fcmd->req_nwwn, (void *)&map.map_nwwn,
2625 	    sizeof (la_wwn_t));
2626 	fcip_rt_update(fptr, &map, 1);
2627 	mutex_enter(&fptr->fcip_rt_mutex);
2628 	frp = fcip_lookup_rtable(fptr, &fcmd->req_pwwn, FCIP_COMPARE_NWWN);
2629 	mutex_exit(&fptr->fcip_rt_mutex);
2630 
2631 	fdestp = fcip_add_dest(fptr, frp);
2632 
2633 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_farp_t),
2634 	    sizeof (la_els_farp_t), NULL, KM_SLEEP);
2635 	if (fcip_pkt == NULL) {
2636 		rval = FC_FAILURE;
2637 		goto farp_done;
2638 	}
2639 	/*
2640 	 * Fill in our port's PWWN and NWWN
2641 	 */
2642 	fcmd->resp_pwwn = fport->fcipp_pwwn;
2643 	fcmd->resp_nwwn = fport->fcipp_nwwn;
2644 
2645 	fcip_init_unicast_pkt(fcip_pkt, fport->fcipp_sid,
2646 	    fcmd->req_id, NULL);
2647 
2648 	fca_dev =
2649 	    fc_ulp_get_fca_device(fport->fcipp_handle, fcmd->req_id);
2650 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
2651 	fc_pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_RSP;
2652 	fc_pkt->pkt_fca_device = fca_dev;
2653 	fcip_pkt->fcip_pkt_dest = fdestp;
2654 
2655 	/*
2656 	 * Attempt a PLOGI again
2657 	 */
2658 	if (fcmd->resp_flags & FARP_INIT_P_LOGI) {
2659 		if (fcip_do_plogi(fptr, frp) != FC_SUCCESS) {
2660 			/*
2661 			 * Login to the remote port failed. There is no
2662 			 * point continuing with the FARP request further
2663 			 * so bail out here.
2664 			 */
2665 			frp->fcipr_state = PORT_DEVICE_INVALID;
2666 			rval = FC_FAILURE;
2667 			goto farp_done;
2668 		}
2669 	}
2670 
2671 	FCIP_CP_OUT(fcmd, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
2672 	    sizeof (la_els_farp_t));
2673 
2674 	rval = fc_ulp_issue_els(fport->fcipp_handle, fc_pkt);
2675 	if (rval != FC_SUCCESS) {
2676 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
2677 		    "fcip_transport of farp reply failed 0x%x", rval));
2678 	}
2679 
2680 farp_done:
2681 	return (rval);
2682 }
2683 
2684 
2685 /*
2686  * Handle FARP responses to our FARP requests. When we receive a FARP
2687  * reply, we need to add the entry for the Port that replied into our
2688  * routing and destination hash tables. It is possible that the remote
2689  * port did not login into us (FARP responses can be received without
2690  * a PLOGI)
2691  */
2692 static int
2693 fcip_handle_farp_response(struct fcip *fptr, la_els_farp_t *fcmd)
2694 {
2695 	int			rval = FC_FAILURE;
2696 	fc_portmap_t 		map;
2697 	struct fcip_routing_table *frp;
2698 	struct fcip_dest *fdestp;
2699 
2700 	/*
2701 	 * Add an entry for the remote port into our routing and destination
2702 	 * tables.
2703 	 */
2704 	map.map_did = fcmd->dest_id;
2705 	map.map_hard_addr.hard_addr = fcmd->dest_id.port_id;
2706 	map.map_state = PORT_DEVICE_VALID;
2707 	map.map_type = PORT_DEVICE_NEW;
2708 	map.map_flags = 0;
2709 	map.map_pd = NULL;
2710 	bcopy((void *)&fcmd->resp_pwwn, (void *)&map.map_pwwn,
2711 	    sizeof (la_wwn_t));
2712 	bcopy((void *)&fcmd->resp_nwwn, (void *)&map.map_nwwn,
2713 	    sizeof (la_wwn_t));
2714 	fcip_rt_update(fptr, &map, 1);
2715 	mutex_enter(&fptr->fcip_rt_mutex);
2716 	frp = fcip_lookup_rtable(fptr, &fcmd->resp_pwwn, FCIP_COMPARE_NWWN);
2717 	mutex_exit(&fptr->fcip_rt_mutex);
2718 
2719 	fdestp = fcip_add_dest(fptr, frp);
2720 
2721 	if (fdestp != NULL) {
2722 		rval = FC_SUCCESS;
2723 	}
2724 	return (rval);
2725 }
2726 
2727 
2728 #define	FCIP_HDRS_LENGTH	\
2729 	sizeof (fcph_network_hdr_t)+sizeof (llc_snap_hdr_t)+sizeof (ipha_t)
2730 
2731 /*
2732  * fcip_data_cb is the heart of most IP operations. This routine is called
2733  * by the transport when any unsolicited IP data arrives at a port (which
2734  * is almost all IP data). This routine then strips off the Network header
2735  * from the payload (after authenticating the received payload ofcourse),
2736  * creates a message blk and sends the data upstream. You will see ugly
2737  * #defines because of problems with using esballoc() as opposed to
2738  * allocb to prevent an extra copy of data. We should probably move to
2739  * esballoc entirely when the MTU eventually will be larger than 1500 bytes
2740  * since copies will get more expensive then. At 1500 byte MTUs, there is
2741  * no noticable difference between using allocb and esballoc. The other
2742  * caveat is that the qlc firmware still cannot tell us accurately the
2743  * no. of valid bytes in the unsol buffer it DMA'ed so we have to resort
2744  * to looking into the IP header and hoping that the no. of bytes speficified
2745  * in the header was actually received.
2746  */
2747 /* ARGSUSED */
2748 static int
2749 fcip_data_cb(opaque_t ulp_handle, opaque_t phandle,
2750     fc_unsol_buf_t *buf, uint32_t claimed)
2751 {
2752 	fcip_port_info_t		*fport;
2753 	struct fcip 			*fptr;
2754 	fcph_network_hdr_t		*nhdr;
2755 	llc_snap_hdr_t			*snaphdr;
2756 	mblk_t				*bp;
2757 	uint32_t 			len;
2758 	uint32_t			hdrlen;
2759 	ushort_t			type;
2760 	ipha_t				*iphdr;
2761 	int				rval;
2762 
2763 #ifdef FCIP_ESBALLOC
2764 	frtn_t				*free_ubuf;
2765 	struct fcip_esballoc_arg	*fesb_argp;
2766 #endif /* FCIP_ESBALLOC */
2767 
2768 	fport = fcip_get_port(phandle);
2769 	if (fport == NULL) {
2770 		return (FC_UNCLAIMED);
2771 	}
2772 
2773 	fptr = fport->fcipp_fcip;
2774 	ASSERT(fptr != NULL);
2775 
2776 	if (fptr == NULL) {
2777 		return (FC_UNCLAIMED);
2778 	}
2779 
2780 	mutex_enter(&fptr->fcip_mutex);
2781 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
2782 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
2783 		mutex_exit(&fptr->fcip_mutex);
2784 		rval = FC_UNCLAIMED;
2785 		goto data_cb_done;
2786 	}
2787 
2788 	/*
2789 	 * set fcip flags to indicate we are in the middle of a
2790 	 * data callback so we can wait till the statechange
2791 	 * is handled before succeeding/failing the SUSPEND/POWER DOWN.
2792 	 */
2793 	fptr->fcip_flags |= FCIP_IN_DATA_CB;
2794 	mutex_exit(&fptr->fcip_mutex);
2795 
2796 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2797 	    (CE_NOTE, "fcip%d, data callback",
2798 	    ddi_get_instance(fport->fcipp_dip)));
2799 
2800 	/*
2801 	 * get to the network and snap headers in the payload
2802 	 */
2803 	nhdr = (fcph_network_hdr_t *)buf->ub_buffer;
2804 	snaphdr = (llc_snap_hdr_t *)(buf->ub_buffer +
2805 	    sizeof (fcph_network_hdr_t));
2806 
2807 	hdrlen = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
2808 
2809 	/*
2810 	 * get the IP header to obtain the no. of bytes we need to read
2811 	 * off from the unsol buffer. This obviously is because not all
2812 	 * data fills up the unsol buffer completely and the firmware
2813 	 * doesn't tell us how many valid bytes are in there as well
2814 	 */
2815 	iphdr = (ipha_t *)(buf->ub_buffer + hdrlen);
2816 	snaphdr->pid = BE_16(snaphdr->pid);
2817 	type = snaphdr->pid;
2818 
2819 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2820 	    (CE_CONT, "SNAPHDR: dsap %x, ssap %x, ctrl %x\n",
2821 	    snaphdr->dsap, snaphdr->ssap, snaphdr->ctrl));
2822 
2823 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2824 	    (CE_CONT, "oui[0] 0x%x oui[1] 0x%x oui[2] 0x%x pid 0x%x\n",
2825 	    snaphdr->oui[0], snaphdr->oui[1], snaphdr->oui[2], snaphdr->pid));
2826 
2827 	/* Authneticate, Authenticate */
2828 	if (type == ETHERTYPE_IP) {
2829 		len = hdrlen + BE_16(iphdr->ipha_length);
2830 	} else if (type == ETHERTYPE_ARP) {
2831 		len = hdrlen + 28;
2832 	} else {
2833 		len = buf->ub_bufsize;
2834 	}
2835 
2836 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2837 	    (CE_CONT, "effective packet length is %d bytes.\n", len));
2838 
2839 	if (len < hdrlen || len > FCIP_UB_SIZE) {
2840 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2841 		    (CE_NOTE, "Incorrect buffer size %d bytes", len));
2842 		rval = FC_UNCLAIMED;
2843 		goto data_cb_done;
2844 	}
2845 
2846 	if (buf->ub_frame.type != FC_TYPE_IS8802_SNAP) {
2847 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "Not IP/ARP data"));
2848 		rval = FC_UNCLAIMED;
2849 		goto data_cb_done;
2850 	}
2851 
2852 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "checking wwn"));
2853 
2854 	if ((fcip_wwn_compare(&nhdr->net_dest_addr, &fport->fcipp_pwwn,
2855 	    FCIP_COMPARE_NWWN) != 0) &&
2856 	    (!IS_BROADCAST_ADDR(&nhdr->net_dest_addr))) {
2857 		rval = FC_UNCLAIMED;
2858 		goto data_cb_done;
2859 	} else if (fcip_cache_on_arp_broadcast &&
2860 	    IS_BROADCAST_ADDR(&nhdr->net_dest_addr)) {
2861 		fcip_cache_arp_broadcast(fptr, buf);
2862 	}
2863 
2864 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_NOTE, "Allocate streams block"));
2865 
2866 	/*
2867 	 * Using esballoc instead of allocb should be faster, atleast at
2868 	 * larger MTUs than 1500 bytes. Someday we'll get there :)
2869 	 */
2870 #if defined(FCIP_ESBALLOC)
2871 	/*
2872 	 * allocate memory for the frtn function arg. The Function
2873 	 * (fcip_ubfree) arg is a struct fcip_esballoc_arg type
2874 	 * which contains pointers to the unsol buffer and the
2875 	 * opaque port handle for releasing the unsol buffer back to
2876 	 * the FCA for reuse
2877 	 */
2878 	fesb_argp = (struct fcip_esballoc_arg *)
2879 	    kmem_zalloc(sizeof (struct fcip_esballoc_arg), KM_NOSLEEP);
2880 
2881 	if (fesb_argp == NULL) {
2882 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2883 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2884 		rval = FC_UNCLAIMED;
2885 		goto data_cb_done;
2886 	}
2887 	/*
2888 	 * Check with KM_NOSLEEP
2889 	 */
2890 	free_ubuf = (frtn_t *)kmem_zalloc(sizeof (frtn_t), KM_NOSLEEP);
2891 	if (free_ubuf == NULL) {
2892 		kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
2893 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2894 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2895 		rval = FC_UNCLAIMED;
2896 		goto data_cb_done;
2897 	}
2898 
2899 	fesb_argp->frtnp = free_ubuf;
2900 	fesb_argp->buf = buf;
2901 	fesb_argp->phandle = phandle;
2902 	free_ubuf->free_func = fcip_ubfree;
2903 	free_ubuf->free_arg = (char *)fesb_argp;
2904 	if ((bp = (mblk_t *)esballoc((unsigned char *)buf->ub_buffer,
2905 	    len, BPRI_MED, free_ubuf)) == NULL) {
2906 		kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
2907 		kmem_free(free_ubuf, sizeof (frtn_t));
2908 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2909 		    (CE_WARN, "esballoc of mblk failed in data_cb"));
2910 		rval = FC_UNCLAIMED;
2911 		goto data_cb_done;
2912 	}
2913 #elif !defined(FCIP_ESBALLOC)
2914 	/*
2915 	 * allocate streams mblk and copy the contents of the
2916 	 * unsolicited buffer into this newly alloc'ed mblk
2917 	 */
2918 	if ((bp = (mblk_t *)fcip_allocb((size_t)len, BPRI_LO)) == NULL) {
2919 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
2920 		    (CE_WARN, "alloc of mblk failed in data_cb"));
2921 		rval = FC_UNCLAIMED;
2922 		goto data_cb_done;
2923 	}
2924 
2925 	/*
2926 	 * Unsolicited buffers handed up to us from the FCA must be
2927 	 * endian clean so just bcopy the data into our mblk. Else
2928 	 * we may have to either copy the data byte by byte or
2929 	 * use the ddi_rep_get* routines to do the copy for us.
2930 	 */
2931 	bcopy(buf->ub_buffer, bp->b_rptr, len);
2932 
2933 	/*
2934 	 * for esballoc'ed mblks - free the UB in the frtn function
2935 	 * along with the memory allocated for the function arg.
2936 	 * for allocb'ed mblk - release the unsolicited buffer here
2937 	 */
2938 	(void) fc_ulp_ubrelease(phandle, 1, &buf->ub_token);
2939 
2940 #endif	/* FCIP_ESBALLOC */
2941 
2942 	bp->b_wptr = bp->b_rptr + len;
2943 	fptr->fcip_ipackets++;
2944 
2945 	if (type == ETHERTYPE_IP) {
2946 		mutex_enter(&fptr->fcip_mutex);
2947 		fptr->fcip_ub_upstream++;
2948 		mutex_exit(&fptr->fcip_mutex);
2949 		bp->b_rptr += hdrlen;
2950 
2951 		/*
2952 		 * Check if ipq is valid in the sendup thread
2953 		 */
2954 		if (fcip_sendup_alloc_enque(fptr, bp, NULL) != FC_SUCCESS) {
2955 			freemsg(bp);
2956 		}
2957 	} else {
2958 		/*
2959 		 * We won't get ethernet 802.3 packets in FCIP but we may get
2960 		 * types other than ETHERTYPE_IP, such as ETHERTYPE_ARP. Let
2961 		 * fcip_sendup() do the matching.
2962 		 */
2963 		mutex_enter(&fptr->fcip_mutex);
2964 		fptr->fcip_ub_upstream++;
2965 		mutex_exit(&fptr->fcip_mutex);
2966 		if (fcip_sendup_alloc_enque(fptr, bp,
2967 		    fcip_accept) != FC_SUCCESS) {
2968 			freemsg(bp);
2969 		}
2970 	}
2971 
2972 	rval = FC_SUCCESS;
2973 
2974 	/*
2975 	 * Unset fcip_flags to indicate we are out of callback and return
2976 	 */
2977 data_cb_done:
2978 	mutex_enter(&fptr->fcip_mutex);
2979 	fptr->fcip_flags &= ~(FCIP_IN_DATA_CB);
2980 	mutex_exit(&fptr->fcip_mutex);
2981 	return (rval);
2982 }
2983 
2984 #if !defined(FCIP_ESBALLOC)
2985 /*
2986  * Allocate a message block for the inbound data to be sent upstream.
2987  */
2988 static void *
2989 fcip_allocb(size_t size, uint_t pri)
2990 {
2991 	mblk_t	*mp;
2992 
2993 	if ((mp = allocb(size, pri)) == NULL) {
2994 		return (NULL);
2995 	}
2996 	return (mp);
2997 }
2998 
2999 #endif
3000 
3001 /*
3002  * This helper routine kmem cache alloc's a sendup element for enquing
3003  * into the sendup list for callbacks upstream from the dedicated sendup
3004  * thread. We enque the msg buf into the sendup list and cv_signal the
3005  * sendup thread to finish the callback for us.
3006  */
3007 static int
3008 fcip_sendup_alloc_enque(struct fcip *fptr, mblk_t *mp, struct fcipstr *(*f)())
3009 {
3010 	struct fcip_sendup_elem 	*msg_elem;
3011 	int				rval = FC_FAILURE;
3012 
3013 	msg_elem = kmem_cache_alloc(fptr->fcip_sendup_cache, KM_NOSLEEP);
3014 	if (msg_elem == NULL) {
3015 		/* drop pkt to floor - update stats */
3016 		rval = FC_FAILURE;
3017 		goto sendup_alloc_done;
3018 	}
3019 	msg_elem->fcipsu_mp = mp;
3020 	msg_elem->fcipsu_func = f;
3021 
3022 	mutex_enter(&fptr->fcip_sendup_mutex);
3023 	if (fptr->fcip_sendup_head == NULL) {
3024 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = msg_elem;
3025 	} else {
3026 		fptr->fcip_sendup_tail->fcipsu_next = msg_elem;
3027 		fptr->fcip_sendup_tail = msg_elem;
3028 	}
3029 	fptr->fcip_sendup_cnt++;
3030 	cv_signal(&fptr->fcip_sendup_cv);
3031 	mutex_exit(&fptr->fcip_sendup_mutex);
3032 	rval = FC_SUCCESS;
3033 
3034 sendup_alloc_done:
3035 	return (rval);
3036 }
3037 
3038 /*
3039  * One of the ways of performing the WWN to D_ID mapping required for
3040  * IPFC data is to cache the unsolicited ARP broadcast messages received
3041  * and update the routing table to add entry for the destination port
3042  * if we are the intended recipient of the ARP broadcast message. This is
3043  * one of the methods recommended in the rfc to obtain the WWN to D_ID mapping
3044  * but is not typically used unless enabled. The driver prefers to use the
3045  * nameserver/lilp map to obtain this mapping.
3046  */
3047 static void
3048 fcip_cache_arp_broadcast(struct fcip *fptr, fc_unsol_buf_t *buf)
3049 {
3050 	fcip_port_info_t		*fport;
3051 	fcph_network_hdr_t		*nhdr;
3052 	struct fcip_routing_table	*frp;
3053 	fc_portmap_t			map;
3054 
3055 	fport = fptr->fcip_port_info;
3056 	if (fport == NULL) {
3057 		return;
3058 	}
3059 	ASSERT(fport != NULL);
3060 
3061 	nhdr = (fcph_network_hdr_t *)buf->ub_buffer;
3062 
3063 	mutex_enter(&fptr->fcip_rt_mutex);
3064 	frp = fcip_lookup_rtable(fptr, &nhdr->net_src_addr, FCIP_COMPARE_NWWN);
3065 	mutex_exit(&fptr->fcip_rt_mutex);
3066 	if (frp == NULL) {
3067 		map.map_did.port_id = buf->ub_frame.s_id;
3068 		map.map_hard_addr.hard_addr = buf->ub_frame.s_id;
3069 		map.map_state = PORT_DEVICE_VALID;
3070 		map.map_type = PORT_DEVICE_NEW;
3071 		map.map_flags = 0;
3072 		map.map_pd = NULL;
3073 		bcopy((void *)&nhdr->net_src_addr, (void *)&map.map_pwwn,
3074 		    sizeof (la_wwn_t));
3075 		bcopy((void *)&nhdr->net_src_addr, (void *)&map.map_nwwn,
3076 		    sizeof (la_wwn_t));
3077 		fcip_rt_update(fptr, &map, 1);
3078 		mutex_enter(&fptr->fcip_rt_mutex);
3079 		frp = fcip_lookup_rtable(fptr, &nhdr->net_src_addr,
3080 		    FCIP_COMPARE_NWWN);
3081 		mutex_exit(&fptr->fcip_rt_mutex);
3082 
3083 		(void) fcip_add_dest(fptr, frp);
3084 	}
3085 
3086 }
3087 
3088 /*
3089  * This is a dedicated thread to do callbacks from fcip's data callback
3090  * routines into the modules upstream. The reason for this thread is
3091  * the data callback function can be called from an interrupt context and
3092  * the upstream modules *can* make calls downstream in the same thread
3093  * context. If the call is to a fabric port which is not yet in our
3094  * routing tables, we may have to query the nameserver/fabric for the
3095  * MAC addr to Port_ID mapping which may be blocking calls.
3096  */
3097 static void
3098 fcip_sendup_thr(void *arg)
3099 {
3100 	struct fcip		*fptr = (struct fcip *)arg;
3101 	struct fcip_sendup_elem	*msg_elem;
3102 	queue_t			*ip4q = NULL;
3103 
3104 	CALLB_CPR_INIT(&fptr->fcip_cpr_info, &fptr->fcip_sendup_mutex,
3105 	    callb_generic_cpr, "fcip_sendup_thr");
3106 
3107 	mutex_enter(&fptr->fcip_sendup_mutex);
3108 	for (;;) {
3109 
3110 		while (fptr->fcip_sendup_thr_initted &&
3111 		    fptr->fcip_sendup_head == NULL) {
3112 			CALLB_CPR_SAFE_BEGIN(&fptr->fcip_cpr_info);
3113 			cv_wait(&fptr->fcip_sendup_cv,
3114 			    &fptr->fcip_sendup_mutex);
3115 			CALLB_CPR_SAFE_END(&fptr->fcip_cpr_info,
3116 			    &fptr->fcip_sendup_mutex);
3117 		}
3118 
3119 		if (fptr->fcip_sendup_thr_initted == 0) {
3120 			break;
3121 		}
3122 
3123 		msg_elem = fptr->fcip_sendup_head;
3124 		fptr->fcip_sendup_head = msg_elem->fcipsu_next;
3125 		msg_elem->fcipsu_next = NULL;
3126 		mutex_exit(&fptr->fcip_sendup_mutex);
3127 
3128 		if (msg_elem->fcipsu_func == NULL) {
3129 			/*
3130 			 * Message for ipq. Check to see if the ipq is
3131 			 * is still valid. Since the thread is asynchronous,
3132 			 * there could have been a close on the stream
3133 			 */
3134 			mutex_enter(&fptr->fcip_mutex);
3135 			if (fptr->fcip_ipq && canputnext(fptr->fcip_ipq)) {
3136 				ip4q = fptr->fcip_ipq;
3137 				mutex_exit(&fptr->fcip_mutex);
3138 				putnext(ip4q, msg_elem->fcipsu_mp);
3139 			} else {
3140 				mutex_exit(&fptr->fcip_mutex);
3141 				freemsg(msg_elem->fcipsu_mp);
3142 			}
3143 		} else {
3144 			fcip_sendup(fptr, msg_elem->fcipsu_mp,
3145 			    msg_elem->fcipsu_func);
3146 		}
3147 
3148 #if !defined(FCIP_ESBALLOC)
3149 		/*
3150 		 * for allocb'ed mblk - decrement upstream count here
3151 		 */
3152 		mutex_enter(&fptr->fcip_mutex);
3153 		ASSERT(fptr->fcip_ub_upstream > 0);
3154 		fptr->fcip_ub_upstream--;
3155 		mutex_exit(&fptr->fcip_mutex);
3156 #endif /* FCIP_ESBALLOC */
3157 
3158 		kmem_cache_free(fptr->fcip_sendup_cache, (void *)msg_elem);
3159 		mutex_enter(&fptr->fcip_sendup_mutex);
3160 		fptr->fcip_sendup_cnt--;
3161 	}
3162 
3163 
3164 #ifndef	__lock_lint
3165 	CALLB_CPR_EXIT(&fptr->fcip_cpr_info);
3166 #else
3167 	mutex_exit(&fptr->fcip_sendup_mutex);
3168 #endif /* __lock_lint */
3169 
3170 	/* Wake up fcip detach thread by the end */
3171 	cv_signal(&fptr->fcip_sendup_cv);
3172 
3173 	thread_exit();
3174 }
3175 
3176 #ifdef FCIP_ESBALLOC
3177 
3178 /*
3179  * called from the stream head when it is done using an unsolicited buffer.
3180  * We release this buffer then to the FCA for reuse.
3181  */
3182 static void
3183 fcip_ubfree(char *arg)
3184 {
3185 	struct fcip_esballoc_arg *fesb_argp = (struct fcip_esballoc_arg *)arg;
3186 	fc_unsol_buf_t	*ubuf;
3187 	frtn_t		*frtnp;
3188 	fcip_port_info_t		*fport;
3189 	struct fcip 			*fptr;
3190 
3191 
3192 	fport = fcip_get_port(fesb_argp->phandle);
3193 	fptr = fport->fcipp_fcip;
3194 
3195 	ASSERT(fesb_argp != NULL);
3196 	ubuf = fesb_argp->buf;
3197 	frtnp = fesb_argp->frtnp;
3198 
3199 
3200 	FCIP_DEBUG(FCIP_DEBUG_UPSTREAM,
3201 	    (CE_WARN, "freeing ubuf after esballoc in fcip_ubfree"));
3202 	(void) fc_ulp_ubrelease(fesb_argp->phandle, 1, &ubuf->ub_token);
3203 
3204 	mutex_enter(&fptr->fcip_mutex);
3205 	ASSERT(fptr->fcip_ub_upstream > 0);
3206 	fptr->fcip_ub_upstream--;
3207 	cv_signal(&fptr->fcip_ub_cv);
3208 	mutex_exit(&fptr->fcip_mutex);
3209 
3210 	kmem_free(frtnp, sizeof (frtn_t));
3211 	kmem_free(fesb_argp, sizeof (struct fcip_esballoc_arg));
3212 }
3213 
3214 #endif /* FCIP_ESBALLOC */
3215 
3216 /*
3217  * handle data other than that of type ETHERTYPE_IP and send it on its
3218  * way upstream to the right streams module to handle
3219  */
3220 static void
3221 fcip_sendup(struct fcip *fptr, mblk_t *mp, struct fcipstr *(*acceptfunc)())
3222 {
3223 	struct fcipstr	*slp, *nslp;
3224 	la_wwn_t	*dhostp;
3225 	mblk_t		*nmp;
3226 	uint32_t 	isgroupaddr;
3227 	int 		type;
3228 	uint32_t	hdrlen;
3229 	fcph_network_hdr_t	*nhdr;
3230 	llc_snap_hdr_t		*snaphdr;
3231 
3232 	nhdr = (fcph_network_hdr_t *)mp->b_rptr;
3233 	snaphdr =
3234 	    (llc_snap_hdr_t *)(mp->b_rptr + sizeof (fcph_network_hdr_t));
3235 	dhostp = &nhdr->net_dest_addr;
3236 	type = snaphdr->pid;
3237 	hdrlen = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
3238 
3239 	/* No group address with fibre channel */
3240 	isgroupaddr = 0;
3241 
3242 	/*
3243 	 * While holding a reader lock on the linked list of streams structures,
3244 	 * attempt to match the address criteria for each stream
3245 	 * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND.
3246 	 */
3247 
3248 	rw_enter(&fcipstruplock, RW_READER);
3249 
3250 	if ((slp = (*acceptfunc)(fcipstrup, fptr, type, dhostp)) == NULL) {
3251 		rw_exit(&fcipstruplock);
3252 		freemsg(mp);
3253 		return;
3254 	}
3255 
3256 	/*
3257 	 * Loop on matching open streams until (*acceptfunc)() returns NULL.
3258 	 */
3259 	for (; nslp = (*acceptfunc)(slp->sl_nextp, fptr, type, dhostp);
3260 	    slp = nslp) {
3261 		if (canputnext(slp->sl_rq)) {
3262 			if (nmp = dupmsg(mp)) {
3263 				if ((slp->sl_flags & FCIP_SLFAST) &&
3264 							!isgroupaddr) {
3265 					nmp->b_rptr += hdrlen;
3266 					putnext(slp->sl_rq, nmp);
3267 				} else if (slp->sl_flags & FCIP_SLRAW) {
3268 					/* No headers when FCIP_SLRAW is set */
3269 					putnext(slp->sl_rq, nmp);
3270 				} else if ((nmp = fcip_addudind(fptr, nmp,
3271 				    nhdr, type))) {
3272 					putnext(slp->sl_rq, nmp);
3273 				}
3274 			}
3275 		}
3276 	}
3277 
3278 	/*
3279 	 * Do the last one.
3280 	 */
3281 	if (canputnext(slp->sl_rq)) {
3282 		if (slp->sl_flags & FCIP_SLFAST) {
3283 			mp->b_rptr += hdrlen;
3284 			putnext(slp->sl_rq, mp);
3285 		} else if (slp->sl_flags & FCIP_SLRAW) {
3286 			putnext(slp->sl_rq, mp);
3287 		} else if ((mp = fcip_addudind(fptr, mp, nhdr, type))) {
3288 			putnext(slp->sl_rq, mp);
3289 		}
3290 	} else {
3291 		freemsg(mp);
3292 	}
3293 
3294 	rw_exit(&fcipstruplock);
3295 }
3296 
3297 /*
3298  * Match the stream based on type and wwn if necessary.
3299  * Destination wwn dhostp is passed to this routine is reserved
3300  * for future usage. We don't need to use it right now since port
3301  * to fcip instance mapping is unique and wwn is already validated when
3302  * packet comes to fcip.
3303  */
3304 /* ARGSUSED */
3305 static struct fcipstr *
3306 fcip_accept(struct fcipstr *slp, struct fcip *fptr, int type, la_wwn_t *dhostp)
3307 {
3308 	t_uscalar_t 	sap;
3309 
3310 	for (; slp; slp = slp->sl_nextp) {
3311 		sap = slp->sl_sap;
3312 		FCIP_DEBUG(FCIP_DEBUG_UPSTREAM, (CE_CONT,
3313 		    "fcip_accept: checking next sap = %x, type = %x",
3314 		    sap, type));
3315 
3316 		if ((slp->sl_fcip == fptr) && (type == sap)) {
3317 			return (slp);
3318 		}
3319 	}
3320 	return (NULL);
3321 }
3322 
3323 /*
3324  * Handle DL_UNITDATA_IND messages
3325  */
3326 static mblk_t *
3327 fcip_addudind(struct fcip *fptr, mblk_t *mp, fcph_network_hdr_t *nhdr,
3328     int type)
3329 {
3330 	dl_unitdata_ind_t	*dludindp;
3331 	struct	fcipdladdr	*dlap;
3332 	mblk_t	*nmp;
3333 	int	size;
3334 	uint32_t hdrlen;
3335 	struct ether_addr	src_addr;
3336 	struct ether_addr	dest_addr;
3337 
3338 
3339 	hdrlen = (sizeof (llc_snap_hdr_t) + sizeof (fcph_network_hdr_t));
3340 	mp->b_rptr += hdrlen;
3341 
3342 	/*
3343 	 * Allocate an M_PROTO mblk for the DL_UNITDATA_IND.
3344 	 */
3345 	size = sizeof (dl_unitdata_ind_t) + FCIPADDRL + FCIPADDRL;
3346 	if ((nmp = allocb(size, BPRI_LO)) == NULL) {
3347 		fptr->fcip_allocbfail++;
3348 		freemsg(mp);
3349 		return (NULL);
3350 	}
3351 	DB_TYPE(nmp) = M_PROTO;
3352 	nmp->b_wptr = nmp->b_datap->db_lim;
3353 	nmp->b_rptr = nmp->b_wptr - size;
3354 
3355 	/*
3356 	 * Construct a DL_UNITDATA_IND primitive.
3357 	 */
3358 	dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
3359 	dludindp->dl_primitive = DL_UNITDATA_IND;
3360 	dludindp->dl_dest_addr_length = FCIPADDRL;
3361 	dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
3362 	dludindp->dl_src_addr_length = FCIPADDRL;
3363 	dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + FCIPADDRL;
3364 	dludindp->dl_group_address = 0;		/* not DL_MULTI */
3365 
3366 	dlap = (struct fcipdladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t));
3367 	wwn_to_ether(&nhdr->net_dest_addr, &dest_addr);
3368 	ether_bcopy(&dest_addr, &dlap->dl_phys);
3369 	dlap->dl_sap = (uint16_t)type;
3370 
3371 	dlap = (struct fcipdladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)
3372 		+ FCIPADDRL);
3373 	wwn_to_ether(&nhdr->net_src_addr, &src_addr);
3374 	ether_bcopy(&src_addr, &dlap->dl_phys);
3375 	dlap->dl_sap = (uint16_t)type;
3376 
3377 	/*
3378 	 * Link the M_PROTO and M_DATA together.
3379 	 */
3380 	nmp->b_cont = mp;
3381 	return (nmp);
3382 }
3383 
3384 
3385 /*
3386  * The open routine. For clone opens, we return the next available minor
3387  * no. for the stream to use
3388  */
3389 /* ARGSUSED */
3390 static int
3391 fcip_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
3392 {
3393 	struct fcipstr	*slp;
3394 	struct fcipstr	**prevslp;
3395 	minor_t	minor;
3396 
3397 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcip_open"));
3398 	/*
3399 	 * We need to ensure that the port driver is loaded before
3400 	 * we proceed
3401 	 */
3402 	if (ddi_hold_installed_driver(ddi_name_to_major(PORT_DRIVER)) == NULL) {
3403 		/* no port driver instances found */
3404 		FCIP_DEBUG(FCIP_DEBUG_STARTUP, (CE_WARN,
3405 		    "!ddi_hold_installed_driver of fp failed\n"));
3406 		return (ENXIO);
3407 	}
3408 	/* serialize opens */
3409 	rw_enter(&fcipstruplock, RW_WRITER);
3410 
3411 	prevslp = &fcipstrup;
3412 	if (sflag == CLONEOPEN) {
3413 		minor = 0;
3414 		for (; (slp = *prevslp) != NULL; prevslp = &slp->sl_nextp) {
3415 			if (minor < slp->sl_minor) {
3416 				break;
3417 			}
3418 			minor ++;
3419 		}
3420 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
3421 		    "getmajor returns 0x%x", getmajor(*devp)));
3422 		*devp = makedevice(getmajor(*devp), minor);
3423 	} else {
3424 		minor = getminor(*devp);
3425 	}
3426 
3427 	/*
3428 	 * check if our qp's private area is already initialized. If yes
3429 	 * the stream is already open - just return
3430 	 */
3431 	if (rq->q_ptr) {
3432 		goto done;
3433 	}
3434 
3435 	slp = GETSTRUCT(struct fcipstr, 1);
3436 	slp->sl_minor = minor;
3437 	slp->sl_rq = rq;
3438 	slp->sl_sap = 0;
3439 	slp->sl_flags = 0;
3440 	slp->sl_state = DL_UNATTACHED;
3441 	slp->sl_fcip = NULL;
3442 
3443 	mutex_init(&slp->sl_lock, NULL, MUTEX_DRIVER, NULL);
3444 
3445 	/*
3446 	 * link this new stream entry into list of active streams
3447 	 */
3448 	slp->sl_nextp = *prevslp;
3449 	*prevslp = slp;
3450 
3451 	rq->q_ptr = WR(rq)->q_ptr = (char *)slp;
3452 
3453 	/*
3454 	 * Disable automatic enabling of our write service procedures
3455 	 * we need to control this explicitly. This will prevent
3456 	 * anyone scheduling of our write service procedures.
3457 	 */
3458 	noenable(WR(rq));
3459 
3460 done:
3461 	rw_exit(&fcipstruplock);
3462 	/*
3463 	 * enable our put and service routines on the read side
3464 	 */
3465 	qprocson(rq);
3466 
3467 	/*
3468 	 * There is only one instance of fcip (instance = 0)
3469 	 * for multiple instances of hardware
3470 	 */
3471 	(void) qassociate(rq, 0);	/* don't allow drcompat to be pushed */
3472 	return (0);
3473 }
3474 
3475 /*
3476  * close an opened stream. The minor no. will then be available for
3477  * future opens.
3478  */
3479 /* ARGSUSED */
3480 static int
3481 fcip_close(queue_t *rq, int flag, cred_t *credp)
3482 {
3483 	struct fcipstr *slp;
3484 	struct fcipstr **prevslp;
3485 
3486 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcip_close"));
3487 	ASSERT(rq);
3488 	/* we should also have the active stream pointer in q_ptr */
3489 	ASSERT(rq->q_ptr);
3490 
3491 	ddi_rele_driver(ddi_name_to_major(PORT_DRIVER));
3492 	/*
3493 	 * disable our put and service procedures. We had enabled them
3494 	 * on open
3495 	 */
3496 	qprocsoff(rq);
3497 	slp = (struct fcipstr *)rq->q_ptr;
3498 
3499 	/*
3500 	 * Implicitly detach stream  a stream from an interface.
3501 	 */
3502 	if (slp->sl_fcip) {
3503 		fcip_dodetach(slp);
3504 	}
3505 
3506 	(void) qassociate(rq, -1);	/* undo association in open */
3507 
3508 	rw_enter(&fcipstruplock, RW_WRITER);
3509 
3510 	/*
3511 	 * unlink this stream from the active stream list and free it
3512 	 */
3513 	for (prevslp = &fcipstrup; (slp = *prevslp) != NULL;
3514 	    prevslp = &slp->sl_nextp) {
3515 		if (slp == (struct fcipstr *)rq->q_ptr) {
3516 			break;
3517 		}
3518 	}
3519 
3520 	/* we should have found slp */
3521 	ASSERT(slp);
3522 
3523 	*prevslp = slp->sl_nextp;
3524 	mutex_destroy(&slp->sl_lock);
3525 	kmem_free(slp, sizeof (struct fcipstr));
3526 	rq->q_ptr = WR(rq)->q_ptr = NULL;
3527 
3528 	rw_exit(&fcipstruplock);
3529 	return (0);
3530 }
3531 
3532 /*
3533  * This is not an extension of the DDI_DETACH request. This routine
3534  * only detaches a stream from an interface
3535  */
3536 static void
3537 fcip_dodetach(struct fcipstr *slp)
3538 {
3539 	struct fcipstr	*tslp;
3540 	struct fcip	*fptr;
3541 
3542 	FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_NOTE, "in fcip_dodetach"));
3543 	ASSERT(slp->sl_fcip != NULL);
3544 
3545 	fptr = slp->sl_fcip;
3546 	slp->sl_fcip = NULL;
3547 
3548 	/*
3549 	 * we don't support promiscuous mode currently but check
3550 	 * for and disable any promiscuous mode operation
3551 	 */
3552 	if (slp->sl_flags & SLALLPHYS) {
3553 		slp->sl_flags &= ~SLALLPHYS;
3554 	}
3555 
3556 	/*
3557 	 * disable ALLMULTI mode if all mulitcast addr are ON
3558 	 */
3559 	if (slp->sl_flags & SLALLMULTI) {
3560 		slp->sl_flags &= ~SLALLMULTI;
3561 	}
3562 
3563 	/*
3564 	 * we are most likely going to perform multicast by
3565 	 * broadcasting to the well known addr (D_ID) 0xFFFFFF or
3566 	 * ALPA 0x00 in case of public loops
3567 	 */
3568 
3569 
3570 	/*
3571 	 * detach unit from device structure.
3572 	 */
3573 	for (tslp = fcipstrup; tslp != NULL; tslp = tslp->sl_nextp) {
3574 		if (tslp->sl_fcip == fptr) {
3575 			break;
3576 		}
3577 	}
3578 	if (tslp == NULL) {
3579 		FCIP_DEBUG(FCIP_DEBUG_DETACH, (CE_WARN,
3580 		"fcip_dodeatch - active stream struct not found"));
3581 
3582 		/* unregister with Fabric nameserver?? */
3583 	}
3584 	slp->sl_state = DL_UNATTACHED;
3585 
3586 	fcip_setipq(fptr);
3587 }
3588 
3589 
3590 /*
3591  * Set or clear device ipq pointer.
3592  * Walk thru all the streams on this device, if a ETHERTYPE_IP
3593  * stream is found, assign device ipq to its sl_rq.
3594  */
3595 static void
3596 fcip_setipq(struct fcip *fptr)
3597 {
3598 	struct fcipstr	*slp;
3599 	int		ok = 1;
3600 	queue_t		*ipq = NULL;
3601 
3602 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "entered fcip_setipq"));
3603 
3604 	rw_enter(&fcipstruplock, RW_READER);
3605 
3606 	for (slp = fcipstrup; slp != NULL; slp = slp->sl_nextp) {
3607 		if (slp->sl_fcip == fptr) {
3608 			if (slp->sl_flags & (SLALLPHYS|SLALLSAP)) {
3609 				ok = 0;
3610 			}
3611 			if (slp->sl_sap == ETHERTYPE_IP) {
3612 				if (ipq == NULL) {
3613 					ipq = slp->sl_rq;
3614 				} else {
3615 					ok = 0;
3616 				}
3617 			}
3618 		}
3619 	}
3620 
3621 	rw_exit(&fcipstruplock);
3622 
3623 	if (fcip_check_port_exists(fptr)) {
3624 		/* fptr passed to us is stale */
3625 		return;
3626 	}
3627 
3628 	mutex_enter(&fptr->fcip_mutex);
3629 	if (ok) {
3630 		fptr->fcip_ipq = ipq;
3631 	} else {
3632 		fptr->fcip_ipq = NULL;
3633 	}
3634 	mutex_exit(&fptr->fcip_mutex);
3635 }
3636 
3637 
3638 /* ARGSUSED */
3639 static void
3640 fcip_ioctl(queue_t *wq, mblk_t *mp)
3641 {
3642 	struct iocblk		*iocp = (struct iocblk *)mp->b_rptr;
3643 	struct fcipstr		*slp = (struct fcipstr *)wq->q_ptr;
3644 
3645 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3646 	    (CE_NOTE, "in fcip ioctl : %d", iocp->ioc_cmd));
3647 
3648 	switch (iocp->ioc_cmd) {
3649 	case DLIOCRAW:
3650 		slp->sl_flags |= FCIP_SLRAW;
3651 		miocack(wq, mp, 0, 0);
3652 		break;
3653 
3654 	case DL_IOC_HDR_INFO:
3655 		fcip_dl_ioc_hdr_info(wq, mp);
3656 		break;
3657 
3658 	default:
3659 		miocnak(wq, mp, 0, EINVAL);
3660 		break;
3661 	}
3662 }
3663 
3664 /*
3665  * The streams 'Put' routine.
3666  */
3667 /* ARGSUSED */
3668 static int
3669 fcip_wput(queue_t *wq, mblk_t *mp)
3670 {
3671 	struct fcipstr *slp = (struct fcipstr *)wq->q_ptr;
3672 	struct fcip *fptr;
3673 	struct fcip_dest *fdestp;
3674 	fcph_network_hdr_t *headerp;
3675 
3676 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3677 	    (CE_NOTE, "in fcip_wput :: type:%x", DB_TYPE(mp)));
3678 
3679 	switch (DB_TYPE(mp)) {
3680 	case M_DATA: {
3681 
3682 		fptr = slp->sl_fcip;
3683 
3684 		if (((slp->sl_flags & (FCIP_SLFAST|FCIP_SLRAW)) == 0) ||
3685 		    (slp->sl_state != DL_IDLE) ||
3686 		    (fptr == NULL)) {
3687 			/*
3688 			 * set error in the message block and send a reply
3689 			 * back upstream. Sun's merror routine does this
3690 			 * for us more cleanly.
3691 			 */
3692 			merror(wq, mp, EPROTO);
3693 			break;
3694 		}
3695 
3696 		/*
3697 		 * if any messages are already enqueued or if the interface
3698 		 * is in promiscuous mode, causing the packets to loop back
3699 		 * up, then enqueue the message. Otherwise just transmit
3700 		 * the message. putq() puts the message on fcip's
3701 		 * write queue and qenable() puts the queue (wq) on
3702 		 * the list of queues to be called by the streams scheduler.
3703 		 */
3704 		if (wq->q_first) {
3705 			(void) putq(wq, mp);
3706 			fptr->fcip_wantw = 1;
3707 			qenable(wq);
3708 		} else if (fptr->fcip_flags & FCIP_PROMISC) {
3709 			/*
3710 			 * Promiscous mode not supported but add this code in
3711 			 * case it will be supported in future.
3712 			 */
3713 			(void) putq(wq, mp);
3714 			qenable(wq);
3715 		} else {
3716 
3717 			headerp = (fcph_network_hdr_t *)mp->b_rptr;
3718 			fdestp = fcip_get_dest(fptr, &headerp->net_dest_addr);
3719 
3720 			if (fdestp == NULL) {
3721 				merror(wq, mp, EPROTO);
3722 				break;
3723 			}
3724 
3725 			ASSERT(fdestp != NULL);
3726 
3727 			(void) fcip_start(wq, mp, fptr, fdestp, KM_SLEEP);
3728 		}
3729 		break;
3730 	}
3731 	case M_PROTO:
3732 	case M_PCPROTO:
3733 		/*
3734 		 * to prevent recursive calls into fcip_proto
3735 		 * (PROTO and PCPROTO messages are handled by fcip_proto)
3736 		 * let the service procedure handle these messages by
3737 		 * calling putq here.
3738 		 */
3739 		(void) putq(wq, mp);
3740 		qenable(wq);
3741 		break;
3742 
3743 	case M_IOCTL:
3744 		fcip_ioctl(wq, mp);
3745 		break;
3746 
3747 	case M_FLUSH:
3748 		if (*mp->b_rptr & FLUSHW) {
3749 			flushq(wq, FLUSHALL);
3750 			*mp->b_rptr &= ~FLUSHW;
3751 		}
3752 		/*
3753 		 * we have both FLUSHW and FLUSHR set with FLUSHRW
3754 		 */
3755 		if (*mp->b_rptr & FLUSHR) {
3756 			/*
3757 			 * send msg back upstream. qreply() takes care
3758 			 * of using the RD(wq) queue on its reply
3759 			 */
3760 			qreply(wq, mp);
3761 		} else {
3762 			freemsg(mp);
3763 		}
3764 		break;
3765 
3766 	default:
3767 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3768 		    (CE_NOTE, "default msg type: %x", DB_TYPE(mp)));
3769 		freemsg(mp);
3770 		break;
3771 	}
3772 	return (0);
3773 }
3774 
3775 
3776 /*
3777  * Handle M_PROTO and M_PCPROTO messages
3778  */
3779 /* ARGSUSED */
3780 static void
3781 fcip_proto(queue_t *wq, mblk_t *mp)
3782 {
3783 	union DL_primitives	*dlp;
3784 	struct fcipstr		*slp;
3785 	t_uscalar_t		prim;
3786 
3787 	slp = (struct fcipstr *)wq->q_ptr;
3788 	dlp = (union DL_primitives *)mp->b_rptr;
3789 	prim = dlp->dl_primitive;		/* the DLPI command */
3790 
3791 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "dl_primitve : %x", prim));
3792 
3793 	mutex_enter(&slp->sl_lock);
3794 
3795 	switch (prim) {
3796 	case DL_UNITDATA_REQ:
3797 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "unit data request"));
3798 		fcip_udreq(wq, mp);
3799 		break;
3800 
3801 	case DL_ATTACH_REQ:
3802 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Attach request"));
3803 		fcip_areq(wq, mp);
3804 		break;
3805 
3806 	case DL_DETACH_REQ:
3807 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Detach request"));
3808 		fcip_dreq(wq, mp);
3809 		break;
3810 
3811 	case DL_BIND_REQ:
3812 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Bind request"));
3813 		fcip_breq(wq, mp);
3814 		break;
3815 
3816 	case DL_UNBIND_REQ:
3817 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "unbind request"));
3818 		fcip_ubreq(wq, mp);
3819 		break;
3820 
3821 	case DL_INFO_REQ:
3822 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "Info request"));
3823 		fcip_ireq(wq, mp);
3824 		break;
3825 
3826 	case DL_SET_PHYS_ADDR_REQ:
3827 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3828 		    (CE_NOTE, "set phy addr request"));
3829 		fcip_spareq(wq, mp);
3830 		break;
3831 
3832 	case DL_PHYS_ADDR_REQ:
3833 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "phy addr request"));
3834 		fcip_pareq(wq, mp);
3835 		break;
3836 
3837 	case DL_ENABMULTI_REQ:
3838 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3839 		    (CE_NOTE, "Enable Multicast request"));
3840 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3841 		break;
3842 
3843 	case DL_DISABMULTI_REQ:
3844 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3845 		    (CE_NOTE, "Disable Multicast request"));
3846 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3847 		break;
3848 
3849 	case DL_PROMISCON_REQ:
3850 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3851 		    (CE_NOTE, "Promiscuous mode ON request"));
3852 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3853 		break;
3854 
3855 	case DL_PROMISCOFF_REQ:
3856 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
3857 		    (CE_NOTE, "Promiscuous mode OFF request"));
3858 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3859 		break;
3860 
3861 	default:
3862 		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
3863 		break;
3864 	}
3865 	mutex_exit(&slp->sl_lock);
3866 }
3867 
3868 /*
3869  * Always enqueue M_PROTO and M_PCPROTO messages pn the wq and M_DATA
3870  * messages sometimes. Processing of M_PROTO and M_PCPROTO messages
3871  * require us to hold fcip's internal locks across (upstream) putnext
3872  * calls. Specifically fcip_intr could hold fcip_intrlock and fcipstruplock
3873  * when it calls putnext(). That thread could loop back around to call
3874  * fcip_wput and eventually fcip_init() to cause a recursive mutex panic
3875  *
3876  * M_DATA messages are enqueued only if we are out of xmit resources. Once
3877  * the transmit resources are available the service procedure is enabled
3878  * and an attempt is made to xmit all messages on the wq.
3879  */
3880 /* ARGSUSED */
3881 static int
3882 fcip_wsrv(queue_t *wq)
3883 {
3884 	mblk_t		*mp;
3885 	struct fcipstr	*slp;
3886 	struct fcip	*fptr;
3887 	struct fcip_dest *fdestp;
3888 	fcph_network_hdr_t *headerp;
3889 
3890 	slp = (struct fcipstr *)wq->q_ptr;
3891 	fptr = slp->sl_fcip;
3892 
3893 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "fcip wsrv"));
3894 
3895 	while (mp = getq(wq)) {
3896 		switch (DB_TYPE(mp)) {
3897 		case M_DATA:
3898 			if (fptr && mp) {
3899 				headerp = (fcph_network_hdr_t *)mp->b_rptr;
3900 				fdestp = fcip_get_dest(fptr,
3901 				    &headerp->net_dest_addr);
3902 				if (fdestp == NULL) {
3903 					freemsg(mp);
3904 					goto done;
3905 				}
3906 				if (fcip_start(wq, mp, fptr, fdestp,
3907 				    KM_SLEEP)) {
3908 					goto done;
3909 				}
3910 			} else {
3911 				freemsg(mp);
3912 			}
3913 			break;
3914 
3915 		case M_PROTO:
3916 		case M_PCPROTO:
3917 			FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3918 			    (CE_NOTE, "PROT msg in wsrv"));
3919 			fcip_proto(wq, mp);
3920 			break;
3921 		default:
3922 			break;
3923 		}
3924 	}
3925 done:
3926 	return (0);
3927 }
3928 
3929 
3930 /*
3931  * This routine is called from fcip_wsrv to send a message downstream
3932  * on the fibre towards its destination. This routine performs the
3933  * actual WWN to D_ID mapping by looking up the routing and destination
3934  * tables.
3935  */
3936 /* ARGSUSED */
3937 static int
3938 fcip_start(queue_t *wq, mblk_t *mp, struct fcip *fptr,
3939     struct fcip_dest *fdestp, int flags)
3940 {
3941 	int			rval;
3942 	int			free;
3943 	fcip_pkt_t		*fcip_pkt;
3944 	fc_packet_t		*fc_pkt;
3945 	fcip_port_info_t	*fport = fptr->fcip_port_info;
3946 	size_t			datalen;
3947 
3948 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "in fcipstart"));
3949 
3950 	ASSERT(fdestp != NULL);
3951 
3952 	/*
3953 	 * Only return if port has gone offline and not come back online
3954 	 * in a while
3955 	 */
3956 	if (fptr->fcip_flags & FCIP_LINK_DOWN) {
3957 		freemsg(mp);
3958 		return (0);
3959 	}
3960 
3961 	/*
3962 	 * The message block coming in here already has the network and
3963 	 * llc_snap hdr stuffed in
3964 	 */
3965 	/*
3966 	 * Traditionally ethernet drivers at sun handle 3 cases here -
3967 	 * 1. messages with one mblk
3968 	 * 2. messages with 2 mblks
3969 	 * 3. messages with >2 mblks
3970 	 * For now lets handle all the 3 cases in a single case where we
3971 	 * put them together in one mblk that has all the data
3972 	 */
3973 
3974 	if (mp->b_cont != NULL) {
3975 		if (!pullupmsg(mp, -1)) {
3976 			FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
3977 			    (CE_WARN, "failed to concat message"));
3978 			freemsg(mp);
3979 			return (1);
3980 		}
3981 	}
3982 
3983 	datalen = msgsize(mp);
3984 
3985 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
3986 	    "msgsize with nhdr & llcsnap hdr in fcip_pkt_alloc 0x%lx",
3987 	    datalen));
3988 
3989 	/*
3990 	 * We cannot have requests larger than FCIPMTU+Headers
3991 	 */
3992 	if (datalen > (FCIPMTU + sizeof (llc_snap_hdr_t) +
3993 		sizeof (fcph_network_hdr_t))) {
3994 		freemsg(mp);
3995 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
3996 		    "fcip_pkt_alloc: datalen is larger than "
3997 		    "max possible size."));
3998 		return (1);
3999 	}
4000 
4001 	fcip_pkt = fcip_pkt_alloc(fptr, mp, flags, datalen);
4002 	if (fcip_pkt == NULL) {
4003 		(void) putbq(wq, mp);
4004 		return (1);
4005 	}
4006 
4007 	fcip_pkt->fcip_pkt_mp = mp;
4008 	fcip_pkt->fcip_pkt_wq = wq;
4009 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
4010 
4011 	mutex_enter(&fdestp->fcipd_mutex);
4012 	/*
4013 	 * If the device dynamically disappeared, just fail the request.
4014 	 */
4015 	if (fdestp->fcipd_rtable == NULL) {
4016 		mutex_exit(&fdestp->fcipd_mutex);
4017 		fcip_pkt_free(fcip_pkt, 1);
4018 		return (1);
4019 	}
4020 
4021 	/*
4022 	 * Now that we've assigned pkt_pd, we can call fc_ulp_init_packet
4023 	 */
4024 
4025 	fc_pkt->pkt_pd = fdestp->fcipd_pd;
4026 
4027 	if (fc_ulp_init_packet((opaque_t)fport->fcipp_handle,
4028 	    fc_pkt, flags) != FC_SUCCESS) {
4029 		mutex_exit(&fdestp->fcipd_mutex);
4030 		fcip_pkt_free(fcip_pkt, 1);
4031 		return (1);
4032 	}
4033 
4034 	fcip_fdestp_enqueue_pkt(fdestp, fcip_pkt);
4035 	fcip_pkt->fcip_pkt_dest = fdestp;
4036 	fc_pkt->pkt_fca_device = fdestp->fcipd_fca_dev;
4037 
4038 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE,
4039 	    "setting cmdlen to 0x%x: rsp 0x%x : data 0x%x",
4040 	    fc_pkt->pkt_cmdlen, fc_pkt->pkt_rsplen, fc_pkt->pkt_datalen));
4041 
4042 	fcip_init_unicast_pkt(fcip_pkt, fport->fcipp_sid,
4043 	    fdestp->fcipd_did, fcip_pkt_callback);
4044 
4045 	fdestp->fcipd_ncmds++;
4046 
4047 	mutex_exit(&fdestp->fcipd_mutex);
4048 	if ((rval = fcip_transport(fcip_pkt)) == FC_SUCCESS) {
4049 		fptr->fcip_opackets++;
4050 		return (0);
4051 	}
4052 
4053 	free = (rval == FC_STATEC_BUSY || rval == FC_OFFLINE ||
4054 	    rval == FC_TRAN_BUSY) ? 0 : 1;
4055 
4056 	mutex_enter(&fdestp->fcipd_mutex);
4057 	rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
4058 
4059 	if (!rval) {
4060 		fcip_pkt = NULL;
4061 	} else {
4062 		fdestp->fcipd_ncmds--;
4063 	}
4064 	mutex_exit(&fdestp->fcipd_mutex);
4065 
4066 	if (fcip_pkt != NULL) {
4067 		fcip_pkt_free(fcip_pkt, free);
4068 	}
4069 
4070 	if (!free) {
4071 		(void) putbq(wq, mp);
4072 	}
4073 
4074 	return (1);
4075 }
4076 
4077 
4078 /*
4079  * This routine enqueus a packet marked to be issued to the
4080  * transport in the dest structure. This enables us to timeout any
4081  * request stuck with the FCA/transport for long periods of time
4082  * without a response. fcip_pkt_timeout will attempt to clean up
4083  * any packets hung in this state of limbo.
4084  */
4085 static void
4086 fcip_fdestp_enqueue_pkt(struct fcip_dest *fdestp, fcip_pkt_t *fcip_pkt)
4087 {
4088 	ASSERT(mutex_owned(&fdestp->fcipd_mutex));
4089 
4090 	/*
4091 	 * Just hang it off the head of packet list
4092 	 */
4093 	fcip_pkt->fcip_pkt_next = fdestp->fcipd_head;
4094 	fcip_pkt->fcip_pkt_prev = NULL;
4095 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
4096 
4097 	if (fdestp->fcipd_head != NULL) {
4098 		ASSERT(fdestp->fcipd_head->fcip_pkt_prev == NULL);
4099 		fdestp->fcipd_head->fcip_pkt_prev = fcip_pkt;
4100 	}
4101 
4102 	fdestp->fcipd_head = fcip_pkt;
4103 }
4104 
4105 
4106 /*
4107  * dequeues any packets after the transport/FCA tells us it has
4108  * been successfully sent on its way. Ofcourse it doesn't mean that
4109  * the packet will actually reach its destination but its atleast
4110  * a step closer in that direction
4111  */
4112 static int
4113 fcip_fdestp_dequeue_pkt(struct fcip_dest *fdestp, fcip_pkt_t *fcip_pkt)
4114 {
4115 	fcip_pkt_t	*fcipd_pkt;
4116 
4117 	ASSERT(mutex_owned(&fdestp->fcipd_mutex));
4118 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_TIMEOUT) {
4119 		fcipd_pkt = fdestp->fcipd_head;
4120 		while (fcipd_pkt) {
4121 			if (fcipd_pkt == fcip_pkt) {
4122 				fcip_pkt_t	*pptr = NULL;
4123 
4124 				if (fcipd_pkt == fdestp->fcipd_head) {
4125 					ASSERT(fcipd_pkt->fcip_pkt_prev ==
4126 					    NULL);
4127 					fdestp->fcipd_head =
4128 					    fcipd_pkt->fcip_pkt_next;
4129 				} else {
4130 					pptr = fcipd_pkt->fcip_pkt_prev;
4131 					ASSERT(pptr != NULL);
4132 					pptr->fcip_pkt_next =
4133 					    fcipd_pkt->fcip_pkt_next;
4134 				}
4135 				if (fcipd_pkt->fcip_pkt_next) {
4136 					pptr = fcipd_pkt->fcip_pkt_next;
4137 					pptr->fcip_pkt_prev =
4138 					    fcipd_pkt->fcip_pkt_prev;
4139 				}
4140 				fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
4141 				break;
4142 			}
4143 			fcipd_pkt = fcipd_pkt->fcip_pkt_next;
4144 		}
4145 	} else {
4146 		if (fcip_pkt->fcip_pkt_prev == NULL) {
4147 			ASSERT(fdestp->fcipd_head == fcip_pkt);
4148 			fdestp->fcipd_head = fcip_pkt->fcip_pkt_next;
4149 		} else {
4150 			fcip_pkt->fcip_pkt_prev->fcip_pkt_next =
4151 			    fcip_pkt->fcip_pkt_next;
4152 		}
4153 
4154 		if (fcip_pkt->fcip_pkt_next) {
4155 			fcip_pkt->fcip_pkt_next->fcip_pkt_prev =
4156 			    fcip_pkt->fcip_pkt_prev;
4157 		}
4158 
4159 		fcipd_pkt = fcip_pkt;
4160 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
4161 	}
4162 
4163 	return (fcipd_pkt == fcip_pkt);
4164 }
4165 
4166 /*
4167  * The transport routine - this is the routine that actually calls
4168  * into the FCA driver (through the transport ofcourse) to transmit a
4169  * datagram on the fibre. The dest struct assoicated with the port to
4170  * which the data is intended is already bound to the packet, this routine
4171  * only takes care of marking the packet a broadcast packet if it is
4172  * intended to be a broadcast request. This permits the transport to send
4173  * the packet down on the wire even if it doesn't have an entry for the
4174  * D_ID in its d_id hash tables.
4175  */
4176 static int
4177 fcip_transport(fcip_pkt_t *fcip_pkt)
4178 {
4179 	struct fcip		*fptr;
4180 	fc_packet_t		*fc_pkt;
4181 	fcip_port_info_t	*fport;
4182 	struct fcip_dest	*fdestp;
4183 	uint32_t		did;
4184 	int			rval = FC_FAILURE;
4185 	struct fcip_routing_table *frp = NULL;
4186 
4187 	fptr = fcip_pkt->fcip_pkt_fptr;
4188 	fport = fptr->fcip_port_info;
4189 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
4190 	fdestp = fcip_pkt->fcip_pkt_dest;
4191 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN, "fcip_transport called"));
4192 
4193 	did = fptr->fcip_broadcast_did;
4194 	if (fc_pkt->pkt_cmd_fhdr.d_id == did &&
4195 	    fc_pkt->pkt_tran_type != FC_PKT_BROADCAST) {
4196 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4197 		    (CE_NOTE, "trantype set to BROADCAST"));
4198 		fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
4199 	}
4200 
4201 	mutex_enter(&fptr->fcip_mutex);
4202 	if ((fc_pkt->pkt_tran_type != FC_PKT_BROADCAST) &&
4203 	    (fc_pkt->pkt_pd == NULL)) {
4204 		mutex_exit(&fptr->fcip_mutex);
4205 		return (rval);
4206 	} else if (fptr->fcip_port_state == FCIP_PORT_OFFLINE) {
4207 		mutex_exit(&fptr->fcip_mutex);
4208 		return (FC_TRAN_BUSY);
4209 	}
4210 	mutex_exit(&fptr->fcip_mutex);
4211 
4212 	if (fdestp) {
4213 		struct fcip_routing_table 	*frp;
4214 
4215 		frp = fdestp->fcipd_rtable;
4216 		mutex_enter(&fptr->fcip_rt_mutex);
4217 		mutex_enter(&fdestp->fcipd_mutex);
4218 		if (fc_pkt->pkt_pd != NULL) {
4219 			if ((frp == NULL) ||
4220 			    (frp && FCIP_RTE_UNAVAIL(frp->fcipr_state))) {
4221 				mutex_exit(&fdestp->fcipd_mutex);
4222 				mutex_exit(&fptr->fcip_rt_mutex);
4223 				if (frp &&
4224 				    (frp->fcipr_state == FCIP_RT_INVALID)) {
4225 					return (FC_TRAN_BUSY);
4226 				} else {
4227 					return (rval);
4228 				}
4229 			}
4230 		}
4231 		mutex_exit(&fdestp->fcipd_mutex);
4232 		mutex_exit(&fptr->fcip_rt_mutex);
4233 		ASSERT(fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_LIST);
4234 	}
4235 
4236 	/* Explicitly invalidate this field till fcip decides to use it */
4237 	fc_pkt->pkt_ulp_rscn_infop = NULL;
4238 
4239 	rval = fc_ulp_transport(fport->fcipp_handle, fc_pkt);
4240 	if (rval == FC_STATEC_BUSY || rval == FC_OFFLINE) {
4241 		/*
4242 		 * Need to queue up the command for retry
4243 		 */
4244 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
4245 		    (CE_WARN, "ulp_transport failed: 0x%x", rval));
4246 	} else if (rval == FC_LOGINREQ && (frp != NULL)) {
4247 		(void) fcip_do_plogi(fptr, frp);
4248 	} else if (rval == FC_BADPACKET && (frp != NULL)) {
4249 		/*
4250 		 * There is a distinct possiblity in our scheme of things
4251 		 * that we have a routing table entry with a NULL pd struct.
4252 		 * Mark the routing table entry for removal if it is not a
4253 		 * broadcast entry
4254 		 */
4255 		if ((frp->fcipr_d_id.port_id != 0x0) &&
4256 		    (frp->fcipr_d_id.port_id != 0xffffff)) {
4257 			mutex_enter(&fptr->fcip_rt_mutex);
4258 			frp->fcipr_pd = NULL;
4259 			frp->fcipr_state = PORT_DEVICE_INVALID;
4260 			mutex_exit(&fptr->fcip_rt_mutex);
4261 		}
4262 	}
4263 
4264 	return (rval);
4265 }
4266 
4267 /*
4268  * Call back routine. Called by the FCA/transport when the messages
4269  * has been put onto the wire towards its intended destination. We can
4270  * now free the fc_packet associated with the message
4271  */
4272 static void
4273 fcip_pkt_callback(fc_packet_t *fc_pkt)
4274 {
4275 	int			rval;
4276 	fcip_pkt_t		*fcip_pkt;
4277 	struct fcip_dest	*fdestp;
4278 
4279 	fcip_pkt = (fcip_pkt_t *)fc_pkt->pkt_ulp_private;
4280 	fdestp = fcip_pkt->fcip_pkt_dest;
4281 
4282 	/*
4283 	 * take the lock early so that we don't have a race condition
4284 	 * with fcip_timeout
4285 	 *
4286 	 * fdestp->fcipd_mutex isn't really intended to lock per
4287 	 * packet struct - see bug 5105592 for permanent solution
4288 	 */
4289 	mutex_enter(&fdestp->fcipd_mutex);
4290 
4291 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_RETURNED;
4292 	fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
4293 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_TIMEOUT) {
4294 		mutex_exit(&fdestp->fcipd_mutex);
4295 		return;
4296 	}
4297 
4298 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "pkt callback"));
4299 
4300 	ASSERT(fdestp->fcipd_rtable != NULL);
4301 	ASSERT(fcip_pkt->fcip_pkt_flags & FCIP_PKT_IN_LIST);
4302 	rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
4303 	fdestp->fcipd_ncmds--;
4304 	mutex_exit(&fdestp->fcipd_mutex);
4305 
4306 	if (rval) {
4307 		fcip_pkt_free(fcip_pkt, 1);
4308 	}
4309 
4310 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_NOTE, "pkt callback done"));
4311 }
4312 
4313 /*
4314  * Return 1 if the topology is supported, else return 0.
4315  * Topology support is consistent with what the whole
4316  * stack supports together.
4317  */
4318 static int
4319 fcip_is_supported_fc_topology(int fc_topology)
4320 {
4321 	switch (fc_topology) {
4322 
4323 	case FC_TOP_PRIVATE_LOOP :
4324 	case FC_TOP_PUBLIC_LOOP :
4325 	case FC_TOP_FABRIC :
4326 	case FC_TOP_NO_NS :
4327 		return (1);
4328 	default :
4329 		return (0);
4330 	}
4331 }
4332 
4333 /*
4334  * handle any topology specific initializations here
4335  * this routine must be called while holding fcip_mutex
4336  */
4337 /* ARGSUSED */
4338 static void
4339 fcip_handle_topology(struct fcip *fptr)
4340 {
4341 
4342 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4343 
4344 	ASSERT(mutex_owned(&fptr->fcip_mutex));
4345 
4346 	/*
4347 	 * Since we know the port's topology - handle topology
4348 	 * specific details here. In Point to Point and Private Loop
4349 	 * topologies - we would probably not have a name server
4350 	 */
4351 
4352 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "port state: %x, topology %x",
4353 		fport->fcipp_pstate, fport->fcipp_topology));
4354 
4355 	fptr->fcip_broadcast_did = fcip_get_broadcast_did(fptr);
4356 	mutex_exit(&fptr->fcip_mutex);
4357 	(void) fcip_dest_add_broadcast_entry(fptr, 0);
4358 	mutex_enter(&fptr->fcip_mutex);
4359 
4360 	if (!fcip_is_supported_fc_topology(fport->fcipp_topology)) {
4361 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4362 		    (CE_WARN, "fcip(0x%x): Unsupported port topology (0x%x)",
4363 		    fptr->fcip_instance, fport->fcipp_topology));
4364 		return;
4365 	}
4366 
4367 	switch (fport->fcipp_topology) {
4368 	case FC_TOP_PRIVATE_LOOP: {
4369 
4370 		fc_portmap_t		*port_map;
4371 		uint32_t		listlen, alloclen;
4372 		/*
4373 		 * we may have to maintain routing. Get a list of
4374 		 * all devices on this port that the transport layer is
4375 		 * aware of. Check if any of them is a IS8802 type port,
4376 		 * if yes get its WWN and DID mapping and cache it in
4377 		 * the purport routing table. Since there is no
4378 		 * State Change notification for private loop/point_point
4379 		 * topologies - this table may not be accurate. The static
4380 		 * routing table is updated on a state change callback.
4381 		 */
4382 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN, "port state valid!!"));
4383 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
4384 		listlen = alloclen = FCIP_MAX_PORTS;
4385 		port_map = (fc_portmap_t *)
4386 		    kmem_zalloc((FCIP_MAX_PORTS * sizeof (fc_portmap_t)),
4387 		    KM_SLEEP);
4388 		if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
4389 		    &listlen, FC_ULP_PLOGI_PRESERVE) == FC_SUCCESS) {
4390 			mutex_exit(&fptr->fcip_mutex);
4391 			fcip_rt_update(fptr, port_map, listlen);
4392 			mutex_enter(&fptr->fcip_mutex);
4393 		}
4394 		if (listlen > alloclen) {
4395 			alloclen = listlen;
4396 		}
4397 		kmem_free(port_map, (alloclen * sizeof (fc_portmap_t)));
4398 		/*
4399 		 * Now fall through and register with the transport
4400 		 * that this port is IP capable
4401 		 */
4402 	}
4403 	/* FALLTHROUGH */
4404 	case FC_TOP_NO_NS:
4405 		/*
4406 		 * If we don't have a nameserver, lets wait until we
4407 		 * have to send out a packet to a remote port and then
4408 		 * try and discover the port using ARP/FARP.
4409 		 */
4410 	/* FALLTHROUGH */
4411 	case FC_TOP_PUBLIC_LOOP:
4412 	case FC_TOP_FABRIC: {
4413 		fc_portmap_t	*port_map;
4414 		uint32_t	listlen, alloclen;
4415 
4416 		/* FC_TYPE of 0x05 goes to word 0, LSB */
4417 		fptr->fcip_port_state = FCIP_PORT_ONLINE;
4418 
4419 		if (!(fptr->fcip_flags & FCIP_REG_INPROGRESS)) {
4420 			fptr->fcip_flags |= FCIP_REG_INPROGRESS;
4421 			if (taskq_dispatch(fptr->fcip_tq, fcip_port_ns,
4422 			    fptr, KM_NOSLEEP) == TASKQID_INVALID) {
4423 				fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4424 			}
4425 		}
4426 
4427 		/*
4428 		 * If fcip_create_nodes_on_demand is overridden to force
4429 		 * discovery of all nodes in Fabric/Public loop topologies
4430 		 * we need to query for and obtain all nodes and log into
4431 		 * them as with private loop devices
4432 		 */
4433 		if (!fcip_create_nodes_on_demand) {
4434 			fptr->fcip_port_state = FCIP_PORT_ONLINE;
4435 			listlen = alloclen = FCIP_MAX_PORTS;
4436 			port_map = (fc_portmap_t *)
4437 			    kmem_zalloc((FCIP_MAX_PORTS *
4438 			    sizeof (fc_portmap_t)), KM_SLEEP);
4439 			if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
4440 			    &listlen, FC_ULP_PLOGI_PRESERVE) == FC_SUCCESS) {
4441 				mutex_exit(&fptr->fcip_mutex);
4442 				fcip_rt_update(fptr, port_map, listlen);
4443 				mutex_enter(&fptr->fcip_mutex);
4444 			}
4445 			if (listlen > alloclen) {
4446 				alloclen = listlen;
4447 			}
4448 			kmem_free(port_map,
4449 			    (alloclen * sizeof (fc_portmap_t)));
4450 		}
4451 		break;
4452 	}
4453 
4454 	default:
4455 		break;
4456 	}
4457 }
4458 
4459 static void
4460 fcip_port_ns(void *arg)
4461 {
4462 	struct	fcip		*fptr = (struct fcip *)arg;
4463 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4464 	fc_ns_cmd_t		ns_cmd;
4465 	uint32_t		types[8];
4466 	ns_rfc_type_t		rfc;
4467 
4468 	mutex_enter(&fptr->fcip_mutex);
4469 	if ((fptr->fcip_flags & (FCIP_DETACHING | FCIP_DETACHED)) ||
4470 	    (fptr->fcip_flags & (FCIP_SUSPENDED | FCIP_POWER_DOWN))) {
4471 		fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4472 		mutex_exit(&fptr->fcip_mutex);
4473 		return;
4474 	}
4475 	mutex_exit(&fptr->fcip_mutex);
4476 
4477 	/*
4478 	 * Prepare the Name server structure to
4479 	 * register with the transport in case of
4480 	 * Fabric configuration.
4481 	 */
4482 	bzero(&rfc, sizeof (rfc));
4483 	bzero(types, sizeof (types));
4484 
4485 	types[FC4_TYPE_WORD_POS(FC_TYPE_IS8802_SNAP)] = (1 <<
4486 	    FC4_TYPE_BIT_POS(FC_TYPE_IS8802_SNAP));
4487 
4488 	rfc.rfc_port_id.port_id = fport->fcipp_sid.port_id;
4489 	bcopy(types, rfc.rfc_types, sizeof (types));
4490 
4491 	ns_cmd.ns_flags = 0;
4492 	ns_cmd.ns_cmd = NS_RFT_ID;
4493 	ns_cmd.ns_req_len = sizeof (rfc);
4494 	ns_cmd.ns_req_payload = (caddr_t)&rfc;
4495 	ns_cmd.ns_resp_len = 0;
4496 	ns_cmd.ns_resp_payload = NULL;
4497 
4498 	/*
4499 	 * Perform the Name Server Registration for FC IS8802_SNAP Type.
4500 	 * We don't expect a reply for registering port type
4501 	 */
4502 	(void) fc_ulp_port_ns(fptr->fcip_port_info->fcipp_handle,
4503 		(opaque_t)0, &ns_cmd);
4504 
4505 	mutex_enter(&fptr->fcip_mutex);
4506 	fptr->fcip_flags &= ~FCIP_REG_INPROGRESS;
4507 	mutex_exit(&fptr->fcip_mutex);
4508 }
4509 
4510 /*
4511  * setup this instance of fcip. This routine inits kstats, allocates
4512  * unsolicited buffers, determines' this port's siblings and handles
4513  * topology specific details which includes registering with the name
4514  * server and also setting up the routing table for this port for
4515  * private loops and point to point topologies
4516  */
4517 static int
4518 fcip_init_port(struct fcip *fptr)
4519 {
4520 	int rval = FC_SUCCESS;
4521 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4522 	static char buf[64];
4523 	size_t	tok_buf_size = 0;
4524 
4525 	ASSERT(fport != NULL);
4526 
4527 	mutex_enter(&fptr->fcip_mutex);
4528 
4529 	/*
4530 	 * setup mac address for this port. Don't be too worried if
4531 	 * the WWN is zero, there is probably nothing attached to
4532 	 * to the port. There is no point allocating unsolicited buffers
4533 	 * for an unused port so return success if we don't have a MAC
4534 	 * address. Do the port init on a state change notification.
4535 	 */
4536 	if (fcip_setup_mac_addr(fptr) == FCIP_INVALID_WWN) {
4537 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
4538 		rval = FC_SUCCESS;
4539 		goto done;
4540 	}
4541 
4542 	/*
4543 	 * clear routing table hash list for this port
4544 	 */
4545 	fcip_rt_flush(fptr);
4546 
4547 	/*
4548 	 * init kstats for this instance
4549 	 */
4550 	fcip_kstat_init(fptr);
4551 
4552 	/*
4553 	 * Allocate unsolicited buffers
4554 	 */
4555 	fptr->fcip_ub_nbufs = fcip_ub_nbufs;
4556 	tok_buf_size = sizeof (*fptr->fcip_ub_tokens) * fcip_ub_nbufs;
4557 
4558 	FCIP_DEBUG(FCIP_DEBUG_INIT,
4559 	    (CE_WARN, "tokBufsize: 0x%lx", tok_buf_size));
4560 
4561 	fptr->fcip_ub_tokens = kmem_zalloc(tok_buf_size, KM_SLEEP);
4562 
4563 	if (fptr->fcip_ub_tokens == NULL) {
4564 		rval = FC_FAILURE;
4565 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4566 		    (CE_WARN, "fcip(%d): failed to allocate unsol buf",
4567 		    fptr->fcip_instance));
4568 		goto done;
4569 	}
4570 	rval = fc_ulp_uballoc(fport->fcipp_handle, &fptr->fcip_ub_nbufs,
4571 		fcip_ub_size, FC_TYPE_IS8802_SNAP, fptr->fcip_ub_tokens);
4572 
4573 	if (rval != FC_SUCCESS) {
4574 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4575 		    (CE_WARN, "fcip(%d): fc_ulp_uballoc failed with 0x%x!!",
4576 		    fptr->fcip_instance, rval));
4577 	}
4578 
4579 	switch (rval) {
4580 	case FC_SUCCESS:
4581 		break;
4582 
4583 	case FC_OFFLINE:
4584 		fptr->fcip_port_state = FCIP_PORT_OFFLINE;
4585 		rval = FC_FAILURE;
4586 		goto done;
4587 
4588 	case FC_UB_ERROR:
4589 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4590 		    (CE_WARN, "invalid ub alloc request !!"));
4591 		rval = FC_FAILURE;
4592 		goto done;
4593 
4594 	case FC_FAILURE:
4595 		/*
4596 		 * requested bytes could not be alloced
4597 		 */
4598 		if (fptr->fcip_ub_nbufs != fcip_ub_nbufs) {
4599 			cmn_err(CE_WARN,
4600 			    "!fcip(0x%x): Failed to alloc unsolicited bufs",
4601 			    ddi_get_instance(fport->fcipp_dip));
4602 			rval = FC_FAILURE;
4603 			goto done;
4604 		}
4605 		break;
4606 
4607 	default:
4608 		rval = FC_FAILURE;
4609 		break;
4610 	}
4611 
4612 	/*
4613 	 * Preallocate a Cache of fcip packets for transmit and receive
4614 	 * We don't want to be holding on to unsolicited buffers while
4615 	 * we transmit the message upstream
4616 	 */
4617 	FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE, "allocating fcip_pkt cache"));
4618 
4619 	(void) sprintf(buf, "fcip%d_cache", fptr->fcip_instance);
4620 	fptr->fcip_xmit_cache = kmem_cache_create(buf,
4621 		(fport->fcipp_fca_pkt_size + sizeof (fcip_pkt_t)),
4622 		8, fcip_cache_constructor, fcip_cache_destructor,
4623 		NULL, (void *)fport, NULL, 0);
4624 
4625 	(void) sprintf(buf, "fcip%d_sendup_cache", fptr->fcip_instance);
4626 	fptr->fcip_sendup_cache = kmem_cache_create(buf,
4627 		sizeof (struct fcip_sendup_elem),
4628 		8, fcip_sendup_constructor, NULL, NULL, (void *)fport, NULL, 0);
4629 
4630 	if (fptr->fcip_xmit_cache == NULL) {
4631 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4632 		    (CE_WARN, "fcip%d unable to allocate xmit cache",
4633 		    fptr->fcip_instance));
4634 		rval = FC_FAILURE;
4635 		goto done;
4636 	}
4637 
4638 	/*
4639 	 * We may need to handle routing tables for point to point and
4640 	 * fcal topologies and register with NameServer for Fabric
4641 	 * topologies.
4642 	 */
4643 	fcip_handle_topology(fptr);
4644 	mutex_exit(&fptr->fcip_mutex);
4645 	if (fcip_dest_add_broadcast_entry(fptr, 1) != FC_SUCCESS) {
4646 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4647 		    (CE_WARN, "fcip(0x%x):add broadcast entry failed!!",
4648 		    fptr->fcip_instance));
4649 		mutex_enter(&fptr->fcip_mutex);
4650 		rval = FC_FAILURE;
4651 		goto done;
4652 	}
4653 
4654 	rval = FC_SUCCESS;
4655 	return (rval);
4656 
4657 done:
4658 	/*
4659 	 * we don't always come here from port_attach - so cleanup
4660 	 * anything done in the init_port routine
4661 	 */
4662 	if (fptr->fcip_kstatp) {
4663 		kstat_delete(fptr->fcip_kstatp);
4664 		fptr->fcip_kstatp = NULL;
4665 	}
4666 
4667 	if (fptr->fcip_xmit_cache) {
4668 		kmem_cache_destroy(fptr->fcip_xmit_cache);
4669 		fptr->fcip_xmit_cache = NULL;
4670 	}
4671 
4672 	if (fptr->fcip_sendup_cache) {
4673 		kmem_cache_destroy(fptr->fcip_sendup_cache);
4674 		fptr->fcip_sendup_cache = NULL;
4675 	}
4676 
4677 	/* release unsolicited buffers */
4678 	if (fptr->fcip_ub_tokens) {
4679 		uint64_t	*tokens = fptr->fcip_ub_tokens;
4680 		fptr->fcip_ub_tokens = NULL;
4681 
4682 		mutex_exit(&fptr->fcip_mutex);
4683 		(void) fc_ulp_ubfree(fport->fcipp_handle, fptr->fcip_ub_nbufs,
4684 			tokens);
4685 		kmem_free(tokens, tok_buf_size);
4686 
4687 	} else {
4688 		mutex_exit(&fptr->fcip_mutex);
4689 	}
4690 
4691 	return (rval);
4692 }
4693 
4694 /*
4695  * Sets up a port's MAC address from its WWN
4696  */
4697 static int
4698 fcip_setup_mac_addr(struct fcip *fptr)
4699 {
4700 	fcip_port_info_t	*fport = fptr->fcip_port_info;
4701 
4702 	ASSERT(mutex_owned(&fptr->fcip_mutex));
4703 
4704 	fptr->fcip_addrflags = 0;
4705 
4706 	/*
4707 	 * we cannot choose a MAC address for our interface - we have
4708 	 * to live with whatever node WWN we get (minus the top two
4709 	 * MSbytes for the MAC address) from the transport layer. We will
4710 	 * treat the WWN as our factory MAC address.
4711 	 */
4712 
4713 	if ((fport->fcipp_nwwn.w.wwn_hi != 0) ||
4714 	    (fport->fcipp_nwwn.w.wwn_lo != 0)) {
4715 		char		etherstr[ETHERSTRL];
4716 
4717 		wwn_to_ether(&fport->fcipp_nwwn, &fptr->fcip_macaddr);
4718 		fcip_ether_to_str(&fptr->fcip_macaddr, etherstr);
4719 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4720 		    (CE_NOTE, "setupmacaddr ouraddr %s", etherstr));
4721 
4722 		fptr->fcip_addrflags = (FCIP_FACTADDR_PRESENT |
4723 						FCIP_FACTADDR_USE);
4724 	} else {
4725 		/*
4726 		 * No WWN - just return failure - there's not much
4727 		 * we can do since we cannot set the WWN.
4728 		 */
4729 		FCIP_DEBUG(FCIP_DEBUG_INIT,
4730 		    (CE_WARN, "Port does not have a valid WWN"));
4731 		return (FCIP_INVALID_WWN);
4732 	}
4733 	return (FC_SUCCESS);
4734 }
4735 
4736 
4737 /*
4738  * flush routing table entries
4739  */
4740 static void
4741 fcip_rt_flush(struct fcip *fptr)
4742 {
4743 	int index;
4744 
4745 	mutex_enter(&fptr->fcip_rt_mutex);
4746 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
4747 		struct fcip_routing_table 	*frtp, *frtp_next;
4748 		frtp = fptr->fcip_rtable[index];
4749 		while (frtp) {
4750 			frtp_next = frtp->fcipr_next;
4751 			kmem_free(frtp, sizeof (struct fcip_routing_table));
4752 			frtp = frtp_next;
4753 		}
4754 		fptr->fcip_rtable[index] = NULL;
4755 	}
4756 	mutex_exit(&fptr->fcip_rt_mutex);
4757 }
4758 
4759 /*
4760  * Free up the fcip softstate and all allocated resources for the
4761  * fcip instance assoicated with a given port driver instance
4762  *
4763  * Given that the list of structures pointed to by fcip_port_head,
4764  * this function is called from multiple sources, and the
4765  * fcip_global_mutex that protects fcip_port_head must be dropped,
4766  * our best solution is to return a value that indicates the next
4767  * port in the list.  This way the caller doesn't need to worry
4768  * about the race condition where it saves off a pointer to the
4769  * next structure in the list and by the time this routine returns,
4770  * that next structure has already been freed.
4771  */
4772 static fcip_port_info_t *
4773 fcip_softstate_free(fcip_port_info_t *fport)
4774 {
4775 	struct fcip		*fptr = NULL;
4776 	int 			instance;
4777 	timeout_id_t		tid;
4778 	opaque_t		phandle = NULL;
4779 	fcip_port_info_t	*prev_fport, *cur_fport, *next_fport = NULL;
4780 
4781 	ASSERT(MUTEX_HELD(&fcip_global_mutex));
4782 
4783 	if (fport) {
4784 		phandle = fport->fcipp_handle;
4785 		fptr = fport->fcipp_fcip;
4786 	} else {
4787 		return (next_fport);
4788 	}
4789 
4790 	if (fptr) {
4791 		mutex_enter(&fptr->fcip_mutex);
4792 		instance = ddi_get_instance(fptr->fcip_dip);
4793 
4794 		/*
4795 		 * dismantle timeout thread for this instance of fcip
4796 		 */
4797 		tid = fptr->fcip_timeout_id;
4798 		fptr->fcip_timeout_id = NULL;
4799 
4800 		mutex_exit(&fptr->fcip_mutex);
4801 		(void) untimeout(tid);
4802 		mutex_enter(&fptr->fcip_mutex);
4803 
4804 		ASSERT(fcip_num_instances >= 0);
4805 		fcip_num_instances--;
4806 
4807 		/*
4808 		 * stop sendup thread
4809 		 */
4810 		mutex_enter(&fptr->fcip_sendup_mutex);
4811 		if (fptr->fcip_sendup_thr_initted) {
4812 			fptr->fcip_sendup_thr_initted = 0;
4813 			cv_signal(&fptr->fcip_sendup_cv);
4814 			cv_wait(&fptr->fcip_sendup_cv,
4815 			    &fptr->fcip_sendup_mutex);
4816 		}
4817 		ASSERT(fptr->fcip_sendup_head == NULL);
4818 		fptr->fcip_sendup_head = fptr->fcip_sendup_tail = NULL;
4819 		mutex_exit(&fptr->fcip_sendup_mutex);
4820 
4821 		/*
4822 		 * dismantle taskq
4823 		 */
4824 		if (fptr->fcip_tq) {
4825 			taskq_t	*tq = fptr->fcip_tq;
4826 
4827 			fptr->fcip_tq = NULL;
4828 
4829 			mutex_exit(&fptr->fcip_mutex);
4830 			taskq_destroy(tq);
4831 			mutex_enter(&fptr->fcip_mutex);
4832 		}
4833 
4834 		if (fptr->fcip_kstatp) {
4835 			kstat_delete(fptr->fcip_kstatp);
4836 			fptr->fcip_kstatp = NULL;
4837 		}
4838 
4839 		/* flush the routing table entries */
4840 		fcip_rt_flush(fptr);
4841 
4842 		if (fptr->fcip_xmit_cache) {
4843 			kmem_cache_destroy(fptr->fcip_xmit_cache);
4844 			fptr->fcip_xmit_cache = NULL;
4845 		}
4846 
4847 		if (fptr->fcip_sendup_cache) {
4848 			kmem_cache_destroy(fptr->fcip_sendup_cache);
4849 			fptr->fcip_sendup_cache = NULL;
4850 		}
4851 
4852 		fcip_cleanup_dest(fptr);
4853 
4854 		/* release unsolicited buffers */
4855 		if (fptr->fcip_ub_tokens) {
4856 			uint64_t	*tokens = fptr->fcip_ub_tokens;
4857 
4858 			fptr->fcip_ub_tokens = NULL;
4859 			mutex_exit(&fptr->fcip_mutex);
4860 			if (phandle) {
4861 				/*
4862 				 * release the global mutex here to
4863 				 * permit any data pending callbacks to
4864 				 * complete. Else we will deadlock in the
4865 				 * FCA waiting for all unsol buffers to be
4866 				 * returned.
4867 				 */
4868 				mutex_exit(&fcip_global_mutex);
4869 				(void) fc_ulp_ubfree(phandle,
4870 				    fptr->fcip_ub_nbufs, tokens);
4871 				mutex_enter(&fcip_global_mutex);
4872 			}
4873 			kmem_free(tokens, (sizeof (*tokens) * fcip_ub_nbufs));
4874 		} else {
4875 			mutex_exit(&fptr->fcip_mutex);
4876 		}
4877 
4878 		mutex_destroy(&fptr->fcip_mutex);
4879 		mutex_destroy(&fptr->fcip_ub_mutex);
4880 		mutex_destroy(&fptr->fcip_rt_mutex);
4881 		mutex_destroy(&fptr->fcip_dest_mutex);
4882 		mutex_destroy(&fptr->fcip_sendup_mutex);
4883 		cv_destroy(&fptr->fcip_farp_cv);
4884 		cv_destroy(&fptr->fcip_sendup_cv);
4885 		cv_destroy(&fptr->fcip_ub_cv);
4886 
4887 		ddi_soft_state_free(fcip_softp, instance);
4888 	}
4889 
4890 	/*
4891 	 * Now dequeue the fcip_port_info from the port list
4892 	 */
4893 	cur_fport = fcip_port_head;
4894 	prev_fport = NULL;
4895 	while (cur_fport != NULL) {
4896 		if (cur_fport == fport) {
4897 			break;
4898 		}
4899 		prev_fport = cur_fport;
4900 		cur_fport = cur_fport->fcipp_next;
4901 	}
4902 
4903 	/*
4904 	 * Assert that we found a port in our port list
4905 	 */
4906 	ASSERT(cur_fport == fport);
4907 
4908 	if (prev_fport) {
4909 		/*
4910 		 * Not the first port in the port list
4911 		 */
4912 		prev_fport->fcipp_next = fport->fcipp_next;
4913 	} else {
4914 		/*
4915 		 * first port
4916 		 */
4917 		fcip_port_head = fport->fcipp_next;
4918 	}
4919 	next_fport = fport->fcipp_next;
4920 	kmem_free(fport, sizeof (fcip_port_info_t));
4921 
4922 	return (next_fport);
4923 }
4924 
4925 
4926 /*
4927  * This is called by transport for any ioctl operations performed
4928  * on the devctl or other transport minor nodes. It is currently
4929  * unused for fcip
4930  */
4931 /* ARGSUSED */
4932 static int
4933 fcip_port_ioctl(opaque_t ulp_handle,  opaque_t port_handle, dev_t dev,
4934 	int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
4935 	uint32_t claimed)
4936 {
4937 	return (FC_UNCLAIMED);
4938 }
4939 
4940 /*
4941  * DL_INFO_REQ - returns information about the DLPI stream to the DLS user
4942  * requesting information about this interface
4943  */
4944 static void
4945 fcip_ireq(queue_t *wq, mblk_t *mp)
4946 {
4947 	struct fcipstr		*slp;
4948 	struct fcip		*fptr;
4949 	dl_info_ack_t		*dlip;
4950 	struct fcipdladdr	*dlap;
4951 	la_wwn_t		*ep;
4952 	int 			size;
4953 	char			etherstr[ETHERSTRL];
4954 
4955 	slp = (struct fcipstr *)wq->q_ptr;
4956 
4957 	fptr = slp->sl_fcip;
4958 
4959 	FCIP_DEBUG(FCIP_DEBUG_DLPI,
4960 	    (CE_NOTE, "fcip_ireq: info request req rcvd"));
4961 
4962 	if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
4963 		dlerrorack(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
4964 		return;
4965 	}
4966 
4967 	/*
4968 	 * Exchange current message for a DL_INFO_ACK
4969 	 */
4970 	size = sizeof (dl_info_ack_t) + FCIPADDRL + ETHERADDRL;
4971 	if ((mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL) {
4972 		return;
4973 	}
4974 
4975 	/*
4976 	 * FILL in the DL_INFO_ACK fields and reply
4977 	 */
4978 	dlip = (dl_info_ack_t *)mp->b_rptr;
4979 	*dlip = fcip_infoack;
4980 	dlip->dl_current_state = slp->sl_state;
4981 	dlap = (struct fcipdladdr *)(mp->b_rptr + dlip->dl_addr_offset);
4982 	dlap->dl_sap = slp->sl_sap;
4983 
4984 
4985 	if (fptr) {
4986 		fcip_ether_to_str(&fptr->fcip_macaddr, etherstr);
4987 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
4988 		    (CE_NOTE, "ireq - our mac: %s", etherstr));
4989 		ether_bcopy(&fptr->fcip_macaddr, &dlap->dl_phys);
4990 	} else {
4991 		bzero((caddr_t)&dlap->dl_phys, ETHERADDRL);
4992 	}
4993 
4994 	ep = (la_wwn_t *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
4995 	ether_bcopy(&fcip_arpbroadcast_addr, ep);
4996 
4997 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "sending back info req.."));
4998 	qreply(wq, mp);
4999 }
5000 
5001 
5002 /*
5003  * To handle DL_UNITDATA_REQ requests.
5004  */
5005 
5006 static void
5007 fcip_udreq(queue_t *wq, mblk_t *mp)
5008 {
5009 	struct fcipstr		*slp;
5010 	struct fcip		*fptr;
5011 	fcip_port_info_t	*fport;
5012 	dl_unitdata_req_t	*dludp;
5013 	mblk_t			*nmp;
5014 	struct fcipdladdr	*dlap;
5015 	fcph_network_hdr_t 	*headerp;
5016 	llc_snap_hdr_t		*lsnap;
5017 	t_uscalar_t		off, len;
5018 	struct fcip_dest	*fdestp;
5019 	la_wwn_t		wwn;
5020 	int			hdr_size;
5021 
5022 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "inside fcip_udreq"));
5023 
5024 	slp = (struct fcipstr *)wq->q_ptr;
5025 
5026 	if (slp->sl_state != DL_IDLE) {
5027 		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
5028 		return;
5029 	}
5030 
5031 	fptr = slp->sl_fcip;
5032 
5033 	if (fptr == NULL) {
5034 		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
5035 		return;
5036 	}
5037 
5038 	fport = fptr->fcip_port_info;
5039 
5040 	dludp = (dl_unitdata_req_t *)mp->b_rptr;
5041 	off = dludp->dl_dest_addr_offset;
5042 	len = dludp->dl_dest_addr_length;
5043 
5044 	/*
5045 	 * Validate destination address format
5046 	 */
5047 	if (!MBLKIN(mp, off, len) || (len != FCIPADDRL)) {
5048 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADADDR, 0);
5049 		return;
5050 	}
5051 
5052 	/*
5053 	 * Error if no M_DATA follows
5054 	 */
5055 	nmp = mp->b_cont;
5056 	if (nmp == NULL) {
5057 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADDATA, 0);
5058 		return;
5059 	}
5060 	dlap = (struct fcipdladdr *)(mp->b_rptr + off);
5061 
5062 	/*
5063 	 * Now get the destination structure for the remote NPORT
5064 	 */
5065 	ether_to_wwn(&dlap->dl_phys, &wwn);
5066 	fdestp = fcip_get_dest(fptr, &wwn);
5067 
5068 	if (fdestp == NULL) {
5069 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE,
5070 		    "udreq - couldn't find dest struct for remote port"));
5071 		dluderrorind(wq, mp, (mp->b_rptr + off), len, DL_BADDATA, 0);
5072 		return;
5073 	}
5074 
5075 	/*
5076 	 * Network header + SAP
5077 	 */
5078 	hdr_size = sizeof (fcph_network_hdr_t) + sizeof (llc_snap_hdr_t);
5079 
5080 	/* DB_REF gives the no. of msgs pointing to this block */
5081 	if ((DB_REF(nmp) == 1) &&
5082 	    (MBLKHEAD(nmp) >= hdr_size) &&
5083 	    (((uintptr_t)mp->b_rptr & 0x1) == 0)) {
5084 		la_wwn_t wwn;
5085 		nmp->b_rptr -= hdr_size;
5086 
5087 		/* first put the network header */
5088 		headerp = (fcph_network_hdr_t *)nmp->b_rptr;
5089 		if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5090 			ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5091 		} else {
5092 			ether_to_wwn(&dlap->dl_phys, &wwn);
5093 		}
5094 		bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5095 		ether_to_wwn(&fptr->fcip_macaddr, &wwn);
5096 		bcopy(&wwn, &headerp->net_src_addr, sizeof (la_wwn_t));
5097 
5098 		/* Now the snap header */
5099 		lsnap = (llc_snap_hdr_t *)(nmp->b_rptr +
5100 		    sizeof (fcph_network_hdr_t));
5101 		lsnap->dsap = 0xAA;
5102 		lsnap->ssap = 0xAA;
5103 		lsnap->ctrl = 0x03;
5104 		lsnap->oui[0] = 0x00;
5105 		lsnap->oui[1] = 0x00; 	/* 80 */
5106 		lsnap->oui[2] = 0x00;	/* C2 */
5107 		lsnap->pid = BE_16((dlap->dl_sap));
5108 
5109 		freeb(mp);
5110 		mp = nmp;
5111 
5112 	} else {
5113 		la_wwn_t wwn;
5114 
5115 		DB_TYPE(mp) = M_DATA;
5116 		headerp = (fcph_network_hdr_t *)mp->b_rptr;
5117 
5118 		/*
5119 		 * Only fill in the low 48bits of WWN for now - we can
5120 		 * fill in the NAA_ID after we find the port in the
5121 		 * routing tables
5122 		 */
5123 		if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5124 			ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5125 		} else {
5126 			ether_to_wwn(&dlap->dl_phys, &wwn);
5127 		}
5128 		bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5129 		/* need to send our PWWN */
5130 		bcopy(&fport->fcipp_pwwn, &headerp->net_src_addr,
5131 		    sizeof (la_wwn_t));
5132 
5133 		lsnap = (llc_snap_hdr_t *)(nmp->b_rptr +
5134 		    sizeof (fcph_network_hdr_t));
5135 		lsnap->dsap = 0xAA;
5136 		lsnap->ssap = 0xAA;
5137 		lsnap->ctrl = 0x03;
5138 		lsnap->oui[0] = 0x00;
5139 		lsnap->oui[1] = 0x00;
5140 		lsnap->oui[2] = 0x00;
5141 		lsnap->pid = BE_16(dlap->dl_sap);
5142 
5143 		mp->b_wptr = mp->b_rptr + hdr_size;
5144 	}
5145 
5146 	/*
5147 	 * Ethernet drivers have a lot of gunk here to put the Type
5148 	 * information (for Ethernet encapsulation (RFC 894) or the
5149 	 * Length (for 802.2/802.3) - I guess we'll just ignore that
5150 	 * here.
5151 	 */
5152 
5153 	/*
5154 	 * Start the I/O on this port. If fcip_start failed for some reason
5155 	 * we call putbq in fcip_start so we don't need to check the
5156 	 * return value from fcip_start
5157 	 */
5158 	(void) fcip_start(wq, mp, fptr, fdestp, KM_SLEEP);
5159 }
5160 
5161 /*
5162  * DL_ATTACH_REQ: attaches a PPA with a stream. ATTACH requets are needed
5163  * for style 2 DLS providers to identify the physical medium through which
5164  * the streams communication will happen
5165  */
5166 static void
5167 fcip_areq(queue_t *wq, mblk_t *mp)
5168 {
5169 	struct fcipstr		*slp;
5170 	union DL_primitives	*dlp;
5171 	fcip_port_info_t	*fport;
5172 	struct fcip		*fptr;
5173 	int			ppa;
5174 
5175 	slp = (struct fcipstr *)wq->q_ptr;
5176 	dlp = (union DL_primitives *)mp->b_rptr;
5177 
5178 	if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
5179 		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
5180 		return;
5181 	}
5182 
5183 	if (slp->sl_state != DL_UNATTACHED) {
5184 		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
5185 		return;
5186 	}
5187 
5188 	ppa = dlp->attach_req.dl_ppa;
5189 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "attach req: ppa %x", ppa));
5190 
5191 	/*
5192 	 * check if the PPA is valid
5193 	 */
5194 
5195 	mutex_enter(&fcip_global_mutex);
5196 
5197 	for (fport = fcip_port_head; fport; fport = fport->fcipp_next) {
5198 		if ((fptr = fport->fcipp_fcip) == NULL) {
5199 			continue;
5200 		}
5201 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "ppa %x, inst %x", ppa,
5202 		    ddi_get_instance(fptr->fcip_dip)));
5203 
5204 		if (ppa == ddi_get_instance(fptr->fcip_dip)) {
5205 			FCIP_DEBUG(FCIP_DEBUG_DLPI,
5206 			    (CE_NOTE, "ppa found %x", ppa));
5207 			break;
5208 		}
5209 	}
5210 
5211 	if (fport == NULL) {
5212 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5213 		    (CE_NOTE, "dlerrorack coz fport==NULL"));
5214 
5215 		mutex_exit(&fcip_global_mutex);
5216 
5217 		if (fc_ulp_get_port_handle(ppa) == NULL) {
5218 			dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0);
5219 			return;
5220 		}
5221 
5222 		/*
5223 		 * Wait for Port attach callback to trigger.  If port_detach
5224 		 * got in while we were waiting, then ddi_get_soft_state
5225 		 * will return NULL, and we'll return error.
5226 		 */
5227 
5228 		delay(drv_usectohz(FCIP_INIT_DELAY));
5229 		mutex_enter(&fcip_global_mutex);
5230 
5231 		fptr = ddi_get_soft_state(fcip_softp, ppa);
5232 		if (fptr == NULL) {
5233 			mutex_exit(&fcip_global_mutex);
5234 			dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0);
5235 			return;
5236 		}
5237 	}
5238 
5239 	/*
5240 	 * set link to device and update our state
5241 	 */
5242 	slp->sl_fcip = fptr;
5243 	slp->sl_state = DL_UNBOUND;
5244 
5245 	mutex_exit(&fcip_global_mutex);
5246 
5247 #ifdef DEBUG
5248 	mutex_enter(&fptr->fcip_mutex);
5249 	if (fptr->fcip_flags & FCIP_LINK_DOWN) {
5250 		FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_WARN, "port not online yet"));
5251 	}
5252 	mutex_exit(&fptr->fcip_mutex);
5253 #endif
5254 
5255 	dlokack(wq, mp, DL_ATTACH_REQ);
5256 }
5257 
5258 
5259 /*
5260  * DL_DETACH request - detaches a PPA from a stream
5261  */
5262 static void
5263 fcip_dreq(queue_t *wq, mblk_t *mp)
5264 {
5265 	struct fcipstr		*slp;
5266 
5267 	slp = (struct fcipstr *)wq->q_ptr;
5268 
5269 	if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
5270 		dlerrorack(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
5271 		return;
5272 	}
5273 
5274 	if (slp->sl_state != DL_UNBOUND) {
5275 		dlerrorack(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
5276 		return;
5277 	}
5278 
5279 	fcip_dodetach(slp);
5280 	dlokack(wq, mp, DL_DETACH_REQ);
5281 }
5282 
5283 /*
5284  * DL_BIND request: requests a DLS provider to bind a DLSAP to the stream.
5285  * DLS users communicate with a physical interface through DLSAPs. Multiple
5286  * DLSAPs can be bound to the same stream (PPA)
5287  */
5288 static void
5289 fcip_breq(queue_t *wq, mblk_t *mp)
5290 {
5291 	struct fcipstr		*slp;
5292 	union DL_primitives	*dlp;
5293 	struct fcip		*fptr;
5294 	struct fcipdladdr	fcipaddr;
5295 	t_uscalar_t		sap;
5296 	int			xidtest;
5297 
5298 	slp = (struct fcipstr *)wq->q_ptr;
5299 
5300 	if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
5301 		dlerrorack(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
5302 		return;
5303 	}
5304 
5305 	if (slp->sl_state != DL_UNBOUND) {
5306 		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
5307 		return;
5308 	}
5309 
5310 	dlp = (union DL_primitives *)mp->b_rptr;
5311 	fptr = slp->sl_fcip;
5312 
5313 	if (fptr == NULL) {
5314 		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
5315 		return;
5316 	}
5317 
5318 	sap = dlp->bind_req.dl_sap;
5319 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "fcip_breq - sap: %x", sap));
5320 	xidtest = dlp->bind_req.dl_xidtest_flg;
5321 
5322 	if (xidtest) {
5323 		dlerrorack(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
5324 		return;
5325 	}
5326 
5327 	FCIP_DEBUG(FCIP_DEBUG_DLPI, (CE_NOTE, "DLBIND: sap : %x", sap));
5328 
5329 	if (sap > ETHERTYPE_MAX) {
5330 		dlerrorack(wq, mp, dlp->dl_primitive, DL_BADSAP, 0);
5331 		return;
5332 	}
5333 	/*
5334 	 * save SAP for this stream and change the link state
5335 	 */
5336 	slp->sl_sap = sap;
5337 	slp->sl_state = DL_IDLE;
5338 
5339 	fcipaddr.dl_sap = sap;
5340 	ether_bcopy(&fptr->fcip_macaddr, &fcipaddr.dl_phys);
5341 	dlbindack(wq, mp, sap, &fcipaddr, FCIPADDRL, 0, 0);
5342 
5343 	fcip_setipq(fptr);
5344 }
5345 
5346 /*
5347  * DL_UNBIND request to unbind a previously bound DLSAP, from this stream
5348  */
5349 static void
5350 fcip_ubreq(queue_t *wq, mblk_t *mp)
5351 {
5352 	struct fcipstr	*slp;
5353 
5354 	slp = (struct fcipstr *)wq->q_ptr;
5355 
5356 	if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
5357 		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
5358 		return;
5359 	}
5360 
5361 	if (slp->sl_state != DL_IDLE) {
5362 		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
5363 		return;
5364 	}
5365 
5366 	slp->sl_state = DL_UNBOUND;
5367 	slp->sl_sap = 0;
5368 
5369 	(void) putnextctl1(RD(wq), M_FLUSH, FLUSHRW);
5370 	dlokack(wq, mp, DL_UNBIND_REQ);
5371 
5372 	fcip_setipq(slp->sl_fcip);
5373 }
5374 
5375 /*
5376  * Return our physical address
5377  */
5378 static void
5379 fcip_pareq(queue_t *wq, mblk_t *mp)
5380 {
5381 	struct fcipstr 		*slp;
5382 	union DL_primitives	*dlp;
5383 	int			type;
5384 	struct fcip		*fptr;
5385 	fcip_port_info_t	*fport;
5386 	struct ether_addr	addr;
5387 
5388 	slp = (struct fcipstr *)wq->q_ptr;
5389 
5390 	if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
5391 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5392 		return;
5393 	}
5394 
5395 	dlp = (union DL_primitives *)mp->b_rptr;
5396 	type = dlp->physaddr_req.dl_addr_type;
5397 	fptr = slp->sl_fcip;
5398 
5399 	if (fptr == NULL) {
5400 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
5401 		return;
5402 	}
5403 
5404 	fport = fptr->fcip_port_info;
5405 
5406 	switch (type) {
5407 	case DL_FACT_PHYS_ADDR:
5408 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5409 		    (CE_NOTE, "returning factory phys addr"));
5410 		wwn_to_ether(&fport->fcipp_pwwn, &addr);
5411 		break;
5412 
5413 	case DL_CURR_PHYS_ADDR:
5414 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5415 		    (CE_NOTE, "returning current phys addr"));
5416 		ether_bcopy(&fptr->fcip_macaddr, &addr);
5417 		break;
5418 
5419 	default:
5420 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5421 		    (CE_NOTE, "Not known cmd type in phys addr"));
5422 		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
5423 		return;
5424 	}
5425 	dlphysaddrack(wq, mp, &addr, ETHERADDRL);
5426 }
5427 
5428 /*
5429  * Set physical address DLPI request
5430  */
5431 static void
5432 fcip_spareq(queue_t *wq, mblk_t *mp)
5433 {
5434 	struct fcipstr		*slp;
5435 	union DL_primitives	*dlp;
5436 	t_uscalar_t		off, len;
5437 	struct ether_addr	*addrp;
5438 	la_wwn_t		wwn;
5439 	struct fcip		*fptr;
5440 	fc_ns_cmd_t		fcip_ns_cmd;
5441 
5442 	slp = (struct fcipstr *)wq->q_ptr;
5443 
5444 	if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
5445 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5446 		return;
5447 	}
5448 
5449 	dlp = (union DL_primitives *)mp->b_rptr;
5450 	len = dlp->set_physaddr_req.dl_addr_length;
5451 	off = dlp->set_physaddr_req.dl_addr_offset;
5452 
5453 	if (!MBLKIN(mp, off, len)) {
5454 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5455 		return;
5456 	}
5457 
5458 	addrp = (struct ether_addr *)(mp->b_rptr + off);
5459 
5460 	/*
5461 	 * If the length of physical address is not correct or address
5462 	 * specified is a broadcast address or multicast addr -
5463 	 * return an error.
5464 	 */
5465 	if ((len != ETHERADDRL) ||
5466 	    ((addrp->ether_addr_octet[0] & 01) == 1) ||
5467 	    (ether_cmp(addrp, &fcip_arpbroadcast_addr) == 0)) {
5468 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
5469 		return;
5470 	}
5471 
5472 	/*
5473 	 * check if a stream is attached to this device. Else return an error
5474 	 */
5475 	if ((fptr = slp->sl_fcip) == NULL) {
5476 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
5477 		return;
5478 	}
5479 
5480 	/*
5481 	 * set the new interface local address. We request the transport
5482 	 * layer to change the Port WWN for this device - return an error
5483 	 * if we don't succeed.
5484 	 */
5485 
5486 	ether_to_wwn(addrp, &wwn);
5487 	if (fcip_set_wwn(&wwn) == FC_SUCCESS) {
5488 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5489 		    (CE_WARN, "WWN changed in spareq"));
5490 	} else {
5491 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
5492 	}
5493 
5494 	/*
5495 	 * register The new Port WWN and Node WWN with the transport
5496 	 * and Nameserver. Hope the transport ensures all current I/O
5497 	 * has stopped before actually attempting to register a new
5498 	 * port and Node WWN else we are hosed. Maybe a Link reset
5499 	 * will get everyone's attention.
5500 	 */
5501 	fcip_ns_cmd.ns_flags = 0;
5502 	fcip_ns_cmd.ns_cmd = NS_RPN_ID;
5503 	fcip_ns_cmd.ns_req_len = sizeof (la_wwn_t);
5504 	fcip_ns_cmd.ns_req_payload = (caddr_t)&wwn.raw_wwn[0];
5505 	fcip_ns_cmd.ns_resp_len = 0;
5506 	fcip_ns_cmd.ns_resp_payload = (caddr_t)0;
5507 	if (fc_ulp_port_ns(fptr->fcip_port_info->fcipp_handle,
5508 	    (opaque_t)0, &fcip_ns_cmd) != FC_SUCCESS) {
5509 		FCIP_DEBUG(FCIP_DEBUG_DLPI,
5510 		    (CE_WARN, "setting Port WWN failed"));
5511 		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
5512 		return;
5513 	}
5514 
5515 	dlokack(wq, mp, DL_SET_PHYS_ADDR_REQ);
5516 }
5517 
5518 /*
5519  * change our port's WWN if permitted by hardware
5520  */
5521 /* ARGSUSED */
5522 static int
5523 fcip_set_wwn(la_wwn_t *pwwn)
5524 {
5525 	/*
5526 	 * We're usually not allowed to change the WWN of adapters
5527 	 * but some adapters do permit us to change the WWN - don't
5528 	 * permit setting of WWNs (yet?) - This behavior could be
5529 	 * modified if needed
5530 	 */
5531 	return (FC_FAILURE);
5532 }
5533 
5534 
5535 /*
5536  * This routine fills in the header for fastpath data requests. What this
5537  * does in simple terms is, instead of sending all data through the Unitdata
5538  * request dlpi code paths (which will then append the protocol specific
5539  * header - network and snap headers in our case), the upper layers issue
5540  * a M_IOCTL with a DL_IOC_HDR_INFO request and ask the streams endpoint
5541  * driver to give the header it needs appended and the upper layer
5542  * allocates and fills in the header and calls our put routine
5543  */
5544 static void
5545 fcip_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp)
5546 {
5547 	mblk_t			*nmp;
5548 	struct fcipstr		*slp;
5549 	struct fcipdladdr	*dlap;
5550 	dl_unitdata_req_t	*dlup;
5551 	fcph_network_hdr_t	*headerp;
5552 	la_wwn_t		wwn;
5553 	llc_snap_hdr_t		*lsnap;
5554 	struct fcip		*fptr;
5555 	fcip_port_info_t	*fport;
5556 	t_uscalar_t		off, len;
5557 	size_t			hdrlen;
5558 	int 			error;
5559 
5560 	slp = (struct fcipstr *)wq->q_ptr;
5561 	fptr = slp->sl_fcip;
5562 	if (fptr == NULL) {
5563 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5564 		    (CE_NOTE, "dliochdr : returns EINVAL1"));
5565 		miocnak(wq, mp, 0, EINVAL);
5566 		return;
5567 	}
5568 
5569 	error = miocpullup(mp, sizeof (dl_unitdata_req_t) + FCIPADDRL);
5570 	if (error != 0) {
5571 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5572 		    (CE_NOTE, "dliochdr : returns %d", error));
5573 		miocnak(wq, mp, 0, error);
5574 		return;
5575 	}
5576 
5577 	fport = fptr->fcip_port_info;
5578 
5579 	/*
5580 	 * check if the DL_UNITDATA_REQ destination addr has valid offset
5581 	 * and length values
5582 	 */
5583 	dlup = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
5584 	off = dlup->dl_dest_addr_offset;
5585 	len = dlup->dl_dest_addr_length;
5586 	if (dlup->dl_primitive != DL_UNITDATA_REQ ||
5587 	    !MBLKIN(mp->b_cont, off, len) || (len != FCIPADDRL)) {
5588 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5589 		    (CE_NOTE, "dliochdr : returns EINVAL2"));
5590 		miocnak(wq, mp, 0, EINVAL);
5591 		return;
5592 	}
5593 
5594 	dlap = (struct fcipdladdr *)(mp->b_cont->b_rptr + off);
5595 
5596 	/*
5597 	 * Allocate a new mblk to hold the ether header
5598 	 */
5599 
5600 	/*
5601 	 * setup space for network header
5602 	 */
5603 	hdrlen = (sizeof (llc_snap_hdr_t) + sizeof (fcph_network_hdr_t));
5604 	if ((nmp = allocb(hdrlen, BPRI_MED)) == NULL) {
5605 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5606 		    (CE_NOTE, "dliochdr : returns ENOMEM"));
5607 		miocnak(wq, mp, 0, ENOMEM);
5608 		return;
5609 	}
5610 	nmp->b_wptr += hdrlen;
5611 
5612 	/*
5613 	 * Fill in the Network Hdr and LLC SNAP header;
5614 	 */
5615 	headerp = (fcph_network_hdr_t *)nmp->b_rptr;
5616 	/*
5617 	 * just fill in the Node WWN here - we can fill in the NAA_ID when
5618 	 * we search the routing table
5619 	 */
5620 	if (ether_cmp(&dlap->dl_phys, &fcip_arpbroadcast_addr) == 0) {
5621 		ether_to_wwn(&fcipnhbroadcastaddr, &wwn);
5622 	} else {
5623 		ether_to_wwn(&dlap->dl_phys, &wwn);
5624 	}
5625 	bcopy(&wwn, &headerp->net_dest_addr, sizeof (la_wwn_t));
5626 	bcopy(&fport->fcipp_pwwn, &headerp->net_src_addr, sizeof (la_wwn_t));
5627 	lsnap = (llc_snap_hdr_t *)(nmp->b_rptr + sizeof (fcph_network_hdr_t));
5628 	lsnap->dsap = 0xAA;
5629 	lsnap->ssap = 0xAA;
5630 	lsnap->ctrl = 0x03;
5631 	lsnap->oui[0] = 0x00;
5632 	lsnap->oui[1] = 0x00;
5633 	lsnap->oui[2] = 0x00;
5634 	lsnap->pid = BE_16(dlap->dl_sap);
5635 
5636 	/*
5637 	 * Link new mblk in after the "request" mblks.
5638 	 */
5639 	linkb(mp, nmp);
5640 
5641 	slp->sl_flags |= FCIP_SLFAST;
5642 
5643 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5644 	    (CE_NOTE, "dliochdr : returns success "));
5645 	miocack(wq, mp, msgsize(mp->b_cont), 0);
5646 }
5647 
5648 
5649 /*
5650  * Establish a kmem cache for fcip packets
5651  */
5652 static int
5653 fcip_cache_constructor(void *buf, void *arg, int flags)
5654 {
5655 	fcip_pkt_t		*fcip_pkt = buf;
5656 	fc_packet_t		*fc_pkt;
5657 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
5658 	int			(*cb) (caddr_t);
5659 	struct fcip		*fptr;
5660 
5661 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
5662 
5663 	ASSERT(fport != NULL);
5664 
5665 	fptr = fport->fcipp_fcip;
5666 
5667 	/*
5668 	 * we allocated space for our private area at the end of the
5669 	 * fc packet. Make sure we point to it correctly. Ideally we
5670 	 * should just push fc_packet_private to the beginning or end
5671 	 * of the fc_packet structure
5672 	 */
5673 	fcip_pkt->fcip_pkt_next = NULL;
5674 	fcip_pkt->fcip_pkt_prev = NULL;
5675 	fcip_pkt->fcip_pkt_dest = NULL;
5676 	fcip_pkt->fcip_pkt_state = 0;
5677 	fcip_pkt->fcip_pkt_reason = 0;
5678 	fcip_pkt->fcip_pkt_flags = 0;
5679 	fcip_pkt->fcip_pkt_fptr = fptr;
5680 	fcip_pkt->fcip_pkt_dma_flags = 0;
5681 
5682 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
5683 	fc_pkt->pkt_ulp_rscn_infop = NULL;
5684 
5685 	/*
5686 	 * We use pkt_cmd_dma for OUTBOUND requests. We don't expect
5687 	 * any responses for outbound IP data so no need to setup
5688 	 * response or data dma handles.
5689 	 */
5690 	if (ddi_dma_alloc_handle(fport->fcipp_dip,
5691 	    &fport->fcipp_cmd_dma_attr, cb, NULL,
5692 	    &fc_pkt->pkt_cmd_dma) != DDI_SUCCESS) {
5693 		return (FCIP_FAILURE);
5694 	}
5695 
5696 	fc_pkt->pkt_cmd_acc = fc_pkt->pkt_resp_acc = NULL;
5697 	fc_pkt->pkt_fca_private = (opaque_t)((caddr_t)buf +
5698 	    sizeof (fcip_pkt_t));
5699 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
5700 
5701 	fc_pkt->pkt_cmd_cookie_cnt = fc_pkt->pkt_resp_cookie_cnt =
5702 	    fc_pkt->pkt_data_cookie_cnt = 0;
5703 	fc_pkt->pkt_cmd_cookie = fc_pkt->pkt_resp_cookie =
5704 	    fc_pkt->pkt_data_cookie = NULL;
5705 
5706 	return (FCIP_SUCCESS);
5707 }
5708 
5709 /*
5710  * destroy the fcip kmem cache
5711  */
5712 static void
5713 fcip_cache_destructor(void *buf, void *arg)
5714 {
5715 	fcip_pkt_t		*fcip_pkt = (fcip_pkt_t *)buf;
5716 	fc_packet_t		*fc_pkt;
5717 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
5718 	struct fcip		*fptr;
5719 
5720 	ASSERT(fport != NULL);
5721 
5722 	fptr = fport->fcipp_fcip;
5723 
5724 	ASSERT(fptr == fcip_pkt->fcip_pkt_fptr);
5725 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
5726 
5727 	if (fc_pkt->pkt_cmd_dma) {
5728 		ddi_dma_free_handle(&fc_pkt->pkt_cmd_dma);
5729 	}
5730 }
5731 
5732 /*
5733  * the fcip destination structure is hashed on Node WWN assuming
5734  * a  NAA_ID of 0x1 (IEEE)
5735  */
5736 static struct fcip_dest *
5737 fcip_get_dest(struct fcip *fptr, la_wwn_t *pwwn)
5738 {
5739 	struct fcip_dest	*fdestp = NULL;
5740 	fcip_port_info_t	*fport;
5741 	int			hash_bucket;
5742 	opaque_t		pd;
5743 	int			rval;
5744 	struct fcip_routing_table *frp;
5745 	la_wwn_t		twwn;
5746 	uint32_t		*twwnp = (uint32_t *)&twwn;
5747 
5748 	hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
5749 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5750 	    (CE_NOTE, "get dest hashbucket : 0x%x", hash_bucket));
5751 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5752 	    (CE_NOTE, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
5753 	    pwwn->raw_wwn[2], pwwn->raw_wwn[3], pwwn->raw_wwn[4],
5754 	    pwwn->raw_wwn[5], pwwn->raw_wwn[6], pwwn->raw_wwn[7]));
5755 
5756 	ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
5757 
5758 	if (fcip_check_port_exists(fptr)) {
5759 		/* fptr is stale, return fdestp */
5760 		return (fdestp);
5761 	}
5762 	fport = fptr->fcip_port_info;
5763 
5764 	/*
5765 	 * First check if we have active I/Os going on with the
5766 	 * destination port (an entry would exist in fcip_dest hash table)
5767 	 */
5768 	mutex_enter(&fptr->fcip_dest_mutex);
5769 	fdestp = fptr->fcip_dest[hash_bucket];
5770 	while (fdestp != NULL) {
5771 		mutex_enter(&fdestp->fcipd_mutex);
5772 		if (fdestp->fcipd_rtable) {
5773 			if (fcip_wwn_compare(pwwn, &fdestp->fcipd_pwwn,
5774 			    FCIP_COMPARE_NWWN) == 0) {
5775 				FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5776 				    (CE_NOTE, "found fdestp"));
5777 				mutex_exit(&fdestp->fcipd_mutex);
5778 				mutex_exit(&fptr->fcip_dest_mutex);
5779 				return (fdestp);
5780 			}
5781 		}
5782 		mutex_exit(&fdestp->fcipd_mutex);
5783 		fdestp = fdestp->fcipd_next;
5784 	}
5785 	mutex_exit(&fptr->fcip_dest_mutex);
5786 
5787 	/*
5788 	 * We did not find the destination port information in our
5789 	 * active port list so search for an entry in our routing
5790 	 * table.
5791 	 */
5792 	mutex_enter(&fptr->fcip_rt_mutex);
5793 	frp = fcip_lookup_rtable(fptr, pwwn, FCIP_COMPARE_NWWN);
5794 	mutex_exit(&fptr->fcip_rt_mutex);
5795 
5796 	if (frp == NULL || (frp && (!FCIP_RTE_UNAVAIL(frp->fcipr_state)) &&
5797 	    frp->fcipr_state != PORT_DEVICE_LOGGED_IN) ||
5798 	    (frp && frp->fcipr_pd == NULL)) {
5799 		/*
5800 		 * No entry for the destination port in our routing
5801 		 * table too. First query the transport to see if it
5802 		 * already has structures for the destination port in
5803 		 * its hash tables. This must be done for all topologies
5804 		 * since we could have retired entries in the hash tables
5805 		 * which may have to be re-added without a statechange
5806 		 * callback happening. Its better to try and get an entry
5807 		 * for the destination port rather than simply failing a
5808 		 * request though it may be an overkill in private loop
5809 		 * topologies.
5810 		 * If a entry for the remote port exists in the transport's
5811 		 * hash tables, we are fine and can add the entry to our
5812 		 * routing and dest hash lists, Else for fabric configs we
5813 		 * query the nameserver if one exists or issue FARP ELS.
5814 		 */
5815 
5816 		/*
5817 		 * We need to do a PortName based Nameserver
5818 		 * query operation. So get the right PortWWN
5819 		 * for the adapter.
5820 		 */
5821 		bcopy(pwwn, &twwn, sizeof (la_wwn_t));
5822 
5823 		/*
5824 		 * Try IEEE Name (Format 1) first, this is the default and
5825 		 * Emulex uses this format.
5826 		 */
5827 		pd = fc_ulp_get_remote_port(fport->fcipp_handle,
5828 					    &twwn, &rval, 1);
5829 
5830 		if (rval != FC_SUCCESS) {
5831 			/*
5832 			 * If IEEE Name (Format 1) query failed, try IEEE
5833 			 * Extended Name (Format 2) which Qlogic uses.
5834 			 * And try port 1 on Qlogic FC-HBA first.
5835 			 * Note: On x86, we need to byte swap the 32-bit
5836 			 * word first, after the modification, swap it back.
5837 			 */
5838 			*twwnp = BE_32(*twwnp);
5839 			twwn.w.nport_id = QLC_PORT_1_ID_BITS;
5840 			twwn.w.naa_id = QLC_PORT_NAA;
5841 			*twwnp = BE_32(*twwnp);
5842 			pd = fc_ulp_get_remote_port(fport->fcipp_handle,
5843 						    &twwn, &rval, 1);
5844 		}
5845 
5846 		if (rval != FC_SUCCESS) {
5847 			/* If still failed, try port 2 on Qlogic FC-HBA. */
5848 			*twwnp = BE_32(*twwnp);
5849 			twwn.w.nport_id = QLC_PORT_2_ID_BITS;
5850 			*twwnp = BE_32(*twwnp);
5851 			pd = fc_ulp_get_remote_port(fport->fcipp_handle,
5852 						    &twwn, &rval, 1);
5853 		}
5854 
5855 		if (rval == FC_SUCCESS) {
5856 			fc_portmap_t	map;
5857 			/*
5858 			 * Add the newly found destination structure
5859 			 * to our routing table. Create a map with
5860 			 * the device we found. We could ask the
5861 			 * transport to give us the list of all
5862 			 * devices connected to our port but we
5863 			 * probably don't need to know all the devices
5864 			 * so let us just constuct a list with only
5865 			 * one device instead.
5866 			 */
5867 
5868 			fc_ulp_copy_portmap(&map, pd);
5869 			fcip_rt_update(fptr, &map, 1);
5870 
5871 			mutex_enter(&fptr->fcip_rt_mutex);
5872 			frp = fcip_lookup_rtable(fptr, pwwn,
5873 			    FCIP_COMPARE_NWWN);
5874 			mutex_exit(&fptr->fcip_rt_mutex);
5875 
5876 			fdestp = fcip_add_dest(fptr, frp);
5877 		} else if (fcip_farp_supported &&
5878 			(FC_TOP_EXTERNAL(fport->fcipp_topology) ||
5879 			(fport->fcipp_topology == FC_TOP_PT_PT))) {
5880 			/*
5881 			 * The Name server request failed so
5882 			 * issue an FARP
5883 			 */
5884 			fdestp = fcip_do_farp(fptr, pwwn, NULL,
5885 				0, 0);
5886 		} else {
5887 		    fdestp = NULL;
5888 		}
5889 	} else if (frp && frp->fcipr_state == PORT_DEVICE_LOGGED_IN) {
5890 		/*
5891 		 * Prepare a dest structure to return to caller
5892 		 */
5893 		fdestp = fcip_add_dest(fptr, frp);
5894 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5895 		    (CE_NOTE, "in fcip get dest non fabric"));
5896 	}
5897 	return (fdestp);
5898 }
5899 
5900 
5901 /*
5902  * Endian clean WWN compare.
5903  * Returns 0 if they compare OK, else return non zero value.
5904  * flag can be bitwise OR of FCIP_COMPARE_NWWN, FCIP_COMPARE_PWWN,
5905  * FCIP_COMPARE_BROADCAST.
5906  */
5907 static int
5908 fcip_wwn_compare(la_wwn_t *wwn1, la_wwn_t *wwn2, int flag)
5909 {
5910 	int rval = 0;
5911 	if ((wwn1->raw_wwn[2] != wwn2->raw_wwn[2]) ||
5912 	    (wwn1->raw_wwn[3] != wwn2->raw_wwn[3]) ||
5913 	    (wwn1->raw_wwn[4] != wwn2->raw_wwn[4]) ||
5914 	    (wwn1->raw_wwn[5] != wwn2->raw_wwn[5]) ||
5915 	    (wwn1->raw_wwn[6] != wwn2->raw_wwn[6]) ||
5916 	    (wwn1->raw_wwn[7] != wwn2->raw_wwn[7])) {
5917 		rval = 1;
5918 	} else if ((flag == FCIP_COMPARE_PWWN) &&
5919 	    (((wwn1->raw_wwn[0] & 0xf0) != (wwn2->raw_wwn[0] & 0xf0)) ||
5920 	    (wwn1->raw_wwn[1] != wwn2->raw_wwn[1]))) {
5921 		rval = 1;
5922 	}
5923 	return (rval);
5924 }
5925 
5926 
5927 /*
5928  * Add an entry for a remote port in the dest hash table. Dest hash table
5929  * has entries for ports in the routing hash table with which we decide
5930  * to establish IP communication with. The no. of entries in the dest hash
5931  * table must always be less than or equal to the entries in the routing
5932  * hash table. Every entry in the dest hash table ofcourse must have a
5933  * corresponding entry in the routing hash table
5934  */
5935 static struct fcip_dest *
5936 fcip_add_dest(struct fcip *fptr, struct fcip_routing_table *frp)
5937 {
5938 	struct fcip_dest *fdestp = NULL;
5939 	la_wwn_t	*pwwn;
5940 	int hash_bucket;
5941 	struct fcip_dest *fdest_new;
5942 
5943 	if (frp == NULL) {
5944 		return (fdestp);
5945 	}
5946 
5947 	pwwn = &frp->fcipr_pwwn;
5948 	mutex_enter(&fptr->fcip_dest_mutex);
5949 	hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
5950 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
5951 	    (CE_NOTE, "add dest hash_bucket: 0x%x", hash_bucket));
5952 
5953 	ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
5954 
5955 	fdestp = fptr->fcip_dest[hash_bucket];
5956 	while (fdestp != NULL) {
5957 		mutex_enter(&fdestp->fcipd_mutex);
5958 		if (fdestp->fcipd_rtable) {
5959 			if (fcip_wwn_compare(pwwn, &fdestp->fcipd_pwwn,
5960 			    FCIP_COMPARE_PWWN) == 0) {
5961 				mutex_exit(&fdestp->fcipd_mutex);
5962 				mutex_exit(&fptr->fcip_dest_mutex);
5963 				return (fdestp);
5964 			}
5965 		}
5966 		mutex_exit(&fdestp->fcipd_mutex);
5967 		fdestp = fdestp->fcipd_next;
5968 	}
5969 
5970 	ASSERT(fdestp == NULL);
5971 
5972 	fdest_new = (struct fcip_dest *)
5973 			kmem_zalloc(sizeof (struct fcip_dest), KM_SLEEP);
5974 
5975 	mutex_init(&fdest_new->fcipd_mutex, NULL, MUTEX_DRIVER, NULL);
5976 	fdest_new->fcipd_next = fptr->fcip_dest[hash_bucket];
5977 	fdest_new->fcipd_refcnt = 0;
5978 	fdest_new->fcipd_rtable = frp;
5979 	fdest_new->fcipd_ncmds = 0;
5980 	fptr->fcip_dest[hash_bucket] = fdest_new;
5981 	fdest_new->fcipd_flags = FCIP_PORT_NOTLOGGED;
5982 
5983 	mutex_exit(&fptr->fcip_dest_mutex);
5984 	return (fdest_new);
5985 }
5986 
5987 /*
5988  * Cleanup the dest hash table and remove all entries
5989  */
5990 static void
5991 fcip_cleanup_dest(struct fcip *fptr)
5992 {
5993 	struct fcip_dest *fdestp = NULL;
5994 	struct fcip_dest *fdest_delp = NULL;
5995 	int i;
5996 
5997 	mutex_enter(&fptr->fcip_dest_mutex);
5998 
5999 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
6000 		fdestp = fptr->fcip_dest[i];
6001 		while (fdestp != NULL) {
6002 			mutex_destroy(&fdestp->fcipd_mutex);
6003 			fdest_delp = fdestp;
6004 			fdestp = fdestp->fcipd_next;
6005 			kmem_free(fdest_delp, sizeof (struct fcip_dest));
6006 			fptr->fcip_dest[i] = NULL;
6007 		}
6008 	}
6009 	mutex_exit(&fptr->fcip_dest_mutex);
6010 }
6011 
6012 
6013 /*
6014  * Send FARP requests for Fabric ports when we don't have the port
6015  * we wish to talk to in our routing hash table. FARP is specially required
6016  * to talk to FC switches for inband switch management. Most FC switches
6017  * today have a switch FC IP address for IP over FC inband switch management
6018  * but the WWN and Port_ID for this traffic is not available through the
6019  * Nameservers since the switch themeselves are transparent.
6020  */
6021 /* ARGSUSED */
6022 static struct fcip_dest *
6023 fcip_do_farp(struct fcip *fptr, la_wwn_t *pwwn, char *ip_addr,
6024     size_t ip_addr_len, int flags)
6025 {
6026 	fcip_pkt_t		*fcip_pkt;
6027 	fc_packet_t		*fc_pkt;
6028 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6029 	la_els_farp_t		farp_cmd;
6030 	la_els_farp_t		*fcmd;
6031 	struct fcip_dest	*fdestp = NULL;
6032 	int			rval;
6033 	clock_t			farp_lbolt;
6034 	la_wwn_t		broadcast_wwn;
6035 	struct fcip_dest	*bdestp;
6036 	struct fcip_routing_table 	*frp;
6037 
6038 	bdestp = fcip_get_dest(fptr, &broadcast_wwn);
6039 
6040 	if (bdestp == NULL) {
6041 		return (fdestp);
6042 	}
6043 
6044 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_farp_t),
6045 	    sizeof (la_els_farp_t), bdestp->fcipd_pd, KM_SLEEP);
6046 
6047 	if (fcip_pkt == NULL) {
6048 		return (fdestp);
6049 	}
6050 
6051 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6052 	ether_to_wwn(&fcip_arpbroadcast_addr, &broadcast_wwn);
6053 
6054 	mutex_enter(&bdestp->fcipd_mutex);
6055 	if (bdestp->fcipd_rtable == NULL) {
6056 		mutex_exit(&bdestp->fcipd_mutex);
6057 		fcip_ipkt_free(fcip_pkt);
6058 		return (fdestp);
6059 	}
6060 
6061 	fcip_pkt->fcip_pkt_dest = bdestp;
6062 	fc_pkt->pkt_fca_device = bdestp->fcipd_fca_dev;
6063 
6064 	bdestp->fcipd_ncmds++;
6065 	mutex_exit(&bdestp->fcipd_mutex);
6066 
6067 	fcip_init_broadcast_pkt(fcip_pkt, NULL, 1);
6068 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
6069 
6070 	/*
6071 	 * Now initialize the FARP payload itself
6072 	 */
6073 	fcmd = &farp_cmd;
6074 	fcmd->ls_code.ls_code = LA_ELS_FARP_REQ;
6075 	fcmd->ls_code.mbz = 0;
6076 	/*
6077 	 * for now just match the Port WWN since the other match addr
6078 	 * code points are optional. We can explore matching the IP address
6079 	 * if needed
6080 	 */
6081 	if (ip_addr) {
6082 		fcmd->match_addr = FARP_MATCH_WW_PN_IPv4;
6083 	} else {
6084 		fcmd->match_addr = FARP_MATCH_WW_PN;
6085 	}
6086 
6087 	/*
6088 	 * Request the responder port to log into us - that way
6089 	 * the Transport is aware of the remote port when we create
6090 	 * an entry for it in our tables
6091 	 */
6092 	fcmd->resp_flags = FARP_INIT_REPLY | FARP_INIT_P_LOGI;
6093 	fcmd->req_id = fport->fcipp_sid;
6094 	fcmd->dest_id.port_id = fc_pkt->pkt_cmd_fhdr.d_id;
6095 	bcopy(&fport->fcipp_pwwn, &fcmd->req_pwwn, sizeof (la_wwn_t));
6096 	bcopy(&fport->fcipp_nwwn, &fcmd->req_nwwn, sizeof (la_wwn_t));
6097 	bcopy(pwwn, &fcmd->resp_pwwn, sizeof (la_wwn_t));
6098 	/*
6099 	 * copy in source IP address if we get to know it
6100 	 */
6101 	if (ip_addr) {
6102 		bcopy(ip_addr, fcmd->resp_ip, ip_addr_len);
6103 	}
6104 
6105 	fc_pkt->pkt_cmdlen = sizeof (la_els_farp_t);
6106 	fc_pkt->pkt_rsplen = sizeof (la_els_farp_t);
6107 	fc_pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6108 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6109 
6110 	/*
6111 	 * Endian safe copy
6112 	 */
6113 	FCIP_CP_OUT(fcmd, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
6114 	    sizeof (la_els_farp_t));
6115 
6116 	/*
6117 	 * send the packet in polled mode.
6118 	 */
6119 	rval = fc_ulp_issue_els(fport->fcipp_handle, fc_pkt);
6120 	if (rval != FC_SUCCESS) {
6121 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6122 		    "fcip_transport of farp pkt failed 0x%x", rval));
6123 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_LIST;
6124 		fcip_ipkt_free(fcip_pkt);
6125 
6126 		mutex_enter(&bdestp->fcipd_mutex);
6127 		bdestp->fcipd_ncmds--;
6128 		mutex_exit(&bdestp->fcipd_mutex);
6129 
6130 		return (fdestp);
6131 	}
6132 
6133 	farp_lbolt = ddi_get_lbolt();
6134 	farp_lbolt += drv_usectohz(FCIP_FARP_TIMEOUT);
6135 
6136 	mutex_enter(&fptr->fcip_mutex);
6137 	fptr->fcip_farp_rsp_flag = 0;
6138 	while (!fptr->fcip_farp_rsp_flag) {
6139 		if (cv_timedwait(&fptr->fcip_farp_cv, &fptr->fcip_mutex,
6140 		    farp_lbolt) == -1) {
6141 			/*
6142 			 * No FARP response from any destination port
6143 			 * so bail out.
6144 			 */
6145 			fptr->fcip_farp_rsp_flag = 1;
6146 		} else {
6147 			/*
6148 			 * We received a FARP response - check to see if the
6149 			 * response was in reply to our FARP request.
6150 			 */
6151 
6152 			mutex_enter(&fptr->fcip_rt_mutex);
6153 			frp = fcip_lookup_rtable(fptr, pwwn, FCIP_COMPARE_NWWN);
6154 			mutex_exit(&fptr->fcip_rt_mutex);
6155 
6156 			if ((frp != NULL) &&
6157 			    !FCIP_RTE_UNAVAIL(frp->fcipr_state)) {
6158 				fdestp = fcip_get_dest(fptr, pwwn);
6159 			} else {
6160 				/*
6161 				 * Not our FARP response so go back and wait
6162 				 * again till FARP_TIMEOUT expires
6163 				 */
6164 				fptr->fcip_farp_rsp_flag = 0;
6165 			}
6166 		}
6167 	}
6168 	mutex_exit(&fptr->fcip_mutex);
6169 
6170 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_LIST;
6171 	fcip_ipkt_free(fcip_pkt);
6172 	mutex_enter(&bdestp->fcipd_mutex);
6173 	bdestp->fcipd_ncmds--;
6174 	mutex_exit(&bdestp->fcipd_mutex);
6175 	return (fdestp);
6176 }
6177 
6178 
6179 
6180 /*
6181  * Helper routine to PLOGI to a remote port we wish to talk to.
6182  * This may not be required since the port driver does logins anyway,
6183  * but this can be required in fabric cases since FARP requests/responses
6184  * don't require you to be logged in?
6185  */
6186 
6187 /* ARGSUSED */
6188 static int
6189 fcip_do_plogi(struct fcip *fptr, struct fcip_routing_table *frp)
6190 {
6191 	fcip_pkt_t		*fcip_pkt;
6192 	fc_packet_t		*fc_pkt;
6193 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6194 	la_els_logi_t		logi;
6195 	int			rval;
6196 	fc_frame_hdr_t		*fr_hdr;
6197 
6198 	/*
6199 	 * Don't bother to login for broadcast RTE entries
6200 	 */
6201 	if ((frp->fcipr_d_id.port_id == 0x0) ||
6202 	    (frp->fcipr_d_id.port_id == 0xffffff)) {
6203 		return (FC_FAILURE);
6204 	}
6205 
6206 	/*
6207 	 * We shouldn't pound in too many logins here
6208 	 *
6209 	 */
6210 	if (frp->fcipr_state == FCIP_RT_LOGIN_PROGRESS ||
6211 	    frp->fcipr_state == PORT_DEVICE_LOGGED_IN) {
6212 		return (FC_SUCCESS);
6213 	}
6214 
6215 	fcip_pkt = fcip_ipkt_alloc(fptr, sizeof (la_els_logi_t),
6216 	    sizeof (la_els_logi_t), frp->fcipr_pd, KM_SLEEP);
6217 
6218 	if (fcip_pkt == NULL) {
6219 		return (FC_FAILURE);
6220 	}
6221 
6222 	/*
6223 	 * Update back pointer for login state update
6224 	 */
6225 	fcip_pkt->fcip_pkt_frp = frp;
6226 	frp->fcipr_state = FCIP_RT_LOGIN_PROGRESS;
6227 
6228 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6229 
6230 	/*
6231 	 * Initialize frame header for ELS
6232 	 */
6233 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6234 	fr_hdr->r_ctl = R_CTL_ELS_REQ;
6235 	fr_hdr->type = FC_TYPE_EXTENDED_LS;
6236 	fr_hdr->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6237 	fr_hdr->df_ctl = 0;
6238 	fr_hdr->s_id = fport->fcipp_sid.port_id;
6239 	fr_hdr->d_id = frp->fcipr_d_id.port_id;
6240 	fr_hdr->seq_cnt = 0;
6241 	fr_hdr->ox_id = 0xffff;
6242 	fr_hdr->rx_id = 0xffff;
6243 	fr_hdr->ro = 0;
6244 
6245 	fc_pkt->pkt_rsplen = sizeof (la_els_logi_t);
6246 	fc_pkt->pkt_comp = fcip_ipkt_callback;
6247 	fc_pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6248 	fc_pkt->pkt_timeout = 10;	/* 10 seconds */
6249 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6250 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6251 
6252 	/*
6253 	 * Everybody does class 3, so let's just set it.  If the transport
6254 	 * knows better, it will deal with the class appropriately.
6255 	 */
6256 
6257 	fc_pkt->pkt_tran_flags = FC_TRAN_INTR | FC_TRAN_CLASS3;
6258 
6259 	/*
6260 	 * we need only fill in the ls_code and the cmd frame header
6261 	 */
6262 	bzero((void *)&logi, sizeof (la_els_logi_t));
6263 	logi.ls_code.ls_code = LA_ELS_PLOGI;
6264 	logi.ls_code.mbz = 0;
6265 
6266 	FCIP_CP_OUT((uint8_t *)&logi, fc_pkt->pkt_cmd, fc_pkt->pkt_cmd_acc,
6267 	    sizeof (la_els_logi_t));
6268 
6269 	rval = fc_ulp_login(fport->fcipp_handle, &fc_pkt, 1);
6270 	if (rval != FC_SUCCESS) {
6271 		cmn_err(CE_WARN,
6272 		    "!fc_ulp_login failed for d_id: 0x%x, rval: 0x%x",
6273 		    frp->fcipr_d_id.port_id, rval);
6274 		fcip_ipkt_free(fcip_pkt);
6275 	}
6276 	return (rval);
6277 }
6278 
6279 /*
6280  * The packet callback routine - called from the transport/FCA after
6281  * it is done DMA'ing/sending out the packet contents on the wire so
6282  * that the alloc'ed packet can be freed
6283  */
6284 static void
6285 fcip_ipkt_callback(fc_packet_t *fc_pkt)
6286 {
6287 	ls_code_t			logi_req;
6288 	ls_code_t			logi_resp;
6289 	fcip_pkt_t			*fcip_pkt;
6290 	fc_frame_hdr_t			*fr_hdr;
6291 	struct fcip 			*fptr;
6292 	fcip_port_info_t		*fport;
6293 	struct fcip_routing_table	*frp;
6294 
6295 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6296 
6297 	FCIP_CP_IN(fc_pkt->pkt_resp, (uint8_t *)&logi_resp,
6298 	    fc_pkt->pkt_resp_acc, sizeof (logi_resp));
6299 
6300 	FCIP_CP_IN(fc_pkt->pkt_cmd, (uint8_t *)&logi_req, fc_pkt->pkt_cmd_acc,
6301 	    sizeof (logi_req));
6302 
6303 	fcip_pkt = (fcip_pkt_t *)fc_pkt->pkt_ulp_private;
6304 	frp = fcip_pkt->fcip_pkt_frp;
6305 	fptr = fcip_pkt->fcip_pkt_fptr;
6306 	fport = fptr->fcip_port_info;
6307 
6308 	ASSERT(logi_req.ls_code == LA_ELS_PLOGI);
6309 
6310 	if (fc_pkt->pkt_state != FC_PKT_SUCCESS ||
6311 	    logi_resp.ls_code != LA_ELS_ACC) {
6312 		/* EMPTY */
6313 
6314 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6315 		    "opcode : 0x%x to d_id: 0x%x failed",
6316 		    logi_req.ls_code, fr_hdr->d_id));
6317 
6318 		mutex_enter(&fptr->fcip_rt_mutex);
6319 		frp->fcipr_state = PORT_DEVICE_INVALID;
6320 		frp->fcipr_invalid_timeout = fptr->fcip_timeout_ticks +
6321 		    (FCIP_RTE_TIMEOUT / 2);
6322 		mutex_exit(&fptr->fcip_rt_mutex);
6323 	} else {
6324 		fc_portid_t	d_id;
6325 
6326 		d_id.port_id = fr_hdr->d_id;
6327 		d_id.priv_lilp_posit = 0;
6328 
6329 		/*
6330 		 * Update PLOGI results; FCA Handle, and Port device handles
6331 		 */
6332 		mutex_enter(&fptr->fcip_rt_mutex);
6333 		frp->fcipr_pd = fc_pkt->pkt_pd;
6334 		frp->fcipr_fca_dev =
6335 		    fc_ulp_get_fca_device(fport->fcipp_handle, d_id);
6336 		frp->fcipr_state = PORT_DEVICE_LOGGED_IN;
6337 		mutex_exit(&fptr->fcip_rt_mutex);
6338 	}
6339 
6340 	fcip_ipkt_free(fcip_pkt);
6341 }
6342 
6343 
6344 /*
6345  * pkt_alloc routine for outbound IP datagrams. The cache constructor
6346  * Only initializes the pkt_cmd_dma (which is where the outbound datagram
6347  * is stuffed) since we don't expect response
6348  */
6349 static fcip_pkt_t *
6350 fcip_pkt_alloc(struct fcip *fptr, mblk_t *bp, int flags, int datalen)
6351 {
6352 	fcip_pkt_t 	*fcip_pkt;
6353 	fc_packet_t	*fc_pkt;
6354 	ddi_dma_cookie_t	pkt_cookie;
6355 	ddi_dma_cookie_t	*cp;
6356 	uint32_t		cnt;
6357 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6358 
6359 	fcip_pkt = kmem_cache_alloc(fptr->fcip_xmit_cache, flags);
6360 	if (fcip_pkt == NULL) {
6361 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM, (CE_WARN,
6362 		    "fcip_pkt_alloc: kmem_cache_alloc failed"));
6363 		return (NULL);
6364 	}
6365 
6366 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6367 	fcip_pkt->fcip_pkt_fcpktp = fc_pkt;
6368 	fc_pkt->pkt_tran_flags = 0;
6369 	fcip_pkt->fcip_pkt_dma_flags = 0;
6370 
6371 	/*
6372 	 * the cache constructor has allocated the dma handle
6373 	 */
6374 	fc_pkt->pkt_cmd = (caddr_t)bp->b_rptr;
6375 	if (ddi_dma_addr_bind_handle(fc_pkt->pkt_cmd_dma, NULL,
6376 	    (caddr_t)bp->b_rptr, datalen, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
6377 	    DDI_DMA_DONTWAIT, NULL, &pkt_cookie,
6378 	    &fc_pkt->pkt_cmd_cookie_cnt) != DDI_DMA_MAPPED) {
6379 			goto fail;
6380 	}
6381 
6382 	fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_BOUND;
6383 
6384 	if (fc_pkt->pkt_cmd_cookie_cnt >
6385 	    fport->fcipp_cmd_dma_attr.dma_attr_sgllen) {
6386 		goto fail;
6387 	}
6388 
6389 	ASSERT(fc_pkt->pkt_cmd_cookie_cnt != 0);
6390 
6391 	cp = fc_pkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6392 	    fc_pkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
6393 	    KM_NOSLEEP);
6394 
6395 	if (cp == NULL) {
6396 		goto fail;
6397 	}
6398 
6399 	*cp = pkt_cookie;
6400 	cp++;
6401 	for (cnt = 1; cnt < fc_pkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
6402 		ddi_dma_nextcookie(fc_pkt->pkt_cmd_dma, &pkt_cookie);
6403 		*cp = pkt_cookie;
6404 	}
6405 
6406 	fc_pkt->pkt_cmdlen = datalen;
6407 
6408 	fcip_pkt->fcip_pkt_mp = NULL;
6409 	fcip_pkt->fcip_pkt_wq = NULL;
6410 	fcip_pkt->fcip_pkt_dest = NULL;
6411 	fcip_pkt->fcip_pkt_next = NULL;
6412 	fcip_pkt->fcip_pkt_prev = NULL;
6413 	fcip_pkt->fcip_pkt_state = 0;
6414 	fcip_pkt->fcip_pkt_reason = 0;
6415 	fcip_pkt->fcip_pkt_flags = 0;
6416 	fcip_pkt->fcip_pkt_frp = NULL;
6417 
6418 	return (fcip_pkt);
6419 fail:
6420 	if (fcip_pkt) {
6421 		fcip_pkt_free(fcip_pkt, 0);
6422 	}
6423 	return ((fcip_pkt_t *)0);
6424 }
6425 
6426 /*
6427  * Free a packet and all its associated resources
6428  */
6429 static void
6430 fcip_pkt_free(struct fcip_pkt *fcip_pkt, int free_mblk)
6431 {
6432 	fc_packet_t	*fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6433 	struct fcip *fptr = fcip_pkt->fcip_pkt_fptr;
6434 
6435 	if (fc_pkt->pkt_cmd_cookie != NULL) {
6436 		kmem_free(fc_pkt->pkt_cmd_cookie, fc_pkt->pkt_cmd_cookie_cnt *
6437 		    sizeof (ddi_dma_cookie_t));
6438 		fc_pkt->pkt_cmd_cookie = NULL;
6439 	}
6440 
6441 	fcip_free_pkt_dma(fcip_pkt);
6442 	if (free_mblk && fcip_pkt->fcip_pkt_mp) {
6443 		freemsg(fcip_pkt->fcip_pkt_mp);
6444 		fcip_pkt->fcip_pkt_mp = NULL;
6445 	}
6446 
6447 	(void) fc_ulp_uninit_packet(fptr->fcip_port_info->fcipp_handle, fc_pkt);
6448 
6449 	kmem_cache_free(fptr->fcip_xmit_cache, (void *)fcip_pkt);
6450 }
6451 
6452 /*
6453  * Allocate a Packet for internal driver use. This is for requests
6454  * that originate from within the driver
6455  */
6456 static fcip_pkt_t *
6457 fcip_ipkt_alloc(struct fcip *fptr, int cmdlen, int resplen,
6458     opaque_t pd, int flags)
6459 {
6460 	fcip_pkt_t 		*fcip_pkt;
6461 	fc_packet_t		*fc_pkt;
6462 	int			(*cb)(caddr_t);
6463 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6464 	size_t			real_len;
6465 	uint_t			held_here = 0;
6466 	ddi_dma_cookie_t	pkt_cookie;
6467 	ddi_dma_cookie_t	*cp;
6468 	uint32_t		cnt;
6469 
6470 	cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
6471 
6472 	fcip_pkt = kmem_zalloc((sizeof (fcip_pkt_t) +
6473 	    fport->fcipp_fca_pkt_size), flags);
6474 
6475 	if (fcip_pkt == NULL) {
6476 		FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6477 		    (CE_WARN, "pkt alloc of ineternal pkt failed"));
6478 		goto fail;
6479 	}
6480 
6481 	fcip_pkt->fcip_pkt_flags = FCIP_PKT_INTERNAL;
6482 	fcip_pkt->fcip_pkt_fptr = fptr;
6483 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6484 	fcip_pkt->fcip_pkt_fcpktp = fc_pkt;
6485 	fc_pkt->pkt_tran_flags = 0;
6486 	fc_pkt->pkt_cmdlen = 0;
6487 	fc_pkt->pkt_rsplen = 0;
6488 	fc_pkt->pkt_datalen = 0;
6489 	fc_pkt->pkt_fca_private = (opaque_t)((caddr_t)fcip_pkt +
6490 	    sizeof (fcip_pkt_t));
6491 	fc_pkt->pkt_ulp_private = (opaque_t)fcip_pkt;
6492 
6493 	if (cmdlen) {
6494 		if (ddi_dma_alloc_handle(fptr->fcip_dip,
6495 		    &fport->fcipp_cmd_dma_attr, cb, NULL,
6496 		    &fc_pkt->pkt_cmd_dma) != DDI_SUCCESS) {
6497 			goto fail;
6498 		}
6499 
6500 		if (ddi_dma_mem_alloc(fc_pkt->pkt_cmd_dma, cmdlen,
6501 		    &fport->fcipp_fca_acc_attr, DDI_DMA_CONSISTENT,
6502 		    cb, NULL, (caddr_t *)&fc_pkt->pkt_cmd,
6503 		    &real_len, &fc_pkt->pkt_cmd_acc) != DDI_SUCCESS) {
6504 			goto fail;
6505 		}
6506 
6507 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_MEM;
6508 		fc_pkt->pkt_cmdlen = cmdlen;
6509 
6510 		if (real_len < cmdlen) {
6511 			goto fail;
6512 		}
6513 
6514 		if (ddi_dma_addr_bind_handle(fc_pkt->pkt_cmd_dma, NULL,
6515 		    (caddr_t)fc_pkt->pkt_cmd, real_len,
6516 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
6517 		    &pkt_cookie, &fc_pkt->pkt_cmd_cookie_cnt) !=
6518 		    DDI_DMA_MAPPED) {
6519 			goto fail;
6520 		}
6521 
6522 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_CMD_DMA_BOUND;
6523 
6524 		if (fc_pkt->pkt_cmd_cookie_cnt >
6525 		    fport->fcipp_cmd_dma_attr.dma_attr_sgllen) {
6526 			goto fail;
6527 		}
6528 
6529 		ASSERT(fc_pkt->pkt_cmd_cookie_cnt != 0);
6530 
6531 		cp = fc_pkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6532 		    fc_pkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
6533 		    KM_NOSLEEP);
6534 
6535 		if (cp == NULL) {
6536 			goto fail;
6537 		}
6538 
6539 		*cp = pkt_cookie;
6540 		cp++;
6541 		for (cnt = 1; cnt < fc_pkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
6542 			ddi_dma_nextcookie(fc_pkt->pkt_cmd_dma, &pkt_cookie);
6543 			*cp = pkt_cookie;
6544 		}
6545 	}
6546 
6547 	if (resplen) {
6548 		if (ddi_dma_alloc_handle(fptr->fcip_dip,
6549 		    &fport->fcipp_resp_dma_attr, cb, NULL,
6550 		    &fc_pkt->pkt_resp_dma) != DDI_SUCCESS) {
6551 			goto fail;
6552 		}
6553 
6554 		if (ddi_dma_mem_alloc(fc_pkt->pkt_resp_dma, resplen,
6555 		    &fport->fcipp_fca_acc_attr, DDI_DMA_CONSISTENT,
6556 		    cb, NULL, (caddr_t *)&fc_pkt->pkt_resp,
6557 		    &real_len, &fc_pkt->pkt_resp_acc) != DDI_SUCCESS) {
6558 			goto fail;
6559 		}
6560 
6561 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_RESP_DMA_MEM;
6562 
6563 		if (real_len < resplen) {
6564 			goto fail;
6565 		}
6566 
6567 		if (ddi_dma_addr_bind_handle(fc_pkt->pkt_resp_dma, NULL,
6568 		    (caddr_t)fc_pkt->pkt_resp, real_len,
6569 		    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
6570 		    &pkt_cookie, &fc_pkt->pkt_resp_cookie_cnt) !=
6571 		    DDI_DMA_MAPPED) {
6572 			goto fail;
6573 		}
6574 
6575 		fcip_pkt->fcip_pkt_dma_flags |= FCIP_RESP_DMA_BOUND;
6576 		fc_pkt->pkt_rsplen = resplen;
6577 
6578 		if (fc_pkt->pkt_resp_cookie_cnt >
6579 		    fport->fcipp_resp_dma_attr.dma_attr_sgllen) {
6580 			goto fail;
6581 		}
6582 
6583 		ASSERT(fc_pkt->pkt_resp_cookie_cnt != 0);
6584 
6585 		cp = fc_pkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
6586 		    fc_pkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
6587 		    KM_NOSLEEP);
6588 
6589 		if (cp == NULL) {
6590 			goto fail;
6591 		}
6592 
6593 		*cp = pkt_cookie;
6594 		cp++;
6595 		for (cnt = 1; cnt < fc_pkt->pkt_resp_cookie_cnt; cnt++, cp++) {
6596 			ddi_dma_nextcookie(fc_pkt->pkt_resp_dma, &pkt_cookie);
6597 			*cp = pkt_cookie;
6598 		}
6599 	}
6600 
6601 	/*
6602 	 * Initialize pkt_pd prior to calling fc_ulp_init_packet
6603 	 */
6604 
6605 	fc_pkt->pkt_pd = pd;
6606 
6607 	/*
6608 	 * Ask the FCA to bless the internal packet
6609 	 */
6610 	if (fc_ulp_init_packet((opaque_t)fport->fcipp_handle,
6611 	    fc_pkt, flags) != FC_SUCCESS) {
6612 		goto fail;
6613 	}
6614 
6615 	/*
6616 	 * Keep track of # of ipkts alloc-ed
6617 	 * This function can get called with mutex either held or not. So, we'll
6618 	 * grab mutex if it is not already held by this thread.
6619 	 * This has to be cleaned up someday.
6620 	 */
6621 	if (!MUTEX_HELD(&fptr->fcip_mutex)) {
6622 		held_here = 1;
6623 		mutex_enter(&fptr->fcip_mutex);
6624 	}
6625 
6626 	fptr->fcip_num_ipkts_pending++;
6627 
6628 	if (held_here)
6629 		mutex_exit(&fptr->fcip_mutex);
6630 
6631 	return (fcip_pkt);
6632 fail:
6633 	if (fcip_pkt) {
6634 		fcip_ipkt_free(fcip_pkt);
6635 	}
6636 
6637 	return (NULL);
6638 }
6639 
6640 /*
6641  * free up an internal IP packet (like a FARP pkt etc)
6642  */
6643 static void
6644 fcip_ipkt_free(fcip_pkt_t *fcip_pkt)
6645 {
6646 	fc_packet_t		*fc_pkt;
6647 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6648 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6649 
6650 	ASSERT(fptr != NULL);
6651 	ASSERT(!mutex_owned(&fptr->fcip_mutex));
6652 
6653 	/* One less ipkt to wait for */
6654 	mutex_enter(&fptr->fcip_mutex);
6655 	if (fptr->fcip_num_ipkts_pending)	/* Safety check */
6656 		fptr->fcip_num_ipkts_pending--;
6657 	mutex_exit(&fptr->fcip_mutex);
6658 
6659 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6660 
6661 	if (fc_pkt->pkt_cmd_cookie != NULL) {
6662 		kmem_free(fc_pkt->pkt_cmd_cookie, fc_pkt->pkt_cmd_cookie_cnt *
6663 		    sizeof (ddi_dma_cookie_t));
6664 		fc_pkt->pkt_cmd_cookie = NULL;
6665 	}
6666 
6667 	if (fc_pkt->pkt_resp_cookie != NULL) {
6668 		kmem_free(fc_pkt->pkt_resp_cookie, fc_pkt->pkt_resp_cookie_cnt *
6669 		    sizeof (ddi_dma_cookie_t));
6670 		fc_pkt->pkt_resp_cookie = NULL;
6671 	}
6672 
6673 	if (fc_ulp_uninit_packet(fport->fcipp_handle, fc_pkt) != FC_SUCCESS) {
6674 		FCIP_DEBUG(FCIP_DEBUG_ELS, (CE_WARN,
6675 		    "fc_ulp_uninit_pkt failed for internal fc pkt 0x%p",
6676 		    (void *)fc_pkt));
6677 	}
6678 	fcip_free_pkt_dma(fcip_pkt);
6679 	kmem_free(fcip_pkt, (sizeof (fcip_pkt_t) + fport->fcipp_fca_pkt_size));
6680 }
6681 
6682 /*
6683  * initialize a unicast request. This is a misnomer because even the
6684  * broadcast requests are initialized with this routine
6685  */
6686 static void
6687 fcip_init_unicast_pkt(fcip_pkt_t *fcip_pkt, fc_portid_t sid, fc_portid_t did,
6688     void (*comp) ())
6689 {
6690 	fc_packet_t		*fc_pkt;
6691 	fc_frame_hdr_t		*fr_hdr;
6692 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6693 
6694 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6695 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6696 
6697 	fr_hdr->r_ctl = R_CTL_DEVICE_DATA | R_CTL_UNSOL_DATA;
6698 	fr_hdr->s_id = sid.port_id;
6699 	fr_hdr->d_id = did.port_id;
6700 	fr_hdr->type = FC_TYPE_IS8802_SNAP;
6701 	fr_hdr->f_ctl = F_CTL_FIRST_SEQ | F_CTL_LAST_SEQ;
6702 	fr_hdr->df_ctl = DF_CTL_NET_HDR;
6703 	fr_hdr->seq_cnt = 0;
6704 	fr_hdr->ox_id = 0xffff;
6705 	fr_hdr->rx_id = 0xffff;
6706 	fr_hdr->ro = 0;
6707 	/*
6708 	 * reset all the length fields
6709 	 */
6710 	fc_pkt->pkt_rsplen = 0;
6711 	fc_pkt->pkt_datalen = 0;
6712 	fc_pkt->pkt_comp = comp;
6713 	if (comp) {
6714 		fc_pkt->pkt_tran_flags |= FC_TRAN_INTR;
6715 	} else {
6716 		fc_pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6717 	}
6718 	fc_pkt->pkt_tran_type = FC_PKT_OUTBOUND | FC_PKT_IP_WRITE;
6719 	fc_pkt->pkt_timeout = fcip_pkt_ttl_ticks;
6720 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6721 }
6722 
6723 
6724 /*
6725  * Initialize a fcip_packet for broadcast data transfers
6726  */
6727 static void
6728 fcip_init_broadcast_pkt(fcip_pkt_t *fcip_pkt, void (*comp) (), int is_els)
6729 {
6730 	fc_packet_t		*fc_pkt;
6731 	fc_frame_hdr_t		*fr_hdr;
6732 	struct fcip		*fptr = fcip_pkt->fcip_pkt_fptr;
6733 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6734 	uint32_t		sid;
6735 	uint32_t		did;
6736 
6737 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6738 	fr_hdr = &fc_pkt->pkt_cmd_fhdr;
6739 	sid = fport->fcipp_sid.port_id;
6740 
6741 	if (is_els) {
6742 		fr_hdr->r_ctl = R_CTL_ELS_REQ;
6743 	} else {
6744 		fr_hdr->r_ctl = R_CTL_DEVICE_DATA | R_CTL_UNSOL_DATA;
6745 	}
6746 	fr_hdr->s_id = sid;
6747 	/*
6748 	 * The destination broadcast address depends on the topology
6749 	 * of the underlying port
6750 	 */
6751 	did = fptr->fcip_broadcast_did;
6752 	/*
6753 	 * mark pkt a broadcast pkt
6754 	 */
6755 	fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
6756 
6757 	fr_hdr->d_id = did;
6758 	fr_hdr->type = FC_TYPE_IS8802_SNAP;
6759 	fr_hdr->f_ctl = F_CTL_FIRST_SEQ | F_CTL_LAST_SEQ | F_CTL_END_SEQ;
6760 	fr_hdr->f_ctl &= ~(F_CTL_SEQ_INITIATIVE);
6761 	fr_hdr->df_ctl = DF_CTL_NET_HDR;
6762 	fr_hdr->seq_cnt = 0;
6763 	fr_hdr->ox_id = 0xffff;
6764 	fr_hdr->rx_id = 0xffff;
6765 	fr_hdr->ro = 0;
6766 	fc_pkt->pkt_comp = comp;
6767 
6768 	if (comp) {
6769 		fc_pkt->pkt_tran_flags |= FC_TRAN_INTR;
6770 	} else {
6771 		fc_pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6772 	}
6773 
6774 	fc_pkt->pkt_tran_type = FC_PKT_BROADCAST;
6775 	fc_pkt->pkt_timeout = fcip_pkt_ttl_ticks;
6776 	fcip_pkt->fcip_pkt_ttl = fptr->fcip_timeout_ticks + fc_pkt->pkt_timeout;
6777 }
6778 
6779 
6780 
6781 /*
6782  * Free up all DMA resources associated with an allocated packet
6783  */
6784 static void
6785 fcip_free_pkt_dma(fcip_pkt_t *fcip_pkt)
6786 {
6787 	fc_packet_t	*fc_pkt;
6788 
6789 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
6790 
6791 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
6792 	    (CE_NOTE, "in freepktdma : flags 0x%x",
6793 	    fcip_pkt->fcip_pkt_dma_flags));
6794 
6795 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_CMD_DMA_BOUND) {
6796 		(void) ddi_dma_unbind_handle(fc_pkt->pkt_cmd_dma);
6797 	}
6798 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_CMD_DMA_MEM) {
6799 		ddi_dma_mem_free(&fc_pkt->pkt_cmd_acc);
6800 	}
6801 
6802 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_RESP_DMA_BOUND) {
6803 		(void) ddi_dma_unbind_handle(fc_pkt->pkt_resp_dma);
6804 	}
6805 	if (fcip_pkt->fcip_pkt_dma_flags & FCIP_RESP_DMA_MEM) {
6806 		ddi_dma_mem_free(&fc_pkt->pkt_resp_acc);
6807 	}
6808 	/*
6809 	 * for internal commands, we need to free up the dma handles too.
6810 	 * This is done in the cache destructor for non internal cmds
6811 	 */
6812 	if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_INTERNAL) {
6813 		if (fc_pkt->pkt_cmd_dma) {
6814 			ddi_dma_free_handle(&fc_pkt->pkt_cmd_dma);
6815 		}
6816 		if (fc_pkt->pkt_resp_dma) {
6817 			ddi_dma_free_handle(&fc_pkt->pkt_resp_dma);
6818 		}
6819 	}
6820 }
6821 
6822 
6823 /*
6824  * helper routine to generate a string, given an ether addr
6825  */
6826 static void
6827 fcip_ether_to_str(struct ether_addr *e, caddr_t s)
6828 {
6829 	int i;
6830 
6831 	for (i = 0; i < sizeof (struct ether_addr); i++, s += 2) {
6832 		FCIP_DEBUG(FCIP_DEBUG_MISC,
6833 		    (CE_CONT, "0x%02X:", e->ether_addr_octet[i]));
6834 		(void) sprintf(s, "%02X", e->ether_addr_octet[i]);
6835 	}
6836 
6837 	*s = '\0';
6838 }
6839 
6840 /*
6841  * When a broadcast request comes from the upper streams modules, it
6842  * is ugly to look into every datagram to figure out if it is a broadcast
6843  * datagram or a unicast packet. Instead just add the broadcast entries
6844  * into our routing and dest tables and the standard hash table look ups
6845  * will find the entries. It is a lot cleaner this way. Also Solaris ifconfig
6846  * seems to be very ethernet specific and it requires broadcasts to the
6847  * ether broadcast addr of 0xffffffffff to succeed even though we specified
6848  * in the dl_info request that our broadcast MAC addr is 0x0000000000
6849  * (can't figure out why RFC2625 did this though). So add broadcast entries
6850  * for both MAC address
6851  */
6852 static int
6853 fcip_dest_add_broadcast_entry(struct fcip *fptr, int new_flag)
6854 {
6855 	fc_portmap_t 		map;
6856 	struct fcip_routing_table *frp;
6857 	uint32_t		did;
6858 	la_wwn_t		broadcast_wwn;
6859 
6860 	/*
6861 	 * get port_id of destination for broadcast - this is topology
6862 	 * dependent
6863 	 */
6864 	did = fptr->fcip_broadcast_did;
6865 
6866 	ether_to_wwn(&fcip_arpbroadcast_addr, &broadcast_wwn);
6867 	bcopy((void *)&broadcast_wwn, (void *)&map.map_pwwn, sizeof (la_wwn_t));
6868 	bcopy((void *)&broadcast_wwn, (void *)&map.map_nwwn, sizeof (la_wwn_t));
6869 
6870 	map.map_did.port_id = did;
6871 	map.map_hard_addr.hard_addr = did;
6872 	map.map_state = PORT_DEVICE_VALID;
6873 	if (new_flag) {
6874 		map.map_type = PORT_DEVICE_NEW;
6875 	} else {
6876 		map.map_type = PORT_DEVICE_CHANGED;
6877 	}
6878 	map.map_flags = 0;
6879 	map.map_pd = NULL;
6880 	bzero(&map.map_fc4_types, sizeof (map.map_fc4_types));
6881 	fcip_rt_update(fptr, &map, 1);
6882 	mutex_enter(&fptr->fcip_rt_mutex);
6883 	frp = fcip_lookup_rtable(fptr, &broadcast_wwn, FCIP_COMPARE_NWWN);
6884 	mutex_exit(&fptr->fcip_rt_mutex);
6885 	if (frp == NULL) {
6886 		return (FC_FAILURE);
6887 	}
6888 	(void) fcip_add_dest(fptr, frp);
6889 	/*
6890 	 * The Upper IP layers expect the traditional broadcast MAC addr
6891 	 * of 0xff ff ff ff ff ff to work too if we want to plumb the fcip
6892 	 * stream through the /etc/hostname.fcipXX file. Instead of checking
6893 	 * each phys addr for a match with fcip's ARP header broadcast
6894 	 * addr (0x00 00 00 00 00 00), its simply easier to add another
6895 	 * broadcast entry for 0xff ff ff ff ff ff.
6896 	 */
6897 	ether_to_wwn(&fcipnhbroadcastaddr, &broadcast_wwn);
6898 	bcopy((void *)&broadcast_wwn, (void *)&map.map_pwwn, sizeof (la_wwn_t));
6899 	bcopy((void *)&broadcast_wwn, (void *)&map.map_nwwn, sizeof (la_wwn_t));
6900 	fcip_rt_update(fptr, &map, 1);
6901 	mutex_enter(&fptr->fcip_rt_mutex);
6902 	frp = fcip_lookup_rtable(fptr, &broadcast_wwn, FCIP_COMPARE_NWWN);
6903 	mutex_exit(&fptr->fcip_rt_mutex);
6904 	if (frp == NULL) {
6905 		return (FC_FAILURE);
6906 	}
6907 	(void) fcip_add_dest(fptr, frp);
6908 	return (FC_SUCCESS);
6909 }
6910 
6911 /*
6912  * We need to obtain the D_ID of the broadcast port for transmitting all
6913  * our broadcast (and multicast) requests. The broadcast D_ID as we know
6914  * is dependent on the link topology
6915  */
6916 static uint32_t
6917 fcip_get_broadcast_did(struct fcip *fptr)
6918 {
6919 	fcip_port_info_t	*fport = fptr->fcip_port_info;
6920 	uint32_t		did = 0;
6921 	uint32_t		sid;
6922 
6923 	sid = fport->fcipp_sid.port_id;
6924 
6925 	switch (fport->fcipp_topology) {
6926 
6927 	case FC_TOP_PT_PT: {
6928 		fc_portmap_t	*port_map = NULL;
6929 		uint32_t	listlen = 0;
6930 
6931 		if (fc_ulp_getportmap(fport->fcipp_handle, &port_map,
6932 		    &listlen, FC_ULP_PLOGI_DONTCARE) == FC_SUCCESS) {
6933 			FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_NOTE,
6934 			    "fcip_gpmap: listlen :  0x%x", listlen));
6935 			if (listlen == 1) {
6936 				did = port_map->map_did.port_id;
6937 			}
6938 		}
6939 		if (port_map) {
6940 			kmem_free(port_map, listlen * sizeof (fc_portmap_t));
6941 		}
6942 		if (listlen != 1) {
6943 			/* Dummy return value */
6944 			return (0x00FFFFFF);
6945 		}
6946 		break;
6947 	}
6948 
6949 	case FC_TOP_NO_NS:
6950 	/* FALLTHROUGH */
6951 	case FC_TOP_FABRIC:
6952 		/*
6953 		 * The broadcast address is the same whether or not
6954 		 * the switch/fabric contains a Name service.
6955 		 */
6956 		did = 0x00FFFFFF;
6957 		break;
6958 
6959 	case FC_TOP_PUBLIC_LOOP:
6960 		/*
6961 		 * The open replicate primitive must not be used. The
6962 		 * broadcast sequence is simply sent to ALPA 0x00. The
6963 		 * fabric controller then propagates the broadcast to all
6964 		 * other ports. The fabric propagates the broadcast by
6965 		 * using the OPNfr primitive.
6966 		 */
6967 		did = 0x00;
6968 		break;
6969 
6970 	case FC_TOP_PRIVATE_LOOP:
6971 		/*
6972 		 * The source port for broadcast in private loop mode
6973 		 * must send an OPN(fr) signal forcing all ports in the
6974 		 * loop to replicate the frames that they receive.
6975 		 */
6976 		did = 0x00FFFFFF;
6977 		break;
6978 
6979 	case FC_TOP_UNKNOWN:
6980 	/* FALLTHROUGH */
6981 	default:
6982 		did = sid;
6983 		FCIP_DEBUG(FCIP_DEBUG_INIT, (CE_WARN,
6984 		    "fcip(0x%x):unknown topology in init_broadcast_pkt",
6985 		    fptr->fcip_instance));
6986 		break;
6987 	}
6988 
6989 	return (did);
6990 }
6991 
6992 
6993 /*
6994  * fcip timeout performs 2 operations:
6995  * 1. timeout any packets sent to the FCA for which a callback hasn't
6996  *    happened. If you are wondering why we need a callback since all
6997  *    traffic in FCIP is unidirectional, hence all exchanges are unidirectional
6998  *    but wait, we can only free up the resources after we know the FCA has
6999  *    DMA'ed out the data. pretty obvious eh :)
7000  *
7001  * 2. Retire and routing table entries we marked up for retiring. This is
7002  *    to give the link a chance to recover instead of marking a port down
7003  *    when we have lost all communication with it after a link transition
7004  */
7005 static void
7006 fcip_timeout(void *arg)
7007 {
7008 	struct fcip 			*fptr = (struct fcip *)arg;
7009 	int				i;
7010 	fcip_pkt_t			*fcip_pkt;
7011 	struct fcip_dest		*fdestp;
7012 	int 				index;
7013 	struct fcip_routing_table 	*frtp;
7014 	int				dispatch_rte_removal = 0;
7015 
7016 	mutex_enter(&fptr->fcip_mutex);
7017 
7018 	fptr->fcip_flags |= FCIP_IN_TIMEOUT;
7019 	fptr->fcip_timeout_ticks += fcip_tick_incr;
7020 
7021 	if (fptr->fcip_flags & (FCIP_DETACHED | FCIP_DETACHING | \
7022 	    FCIP_SUSPENDED | FCIP_POWER_DOWN)) {
7023 		fptr->fcip_flags &= ~(FCIP_IN_TIMEOUT);
7024 		mutex_exit(&fptr->fcip_mutex);
7025 		return;
7026 	}
7027 
7028 	if (fptr->fcip_port_state == FCIP_PORT_OFFLINE) {
7029 		if (fptr->fcip_timeout_ticks > fptr->fcip_mark_offline) {
7030 			fptr->fcip_flags |= FCIP_LINK_DOWN;
7031 		}
7032 	}
7033 	if (!fptr->fcip_flags & FCIP_RTE_REMOVING) {
7034 		dispatch_rte_removal = 1;
7035 	}
7036 	mutex_exit(&fptr->fcip_mutex);
7037 
7038 	/*
7039 	 * Check if we have any Invalid routing table entries in our
7040 	 * hashtable we have marked off for deferred removal. If any,
7041 	 * we can spawn a taskq thread to do the cleanup for us. We
7042 	 * need to avoid cleanup in the timeout thread since we may
7043 	 * have to wait for outstanding commands to complete before
7044 	 * we retire a routing table entry. Also dispatch the taskq
7045 	 * thread only if we are already do not have a taskq thread
7046 	 * dispatched.
7047 	 */
7048 	if (dispatch_rte_removal) {
7049 		mutex_enter(&fptr->fcip_rt_mutex);
7050 		for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
7051 			frtp = fptr->fcip_rtable[index];
7052 			while (frtp) {
7053 				if ((frtp->fcipr_state == FCIP_RT_INVALID) &&
7054 				    (fptr->fcip_timeout_ticks >
7055 				    frtp->fcipr_invalid_timeout)) {
7056 					/*
7057 					 * If we cannot schedule a task thread
7058 					 * let us attempt again on the next
7059 					 * tick rather than call
7060 					 * fcip_rte_remove_deferred() from here
7061 					 * directly since the routine can sleep.
7062 					 */
7063 					frtp->fcipr_state = FCIP_RT_RETIRED;
7064 
7065 					mutex_enter(&fptr->fcip_mutex);
7066 					fptr->fcip_flags |= FCIP_RTE_REMOVING;
7067 					mutex_exit(&fptr->fcip_mutex);
7068 
7069 					if (taskq_dispatch(fptr->fcip_tq,
7070 					    fcip_rte_remove_deferred, fptr,
7071 					    KM_NOSLEEP) == TASKQID_INVALID) {
7072 						/*
7073 						 * failed - so mark the entry
7074 						 * as invalid again.
7075 						 */
7076 						frtp->fcipr_state =
7077 						    FCIP_RT_INVALID;
7078 
7079 						mutex_enter(&fptr->fcip_mutex);
7080 						fptr->fcip_flags &=
7081 						    ~FCIP_RTE_REMOVING;
7082 						mutex_exit(&fptr->fcip_mutex);
7083 					}
7084 				}
7085 				frtp = frtp->fcipr_next;
7086 			}
7087 		}
7088 		mutex_exit(&fptr->fcip_rt_mutex);
7089 	}
7090 
7091 	mutex_enter(&fptr->fcip_dest_mutex);
7092 
7093 	/*
7094 	 * Now timeout any packets stuck with the transport/FCA for too long
7095 	 */
7096 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
7097 		fdestp = fptr->fcip_dest[i];
7098 		while (fdestp != NULL) {
7099 			mutex_enter(&fdestp->fcipd_mutex);
7100 			for (fcip_pkt = fdestp->fcipd_head; fcip_pkt != NULL;
7101 			    fcip_pkt = fcip_pkt->fcip_pkt_next) {
7102 				if (fcip_pkt->fcip_pkt_flags &
7103 				    (FCIP_PKT_RETURNED | FCIP_PKT_IN_TIMEOUT |
7104 				    FCIP_PKT_IN_ABORT)) {
7105 					continue;
7106 				}
7107 				if (fptr->fcip_timeout_ticks >
7108 				    fcip_pkt->fcip_pkt_ttl) {
7109 					fcip_pkt->fcip_pkt_flags |=
7110 					    FCIP_PKT_IN_TIMEOUT;
7111 
7112 					mutex_exit(&fdestp->fcipd_mutex);
7113 					if (taskq_dispatch(fptr->fcip_tq,
7114 					    fcip_pkt_timeout, fcip_pkt,
7115 					    KM_NOSLEEP) == TASKQID_INVALID) {
7116 						/*
7117 						 * timeout immediately
7118 						 */
7119 						fcip_pkt_timeout(fcip_pkt);
7120 					}
7121 					mutex_enter(&fdestp->fcipd_mutex);
7122 					/*
7123 					 * The linked list is altered because
7124 					 * of one of the following reasons:
7125 					 *	a. Timeout code dequeued a pkt
7126 					 *	b. Pkt completion happened
7127 					 *
7128 					 * So restart the spin starting at
7129 					 * the head again; This is a bit
7130 					 * excessive, but okay since
7131 					 * fcip_timeout_ticks isn't incremented
7132 					 * for this spin, we will skip the
7133 					 * not-to-be-timedout packets quickly
7134 					 */
7135 					fcip_pkt = fdestp->fcipd_head;
7136 					if (fcip_pkt == NULL) {
7137 						break;
7138 					}
7139 				}
7140 			}
7141 			mutex_exit(&fdestp->fcipd_mutex);
7142 			fdestp = fdestp->fcipd_next;
7143 		}
7144 	}
7145 	mutex_exit(&fptr->fcip_dest_mutex);
7146 
7147 	/*
7148 	 * reschedule the timeout thread
7149 	 */
7150 	mutex_enter(&fptr->fcip_mutex);
7151 
7152 	fptr->fcip_timeout_id = timeout(fcip_timeout, fptr,
7153 	    drv_usectohz(1000000));
7154 	fptr->fcip_flags &= ~(FCIP_IN_TIMEOUT);
7155 	mutex_exit(&fptr->fcip_mutex);
7156 }
7157 
7158 
7159 /*
7160  * This routine is either called from taskq or directly from fcip_timeout
7161  * does the actual job of aborting the packet
7162  */
7163 static void
7164 fcip_pkt_timeout(void *arg)
7165 {
7166 	fcip_pkt_t		*fcip_pkt = (fcip_pkt_t *)arg;
7167 	struct fcip_dest	*fdestp;
7168 	struct fcip		*fptr;
7169 	fc_packet_t		*fc_pkt;
7170 	fcip_port_info_t	*fport;
7171 	int			rval;
7172 
7173 	fdestp = fcip_pkt->fcip_pkt_dest;
7174 	fptr = fcip_pkt->fcip_pkt_fptr;
7175 	fport = fptr->fcip_port_info;
7176 	fc_pkt = FCIP_PKT_TO_FC_PKT(fcip_pkt);
7177 
7178 	/*
7179 	 * try to abort the pkt
7180 	 */
7181 	fcip_pkt->fcip_pkt_flags |= FCIP_PKT_IN_ABORT;
7182 	rval = fc_ulp_abort(fport->fcipp_handle, fc_pkt, KM_NOSLEEP);
7183 
7184 	FCIP_DEBUG(FCIP_DEBUG_DOWNSTREAM,
7185 	    (CE_NOTE, "fc_ulp_abort returns: 0x%x", rval));
7186 
7187 	if (rval == FC_SUCCESS) {
7188 		ASSERT(fdestp != NULL);
7189 
7190 		/*
7191 		 * dequeue the pkt from the dest structure pkt list
7192 		 */
7193 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
7194 		mutex_enter(&fdestp->fcipd_mutex);
7195 		rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
7196 		ASSERT(rval == 1);
7197 		mutex_exit(&fdestp->fcipd_mutex);
7198 
7199 		/*
7200 		 * Now cleanup the pkt and free the mblk
7201 		 */
7202 		fcip_pkt_free(fcip_pkt, 1);
7203 	} else {
7204 		/*
7205 		 * abort failed - just mark the pkt as done and
7206 		 * wait for it to complete in fcip_pkt_callback since
7207 		 * the pkt has already been xmitted by the FCA
7208 		 */
7209 		fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_TIMEOUT;
7210 		if (fcip_pkt->fcip_pkt_flags & FCIP_PKT_RETURNED) {
7211 			fcip_pkt->fcip_pkt_flags &= ~FCIP_PKT_IN_ABORT;
7212 			mutex_enter(&fdestp->fcipd_mutex);
7213 			rval = fcip_fdestp_dequeue_pkt(fdestp, fcip_pkt);
7214 			ASSERT(rval == 1);
7215 			mutex_exit(&fdestp->fcipd_mutex);
7216 
7217 			fcip_pkt_free(fcip_pkt, 1);
7218 		}
7219 		return;
7220 	}
7221 }
7222 
7223 
7224 /*
7225  * Remove  a routing table entry marked for deferred removal. This routine
7226  * unlike fcip_pkt_timeout, is always called from a taskq context
7227  */
7228 static void
7229 fcip_rte_remove_deferred(void *arg)
7230 {
7231 	struct fcip 			*fptr = (struct fcip *)arg;
7232 	int				hash_bucket;
7233 	struct fcip_dest 		*fdestp;
7234 	la_wwn_t			*pwwn;
7235 	int 				index;
7236 	struct fcip_routing_table 	*frtp, *frtp_next, *frtp_prev;
7237 
7238 
7239 	mutex_enter(&fptr->fcip_rt_mutex);
7240 	for (index = 0; index < FCIP_RT_HASH_ELEMS; index++) {
7241 		frtp = fptr->fcip_rtable[index];
7242 		frtp_prev = NULL;
7243 		while (frtp) {
7244 			frtp_next = frtp->fcipr_next;
7245 
7246 			if (frtp->fcipr_state == FCIP_RT_RETIRED) {
7247 
7248 				pwwn = &frtp->fcipr_pwwn;
7249 				/*
7250 				 * Get hold of destination pointer
7251 				 */
7252 				mutex_enter(&fptr->fcip_dest_mutex);
7253 
7254 				hash_bucket = FCIP_DEST_HASH(pwwn->raw_wwn);
7255 				ASSERT(hash_bucket < FCIP_DEST_HASH_ELEMS);
7256 
7257 				fdestp = fptr->fcip_dest[hash_bucket];
7258 				while (fdestp != NULL) {
7259 					mutex_enter(&fdestp->fcipd_mutex);
7260 					if (fdestp->fcipd_rtable) {
7261 						if (fcip_wwn_compare(pwwn,
7262 						    &fdestp->fcipd_pwwn,
7263 						    FCIP_COMPARE_PWWN) == 0) {
7264 							mutex_exit(
7265 							&fdestp->fcipd_mutex);
7266 							break;
7267 						}
7268 					}
7269 					mutex_exit(&fdestp->fcipd_mutex);
7270 					fdestp = fdestp->fcipd_next;
7271 				}
7272 
7273 				mutex_exit(&fptr->fcip_dest_mutex);
7274 				if (fdestp == NULL) {
7275 					frtp_prev = frtp;
7276 					frtp = frtp_next;
7277 					continue;
7278 				}
7279 
7280 				mutex_enter(&fdestp->fcipd_mutex);
7281 				if (fdestp->fcipd_ncmds) {
7282 					/*
7283 					 * Instead of waiting to drain commands
7284 					 * let us revisit this RT entry in
7285 					 * the next pass.
7286 					 */
7287 					mutex_exit(&fdestp->fcipd_mutex);
7288 					frtp_prev = frtp;
7289 					frtp = frtp_next;
7290 					continue;
7291 				}
7292 
7293 				/*
7294 				 * We are clean, so remove the RTE
7295 				 */
7296 				fdestp->fcipd_rtable = NULL;
7297 				mutex_exit(&fdestp->fcipd_mutex);
7298 
7299 				if (frtp_prev == NULL) {
7300 					/* first element */
7301 					fptr->fcip_rtable[index] =
7302 					    frtp->fcipr_next;
7303 				} else {
7304 					frtp_prev->fcipr_next =
7305 					    frtp->fcipr_next;
7306 				}
7307 				kmem_free(frtp,
7308 				    sizeof (struct fcip_routing_table));
7309 
7310 				frtp = frtp_next;
7311 			} else {
7312 				frtp_prev = frtp;
7313 				frtp = frtp_next;
7314 			}
7315 		}
7316 	}
7317 	mutex_exit(&fptr->fcip_rt_mutex);
7318 	/*
7319 	 * Clear the RTE_REMOVING flag
7320 	 */
7321 	mutex_enter(&fptr->fcip_mutex);
7322 	fptr->fcip_flags &= ~FCIP_RTE_REMOVING;
7323 	mutex_exit(&fptr->fcip_mutex);
7324 }
7325 
7326 /*
7327  * Walk through all the dest hash table entries and count up the total
7328  * no. of packets outstanding against a given port
7329  */
7330 static int
7331 fcip_port_get_num_pkts(struct fcip *fptr)
7332 {
7333 	int 			num_cmds = 0;
7334 	int 			i;
7335 	struct fcip_dest	*fdestp;
7336 
7337 	ASSERT(mutex_owned(&fptr->fcip_dest_mutex));
7338 
7339 	for (i = 0; i < FCIP_DEST_HASH_ELEMS; i++) {
7340 		fdestp = fptr->fcip_dest[i];
7341 		while (fdestp != NULL) {
7342 			mutex_enter(&fdestp->fcipd_mutex);
7343 
7344 			ASSERT(fdestp->fcipd_ncmds >= 0);
7345 
7346 			if (fdestp->fcipd_ncmds > 0) {
7347 				num_cmds += fdestp->fcipd_ncmds;
7348 			}
7349 			mutex_exit(&fdestp->fcipd_mutex);
7350 			fdestp = fdestp->fcipd_next;
7351 		}
7352 	}
7353 
7354 	return (num_cmds);
7355 }
7356 
7357 
7358 /*
7359  * Walk through the routing table for this state instance and see if there is a
7360  * PLOGI in progress for any of the entries. Return success even if we find one.
7361  */
7362 static int
7363 fcip_plogi_in_progress(struct fcip *fptr)
7364 {
7365 	int				i;
7366 	struct fcip_routing_table	*frp;
7367 
7368 	ASSERT(mutex_owned(&fptr->fcip_rt_mutex));
7369 
7370 	for (i = 0; i < FCIP_RT_HASH_ELEMS; i++) {
7371 		frp = fptr->fcip_rtable[i];
7372 		while (frp) {
7373 			if (frp->fcipr_state == FCIP_RT_LOGIN_PROGRESS) {
7374 				/* Found an entry where PLOGI is in progress */
7375 				return (1);
7376 			}
7377 			frp = frp->fcipr_next;
7378 		}
7379 	}
7380 
7381 	return (0);
7382 }
7383 
7384 /*
7385  * Walk through the fcip port global list and check if the given port exists in
7386  * the list. Returns "0" if port exists and "1" if otherwise.
7387  */
7388 static int
7389 fcip_check_port_exists(struct fcip *fptr)
7390 {
7391 	fcip_port_info_t	*cur_fport;
7392 	fcip_port_info_t	*fport;
7393 
7394 	mutex_enter(&fcip_global_mutex);
7395 	fport = fptr->fcip_port_info;
7396 	cur_fport = fcip_port_head;
7397 	while (cur_fport != NULL) {
7398 		if (cur_fport == fport) {
7399 			/* Found */
7400 			mutex_exit(&fcip_global_mutex);
7401 			return (0);
7402 		} else {
7403 			cur_fport = cur_fport->fcipp_next;
7404 		}
7405 	}
7406 	mutex_exit(&fcip_global_mutex);
7407 
7408 	return (1);
7409 }
7410 
7411 /*
7412  * Constructor to initialize the sendup elements for callback into
7413  * modules upstream
7414  */
7415 
7416 /* ARGSUSED */
7417 static int
7418 fcip_sendup_constructor(void *buf, void *arg, int flags)
7419 {
7420 	struct fcip_sendup_elem	*msg_elem = (struct fcip_sendup_elem *)buf;
7421 	fcip_port_info_t	*fport = (fcip_port_info_t *)arg;
7422 
7423 	ASSERT(fport != NULL);
7424 
7425 	msg_elem->fcipsu_mp = NULL;
7426 	msg_elem->fcipsu_func = NULL;
7427 	msg_elem->fcipsu_next = NULL;
7428 
7429 	return (FCIP_SUCCESS);
7430 }
7431