1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /* Copyright 2009 QLogic Corporation */
23 
24 /*
25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 #pragma ident	"Copyright 2009 QLogic Corporation; ql_api.c"
30 
31 /*
32  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
33  *
34  * ***********************************************************************
35  * *									**
36  * *				NOTICE					**
37  * *		COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION		**
38  * *			ALL RIGHTS RESERVED				**
39  * *									**
40  * ***********************************************************************
41  *
42  */
43 
44 #include <ql_apps.h>
45 #include <ql_api.h>
46 #include <ql_debug.h>
47 #include <ql_init.h>
48 #include <ql_iocb.h>
49 #include <ql_ioctl.h>
50 #include <ql_isr.h>
51 #include <ql_mbx.h>
52 #include <ql_xioctl.h>
53 
54 /*
55  * Solaris external defines.
56  */
57 extern pri_t minclsyspri;
58 extern pri_t maxclsyspri;
59 
60 /*
61  * dev_ops functions prototypes
62  */
63 static int ql_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
64 static int ql_attach(dev_info_t *, ddi_attach_cmd_t);
65 static int ql_detach(dev_info_t *, ddi_detach_cmd_t);
66 static int ql_power(dev_info_t *, int, int);
67 static int ql_quiesce(dev_info_t *);
68 
69 /*
70  * FCA functions prototypes exported by means of the transport table
71  */
72 static opaque_t ql_bind_port(dev_info_t *, fc_fca_port_info_t *,
73     fc_fca_bind_info_t *);
74 static void ql_unbind_port(opaque_t);
75 static int ql_init_pkt(opaque_t, fc_packet_t *, int);
76 static int ql_un_init_pkt(opaque_t, fc_packet_t *);
77 static int ql_els_send(opaque_t, fc_packet_t *);
78 static int ql_get_cap(opaque_t, char *, void *);
79 static int ql_set_cap(opaque_t, char *, void *);
80 static int ql_getmap(opaque_t, fc_lilpmap_t *);
81 static int ql_transport(opaque_t, fc_packet_t *);
82 static int ql_ub_alloc(opaque_t, uint64_t *, uint32_t, uint32_t *, uint32_t);
83 static int ql_ub_free(opaque_t, uint32_t, uint64_t *);
84 static int ql_ub_release(opaque_t, uint32_t, uint64_t *);
85 static int ql_abort(opaque_t, fc_packet_t *, int);
86 static int ql_reset(opaque_t, uint32_t);
87 static int ql_port_manage(opaque_t, fc_fca_pm_t *);
88 static opaque_t ql_get_device(opaque_t, fc_portid_t);
89 
90 /*
91  * FCA Driver Support Function Prototypes.
92  */
93 static uint16_t	ql_wait_outstanding(ql_adapter_state_t *);
94 static void ql_task_mgmt(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
95     ql_srb_t *);
96 static void ql_task_daemon(void *);
97 static void ql_task_thread(ql_adapter_state_t *);
98 static void ql_unsol_callback(ql_srb_t *);
99 static void ql_free_unsolicited_buffer(ql_adapter_state_t *,
100     fc_unsol_buf_t *);
101 static void ql_timer(void *);
102 static void ql_watchdog(ql_adapter_state_t *, uint32_t *, uint32_t *);
103 static void ql_cmd_timeout(ql_adapter_state_t *, ql_tgt_t *q, ql_srb_t *,
104     uint32_t *, uint32_t *);
105 static void ql_halt(ql_adapter_state_t *, int);
106 static int ql_els_plogi(ql_adapter_state_t *, fc_packet_t *);
107 static int ql_els_flogi(ql_adapter_state_t *, fc_packet_t *);
108 static int ql_els_logo(ql_adapter_state_t *, fc_packet_t *);
109 static int ql_els_prli(ql_adapter_state_t *, fc_packet_t *);
110 static int ql_els_prlo(ql_adapter_state_t *, fc_packet_t *);
111 static int ql_els_adisc(ql_adapter_state_t *, fc_packet_t *);
112 static int ql_els_linit(ql_adapter_state_t *, fc_packet_t *);
113 static int ql_els_lpc(ql_adapter_state_t *, fc_packet_t *);
114 static int ql_els_lsts(ql_adapter_state_t *, fc_packet_t *);
115 static int ql_els_scr(ql_adapter_state_t *, fc_packet_t *);
116 static int ql_els_rscn(ql_adapter_state_t *, fc_packet_t *);
117 static int ql_els_farp_req(ql_adapter_state_t *, fc_packet_t *);
118 static int ql_els_farp_reply(ql_adapter_state_t *, fc_packet_t *);
119 static int ql_els_rls(ql_adapter_state_t *, fc_packet_t *);
120 static int ql_els_rnid(ql_adapter_state_t *, fc_packet_t *);
121 static int ql_login_port(ql_adapter_state_t *, port_id_t);
122 static int ql_login_fabric_port(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
123 static int ql_logout_port(ql_adapter_state_t *, port_id_t);
124 static ql_lun_t *ql_lun_queue(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
125 static int ql_fcp_scsi_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
126 static int ql_fcp_ip_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
127 static int ql_fc_services(ql_adapter_state_t *, fc_packet_t *);
128 static int ql_poll_cmd(ql_adapter_state_t *, ql_srb_t *, time_t);
129 static int ql_start_cmd(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
130     ql_srb_t *);
131 static int ql_kstat_update(kstat_t *, int);
132 static ql_adapter_state_t *ql_fca_handle_to_state(opaque_t);
133 static ql_adapter_state_t *ql_cmd_setup(opaque_t, fc_packet_t *, int *);
134 static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, uint8_t);
135 static void ql_rst_aen(ql_adapter_state_t *);
136 static void ql_restart_queues(ql_adapter_state_t *);
137 static void ql_abort_queues(ql_adapter_state_t *);
138 static void ql_idle_check(ql_adapter_state_t *);
139 static int ql_loop_resync(ql_adapter_state_t *);
140 static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
141 static size_t ql_25xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
142 static int ql_save_config_regs(dev_info_t *);
143 static int ql_restore_config_regs(dev_info_t *);
144 static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
145 static int ql_handle_rscn_update(ql_adapter_state_t *);
146 static int ql_send_plogi(ql_adapter_state_t *, ql_tgt_t *, ql_head_t *);
147 static int ql_process_rscn_for_device(ql_adapter_state_t *, ql_tgt_t *);
148 static int ql_dump_firmware(ql_adapter_state_t *);
149 static int ql_process_logo_for_device(ql_adapter_state_t *, ql_tgt_t *);
150 static int ql_2200_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
151 static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
152 static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
153 static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
154 static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
155     void *);
156 static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
157     uint8_t);
158 static int ql_busy_plogi(ql_adapter_state_t *, fc_packet_t *, ql_tgt_t *);
159 static int ql_suspend_adapter(ql_adapter_state_t *);
160 static int ql_bstr_to_dec(char *, uint32_t *, uint32_t);
161 static void ql_update_rscn(ql_adapter_state_t *, fc_affected_id_t *);
162 int ql_alloc_dma_resouce(ql_adapter_state_t *, dma_mem_t *, int);
163 static int ql_bind_dma_buffer(ql_adapter_state_t *, dma_mem_t *, int);
164 static void ql_unbind_dma_buffer(ql_adapter_state_t *, dma_mem_t *);
165 static void ql_timeout_insert(ql_adapter_state_t *, ql_tgt_t *, ql_srb_t *);
166 static int ql_setup_interrupts(ql_adapter_state_t *);
167 static int ql_setup_msi(ql_adapter_state_t *);
168 static int ql_setup_msix(ql_adapter_state_t *);
169 static int ql_setup_fixed(ql_adapter_state_t *);
170 static void ql_release_intr(ql_adapter_state_t *);
171 static void ql_disable_intr(ql_adapter_state_t *);
172 static int ql_legacy_intr(ql_adapter_state_t *);
173 static int ql_init_mutex(ql_adapter_state_t *);
174 static void ql_destroy_mutex(ql_adapter_state_t *);
175 static void ql_iidma(ql_adapter_state_t *);
176 
177 static int ql_n_port_plogi(ql_adapter_state_t *);
178 static void ql_fca_isp_els_request(ql_adapter_state_t *, fc_packet_t *,
179     els_descriptor_t *);
180 static void ql_isp_els_request_ctor(els_descriptor_t *,
181     els_passthru_entry_t *);
182 static int ql_p2p_plogi(ql_adapter_state_t *, fc_packet_t *);
183 /*
184  * Global data
185  */
186 static uint8_t	ql_enable_pm = 1;
187 static int	ql_flash_sbus_fpga = 0;
188 uint32_t	ql_os_release_level;
189 uint32_t	ql_disable_aif = 0;
190 uint32_t	ql_disable_msi = 0;
191 uint32_t	ql_disable_msix = 0;
192 
193 /* Timer routine variables. */
194 static timeout_id_t	ql_timer_timeout_id = NULL;
195 static clock_t		ql_timer_ticks;
196 
197 /* Soft state head pointer. */
198 void *ql_state = NULL;
199 
200 /* Head adapter link. */
201 ql_head_t ql_hba = {
202 	NULL,
203 	NULL
204 };
205 
206 /* Global hba index */
207 uint32_t ql_gfru_hba_index = 1;
208 
209 /*
210  * Some IP defines and globals
211  */
212 uint32_t	ql_ip_buffer_count = 128;
213 uint32_t	ql_ip_low_water = 10;
214 uint8_t		ql_ip_fast_post_count = 5;
215 static int	ql_ip_mtu = 65280;		/* equivalent to FCIPMTU */
216 
217 /* Device AL_PA to Device Head Queue index array. */
218 uint8_t ql_alpa_to_index[] = {
219 	0x7e, 0x7d, 0x7c, 0x00, 0x7b, 0x01, 0x02, 0x03, 0x7a, 0x04,
220 	0x05, 0x06, 0x07, 0x08, 0x09, 0x79, 0x78, 0x0a, 0x0b, 0x0c,
221 	0x0d, 0x0e, 0x0f, 0x77, 0x76, 0x10, 0x11, 0x75, 0x12, 0x74,
222 	0x73, 0x72, 0x13, 0x14, 0x15, 0x71, 0x16, 0x70, 0x6f, 0x6e,
223 	0x17, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x18, 0x19, 0x67,
224 	0x66, 0x65, 0x64, 0x63, 0x62, 0x20, 0x21, 0x61, 0x60, 0x23,
225 	0x5f, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x5e, 0x2a, 0x5d,
226 	0x5c, 0x5b, 0x2b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x2c,
227 	0x2d, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x2e, 0x2f, 0x4e,
228 	0x4d, 0x30, 0x4c, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x4b,
229 	0x37, 0x4a, 0x49, 0x48, 0x38, 0x47, 0x46, 0x45, 0x44, 0x43,
230 	0x42, 0x39, 0x3a, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b,
231 	0x3c, 0x3b, 0x3a, 0x3d, 0x39, 0x3e, 0x3f, 0x40, 0x38, 0x37,
232 	0x36, 0x41, 0x35, 0x42, 0x43, 0x44, 0x34, 0x45, 0x46, 0x47,
233 	0x48, 0x49, 0x4a, 0x33, 0x32, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
234 	0x50, 0x31, 0x30, 0x51, 0x52, 0x2f, 0x53, 0x2e, 0x2d, 0x2c,
235 	0x54, 0x55, 0x56, 0x2b, 0x57, 0x2a, 0x29, 0x28, 0x58, 0x27,
236 	0x26, 0x25, 0x24, 0x23, 0x22, 0x59, 0x5a, 0x21, 0x20, 0x1f,
237 	0x1e, 0x1d, 0x1c, 0x5b, 0x5c, 0x1b, 0x1a, 0x5d, 0x19, 0x5e,
238 	0x5f, 0x60, 0x61, 0x62, 0x63, 0x18, 0x64, 0x17, 0x16, 0x15,
239 	0x65, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x66, 0x67, 0x0e,
240 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x68, 0x69, 0x08, 0x07, 0x6a,
241 	0x06, 0x6b, 0x6c, 0x6d, 0x05, 0x04, 0x03, 0x6e, 0x02, 0x6f,
242 	0x70, 0x71, 0x01, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x00,
243 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f, 0x80, 0x00, 0x01,
244 	0x02, 0x03, 0x80, 0x7f, 0x7e, 0x04
245 };
246 
247 /* Device loop_id to ALPA array. */
248 static uint8_t ql_index_to_alpa[] = {
249 	0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
250 	0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
251 	0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
252 	0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
253 	0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
254 	0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
255 	0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
256 	0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
257 	0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
258 	0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
259 	0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
260 	0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
261 	0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
262 };
263 
264 /* 2200 register offsets */
265 static reg_off_t reg_off_2200 = {
266 	0x00, 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
267 	0x18, 0x18, 0x1A, 0x1A, /* req in, out, resp in, out */
268 	0x00, 0x00, /* intr info lo, hi */
269 	24, /* Number of mailboxes */
270 	/* Mailbox register offsets */
271 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
272 	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
273 	0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
274 	/* 2200 does not have mailbox 24-31 */
275 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 	0x96, 0xa4, 0xb0, 0xb8, 0xc0, 0xcc, 0xce,
277 	/* host to host sema */
278 	0x00,
279 	/* 2200 does not have pri_req_in, pri_req_out, */
280 	/* atio_req_in, atio_req_out, io_base_addr */
281 	0xff, 0xff, 0xff, 0xff,	0xff
282 };
283 
284 /* 2300 register offsets */
285 static reg_off_t reg_off_2300 = {
286 	0x00, 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
287 	0x10, 0x12, 0x14, 0x16, /* req in, out, resp in, out */
288 	0x18, 0x1A, /* intr info lo, hi */
289 	32, /* Number of mailboxes */
290 	/* Mailbox register offsets */
291 	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
292 	0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
293 	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
294 	0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
295 	0x96, 0xa4, 0xb0, 0x80, 0xc0, 0xcc, 0xce,
296 	/* host to host sema */
297 	0x1c,
298 	/* 2300 does not have pri_req_in, pri_req_out, */
299 	/* atio_req_in, atio_req_out, io_base_addr */
300 	0xff, 0xff, 0xff, 0xff,	0xff
301 };
302 
303 /* 2400/2500 register offsets */
304 reg_off_t reg_off_2400_2500 = {
305 	0x00, 0x04,		/* flash_address, flash_data */
306 	0x08, 0x0c, 0x10,	/* ctrl_status, ictrl, istatus */
307 	/* 2400 does not have semaphore, nvram */
308 	0x14, 0x18,
309 	0x1c, 0x20, 0x24, 0x28, /* req_in, req_out, resp_in, resp_out */
310 	0x44, 0x46,		/* intr info lo, hi */
311 	32,			/* Number of mailboxes */
312 	/* Mailbox register offsets */
313 	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
314 	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
315 	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
316 	0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
317 	/* 2400 does not have fpm_diag_config, pcr, mctr, fb_cmd */
318 	0xff, 0xff, 0xff, 0xff,
319 	0x48, 0x4c, 0x50,	/* hccr, gpiod, gpioe */
320 	0xff,			/* host to host sema */
321 	0x2c, 0x30,		/* pri_req_in, pri_req_out */
322 	0x3c, 0x40,		/* atio_req_in, atio_req_out */
323 	0x54			/* io_base_addr */
324 };
325 
326 /* mutex for protecting variables shared by all instances of the driver */
327 kmutex_t ql_global_mutex;
328 kmutex_t ql_global_hw_mutex;
329 kmutex_t ql_global_el_mutex;
330 
331 /* DMA access attribute structure. */
332 static ddi_device_acc_attr_t ql_dev_acc_attr = {
333 	DDI_DEVICE_ATTR_V0,
334 	DDI_STRUCTURE_LE_ACC,
335 	DDI_STRICTORDER_ACC
336 };
337 
338 /* I/O DMA attributes structures. */
339 static ddi_dma_attr_t ql_64bit_io_dma_attr = {
340 	DMA_ATTR_V0,			/* dma_attr_version */
341 	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
342 	QL_DMA_HIGH_64BIT_ADDRESS,	/* high DMA address range */
343 	QL_DMA_XFER_COUNTER,		/* DMA counter register */
344 	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
345 	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
346 	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
347 	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
348 	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
349 	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
350 	QL_DMA_GRANULARITY,		/* granularity of device */
351 	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
352 };
353 
354 static ddi_dma_attr_t ql_32bit_io_dma_attr = {
355 	DMA_ATTR_V0,			/* dma_attr_version */
356 	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
357 	QL_DMA_HIGH_32BIT_ADDRESS,	/* high DMA address range */
358 	QL_DMA_XFER_COUNTER,		/* DMA counter register */
359 	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
360 	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
361 	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
362 	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
363 	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
364 	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
365 	QL_DMA_GRANULARITY,		/* granularity of device */
366 	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
367 };
368 
369 /* Load the default dma attributes */
370 static	ddi_dma_attr_t	ql_32fcsm_cmd_dma_attr;
371 static	ddi_dma_attr_t	ql_64fcsm_cmd_dma_attr;
372 static	ddi_dma_attr_t	ql_32fcsm_rsp_dma_attr;
373 static	ddi_dma_attr_t	ql_64fcsm_rsp_dma_attr;
374 static	ddi_dma_attr_t	ql_32fcip_cmd_dma_attr;
375 static	ddi_dma_attr_t	ql_64fcip_cmd_dma_attr;
376 static	ddi_dma_attr_t	ql_32fcip_rsp_dma_attr;
377 static	ddi_dma_attr_t	ql_64fcip_rsp_dma_attr;
378 static	ddi_dma_attr_t	ql_32fcp_cmd_dma_attr;
379 static	ddi_dma_attr_t	ql_64fcp_cmd_dma_attr;
380 static	ddi_dma_attr_t	ql_32fcp_rsp_dma_attr;
381 static	ddi_dma_attr_t	ql_64fcp_rsp_dma_attr;
382 static	ddi_dma_attr_t	ql_32fcp_data_dma_attr;
383 static	ddi_dma_attr_t	ql_64fcp_data_dma_attr;
384 
385 /* Static declarations of cb_ops entry point functions... */
386 static struct cb_ops ql_cb_ops = {
387 	ql_open,			/* b/c open */
388 	ql_close,			/* b/c close */
389 	nodev,				/* b strategy */
390 	nodev,				/* b print */
391 	nodev,				/* b dump */
392 	nodev,				/* c read */
393 	nodev,				/* c write */
394 	ql_ioctl,			/* c ioctl */
395 	nodev,				/* c devmap */
396 	nodev,				/* c mmap */
397 	nodev,				/* c segmap */
398 	nochpoll,			/* c poll */
399 	nodev,				/* cb_prop_op */
400 	NULL,				/* streamtab  */
401 	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
402 	CB_REV,				/* cb_ops revision */
403 	nodev,				/* c aread */
404 	nodev				/* c awrite */
405 };
406 
407 /* Static declarations of dev_ops entry point functions... */
408 static struct dev_ops ql_devops = {
409 	DEVO_REV,			/* devo_rev */
410 	0,				/* refcnt */
411 	ql_getinfo,			/* getinfo */
412 	nulldev,			/* identify */
413 	nulldev,			/* probe */
414 	ql_attach,			/* attach */
415 	ql_detach,			/* detach */
416 	nodev,				/* reset */
417 	&ql_cb_ops,			/* char/block ops */
418 	NULL,				/* bus operations */
419 	ql_power,			/* power management */
420 	ql_quiesce			/* quiesce device */
421 };
422 
423 /* ELS command code to text converter */
424 cmd_table_t els_cmd_tbl[] = ELS_CMD_TABLE();
425 /* Mailbox command code to text converter */
426 cmd_table_t mbox_cmd_tbl[] = MBOX_CMD_TABLE();
427 
428 char qlc_driver_version[] = QL_VERSION;
429 
430 /*
431  * Loadable Driver Interface Structures.
432  * Declare and initialize the module configuration section...
433  */
434 static struct modldrv modldrv = {
435 	&mod_driverops,				/* type of module: driver */
436 	"SunFC Qlogic FCA v" QL_VERSION,	/* name of module */
437 	&ql_devops				/* driver dev_ops */
438 };
439 
440 static struct modlinkage modlinkage = {
441 	MODREV_1,
442 	&modldrv,
443 	NULL
444 };
445 
446 /* ************************************************************************ */
447 /*				Loadable Module Routines.		    */
448 /* ************************************************************************ */
449 
450 /*
451  * _init
452  *	Initializes a loadable module. It is called before any other
453  *	routine in a loadable module.
454  *
455  * Returns:
456  *	0 = success
457  *
458  * Context:
459  *	Kernel context.
460  */
461 int
462 _init(void)
463 {
464 	uint16_t	w16;
465 	int		rval = 0;
466 
467 	/* Get OS major release level. */
468 	for (w16 = 0; w16 < sizeof (utsname.release); w16++) {
469 		if (utsname.release[w16] == '.') {
470 			w16++;
471 			break;
472 		}
473 	}
474 	if (w16 < sizeof (utsname.release)) {
475 		(void) ql_bstr_to_dec(&utsname.release[w16],
476 		    &ql_os_release_level, 0);
477 	} else {
478 		ql_os_release_level = 0;
479 	}
480 	if (ql_os_release_level < 6) {
481 		cmn_err(CE_WARN, "%s Unsupported OS release level = %d",
482 		    QL_NAME, ql_os_release_level);
483 		rval = EINVAL;
484 	}
485 	if (ql_os_release_level == 6) {
486 		ql_32bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
487 		ql_64bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
488 	}
489 
490 	if (rval == 0) {
491 		rval = ddi_soft_state_init(&ql_state,
492 		    sizeof (ql_adapter_state_t), 0);
493 	}
494 	if (rval == 0) {
495 		/* allow the FC Transport to tweak the dev_ops */
496 		fc_fca_init(&ql_devops);
497 
498 		mutex_init(&ql_global_mutex, NULL, MUTEX_DRIVER, NULL);
499 		mutex_init(&ql_global_hw_mutex, NULL, MUTEX_DRIVER, NULL);
500 		mutex_init(&ql_global_el_mutex, NULL, MUTEX_DRIVER, NULL);
501 		rval = mod_install(&modlinkage);
502 		if (rval != 0) {
503 			mutex_destroy(&ql_global_hw_mutex);
504 			mutex_destroy(&ql_global_mutex);
505 			mutex_destroy(&ql_global_el_mutex);
506 			ddi_soft_state_fini(&ql_state);
507 		} else {
508 			/*EMPTY*/
509 			ql_32fcsm_cmd_dma_attr = ql_32bit_io_dma_attr;
510 			ql_64fcsm_cmd_dma_attr = ql_64bit_io_dma_attr;
511 			ql_32fcsm_rsp_dma_attr = ql_32bit_io_dma_attr;
512 			ql_64fcsm_rsp_dma_attr = ql_64bit_io_dma_attr;
513 			ql_32fcip_cmd_dma_attr = ql_32bit_io_dma_attr;
514 			ql_64fcip_cmd_dma_attr = ql_64bit_io_dma_attr;
515 			ql_32fcip_rsp_dma_attr = ql_32bit_io_dma_attr;
516 			ql_64fcip_rsp_dma_attr = ql_64bit_io_dma_attr;
517 			ql_32fcp_cmd_dma_attr = ql_32bit_io_dma_attr;
518 			ql_64fcp_cmd_dma_attr = ql_64bit_io_dma_attr;
519 			ql_32fcp_rsp_dma_attr = ql_32bit_io_dma_attr;
520 			ql_64fcp_rsp_dma_attr = ql_64bit_io_dma_attr;
521 			ql_32fcp_data_dma_attr = ql_32bit_io_dma_attr;
522 			ql_64fcp_data_dma_attr = ql_64bit_io_dma_attr;
523 			ql_32fcsm_cmd_dma_attr.dma_attr_sgllen =
524 			    ql_64fcsm_cmd_dma_attr.dma_attr_sgllen =
525 			    QL_FCSM_CMD_SGLLEN;
526 			ql_32fcsm_rsp_dma_attr.dma_attr_sgllen =
527 			    ql_64fcsm_rsp_dma_attr.dma_attr_sgllen =
528 			    QL_FCSM_RSP_SGLLEN;
529 			ql_32fcip_cmd_dma_attr.dma_attr_sgllen =
530 			    ql_64fcip_cmd_dma_attr.dma_attr_sgllen =
531 			    QL_FCIP_CMD_SGLLEN;
532 			ql_32fcip_rsp_dma_attr.dma_attr_sgllen =
533 			    ql_64fcip_rsp_dma_attr.dma_attr_sgllen =
534 			    QL_FCIP_RSP_SGLLEN;
535 			ql_32fcp_cmd_dma_attr.dma_attr_sgllen =
536 			    ql_64fcp_cmd_dma_attr.dma_attr_sgllen =
537 			    QL_FCP_CMD_SGLLEN;
538 			ql_32fcp_rsp_dma_attr.dma_attr_sgllen =
539 			    ql_64fcp_rsp_dma_attr.dma_attr_sgllen =
540 			    QL_FCP_RSP_SGLLEN;
541 		}
542 	}
543 
544 	if (rval != 0) {
545 		cmn_err(CE_CONT, "?Unable to install/attach driver '%s'",
546 		    QL_NAME);
547 	}
548 
549 	return (rval);
550 }
551 
552 /*
553  * _fini
554  *	Prepares a module for unloading. It is called when the system
555  *	wants to unload a module. If the module determines that it can
556  *	be unloaded, then _fini() returns the value returned by
557  *	mod_remove(). Upon successful return from _fini() no other
558  *	routine in the module will be called before _init() is called.
559  *
560  * Returns:
561  *	0 = success
562  *
563  * Context:
564  *	Kernel context.
565  */
566 int
567 _fini(void)
568 {
569 	int	rval;
570 
571 	rval = mod_remove(&modlinkage);
572 	if (rval == 0) {
573 		mutex_destroy(&ql_global_hw_mutex);
574 		mutex_destroy(&ql_global_mutex);
575 		mutex_destroy(&ql_global_el_mutex);
576 		ddi_soft_state_fini(&ql_state);
577 	}
578 
579 	return (rval);
580 }
581 
582 /*
583  * _info
584  *	Returns information about loadable module.
585  *
586  * Input:
587  *	modinfo = pointer to module information structure.
588  *
589  * Returns:
590  *	Value returned by mod_info().
591  *
592  * Context:
593  *	Kernel context.
594  */
595 int
596 _info(struct modinfo *modinfop)
597 {
598 	return (mod_info(&modlinkage, modinfop));
599 }
600 
601 /* ************************************************************************ */
602 /*			dev_ops functions				    */
603 /* ************************************************************************ */
604 
605 /*
606  * ql_getinfo
607  *	Returns the pointer associated with arg when cmd is
608  *	set to DDI_INFO_DEVT2DEVINFO, or it should return the
609  *	instance number associated with arg when cmd is set
610  *	to DDI_INFO_DEV2INSTANCE.
611  *
612  * Input:
613  *	dip = Do not use.
614  *	cmd = command argument.
615  *	arg = command specific argument.
616  *	resultp = pointer to where request information is stored.
617  *
618  * Returns:
619  *	DDI_SUCCESS or DDI_FAILURE.
620  *
621  * Context:
622  *	Kernel context.
623  */
624 /* ARGSUSED */
625 static int
626 ql_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
627 {
628 	ql_adapter_state_t	*ha;
629 	int			minor;
630 	int			rval = DDI_FAILURE;
631 
632 	minor = (int)(getminor((dev_t)arg));
633 	ha = ddi_get_soft_state(ql_state, minor);
634 	if (ha == NULL) {
635 		QL_PRINT_2(CE_CONT, "failed, unknown minor=%d\n",
636 		    getminor((dev_t)arg));
637 		*resultp = NULL;
638 		return (rval);
639 	}
640 
641 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
642 
643 	switch (cmd) {
644 	case DDI_INFO_DEVT2DEVINFO:
645 		*resultp = ha->dip;
646 		rval = DDI_SUCCESS;
647 		break;
648 	case DDI_INFO_DEVT2INSTANCE:
649 		*resultp = (void *)(uintptr_t)(ha->instance);
650 		rval = DDI_SUCCESS;
651 		break;
652 	default:
653 		EL(ha, "failed, unsupported cmd=%d\n", cmd);
654 		rval = DDI_FAILURE;
655 		break;
656 	}
657 
658 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
659 
660 	return (rval);
661 }
662 
663 /*
664  * ql_attach
665  *	Configure and attach an instance of the driver
666  *	for a port.
667  *
668  * Input:
669  *	dip = pointer to device information structure.
670  *	cmd = attach type.
671  *
672  * Returns:
673  *	DDI_SUCCESS or DDI_FAILURE.
674  *
675  * Context:
676  *	Kernel context.
677  */
678 static int
679 ql_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
680 {
681 	uint32_t		size;
682 	int			rval;
683 	int			instance;
684 	uint_t			progress = 0;
685 	char			*buf;
686 	ushort_t		caps_ptr, cap;
687 	fc_fca_tran_t		*tran;
688 	ql_adapter_state_t	*ha = NULL;
689 
690 	static char *pmcomps[] = {
691 		NULL,
692 		PM_LEVEL_D3_STR,		/* Device OFF */
693 		PM_LEVEL_D0_STR,		/* Device ON */
694 	};
695 
696 	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n",
697 	    ddi_get_instance(dip), cmd);
698 
699 	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
700 
701 	switch (cmd) {
702 	case DDI_ATTACH:
703 		/* first get the instance */
704 		instance = ddi_get_instance(dip);
705 
706 		cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
707 		    QL_NAME, instance, QL_VERSION);
708 
709 		/* Correct OS version? */
710 		if (ql_os_release_level != 11) {
711 			cmn_err(CE_WARN, "%s(%d): This driver is for Solaris "
712 			    "11", QL_NAME, instance);
713 			goto attach_failed;
714 		}
715 
716 		/* Hardware is installed in a DMA-capable slot? */
717 		if (ddi_slaveonly(dip) == DDI_SUCCESS) {
718 			cmn_err(CE_WARN, "%s(%d): slave only", QL_NAME,
719 			    instance);
720 			goto attach_failed;
721 		}
722 
723 		/* No support for high-level interrupts */
724 		if (ddi_intr_hilevel(dip, 0) != 0) {
725 			cmn_err(CE_WARN, "%s(%d): High level interrupt"
726 			    " not supported", QL_NAME, instance);
727 			goto attach_failed;
728 		}
729 
730 		/* Allocate our per-device-instance structure */
731 		if (ddi_soft_state_zalloc(ql_state,
732 		    instance) != DDI_SUCCESS) {
733 			cmn_err(CE_WARN, "%s(%d): soft state alloc failed",
734 			    QL_NAME, instance);
735 			goto attach_failed;
736 		}
737 		progress |= QL_SOFT_STATE_ALLOCED;
738 
739 		ha = ddi_get_soft_state(ql_state, instance);
740 		if (ha == NULL) {
741 			cmn_err(CE_WARN, "%s(%d): can't get soft state",
742 			    QL_NAME, instance);
743 			goto attach_failed;
744 		}
745 		ha->dip = dip;
746 		ha->instance = instance;
747 		ha->hba.base_address = ha;
748 		ha->pha = ha;
749 
750 		if (ql_el_trace_desc_ctor(ha) != DDI_SUCCESS) {
751 			cmn_err(CE_WARN, "%s(%d): can't setup el tracing",
752 			    QL_NAME, instance);
753 			goto attach_failed;
754 		}
755 
756 		/* Get extended logging and dump flags. */
757 		ql_common_properties(ha);
758 
759 		if (strcmp(ddi_driver_name(ddi_get_parent(dip)),
760 		    "sbus") == 0) {
761 			EL(ha, "%s SBUS card detected", QL_NAME);
762 			ha->cfg_flags |= CFG_SBUS_CARD;
763 		}
764 
765 		ha->dev = kmem_zalloc(sizeof (*ha->dev) *
766 		    DEVICE_HEAD_LIST_SIZE, KM_SLEEP);
767 
768 		ha->outstanding_cmds = kmem_zalloc(
769 		    sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS,
770 		    KM_SLEEP);
771 
772 		ha->ub_array = kmem_zalloc(sizeof (*ha->ub_array) *
773 		    QL_UB_LIMIT, KM_SLEEP);
774 
775 		ha->adapter_stats = kmem_zalloc(sizeof (*ha->adapter_stats),
776 		    KM_SLEEP);
777 
778 		(void) ddi_pathname(dip, buf);
779 		ha->devpath = kmem_zalloc(strlen(buf)+1, KM_SLEEP);
780 		if (ha->devpath == NULL) {
781 			EL(ha, "devpath mem alloc failed\n");
782 		} else {
783 			(void) strcpy(ha->devpath, buf);
784 			EL(ha, "devpath is: %s\n", ha->devpath);
785 		}
786 
787 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
788 			/*
789 			 * For cards where PCI is mapped to sbus e.g. Ivory.
790 			 *
791 			 * 0x00	: 0x000 - 0x0FF PCI Config Space for 2200
792 			 *	: 0x100 - 0x3FF PCI IO space for 2200
793 			 * 0x01	: 0x000 - 0x0FF PCI Config Space for fpga
794 			 *	: 0x100 - 0x3FF PCI IO Space for fpga
795 			 */
796 			if (ddi_regs_map_setup(dip, 0, (caddr_t *)&ha->iobase,
797 			    0x100, 0x300, &ql_dev_acc_attr, &ha->dev_handle)
798 			    != DDI_SUCCESS) {
799 				cmn_err(CE_WARN, "%s(%d): Unable to map device"
800 				    " registers", QL_NAME, instance);
801 				goto attach_failed;
802 			}
803 			if (ddi_regs_map_setup(dip, 1,
804 			    (caddr_t *)&ha->sbus_fpga_iobase, 0, 0x400,
805 			    &ql_dev_acc_attr, &ha->sbus_fpga_dev_handle)
806 			    != DDI_SUCCESS) {
807 				/* We should not fail attach here */
808 				cmn_err(CE_WARN, "%s(%d): Unable to map FPGA",
809 				    QL_NAME, instance);
810 				ha->sbus_fpga_iobase = NULL;
811 			}
812 			progress |= QL_REGS_MAPPED;
813 		} else {
814 			/*
815 			 * Setup the ISP2200 registers address mapping to be
816 			 * accessed by this particular driver.
817 			 * 0x0   Configuration Space
818 			 * 0x1   I/O Space
819 			 * 0x2   32-bit Memory Space address
820 			 * 0x3   64-bit Memory Space address
821 			 */
822 			if (ddi_regs_map_setup(dip, 2, (caddr_t *)&ha->iobase,
823 			    0, 0x100, &ql_dev_acc_attr,
824 			    &ha->dev_handle) != DDI_SUCCESS) {
825 				cmn_err(CE_WARN, "%s(%d): regs_map_setup "
826 				    "failed", QL_NAME, instance);
827 				goto attach_failed;
828 			}
829 			progress |= QL_REGS_MAPPED;
830 
831 			/*
832 			 * We need I/O space mappings for 23xx HBAs for
833 			 * loading flash (FCode). The chip has a bug due to
834 			 * which loading flash fails through mem space
835 			 * mappings in PCI-X mode.
836 			 */
837 			if (ddi_regs_map_setup(dip, 1,
838 			    (caddr_t *)&ha->iomap_iobase, 0, 0x100,
839 			    &ql_dev_acc_attr,
840 			    &ha->iomap_dev_handle) != DDI_SUCCESS) {
841 				cmn_err(CE_WARN, "%s(%d): regs_map_setup(I/O)"
842 				    " failed", QL_NAME, instance);
843 				goto attach_failed;
844 			}
845 			progress |= QL_IOMAP_IOBASE_MAPPED;
846 		}
847 
848 		/*
849 		 * We should map config space before adding interrupt
850 		 * So that the chip type (2200 or 2300) can be determined
851 		 * before the interrupt routine gets a chance to execute.
852 		 */
853 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
854 			if (ddi_regs_map_setup(dip, 0,
855 			    (caddr_t *)&ha->sbus_config_base, 0, 0x100,
856 			    &ql_dev_acc_attr, &ha->sbus_config_handle) !=
857 			    DDI_SUCCESS) {
858 				cmn_err(CE_WARN, "%s(%d): Unable to map sbus "
859 				    "config registers", QL_NAME, instance);
860 				goto attach_failed;
861 			}
862 		} else {
863 			if (pci_config_setup(ha->dip, &ha->pci_handle) !=
864 			    DDI_SUCCESS) {
865 				cmn_err(CE_WARN, "%s(%d): can't setup PCI "
866 				    "config space", QL_NAME, instance);
867 				goto attach_failed;
868 			}
869 		}
870 		progress |= QL_CONFIG_SPACE_SETUP;
871 
872 		ha->subsys_id = (uint16_t)ql_pci_config_get16(ha,
873 		    PCI_CONF_SUBSYSID);
874 		ha->subven_id = (uint16_t)ql_pci_config_get16(ha,
875 		    PCI_CONF_SUBVENID);
876 		ha->ven_id = (uint16_t)ql_pci_config_get16(ha,
877 		    PCI_CONF_VENID);
878 		ha->device_id = (uint16_t)ql_pci_config_get16(ha,
879 		    PCI_CONF_DEVID);
880 		ha->rev_id = (uint8_t)ql_pci_config_get8(ha,
881 		    PCI_CONF_REVID);
882 
883 		EL(ha, "ISP%x chip detected (RevID=%x, VenID=%x, SVenID=%x, "
884 		    "SSysID=%x)\n", ha->device_id, ha->rev_id, ha->ven_id,
885 		    ha->subven_id, ha->subsys_id);
886 
887 		switch (ha->device_id) {
888 		case 0x2300:
889 		case 0x2312:
890 #if !defined(__sparc) || defined(QL_DEBUG_ROUTINES)
891 		/*
892 		 * per marketing, fibre-lite HBA's are not supported
893 		 * on sparc platforms
894 		 */
895 		case 0x6312:
896 		case 0x6322:
897 #endif	/* !defined(__sparc) || defined(QL_DEBUG_ROUTINES) */
898 			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
899 				ha->flags |= FUNCTION_1;
900 			}
901 			if (ha->device_id == 0x6322) {
902 				ha->cfg_flags |= CFG_CTRL_6322;
903 				ha->fw_class = 0x6322;
904 				ha->risc_dump_size = QL_6322_FW_DUMP_SIZE;
905 			} else {
906 				ha->cfg_flags |= CFG_CTRL_2300;
907 				ha->fw_class = 0x2300;
908 				ha->risc_dump_size = QL_2300_FW_DUMP_SIZE;
909 			}
910 			ha->reg_off = &reg_off_2300;
911 			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
912 				goto attach_failed;
913 			}
914 			ha->fcp_cmd = ql_command_iocb;
915 			ha->ip_cmd = ql_ip_iocb;
916 			ha->ms_cmd = ql_ms_iocb;
917 			if (CFG_IST(ha, CFG_SBUS_CARD)) {
918 				ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS;
919 				ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS;
920 			} else {
921 				ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS;
922 				ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
923 			}
924 			break;
925 
926 		case 0x2200:
927 			ha->cfg_flags |= CFG_CTRL_2200;
928 			ha->reg_off = &reg_off_2200;
929 			ha->fw_class = 0x2200;
930 			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
931 				goto attach_failed;
932 			}
933 			ha->risc_dump_size = QL_2200_FW_DUMP_SIZE;
934 			ha->fcp_cmd = ql_command_iocb;
935 			ha->ip_cmd = ql_ip_iocb;
936 			ha->ms_cmd = ql_ms_iocb;
937 			if (CFG_IST(ha, CFG_SBUS_CARD)) {
938 				ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS;
939 				ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS;
940 			} else {
941 				ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS;
942 				ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
943 			}
944 			break;
945 
946 		case 0x2422:
947 		case 0x2432:
948 		case 0x5422:
949 		case 0x5432:
950 		case 0x8432:
951 #ifdef __sparc
952 			/*
953 			 * Per marketing, the QLA/QLE-2440's (which
954 			 * also use the 2422 & 2432) are only for the
955 			 * x86 platform (SMB market).
956 			 */
957 			if (ha->subsys_id == 0x145 || ha->subsys_id == 0x147 ||
958 			    ha->subsys_id == 0x13e) {
959 				cmn_err(CE_WARN,
960 				    "%s(%d): Unsupported HBA ssid: %x",
961 				    QL_NAME, instance, ha->subsys_id);
962 				goto attach_failed;
963 			}
964 #endif	/* __sparc */
965 			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
966 				ha->flags |= FUNCTION_1;
967 			}
968 			ha->cfg_flags |= CFG_CTRL_2422;
969 			if (ha->device_id == 0x8432) {
970 				ha->cfg_flags |= CFG_CTRL_MENLO;
971 			} else {
972 				ha->flags |= VP_ENABLED;
973 			}
974 
975 			ha->reg_off = &reg_off_2400_2500;
976 			ha->fw_class = 0x2400;
977 			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
978 				goto attach_failed;
979 			}
980 			ha->risc_dump_size = QL_24XX_FW_DUMP_SIZE;
981 			ha->fcp_cmd = ql_command_24xx_iocb;
982 			ha->ip_cmd = ql_ip_24xx_iocb;
983 			ha->ms_cmd = ql_ms_24xx_iocb;
984 			ha->els_cmd = ql_els_24xx_iocb;
985 			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
986 			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
987 			break;
988 
989 		case 0x2522:
990 		case 0x2532:
991 			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
992 				ha->flags |= FUNCTION_1;
993 			}
994 			ha->cfg_flags |= CFG_CTRL_25XX;
995 			ha->flags |= VP_ENABLED;
996 			ha->fw_class = 0x2500;
997 			ha->reg_off = &reg_off_2400_2500;
998 			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
999 				goto attach_failed;
1000 			}
1001 			ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
1002 			ha->fcp_cmd = ql_command_24xx_iocb;
1003 			ha->ip_cmd = ql_ip_24xx_iocb;
1004 			ha->ms_cmd = ql_ms_24xx_iocb;
1005 			ha->els_cmd = ql_els_24xx_iocb;
1006 			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1007 			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1008 			break;
1009 
1010 		case 0x8001:
1011 			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 4) {
1012 				ha->flags |= FUNCTION_1;
1013 			}
1014 			ha->cfg_flags |= CFG_CTRL_81XX;
1015 			ha->flags |= VP_ENABLED;
1016 			ha->fw_class = 0x8100;
1017 			ha->reg_off = &reg_off_2400_2500;
1018 			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1019 				goto attach_failed;
1020 			}
1021 			ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
1022 			ha->fcp_cmd = ql_command_24xx_iocb;
1023 			ha->ip_cmd = ql_ip_24xx_iocb;
1024 			ha->ms_cmd = ql_ms_24xx_iocb;
1025 			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1026 			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1027 			break;
1028 
1029 		default:
1030 			cmn_err(CE_WARN, "%s(%d): Unsupported device id: %x",
1031 			    QL_NAME, instance, ha->device_id);
1032 			goto attach_failed;
1033 		}
1034 
1035 		/* Setup hba buffer. */
1036 
1037 		size = CFG_IST(ha, CFG_CTRL_242581) ?
1038 		    (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE) :
1039 		    (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE +
1040 		    RCVBUF_QUEUE_SIZE);
1041 
1042 		if (ql_get_dma_mem(ha, &ha->hba_buf, size, LITTLE_ENDIAN_DMA,
1043 		    QL_DMA_RING_ALIGN) != QL_SUCCESS) {
1044 			cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
1045 			    "alloc failed", QL_NAME, instance);
1046 			goto attach_failed;
1047 		}
1048 		progress |= QL_HBA_BUFFER_SETUP;
1049 
1050 		/* Setup buffer pointers. */
1051 		ha->request_dvma = ha->hba_buf.cookie.dmac_laddress +
1052 		    REQUEST_Q_BUFFER_OFFSET;
1053 		ha->request_ring_bp = (struct cmd_entry *)
1054 		    ((caddr_t)ha->hba_buf.bp + REQUEST_Q_BUFFER_OFFSET);
1055 
1056 		ha->response_dvma = ha->hba_buf.cookie.dmac_laddress +
1057 		    RESPONSE_Q_BUFFER_OFFSET;
1058 		ha->response_ring_bp = (struct sts_entry *)
1059 		    ((caddr_t)ha->hba_buf.bp + RESPONSE_Q_BUFFER_OFFSET);
1060 
1061 		ha->rcvbuf_dvma = ha->hba_buf.cookie.dmac_laddress +
1062 		    RCVBUF_Q_BUFFER_OFFSET;
1063 		ha->rcvbuf_ring_bp = (struct rcvbuf *)
1064 		    ((caddr_t)ha->hba_buf.bp + RCVBUF_Q_BUFFER_OFFSET);
1065 
1066 		/* Allocate resource for QLogic IOCTL */
1067 		(void) ql_alloc_xioctl_resource(ha);
1068 
1069 		/* Setup interrupts */
1070 		if ((rval = ql_setup_interrupts(ha)) != DDI_SUCCESS) {
1071 			cmn_err(CE_WARN, "%s(%d): Failed to add interrupt, "
1072 			    "rval=%xh", QL_NAME, instance, rval);
1073 			goto attach_failed;
1074 		}
1075 
1076 		progress |= (QL_INTR_ADDED | QL_MUTEX_CV_INITED);
1077 
1078 		/*
1079 		 * Allocate an N Port information structure
1080 		 * for use when in P2P topology.
1081 		 */
1082 		ha->n_port = (ql_n_port_info_t *)
1083 		    kmem_zalloc(sizeof (ql_n_port_info_t), KM_SLEEP);
1084 		if (ha->n_port == NULL) {
1085 			cmn_err(CE_WARN, "%s(%d): Failed to create N Port info",
1086 			    QL_NAME, instance);
1087 			goto attach_failed;
1088 		}
1089 
1090 		progress |= QL_N_PORT_INFO_CREATED;
1091 
1092 		/*
1093 		 * Determine support for Power Management
1094 		 */
1095 		caps_ptr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR);
1096 
1097 		while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
1098 			cap = (uint8_t)ql_pci_config_get8(ha, caps_ptr);
1099 			if (cap == PCI_CAP_ID_PM) {
1100 				ha->pm_capable = 1;
1101 				break;
1102 			}
1103 			caps_ptr = (uint8_t)ql_pci_config_get8(ha, caps_ptr +
1104 			    PCI_CAP_NEXT_PTR);
1105 		}
1106 
1107 		if (ha->pm_capable) {
1108 			/*
1109 			 * Enable PM for 2200 based HBAs only.
1110 			 */
1111 			if (ha->device_id != 0x2200) {
1112 				ha->pm_capable = 0;
1113 			}
1114 		}
1115 
1116 		if (ha->pm_capable) {
1117 			ha->pm_capable = ql_enable_pm;
1118 		}
1119 
1120 		if (ha->pm_capable) {
1121 			/*
1122 			 * Initialize power management bookkeeping;
1123 			 * components are created idle.
1124 			 */
1125 			(void) sprintf(buf, "NAME=%s(%d)", QL_NAME, instance);
1126 			pmcomps[0] = buf;
1127 
1128 			/*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
1129 			if (ddi_prop_update_string_array(DDI_DEV_T_NONE,
1130 			    dip, "pm-components", pmcomps,
1131 			    sizeof (pmcomps) / sizeof (pmcomps[0])) !=
1132 			    DDI_PROP_SUCCESS) {
1133 				cmn_err(CE_WARN, "%s(%d): failed to create"
1134 				    " pm-components property", QL_NAME,
1135 				    instance);
1136 
1137 				/* Initialize adapter. */
1138 				ha->power_level = PM_LEVEL_D0;
1139 				if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1140 					cmn_err(CE_WARN, "%s(%d): failed to"
1141 					    " initialize adapter", QL_NAME,
1142 					    instance);
1143 					goto attach_failed;
1144 				}
1145 			} else {
1146 				ha->power_level = PM_LEVEL_D3;
1147 				if (pm_raise_power(dip, QL_POWER_COMPONENT,
1148 				    PM_LEVEL_D0) != DDI_SUCCESS) {
1149 					cmn_err(CE_WARN, "%s(%d): failed to"
1150 					    " raise power or initialize"
1151 					    " adapter", QL_NAME, instance);
1152 				}
1153 				ASSERT(ha->power_level == PM_LEVEL_D0);
1154 			}
1155 		} else {
1156 			/* Initialize adapter. */
1157 			ha->power_level = PM_LEVEL_D0;
1158 			if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1159 				cmn_err(CE_WARN, "%s(%d): failed to initialize"
1160 				    " adapter", QL_NAME, instance);
1161 			}
1162 		}
1163 
1164 		if (ha->fw_major_version == 0 && ha->fw_minor_version == 0 &&
1165 		    ha->fw_subminor_version == 0) {
1166 			cmn_err(CE_NOTE, "!%s(%d): Firmware not loaded",
1167 			    QL_NAME, ha->instance);
1168 		} else {
1169 			cmn_err(CE_NOTE, "!%s(%d): Firmware version %d.%d.%d",
1170 			    QL_NAME, ha->instance, ha->fw_major_version,
1171 			    ha->fw_minor_version, ha->fw_subminor_version);
1172 		}
1173 
1174 		ha->k_stats = kstat_create(QL_NAME, instance, "statistics",
1175 		    "controller", KSTAT_TYPE_RAW,
1176 		    (uint32_t)sizeof (ql_adapter_stat_t), KSTAT_FLAG_VIRTUAL);
1177 		if (ha->k_stats == NULL) {
1178 			cmn_err(CE_WARN, "%s(%d): Failed to create kstat",
1179 			    QL_NAME, instance);
1180 			goto attach_failed;
1181 		}
1182 		progress |= QL_KSTAT_CREATED;
1183 
1184 		ha->adapter_stats->version = 1;
1185 		ha->k_stats->ks_data = (void *)ha->adapter_stats;
1186 		ha->k_stats->ks_private = ha;
1187 		ha->k_stats->ks_update = ql_kstat_update;
1188 		ha->k_stats->ks_ndata = 1;
1189 		ha->k_stats->ks_data_size = sizeof (ql_adapter_stat_t);
1190 		kstat_install(ha->k_stats);
1191 
1192 		if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
1193 		    instance, DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
1194 			cmn_err(CE_WARN, "%s(%d): failed to create minor node",
1195 			    QL_NAME, instance);
1196 			goto attach_failed;
1197 		}
1198 		progress |= QL_MINOR_NODE_CREATED;
1199 
1200 		/* Allocate a transport structure for this instance */
1201 		tran = kmem_zalloc(sizeof (fc_fca_tran_t), KM_SLEEP);
1202 		ASSERT(tran != NULL);
1203 
1204 		progress |= QL_FCA_TRAN_ALLOCED;
1205 
1206 		/* fill in the structure */
1207 		tran->fca_numports = 1;
1208 		tran->fca_version = FCTL_FCA_MODREV_5;
1209 		if (CFG_IST(ha, CFG_CTRL_2422)) {
1210 			tran->fca_num_npivports = MAX_24_VIRTUAL_PORTS;
1211 		} else if (CFG_IST(ha, CFG_CTRL_2581)) {
1212 			tran->fca_num_npivports = MAX_25_VIRTUAL_PORTS;
1213 		}
1214 		bcopy(ha->loginparams.node_ww_name.raw_wwn,
1215 		    tran->fca_perm_pwwn.raw_wwn, 8);
1216 
1217 		EL(ha, "FCA version %d\n", tran->fca_version);
1218 
1219 		/* Specify the amount of space needed in each packet */
1220 		tran->fca_pkt_size = sizeof (ql_srb_t);
1221 
1222 		/* command limits are usually dictated by hardware */
1223 		tran->fca_cmd_max = MAX_OUTSTANDING_COMMANDS;
1224 
1225 		/* dmaattr are static, set elsewhere. */
1226 		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1227 			tran->fca_dma_attr = &ql_64bit_io_dma_attr;
1228 			tran->fca_dma_fcp_cmd_attr = &ql_64fcp_cmd_dma_attr;
1229 			tran->fca_dma_fcp_rsp_attr = &ql_64fcp_rsp_dma_attr;
1230 			tran->fca_dma_fcp_data_attr = &ql_64fcp_data_dma_attr;
1231 			tran->fca_dma_fcsm_cmd_attr = &ql_64fcsm_cmd_dma_attr;
1232 			tran->fca_dma_fcsm_rsp_attr = &ql_64fcsm_rsp_dma_attr;
1233 			tran->fca_dma_fcip_cmd_attr = &ql_64fcip_cmd_dma_attr;
1234 			tran->fca_dma_fcip_rsp_attr = &ql_64fcip_rsp_dma_attr;
1235 		} else {
1236 			tran->fca_dma_attr = &ql_32bit_io_dma_attr;
1237 			tran->fca_dma_fcp_cmd_attr = &ql_32fcp_cmd_dma_attr;
1238 			tran->fca_dma_fcp_rsp_attr = &ql_32fcp_rsp_dma_attr;
1239 			tran->fca_dma_fcp_data_attr = &ql_32fcp_data_dma_attr;
1240 			tran->fca_dma_fcsm_cmd_attr = &ql_32fcsm_cmd_dma_attr;
1241 			tran->fca_dma_fcsm_rsp_attr = &ql_32fcsm_rsp_dma_attr;
1242 			tran->fca_dma_fcip_cmd_attr = &ql_32fcip_cmd_dma_attr;
1243 			tran->fca_dma_fcip_rsp_attr = &ql_32fcip_rsp_dma_attr;
1244 		}
1245 
1246 		tran->fca_acc_attr = &ql_dev_acc_attr;
1247 		tran->fca_iblock = &(ha->iblock_cookie);
1248 
1249 		/* the remaining values are simply function vectors */
1250 		tran->fca_bind_port = ql_bind_port;
1251 		tran->fca_unbind_port = ql_unbind_port;
1252 		tran->fca_init_pkt = ql_init_pkt;
1253 		tran->fca_un_init_pkt = ql_un_init_pkt;
1254 		tran->fca_els_send = ql_els_send;
1255 		tran->fca_get_cap = ql_get_cap;
1256 		tran->fca_set_cap = ql_set_cap;
1257 		tran->fca_getmap = ql_getmap;
1258 		tran->fca_transport = ql_transport;
1259 		tran->fca_ub_alloc = ql_ub_alloc;
1260 		tran->fca_ub_free = ql_ub_free;
1261 		tran->fca_ub_release = ql_ub_release;
1262 		tran->fca_abort = ql_abort;
1263 		tran->fca_reset = ql_reset;
1264 		tran->fca_port_manage = ql_port_manage;
1265 		tran->fca_get_device = ql_get_device;
1266 
1267 		/* give it to the FC transport */
1268 		if (fc_fca_attach(dip, tran) != DDI_SUCCESS) {
1269 			cmn_err(CE_WARN, "%s(%d): FCA attach failed", QL_NAME,
1270 			    instance);
1271 			goto attach_failed;
1272 		}
1273 		progress |= QL_FCA_ATTACH_DONE;
1274 
1275 		/* Stash the structure so it can be freed at detach */
1276 		ha->tran = tran;
1277 
1278 		/* Acquire global state lock. */
1279 		GLOBAL_STATE_LOCK();
1280 
1281 		/* Add adapter structure to link list. */
1282 		ql_add_link_b(&ql_hba, &ha->hba);
1283 
1284 		/* Start one second driver timer. */
1285 		if (ql_timer_timeout_id == NULL) {
1286 			ql_timer_ticks = drv_usectohz(1000000);
1287 			ql_timer_timeout_id = timeout(ql_timer, (void *)0,
1288 			    ql_timer_ticks);
1289 		}
1290 
1291 		/* Release global state lock. */
1292 		GLOBAL_STATE_UNLOCK();
1293 
1294 		/* Determine and populate HBA fru info */
1295 		ql_setup_fruinfo(ha);
1296 
1297 		/* Setup task_daemon thread. */
1298 		(void) thread_create(NULL, 0, (void (*)())ql_task_daemon, ha,
1299 		    0, &p0, TS_RUN, minclsyspri);
1300 
1301 		progress |= QL_TASK_DAEMON_STARTED;
1302 
1303 		ddi_report_dev(dip);
1304 
1305 		/* Disable link reset in panic path */
1306 		ha->lip_on_panic = 1;
1307 
1308 		rval = DDI_SUCCESS;
1309 		break;
1310 
1311 attach_failed:
1312 		if (progress & QL_FCA_ATTACH_DONE) {
1313 			(void) fc_fca_detach(dip);
1314 			progress &= ~QL_FCA_ATTACH_DONE;
1315 		}
1316 
1317 		if (progress & QL_FCA_TRAN_ALLOCED) {
1318 			kmem_free(tran, sizeof (fc_fca_tran_t));
1319 			progress &= ~QL_FCA_TRAN_ALLOCED;
1320 		}
1321 
1322 		if (progress & QL_MINOR_NODE_CREATED) {
1323 			ddi_remove_minor_node(dip, "devctl");
1324 			progress &= ~QL_MINOR_NODE_CREATED;
1325 		}
1326 
1327 		if (progress & QL_KSTAT_CREATED) {
1328 			kstat_delete(ha->k_stats);
1329 			progress &= ~QL_KSTAT_CREATED;
1330 		}
1331 
1332 		if (progress & QL_N_PORT_INFO_CREATED) {
1333 			kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
1334 			progress &= ~QL_N_PORT_INFO_CREATED;
1335 		}
1336 
1337 		if (progress & QL_TASK_DAEMON_STARTED) {
1338 			TASK_DAEMON_LOCK(ha);
1339 
1340 			ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
1341 
1342 			cv_signal(&ha->cv_task_daemon);
1343 
1344 			/* Release task daemon lock. */
1345 			TASK_DAEMON_UNLOCK(ha);
1346 
1347 			/* Wait for for task daemon to stop running. */
1348 			while (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
1349 				ql_delay(ha, 10000);
1350 			}
1351 			progress &= ~QL_TASK_DAEMON_STARTED;
1352 		}
1353 
1354 		if (progress & QL_IOMAP_IOBASE_MAPPED) {
1355 			ddi_regs_map_free(&ha->iomap_dev_handle);
1356 			progress &= ~QL_IOMAP_IOBASE_MAPPED;
1357 		}
1358 
1359 		if (progress & QL_CONFIG_SPACE_SETUP) {
1360 			if (CFG_IST(ha, CFG_SBUS_CARD)) {
1361 				ddi_regs_map_free(&ha->sbus_config_handle);
1362 			} else {
1363 				pci_config_teardown(&ha->pci_handle);
1364 			}
1365 			progress &= ~QL_CONFIG_SPACE_SETUP;
1366 		}
1367 
1368 		if (progress & QL_INTR_ADDED) {
1369 			ql_disable_intr(ha);
1370 			ql_release_intr(ha);
1371 			progress &= ~QL_INTR_ADDED;
1372 		}
1373 
1374 		if (progress & QL_MUTEX_CV_INITED) {
1375 			ql_destroy_mutex(ha);
1376 			progress &= ~QL_MUTEX_CV_INITED;
1377 		}
1378 
1379 		if (progress & QL_HBA_BUFFER_SETUP) {
1380 			ql_free_phys(ha, &ha->hba_buf);
1381 			progress &= ~QL_HBA_BUFFER_SETUP;
1382 		}
1383 
1384 		if (progress & QL_REGS_MAPPED) {
1385 			ddi_regs_map_free(&ha->dev_handle);
1386 			if (ha->sbus_fpga_iobase != NULL) {
1387 				ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
1388 			}
1389 			progress &= ~QL_REGS_MAPPED;
1390 		}
1391 
1392 		if (progress & QL_SOFT_STATE_ALLOCED) {
1393 
1394 			ql_fcache_rel(ha->fcache);
1395 
1396 			ASSERT(ha->dev && ha->outstanding_cmds &&
1397 			    ha->ub_array && ha->adapter_stats);
1398 
1399 			kmem_free(ha->adapter_stats,
1400 			    sizeof (*ha->adapter_stats));
1401 
1402 			kmem_free(ha->ub_array, sizeof (*ha->ub_array) *
1403 			    QL_UB_LIMIT);
1404 
1405 			kmem_free(ha->outstanding_cmds,
1406 			    sizeof (*ha->outstanding_cmds) *
1407 			    MAX_OUTSTANDING_COMMANDS);
1408 
1409 			if (ha->devpath != NULL) {
1410 				kmem_free(ha->devpath,
1411 				    strlen(ha->devpath) + 1);
1412 			}
1413 
1414 			kmem_free(ha->dev, sizeof (*ha->dev) *
1415 			    DEVICE_HEAD_LIST_SIZE);
1416 
1417 			if (ha->xioctl != NULL) {
1418 				ql_free_xioctl_resource(ha);
1419 			}
1420 
1421 			if (ha->fw_module != NULL) {
1422 				(void) ddi_modclose(ha->fw_module);
1423 			}
1424 
1425 			ddi_soft_state_free(ql_state, instance);
1426 			progress &= ~QL_SOFT_STATE_ALLOCED;
1427 		}
1428 		ASSERT(progress == 0);
1429 
1430 		ddi_prop_remove_all(dip);
1431 		rval = DDI_FAILURE;
1432 		break;
1433 
1434 	case DDI_RESUME:
1435 		rval = DDI_FAILURE;
1436 
1437 		ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
1438 		if (ha == NULL) {
1439 			cmn_err(CE_WARN, "%s(%d): can't get soft state",
1440 			    QL_NAME, instance);
1441 			break;
1442 		}
1443 
1444 		ha->power_level = PM_LEVEL_D3;
1445 		if (ha->pm_capable) {
1446 			/*
1447 			 * Get ql_power to do power on initialization
1448 			 */
1449 			if (pm_raise_power(dip, QL_POWER_COMPONENT,
1450 			    PM_LEVEL_D0) != DDI_SUCCESS) {
1451 				cmn_err(CE_WARN, "%s(%d): can't raise adapter"
1452 				    " power", QL_NAME, instance);
1453 			}
1454 		}
1455 
1456 		/*
1457 		 * There is a bug in DR that prevents PM framework
1458 		 * from calling ql_power.
1459 		 */
1460 		if (ha->power_level == PM_LEVEL_D3) {
1461 			ha->power_level = PM_LEVEL_D0;
1462 
1463 			if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1464 				cmn_err(CE_WARN, "%s(%d): can't initialize the"
1465 				    " adapter", QL_NAME, instance);
1466 			}
1467 
1468 			/* Wake up task_daemon. */
1469 			ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG,
1470 			    0);
1471 		}
1472 
1473 		/* Acquire global state lock. */
1474 		GLOBAL_STATE_LOCK();
1475 
1476 		/* Restart driver timer. */
1477 		if (ql_timer_timeout_id == NULL) {
1478 			ql_timer_timeout_id = timeout(ql_timer, (void *)0,
1479 			    ql_timer_ticks);
1480 		}
1481 
1482 		/* Release global state lock. */
1483 		GLOBAL_STATE_UNLOCK();
1484 
1485 		/* Wake up command start routine. */
1486 		ADAPTER_STATE_LOCK(ha);
1487 		ha->flags &= ~ADAPTER_SUSPENDED;
1488 		ADAPTER_STATE_UNLOCK(ha);
1489 
1490 		/*
1491 		 * Transport doesn't make FC discovery in polled
1492 		 * mode; So we need the daemon thread's services
1493 		 * right here.
1494 		 */
1495 		(void) callb_generic_cpr(&ha->cprinfo, CB_CODE_CPR_RESUME);
1496 
1497 		rval = DDI_SUCCESS;
1498 
1499 		/* Restart IP if it was running. */
1500 		if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
1501 			(void) ql_initialize_ip(ha);
1502 			ql_isp_rcvbuf(ha);
1503 		}
1504 		break;
1505 
1506 	default:
1507 		cmn_err(CE_WARN, "%s(%d): attach, unknown code:"
1508 		    " %x", QL_NAME, ddi_get_instance(dip), cmd);
1509 		rval = DDI_FAILURE;
1510 		break;
1511 	}
1512 
1513 	kmem_free(buf, MAXPATHLEN);
1514 
1515 	if (rval != DDI_SUCCESS) {
1516 		/*EMPTY*/
1517 		QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
1518 		    ddi_get_instance(dip), rval);
1519 	} else {
1520 		/*EMPTY*/
1521 		QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
1522 	}
1523 
1524 	return (rval);
1525 }
1526 
1527 /*
1528  * ql_detach
1529  *	Used to remove all the states associated with a given
1530  *	instances of a device node prior to the removal of that
1531  *	instance from the system.
1532  *
1533  * Input:
1534  *	dip = pointer to device information structure.
1535  *	cmd = type of detach.
1536  *
1537  * Returns:
1538  *	DDI_SUCCESS or DDI_FAILURE.
1539  *
1540  * Context:
1541  *	Kernel context.
1542  */
1543 static int
1544 ql_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1545 {
1546 	ql_adapter_state_t	*ha, *vha;
1547 	ql_tgt_t		*tq;
1548 	int			try;
1549 	uint16_t		index;
1550 	ql_link_t		*link;
1551 	char			*buf;
1552 	timeout_id_t		timer_id = NULL;
1553 	int			rval = DDI_SUCCESS;
1554 
1555 	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
1556 	if (ha == NULL) {
1557 		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
1558 		    ddi_get_instance(dip));
1559 		return (DDI_FAILURE);
1560 	}
1561 
1562 	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, cmd);
1563 
1564 	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
1565 
1566 	switch (cmd) {
1567 	case DDI_DETACH:
1568 		ADAPTER_STATE_LOCK(ha);
1569 		ha->flags |= (ADAPTER_SUSPENDED | ABORT_CMDS_LOOP_DOWN_TMO);
1570 		ADAPTER_STATE_UNLOCK(ha);
1571 
1572 		/* Acquire task daemon lock. */
1573 		TASK_DAEMON_LOCK(ha);
1574 
1575 		ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
1576 		cv_signal(&ha->cv_task_daemon);
1577 
1578 		/* Release task daemon lock. */
1579 		TASK_DAEMON_UNLOCK(ha);
1580 
1581 		/*
1582 		 * Wait for task daemon to stop running.
1583 		 * Internal command timeout is approximately
1584 		 * 30 seconds, so it would help in some corner
1585 		 * cases to wait that long
1586 		 */
1587 		try = 0;
1588 		while ((ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) &&
1589 		    try < 3000) {
1590 			ql_delay(ha, 10000);
1591 			try++;
1592 		}
1593 
1594 		TASK_DAEMON_LOCK(ha);
1595 		if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
1596 			ha->task_daemon_flags &= ~TASK_DAEMON_STOP_FLG;
1597 			TASK_DAEMON_UNLOCK(ha);
1598 			EL(ha, "failed, could not stop task daemon\n");
1599 			return (DDI_FAILURE);
1600 		}
1601 		TASK_DAEMON_UNLOCK(ha);
1602 
1603 		/* Acquire global state lock. */
1604 		GLOBAL_STATE_LOCK();
1605 
1606 		/* Disable driver timer if no adapters. */
1607 		if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
1608 		    ql_hba.last == &ha->hba) {
1609 			timer_id = ql_timer_timeout_id;
1610 			ql_timer_timeout_id = NULL;
1611 		}
1612 		ql_remove_link(&ql_hba, &ha->hba);
1613 
1614 		GLOBAL_STATE_UNLOCK();
1615 
1616 		if (timer_id) {
1617 			(void) untimeout(timer_id);
1618 		}
1619 
1620 		if (ha->pm_capable) {
1621 			if (pm_lower_power(dip, QL_POWER_COMPONENT,
1622 			    PM_LEVEL_D3) != DDI_SUCCESS) {
1623 				cmn_err(CE_WARN, "%s(%d): failed to lower the"
1624 				    " power", QL_NAME, ha->instance);
1625 			}
1626 		}
1627 
1628 		/*
1629 		 * If pm_lower_power shutdown the adapter, there
1630 		 * isn't much else to do
1631 		 */
1632 		if (ha->power_level != PM_LEVEL_D3) {
1633 			ql_halt(ha, PM_LEVEL_D3);
1634 		}
1635 
1636 		/* Remove virtual ports. */
1637 		while ((vha = ha->vp_next) != NULL) {
1638 			ql_vport_destroy(vha);
1639 		}
1640 
1641 		/* Free target queues. */
1642 		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
1643 			link = ha->dev[index].first;
1644 			while (link != NULL) {
1645 				tq = link->base_address;
1646 				link = link->next;
1647 				ql_dev_free(ha, tq);
1648 			}
1649 		}
1650 
1651 		/*
1652 		 * Free unsolicited buffers.
1653 		 * If we are here then there are no ULPs still
1654 		 * alive that wish to talk to ql so free up
1655 		 * any SRB_IP_UB_UNUSED buffers that are
1656 		 * lingering around
1657 		 */
1658 		QL_UB_LOCK(ha);
1659 		for (index = 0; index < QL_UB_LIMIT; index++) {
1660 			fc_unsol_buf_t *ubp = ha->ub_array[index];
1661 
1662 			if (ubp != NULL) {
1663 				ql_srb_t *sp = ubp->ub_fca_private;
1664 
1665 				sp->flags |= SRB_UB_FREE_REQUESTED;
1666 
1667 				while (!(sp->flags & SRB_UB_IN_FCA) ||
1668 				    (sp->flags & (SRB_UB_CALLBACK |
1669 				    SRB_UB_ACQUIRED))) {
1670 					QL_UB_UNLOCK(ha);
1671 					delay(drv_usectohz(100000));
1672 					QL_UB_LOCK(ha);
1673 				}
1674 				ha->ub_array[index] = NULL;
1675 
1676 				QL_UB_UNLOCK(ha);
1677 				ql_free_unsolicited_buffer(ha, ubp);
1678 				QL_UB_LOCK(ha);
1679 			}
1680 		}
1681 		QL_UB_UNLOCK(ha);
1682 
1683 		/* Free any saved RISC code. */
1684 		if (ha->risc_code != NULL) {
1685 			kmem_free(ha->risc_code, ha->risc_code_size);
1686 			ha->risc_code = NULL;
1687 			ha->risc_code_size = 0;
1688 		}
1689 
1690 		if (ha->fw_module != NULL) {
1691 			(void) ddi_modclose(ha->fw_module);
1692 			ha->fw_module = NULL;
1693 		}
1694 
1695 		/* Free resources. */
1696 		ddi_prop_remove_all(dip);
1697 		(void) fc_fca_detach(dip);
1698 		kmem_free(ha->tran, sizeof (fc_fca_tran_t));
1699 		ddi_remove_minor_node(dip, "devctl");
1700 		if (ha->k_stats != NULL) {
1701 			kstat_delete(ha->k_stats);
1702 		}
1703 
1704 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
1705 			ddi_regs_map_free(&ha->sbus_config_handle);
1706 		} else {
1707 			ddi_regs_map_free(&ha->iomap_dev_handle);
1708 			pci_config_teardown(&ha->pci_handle);
1709 		}
1710 
1711 		ql_disable_intr(ha);
1712 		ql_release_intr(ha);
1713 
1714 		ql_free_xioctl_resource(ha);
1715 
1716 		ql_destroy_mutex(ha);
1717 
1718 		ql_free_phys(ha, &ha->hba_buf);
1719 		ql_free_phys(ha, &ha->fwexttracebuf);
1720 		ql_free_phys(ha, &ha->fwfcetracebuf);
1721 
1722 		ddi_regs_map_free(&ha->dev_handle);
1723 		if (ha->sbus_fpga_iobase != NULL) {
1724 			ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
1725 		}
1726 
1727 		ql_fcache_rel(ha->fcache);
1728 		if (ha->vcache != NULL) {
1729 			kmem_free(ha->vcache, QL_24XX_VPD_SIZE);
1730 		}
1731 
1732 		if (ha->pi_attrs != NULL) {
1733 			kmem_free(ha->pi_attrs, sizeof (fca_port_attrs_t));
1734 		}
1735 
1736 		ASSERT(ha->dev && ha->outstanding_cmds && ha->ub_array &&
1737 		    ha->adapter_stats);
1738 
1739 		kmem_free(ha->adapter_stats, sizeof (*ha->adapter_stats));
1740 
1741 		kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
1742 
1743 		kmem_free(ha->outstanding_cmds,
1744 		    sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS);
1745 
1746 		if (ha->n_port != NULL) {
1747 			kmem_free(&ha->n_port, sizeof (ql_n_port_info_t));
1748 		}
1749 
1750 		if (ha->devpath != NULL) {
1751 			kmem_free(ha->devpath, strlen(ha->devpath) + 1);
1752 		}
1753 
1754 		kmem_free(ha->dev, sizeof (*ha->dev) * DEVICE_HEAD_LIST_SIZE);
1755 
1756 		EL(ha, "detached\n");
1757 
1758 		ddi_soft_state_free(ql_state, (int)ha->instance);
1759 
1760 		break;
1761 
1762 	case DDI_SUSPEND:
1763 		ADAPTER_STATE_LOCK(ha);
1764 
1765 		try = 0;
1766 		ha->flags |= ADAPTER_SUSPENDED;
1767 		while (ha->flags & ADAPTER_TIMER_BUSY && try++ < 10) {
1768 			ADAPTER_STATE_UNLOCK(ha);
1769 			delay(drv_usectohz(1000000));
1770 			ADAPTER_STATE_LOCK(ha);
1771 		}
1772 		if (ha->busy || ha->flags & ADAPTER_TIMER_BUSY) {
1773 			ha->flags &= ~ADAPTER_SUSPENDED;
1774 			ADAPTER_STATE_UNLOCK(ha);
1775 			rval = DDI_FAILURE;
1776 			cmn_err(CE_WARN, "!%s(%d): Fail suspend"
1777 			    " busy %xh flags %xh", QL_NAME, ha->instance,
1778 			    ha->busy, ha->flags);
1779 			break;
1780 		}
1781 
1782 		ADAPTER_STATE_UNLOCK(ha);
1783 
1784 		if (ha->flags & IP_INITIALIZED) {
1785 			(void) ql_shutdown_ip(ha);
1786 		}
1787 
1788 		try = ql_suspend_adapter(ha);
1789 		if (try != QL_SUCCESS) {
1790 			ADAPTER_STATE_LOCK(ha);
1791 			ha->flags &= ~ADAPTER_SUSPENDED;
1792 			ADAPTER_STATE_UNLOCK(ha);
1793 			cmn_err(CE_WARN, "%s(%d): Fail suspend rval %xh",
1794 			    QL_NAME, ha->instance, try);
1795 
1796 			/* Restart IP if it was running. */
1797 			if (ha->flags & IP_ENABLED &&
1798 			    !(ha->flags & IP_INITIALIZED)) {
1799 				(void) ql_initialize_ip(ha);
1800 				ql_isp_rcvbuf(ha);
1801 			}
1802 			rval = DDI_FAILURE;
1803 			break;
1804 		}
1805 
1806 		/* Acquire global state lock. */
1807 		GLOBAL_STATE_LOCK();
1808 
1809 		/* Disable driver timer if last adapter. */
1810 		if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
1811 		    ql_hba.last == &ha->hba) {
1812 			timer_id = ql_timer_timeout_id;
1813 			ql_timer_timeout_id = NULL;
1814 		}
1815 		GLOBAL_STATE_UNLOCK();
1816 
1817 		if (timer_id) {
1818 			(void) untimeout(timer_id);
1819 		}
1820 
1821 		break;
1822 
1823 	default:
1824 		rval = DDI_FAILURE;
1825 		break;
1826 	}
1827 
1828 	kmem_free(buf, MAXPATHLEN);
1829 
1830 	if (rval != DDI_SUCCESS) {
1831 		if (ha != NULL) {
1832 			EL(ha, "failed, rval = %xh\n", rval);
1833 		} else {
1834 			/*EMPTY*/
1835 			QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
1836 			    ddi_get_instance(dip), rval);
1837 		}
1838 	} else {
1839 		/*EMPTY*/
1840 		QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
1841 	}
1842 
1843 	return (rval);
1844 }
1845 
1846 /*
1847  * ql_power
1848  *	Power a device attached to the system.
1849  *
1850  * Input:
1851  *	dip = pointer to device information structure.
1852  *	component = device.
1853  *	level = power level.
1854  *
1855  * Returns:
1856  *	DDI_SUCCESS or DDI_FAILURE.
1857  *
1858  * Context:
1859  *	Kernel context.
1860  */
1861 /* ARGSUSED */
1862 static int
1863 ql_power(dev_info_t *dip, int component, int level)
1864 {
1865 	int			rval = DDI_FAILURE;
1866 	off_t			csr;
1867 	uint8_t			saved_pm_val;
1868 	ql_adapter_state_t	*ha;
1869 	char			*buf;
1870 	char			*path;
1871 
1872 	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
1873 	if (ha == NULL || ha->pm_capable == 0) {
1874 		QL_PRINT_2(CE_CONT, "(%d): no hba or PM not supported\n",
1875 		    ddi_get_instance(dip));
1876 		return (rval);
1877 	}
1878 
1879 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
1880 
1881 	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
1882 	path = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
1883 
1884 	if (component != QL_POWER_COMPONENT || (level != PM_LEVEL_D0 &&
1885 	    level != PM_LEVEL_D3)) {
1886 		EL(ha, "invalid, component=%xh or level=%xh\n",
1887 		    component, level);
1888 		return (rval);
1889 	}
1890 
1891 	GLOBAL_HW_LOCK();
1892 	csr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR) + PCI_PMCSR;
1893 	GLOBAL_HW_UNLOCK();
1894 
1895 	ASSERT(csr == QL_PM_CS_REG);
1896 
1897 	(void) snprintf(buf, sizeof (buf),
1898 	    "Qlogic %s(%d): %s\n\t", QL_NAME, ddi_get_instance(dip),
1899 	    ddi_pathname(dip, path));
1900 
1901 	switch (level) {
1902 	case PM_LEVEL_D0:	/* power up to D0 state - fully on */
1903 
1904 		QL_PM_LOCK(ha);
1905 		if (ha->power_level == PM_LEVEL_D0) {
1906 			QL_PM_UNLOCK(ha);
1907 			rval = DDI_SUCCESS;
1908 			break;
1909 		}
1910 
1911 		/*
1912 		 * Enable interrupts now
1913 		 */
1914 		saved_pm_val = ha->power_level;
1915 		ha->power_level = PM_LEVEL_D0;
1916 		QL_PM_UNLOCK(ha);
1917 
1918 		GLOBAL_HW_LOCK();
1919 
1920 		ql_pci_config_put16(ha, csr, PCI_PMCSR_D0);
1921 
1922 		/*
1923 		 * Delay after reset, for chip to recover.
1924 		 * Otherwise causes system PANIC
1925 		 */
1926 		drv_usecwait(200000);
1927 
1928 		GLOBAL_HW_UNLOCK();
1929 
1930 		if (ha->config_saved) {
1931 			ha->config_saved = 0;
1932 			if (QL_RESTORE_CONFIG_REGS(dip) != DDI_SUCCESS) {
1933 				QL_PM_LOCK(ha);
1934 				ha->power_level = saved_pm_val;
1935 				QL_PM_UNLOCK(ha);
1936 				cmn_err(CE_WARN, "%s failed to restore "
1937 				    "config regs", buf);
1938 				break;
1939 			}
1940 		}
1941 
1942 		if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1943 			cmn_err(CE_WARN, "%s adapter initialization failed",
1944 			    buf);
1945 		}
1946 
1947 		/* Wake up task_daemon. */
1948 		ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG |
1949 		    TASK_DAEMON_SLEEPING_FLG, 0);
1950 
1951 		/* Restart IP if it was running. */
1952 		if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
1953 			(void) ql_initialize_ip(ha);
1954 			ql_isp_rcvbuf(ha);
1955 		}
1956 
1957 		cmn_err(CE_NOTE, QL_BANG "ql_power(%d): %s is powered ON\n",
1958 		    ha->instance, QL_NAME);
1959 
1960 		rval = DDI_SUCCESS;
1961 		break;
1962 
1963 	case PM_LEVEL_D3:	/* power down to D3 state - off */
1964 
1965 		QL_PM_LOCK(ha);
1966 
1967 		if (ha->busy || ((ha->task_daemon_flags &
1968 		    TASK_DAEMON_SLEEPING_FLG) == 0)) {
1969 			QL_PM_UNLOCK(ha);
1970 			break;
1971 		}
1972 
1973 		if (ha->power_level == PM_LEVEL_D3) {
1974 			rval = DDI_SUCCESS;
1975 			QL_PM_UNLOCK(ha);
1976 			break;
1977 		}
1978 		QL_PM_UNLOCK(ha);
1979 
1980 		if (QL_SAVE_CONFIG_REGS(dip) != DDI_SUCCESS) {
1981 			cmn_err(CE_WARN, "!Qlogic %s(%d): %s failed to save"
1982 			    " config regs", QL_NAME, ha->instance, buf);
1983 			break;
1984 		}
1985 		ha->config_saved = 1;
1986 
1987 		/*
1988 		 * Don't enable interrupts. Running mailbox commands with
1989 		 * interrupts enabled could cause hangs since pm_run_scan()
1990 		 * runs out of a callout thread and on single cpu systems
1991 		 * cv_timedwait(), called from ql_mailbox_command(), would
1992 		 * not get to run.
1993 		 */
1994 		TASK_DAEMON_LOCK(ha);
1995 		ha->task_daemon_flags |= TASK_DAEMON_POWERING_DOWN;
1996 		TASK_DAEMON_UNLOCK(ha);
1997 
1998 		ql_halt(ha, PM_LEVEL_D3);
1999 
2000 		/*
2001 		 * Setup ql_intr to ignore interrupts from here on.
2002 		 */
2003 		QL_PM_LOCK(ha);
2004 		ha->power_level = PM_LEVEL_D3;
2005 		QL_PM_UNLOCK(ha);
2006 
2007 		/*
2008 		 * Wait for ISR to complete.
2009 		 */
2010 		INTR_LOCK(ha);
2011 		ql_pci_config_put16(ha, csr, PCI_PMCSR_D3HOT);
2012 		INTR_UNLOCK(ha);
2013 
2014 		cmn_err(CE_NOTE, QL_BANG "ql_power(%d): %s is powered OFF\n",
2015 		    ha->instance, QL_NAME);
2016 
2017 		rval = DDI_SUCCESS;
2018 		break;
2019 	}
2020 
2021 	kmem_free(buf, MAXPATHLEN);
2022 	kmem_free(path, MAXPATHLEN);
2023 
2024 	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
2025 
2026 	return (rval);
2027 }
2028 
2029 /*
2030  * ql_quiesce
2031  *	quiesce a device attached to the system.
2032  *
2033  * Input:
2034  *	dip = pointer to device information structure.
2035  *
2036  * Returns:
2037  *	DDI_SUCCESS
2038  *
2039  * Context:
2040  *	Kernel context.
2041  */
2042 static int
2043 ql_quiesce(dev_info_t *dip)
2044 {
2045 	ql_adapter_state_t	*ha;
2046 	uint32_t		timer;
2047 	uint32_t		stat;
2048 
2049 	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
2050 	if (ha == NULL) {
2051 		/* Oh well.... */
2052 		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
2053 		    ddi_get_instance(dip));
2054 		return (DDI_SUCCESS);
2055 	}
2056 
2057 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2058 
2059 	if (CFG_IST(ha, CFG_CTRL_242581)) {
2060 		WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
2061 		WRT16_IO_REG(ha, mailbox[0], MBC_STOP_FIRMWARE);
2062 		WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
2063 		for (timer = 0; timer < 30000; timer++) {
2064 			stat = RD32_IO_REG(ha, intr_info_lo);
2065 			if (stat & BIT_15) {
2066 				if ((stat & 0xff) < 0x12) {
2067 					WRT32_IO_REG(ha, hccr,
2068 					    HC24_CLR_RISC_INT);
2069 					break;
2070 				}
2071 				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
2072 			}
2073 			drv_usecwait(100);
2074 		}
2075 		/* Reset the chip. */
2076 		WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
2077 		    MWB_4096_BYTES);
2078 		drv_usecwait(100);
2079 
2080 	} else {
2081 		/* Disable ISP interrupts. */
2082 		WRT16_IO_REG(ha, ictrl, 0);
2083 		/* Select RISC module registers. */
2084 		WRT16_IO_REG(ha, ctrl_status, 0);
2085 		/* Reset ISP semaphore. */
2086 		WRT16_IO_REG(ha, semaphore, 0);
2087 		/* Reset RISC module. */
2088 		WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
2089 		/* Release RISC module. */
2090 		WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
2091 	}
2092 
2093 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2094 
2095 	return (DDI_SUCCESS);
2096 }
2097 
2098 /* ************************************************************************ */
2099 /*		Fibre Channel Adapter (FCA) Transport Functions.	    */
2100 /* ************************************************************************ */
2101 
2102 /*
2103  * ql_bind_port
2104  *	Handling port binding. The FC Transport attempts to bind an FCA port
2105  *	when it is ready to start transactions on the port. The FC Transport
2106  *	will call the fca_bind_port() function specified in the fca_transport
2107  *	structure it receives. The FCA must fill in the port_info structure
2108  *	passed in the call and also stash the information for future calls.
2109  *
2110  * Input:
2111  *	dip = pointer to FCA information structure.
2112  *	port_info = pointer to port information structure.
2113  *	bind_info = pointer to bind information structure.
2114  *
2115  * Returns:
2116  *	NULL = failure
2117  *
2118  * Context:
2119  *	Kernel context.
2120  */
2121 static opaque_t
2122 ql_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
2123     fc_fca_bind_info_t *bind_info)
2124 {
2125 	ql_adapter_state_t	*ha, *vha;
2126 	opaque_t		fca_handle = NULL;
2127 	port_id_t		d_id;
2128 	int			port_npiv = bind_info->port_npiv;
2129 	uchar_t			*port_nwwn = bind_info->port_nwwn.raw_wwn;
2130 	uchar_t			*port_pwwn = bind_info->port_pwwn.raw_wwn;
2131 
2132 	/* get state info based on the dip */
2133 	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
2134 	if (ha == NULL) {
2135 		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
2136 		    ddi_get_instance(dip));
2137 		return (NULL);
2138 	}
2139 	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
2140 
2141 	/* Verify port number is supported. */
2142 	if (port_npiv != 0) {
2143 		if (!(ha->flags & VP_ENABLED)) {
2144 			QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_NOT_SUPPORTED\n",
2145 			    ha->instance);
2146 			port_info->pi_error = FC_NPIV_NOT_SUPPORTED;
2147 			return (NULL);
2148 		}
2149 		if (!(ha->flags & POINT_TO_POINT)) {
2150 			QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_WRONG_TOPOLOGY\n",
2151 			    ha->instance);
2152 			port_info->pi_error = FC_NPIV_WRONG_TOPOLOGY;
2153 			return (NULL);
2154 		}
2155 		if (!(ha->flags & FDISC_ENABLED)) {
2156 			QL_PRINT_2(CE_CONT, "(%d): switch does not support "
2157 			    "FDISC\n", ha->instance);
2158 			port_info->pi_error = FC_NPIV_FDISC_FAILED;
2159 			return (NULL);
2160 		}
2161 		if (bind_info->port_num > (CFG_IST(ha, CFG_CTRL_2422) ?
2162 		    MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS)) {
2163 			QL_PRINT_2(CE_CONT, "(%d): port number=%d "
2164 			    "FC_OUTOFBOUNDS\n", ha->instance);
2165 			port_info->pi_error = FC_OUTOFBOUNDS;
2166 			return (NULL);
2167 		}
2168 	} else if (bind_info->port_num != 0) {
2169 		QL_PRINT_2(CE_CONT, "(%d): failed, port number=%d is not "
2170 		    "supported\n", ha->instance, bind_info->port_num);
2171 		port_info->pi_error = FC_OUTOFBOUNDS;
2172 		return (NULL);
2173 	}
2174 
2175 	/* Locate port context. */
2176 	for (vha = ha; vha != NULL; vha = vha->vp_next) {
2177 		if (vha->vp_index == bind_info->port_num) {
2178 			break;
2179 		}
2180 	}
2181 
2182 	/* If virtual port does not exist. */
2183 	if (vha == NULL) {
2184 		vha = ql_vport_create(ha, (uint8_t)bind_info->port_num);
2185 	}
2186 
2187 	/* make sure this port isn't already bound */
2188 	if (vha->flags & FCA_BOUND) {
2189 		port_info->pi_error = FC_ALREADY;
2190 	} else {
2191 		if (vha->vp_index != 0) {
2192 			bcopy(port_nwwn,
2193 			    vha->loginparams.node_ww_name.raw_wwn, 8);
2194 			bcopy(port_pwwn,
2195 			    vha->loginparams.nport_ww_name.raw_wwn, 8);
2196 		}
2197 		if (vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
2198 			if (ql_vport_enable(vha) != QL_SUCCESS) {
2199 				QL_PRINT_2(CE_CONT, "(%d): failed to enable "
2200 				    "virtual port=%d\n", ha->instance,
2201 				    vha->vp_index);
2202 				port_info->pi_error = FC_NPIV_FDISC_FAILED;
2203 				return (NULL);
2204 			}
2205 			cmn_err(CE_CONT, "!Qlogic %s(%d) NPIV(%d) "
2206 			    "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x : "
2207 			    "WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
2208 			    QL_NAME, ha->instance, vha->vp_index,
2209 			    port_pwwn[0], port_pwwn[1], port_pwwn[2],
2210 			    port_pwwn[3], port_pwwn[4], port_pwwn[5],
2211 			    port_pwwn[6], port_pwwn[7],
2212 			    port_nwwn[0], port_nwwn[1], port_nwwn[2],
2213 			    port_nwwn[3], port_nwwn[4], port_nwwn[5],
2214 			    port_nwwn[6], port_nwwn[7]);
2215 		}
2216 
2217 		/* stash the bind_info supplied by the FC Transport */
2218 		vha->bind_info.port_handle = bind_info->port_handle;
2219 		vha->bind_info.port_statec_cb =
2220 		    bind_info->port_statec_cb;
2221 		vha->bind_info.port_unsol_cb = bind_info->port_unsol_cb;
2222 
2223 		/* Set port's source ID. */
2224 		port_info->pi_s_id.port_id = vha->d_id.b24;
2225 
2226 		/* copy out the default login parameters */
2227 		bcopy((void *)&vha->loginparams,
2228 		    (void *)&port_info->pi_login_params,
2229 		    sizeof (la_els_logi_t));
2230 
2231 		/* Set port's hard address if enabled. */
2232 		port_info->pi_hard_addr.hard_addr = 0;
2233 		if (bind_info->port_num == 0) {
2234 			d_id.b24 = ha->d_id.b24;
2235 			if (CFG_IST(ha, CFG_CTRL_242581)) {
2236 				if (ha->init_ctrl_blk.cb24.
2237 				    firmware_options_1[0] & BIT_0) {
2238 					d_id.b.al_pa = ql_index_to_alpa[ha->
2239 					    init_ctrl_blk.cb24.
2240 					    hard_address[0]];
2241 					port_info->pi_hard_addr.hard_addr =
2242 					    d_id.b24;
2243 				}
2244 			} else if (ha->init_ctrl_blk.cb.firmware_options[0] &
2245 			    BIT_0) {
2246 				d_id.b.al_pa = ql_index_to_alpa[ha->
2247 				    init_ctrl_blk.cb.hard_address[0]];
2248 				port_info->pi_hard_addr.hard_addr = d_id.b24;
2249 			}
2250 
2251 			/* Set the node id data */
2252 			if (ql_get_rnid_params(ha,
2253 			    sizeof (port_info->pi_rnid_params.params),
2254 			    (caddr_t)&port_info->pi_rnid_params.params) ==
2255 			    QL_SUCCESS) {
2256 				port_info->pi_rnid_params.status = FC_SUCCESS;
2257 			} else {
2258 				port_info->pi_rnid_params.status = FC_FAILURE;
2259 			}
2260 
2261 			/* Populate T11 FC-HBA details */
2262 			ql_populate_hba_fru_details(ha, port_info);
2263 			ha->pi_attrs = kmem_zalloc(sizeof (fca_port_attrs_t),
2264 			    KM_SLEEP);
2265 			if (ha->pi_attrs != NULL) {
2266 				bcopy(&port_info->pi_attrs, ha->pi_attrs,
2267 				    sizeof (fca_port_attrs_t));
2268 			}
2269 		} else {
2270 			port_info->pi_rnid_params.status = FC_FAILURE;
2271 			if (ha->pi_attrs != NULL) {
2272 				bcopy(ha->pi_attrs, &port_info->pi_attrs,
2273 				    sizeof (fca_port_attrs_t));
2274 			}
2275 		}
2276 
2277 		/* Generate handle for this FCA. */
2278 		fca_handle = (opaque_t)vha;
2279 
2280 		ADAPTER_STATE_LOCK(ha);
2281 		vha->flags |= FCA_BOUND;
2282 		ADAPTER_STATE_UNLOCK(ha);
2283 		/* Set port's current state. */
2284 		port_info->pi_port_state = vha->state;
2285 	}
2286 
2287 	QL_PRINT_10(CE_CONT, "(%d,%d): done, pi_port_state=%xh, "
2288 	    "pi_s_id.port_id=%xh\n", ha->instance, ha->vp_index,
2289 	    port_info->pi_port_state, port_info->pi_s_id.port_id);
2290 
2291 	return (fca_handle);
2292 }
2293 
2294 /*
2295  * ql_unbind_port
2296  *	To unbind a Fibre Channel Adapter from an FC Port driver.
2297  *
2298  * Input:
2299  *	fca_handle = handle setup by ql_bind_port().
2300  *
2301  * Context:
2302  *	Kernel context.
2303  */
2304 static void
2305 ql_unbind_port(opaque_t fca_handle)
2306 {
2307 	ql_adapter_state_t	*ha;
2308 	ql_tgt_t		*tq;
2309 	uint32_t		flgs;
2310 
2311 	ha = ql_fca_handle_to_state(fca_handle);
2312 	if (ha == NULL) {
2313 		/*EMPTY*/
2314 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2315 		    (void *)fca_handle);
2316 	} else {
2317 		QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance,
2318 		    ha->vp_index);
2319 
2320 		if (!(ha->flags & FCA_BOUND)) {
2321 			/*EMPTY*/
2322 			QL_PRINT_2(CE_CONT, "(%d): port=%d already unbound\n",
2323 			    ha->instance, ha->vp_index);
2324 		} else {
2325 			if (ha->vp_index != 0 && ha->flags & VP_ENABLED) {
2326 				if ((tq = ql_loop_id_to_queue(ha,
2327 				    FL_PORT_24XX_HDL)) != NULL) {
2328 					(void) ql_logout_fabric_port(ha, tq);
2329 				}
2330 				(void) ql_vport_control(ha, (uint8_t)
2331 				    (CFG_IST(ha, CFG_CTRL_2425) ?
2332 				    VPC_DISABLE_INIT : VPC_DISABLE_LOGOUT));
2333 				flgs = FCA_BOUND | VP_ENABLED;
2334 			} else {
2335 				flgs = FCA_BOUND;
2336 			}
2337 			ADAPTER_STATE_LOCK(ha);
2338 			ha->flags &= ~flgs;
2339 			ADAPTER_STATE_UNLOCK(ha);
2340 		}
2341 
2342 		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
2343 		    ha->vp_index);
2344 	}
2345 }
2346 
2347 /*
2348  * ql_init_pkt
2349  *	Initialize FCA portion of packet.
2350  *
2351  * Input:
2352  *	fca_handle = handle setup by ql_bind_port().
2353  *	pkt = pointer to fc_packet.
2354  *
2355  * Returns:
2356  *	FC_SUCCESS - the packet has successfully been initialized.
2357  *	FC_UNBOUND - the fca_handle specified is not bound.
2358  *	FC_NOMEM - the FCA failed initialization due to an allocation error.
2359  *	FC_FAILURE - the FCA failed initialization for undisclosed reasons
2360  *
2361  * Context:
2362  *	Kernel context.
2363  */
2364 /* ARGSUSED */
2365 static int
2366 ql_init_pkt(opaque_t fca_handle, fc_packet_t *pkt, int sleep)
2367 {
2368 	ql_adapter_state_t	*ha;
2369 	ql_srb_t		*sp;
2370 
2371 	ha = ql_fca_handle_to_state(fca_handle);
2372 	if (ha == NULL) {
2373 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2374 		    (void *)fca_handle);
2375 		return (FC_UNBOUND);
2376 	}
2377 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2378 
2379 	ASSERT(ha->power_level == PM_LEVEL_D0);
2380 
2381 	sp = (ql_srb_t *)pkt->pkt_fca_private;
2382 	sp->flags = 0;
2383 
2384 	/* init cmd links */
2385 	sp->cmd.base_address = sp;
2386 	sp->cmd.prev = NULL;
2387 	sp->cmd.next = NULL;
2388 	sp->cmd.head = NULL;
2389 
2390 	/* init watchdog links */
2391 	sp->wdg.base_address = sp;
2392 	sp->wdg.prev = NULL;
2393 	sp->wdg.next = NULL;
2394 	sp->wdg.head = NULL;
2395 	sp->pkt = pkt;
2396 	sp->ha = ha;
2397 	sp->magic_number = QL_FCA_BRAND;
2398 
2399 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2400 
2401 	return (FC_SUCCESS);
2402 }
2403 
2404 /*
2405  * ql_un_init_pkt
2406  *	Release all local resources bound to packet.
2407  *
2408  * Input:
2409  *	fca_handle = handle setup by ql_bind_port().
2410  *	pkt = pointer to fc_packet.
2411  *
2412  * Returns:
2413  *	FC_SUCCESS - the packet has successfully been invalidated.
2414  *	FC_UNBOUND - the fca_handle specified is not bound.
2415  *	FC_BADPACKET - the packet has not been initialized or has
2416  *			already been freed by this FCA.
2417  *
2418  * Context:
2419  *	Kernel context.
2420  */
2421 static int
2422 ql_un_init_pkt(opaque_t fca_handle, fc_packet_t *pkt)
2423 {
2424 	ql_adapter_state_t *ha;
2425 	int rval;
2426 	ql_srb_t *sp;
2427 
2428 	ha = ql_fca_handle_to_state(fca_handle);
2429 	if (ha == NULL) {
2430 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2431 		    (void *)fca_handle);
2432 		return (FC_UNBOUND);
2433 	}
2434 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2435 
2436 	sp = (ql_srb_t *)pkt->pkt_fca_private;
2437 	ASSERT(sp->magic_number == QL_FCA_BRAND);
2438 
2439 	if (sp->magic_number != QL_FCA_BRAND) {
2440 		EL(ha, "failed, FC_BADPACKET\n");
2441 		rval = FC_BADPACKET;
2442 	} else {
2443 		sp->magic_number = NULL;
2444 
2445 		ASSERT((sp->flags & (SRB_IN_DEVICE_QUEUE |
2446 		    SRB_IN_TOKEN_ARRAY)) == 0);
2447 
2448 		rval = FC_SUCCESS;
2449 	}
2450 
2451 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2452 
2453 	return (rval);
2454 }
2455 
2456 /*
2457  * ql_els_send
2458  *	Issue a extended link service request.
2459  *
2460  * Input:
2461  *	fca_handle = handle setup by ql_bind_port().
2462  *	pkt = pointer to fc_packet.
2463  *
2464  * Returns:
2465  *	FC_SUCCESS - the command was successful.
2466  *	FC_ELS_FREJECT - the command was rejected by a Fabric.
2467  *	FC_ELS_PREJECT - the command was rejected by an N-port.
2468  *	FC_TRANSPORT_ERROR - a transport error occurred.
2469  *	FC_UNBOUND - the fca_handle specified is not bound.
2470  *	FC_ELS_BAD - the FCA can not issue the requested ELS.
2471  *
2472  * Context:
2473  *	Kernel context.
2474  */
2475 static int
2476 ql_els_send(opaque_t fca_handle, fc_packet_t *pkt)
2477 {
2478 	ql_adapter_state_t	*ha;
2479 	int			rval;
2480 	clock_t			timer;
2481 	ls_code_t		els;
2482 	la_els_rjt_t		rjt;
2483 	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
2484 
2485 	/* Verify proper command. */
2486 	ha = ql_cmd_setup(fca_handle, pkt, &rval);
2487 	if (ha == NULL) {
2488 		QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
2489 		    rval, fca_handle);
2490 		return (FC_INVALID_REQUEST);
2491 	}
2492 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2493 
2494 	ASSERT(ha->power_level == PM_LEVEL_D0);
2495 
2496 	/* Wait for suspension to end. */
2497 	TASK_DAEMON_LOCK(ha);
2498 	while (ha->task_daemon_flags & QL_SUSPENDED) {
2499 		ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
2500 
2501 		/* 30 seconds from now */
2502 		timer = ddi_get_lbolt();
2503 		timer += drv_usectohz(30000000);
2504 
2505 		if (cv_timedwait(&ha->pha->cv_dr_suspended,
2506 		    &ha->pha->task_daemon_mutex, timer) == -1) {
2507 			/*
2508 			 * The timeout time 'timer' was
2509 			 * reached without the condition
2510 			 * being signaled.
2511 			 */
2512 			pkt->pkt_state = FC_PKT_TRAN_BSY;
2513 			pkt->pkt_reason = FC_REASON_XCHG_BSY;
2514 
2515 			/* Release task daemon lock. */
2516 			TASK_DAEMON_UNLOCK(ha);
2517 
2518 			EL(ha, "QL_SUSPENDED failed=%xh\n",
2519 			    QL_FUNCTION_TIMEOUT);
2520 			return (FC_TRAN_BUSY);
2521 		}
2522 	}
2523 	/* Release task daemon lock. */
2524 	TASK_DAEMON_UNLOCK(ha);
2525 
2526 	/* Setup response header. */
2527 	bcopy((void *)&pkt->pkt_cmd_fhdr, (void *)&pkt->pkt_resp_fhdr,
2528 	    sizeof (fc_frame_hdr_t));
2529 
2530 	if (pkt->pkt_rsplen) {
2531 		bzero((void *)pkt->pkt_resp, pkt->pkt_rsplen);
2532 	}
2533 
2534 	pkt->pkt_resp_fhdr.d_id = ha->d_id.b24;
2535 	pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
2536 	pkt->pkt_resp_fhdr.r_ctl = R_CTL_EXTENDED_SVC |
2537 	    R_CTL_SOLICITED_CONTROL;
2538 	pkt->pkt_resp_fhdr.f_ctl = F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ |
2539 	    F_CTL_END_SEQ;
2540 
2541 	sp->flags &= ~(SRB_UB_CALLBACK | SRB_UB_RSCN | SRB_UB_FCP |
2542 	    SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT | SRB_FCP_RSP_PKT |
2543 	    SRB_IP_PKT | SRB_COMMAND_TIMEOUT | SRB_UB_ACQUIRED | SRB_MS_PKT);
2544 
2545 	sp->flags |= SRB_ELS_PKT;
2546 
2547 	/* map the type of ELS to a function */
2548 	ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
2549 	    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
2550 
2551 #if 0
2552 	QL_PRINT_3(CE_CONT, "(%d): command fhdr:\n", ha->instance);
2553 	QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
2554 	    sizeof (fc_frame_hdr_t) / 4);
2555 	QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
2556 	QL_DUMP_3((uint8_t *)&els, 32, sizeof (els) / 4);
2557 #endif
2558 
2559 	sp->iocb = ha->els_cmd;
2560 	sp->req_cnt = 1;
2561 
2562 	switch (els.ls_code) {
2563 	case LA_ELS_RJT:
2564 	case LA_ELS_ACC:
2565 		EL(ha, "LA_ELS_RJT\n");
2566 		pkt->pkt_state = FC_PKT_SUCCESS;
2567 		rval = FC_SUCCESS;
2568 		break;
2569 	case LA_ELS_PLOGI:
2570 	case LA_ELS_PDISC:
2571 		rval = ql_els_plogi(ha, pkt);
2572 		break;
2573 	case LA_ELS_FLOGI:
2574 	case LA_ELS_FDISC:
2575 		rval = ql_els_flogi(ha, pkt);
2576 		break;
2577 	case LA_ELS_LOGO:
2578 		rval = ql_els_logo(ha, pkt);
2579 		break;
2580 	case LA_ELS_PRLI:
2581 		rval = ql_els_prli(ha, pkt);
2582 		break;
2583 	case LA_ELS_PRLO:
2584 		rval = ql_els_prlo(ha, pkt);
2585 		break;
2586 	case LA_ELS_ADISC:
2587 		rval = ql_els_adisc(ha, pkt);
2588 		break;
2589 	case LA_ELS_LINIT:
2590 		rval = ql_els_linit(ha, pkt);
2591 		break;
2592 	case LA_ELS_LPC:
2593 		rval = ql_els_lpc(ha, pkt);
2594 		break;
2595 	case LA_ELS_LSTS:
2596 		rval = ql_els_lsts(ha, pkt);
2597 		break;
2598 	case LA_ELS_SCR:
2599 		rval = ql_els_scr(ha, pkt);
2600 		break;
2601 	case LA_ELS_RSCN:
2602 		rval = ql_els_rscn(ha, pkt);
2603 		break;
2604 	case LA_ELS_FARP_REQ:
2605 		rval = ql_els_farp_req(ha, pkt);
2606 		break;
2607 	case LA_ELS_FARP_REPLY:
2608 		rval = ql_els_farp_reply(ha, pkt);
2609 		break;
2610 	case LA_ELS_RLS:
2611 		rval = ql_els_rls(ha, pkt);
2612 		break;
2613 	case LA_ELS_RNID:
2614 		rval = ql_els_rnid(ha, pkt);
2615 		break;
2616 	default:
2617 		EL(ha, "LA_ELS_RJT, FC_REASON_CMD_UNSUPPORTED=%xh\n",
2618 		    els.ls_code);
2619 		/* Build RJT. */
2620 		bzero(&rjt, sizeof (rjt));
2621 		rjt.ls_code.ls_code = LA_ELS_RJT;
2622 		rjt.reason = FC_REASON_CMD_UNSUPPORTED;
2623 
2624 		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
2625 		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
2626 
2627 		pkt->pkt_state = FC_PKT_LOCAL_RJT;
2628 		pkt->pkt_reason = FC_REASON_UNSUPPORTED;
2629 		rval = FC_SUCCESS;
2630 		break;
2631 	}
2632 
2633 #if 0
2634 	QL_PRINT_3(CE_CONT, "(%d): response fhdr:\n", ha->instance);
2635 	QL_DUMP_3((uint8_t *)&pkt->pkt_resp_fhdr, 32,
2636 	    sizeof (fc_frame_hdr_t) / 4);
2637 #endif
2638 	/*
2639 	 * Return success if the srb was consumed by an iocb. The packet
2640 	 * completion callback will be invoked by the response handler.
2641 	 */
2642 	if (rval == QL_CONSUMED) {
2643 		rval = FC_SUCCESS;
2644 	} else if (rval == FC_SUCCESS &&
2645 	    !(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
2646 		/* Do command callback only if no error */
2647 		ql_awaken_task_daemon(ha, sp, 0, 0);
2648 	}
2649 
2650 	if (rval != FC_SUCCESS) {
2651 		EL(ha, "failed, rval = %xh\n", rval);
2652 	} else {
2653 		/*EMPTY*/
2654 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2655 	}
2656 	return (rval);
2657 }
2658 
2659 /*
2660  * ql_get_cap
2661  *	Export FCA hardware and software capabilities.
2662  *
2663  * Input:
2664  *	fca_handle = handle setup by ql_bind_port().
2665  *	cap = pointer to the capabilities string.
2666  *	ptr = buffer pointer for return capability.
2667  *
2668  * Returns:
2669  *	FC_CAP_ERROR - no such capability
2670  *	FC_CAP_FOUND - the capability was returned and cannot be set
2671  *	FC_CAP_SETTABLE - the capability was returned and can be set
2672  *	FC_UNBOUND - the fca_handle specified is not bound.
2673  *
2674  * Context:
2675  *	Kernel context.
2676  */
2677 static int
2678 ql_get_cap(opaque_t fca_handle, char *cap, void *ptr)
2679 {
2680 	ql_adapter_state_t	*ha;
2681 	int			rval;
2682 	uint32_t		*rptr = (uint32_t *)ptr;
2683 
2684 	ha = ql_fca_handle_to_state(fca_handle);
2685 	if (ha == NULL) {
2686 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2687 		    (void *)fca_handle);
2688 		return (FC_UNBOUND);
2689 	}
2690 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2691 
2692 	if (strcmp(cap, FC_NODE_WWN) == 0) {
2693 		bcopy((void *)&ha->loginparams.node_ww_name.raw_wwn[0],
2694 		    ptr, 8);
2695 		rval = FC_CAP_FOUND;
2696 	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
2697 		bcopy((void *)&ha->loginparams, ptr,
2698 		    sizeof (la_els_logi_t));
2699 		rval = FC_CAP_FOUND;
2700 	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
2701 		*rptr = (uint32_t)QL_UB_LIMIT;
2702 		rval = FC_CAP_FOUND;
2703 	} else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
2704 
2705 		dev_info_t	*psydip = NULL;
2706 #ifdef __sparc
2707 		/*
2708 		 * Disable streaming for certain 2 chip adapters
2709 		 * below Psycho to handle Psycho byte hole issue.
2710 		 */
2711 		if ((CFG_IST(ha, CFG_MULTI_CHIP_ADAPTER)) &&
2712 		    (!CFG_IST(ha, CFG_SBUS_CARD))) {
2713 			for (psydip = ddi_get_parent(ha->dip); psydip;
2714 			    psydip = ddi_get_parent(psydip)) {
2715 				if (strcmp(ddi_driver_name(psydip),
2716 				    "pcipsy") == 0) {
2717 					break;
2718 				}
2719 			}
2720 		}
2721 #endif	/* __sparc */
2722 
2723 		if (psydip) {
2724 			*rptr = (uint32_t)FC_NO_STREAMING;
2725 			EL(ha, "No Streaming\n");
2726 		} else {
2727 			*rptr = (uint32_t)FC_ALLOW_STREAMING;
2728 			EL(ha, "Allow Streaming\n");
2729 		}
2730 		rval = FC_CAP_FOUND;
2731 	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
2732 		if (CFG_IST(ha, CFG_CTRL_242581)) {
2733 			*rptr = (uint32_t)CHAR_TO_SHORT(
2734 			    ha->init_ctrl_blk.cb24.max_frame_length[0],
2735 			    ha->init_ctrl_blk.cb24.max_frame_length[1]);
2736 		} else {
2737 			*rptr = (uint32_t)CHAR_TO_SHORT(
2738 			    ha->init_ctrl_blk.cb.max_frame_length[0],
2739 			    ha->init_ctrl_blk.cb.max_frame_length[1]);
2740 		}
2741 		rval = FC_CAP_FOUND;
2742 	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
2743 		*rptr = FC_RESET_RETURN_ALL;
2744 		rval = FC_CAP_FOUND;
2745 	} else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
2746 		*rptr = FC_NO_DVMA_SPACE;
2747 		rval = FC_CAP_FOUND;
2748 	} else {
2749 		EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
2750 		rval = FC_CAP_ERROR;
2751 	}
2752 
2753 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2754 
2755 	return (rval);
2756 }
2757 
2758 /*
2759  * ql_set_cap
2760  *	Allow the FC Transport to set FCA capabilities if possible.
2761  *
2762  * Input:
2763  *	fca_handle = handle setup by ql_bind_port().
2764  *	cap = pointer to the capabilities string.
2765  *	ptr = buffer pointer for capability.
2766  *
2767  * Returns:
2768  *	FC_CAP_ERROR - no such capability
2769  *	FC_CAP_FOUND - the capability cannot be set by the FC Transport.
2770  *	FC_CAP_SETTABLE - the capability was successfully set.
2771  *	FC_UNBOUND - the fca_handle specified is not bound.
2772  *
2773  * Context:
2774  *	Kernel context.
2775  */
2776 /* ARGSUSED */
2777 static int
2778 ql_set_cap(opaque_t fca_handle, char *cap, void *ptr)
2779 {
2780 	ql_adapter_state_t	*ha;
2781 	int			rval;
2782 
2783 	ha = ql_fca_handle_to_state(fca_handle);
2784 	if (ha == NULL) {
2785 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2786 		    (void *)fca_handle);
2787 		return (FC_UNBOUND);
2788 	}
2789 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2790 
2791 	if (strcmp(cap, FC_NODE_WWN) == 0) {
2792 		rval = FC_CAP_FOUND;
2793 	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
2794 		rval = FC_CAP_FOUND;
2795 	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
2796 		rval = FC_CAP_FOUND;
2797 	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
2798 		rval = FC_CAP_FOUND;
2799 	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
2800 		rval = FC_CAP_FOUND;
2801 	} else {
2802 		EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
2803 		rval = FC_CAP_ERROR;
2804 	}
2805 
2806 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2807 
2808 	return (rval);
2809 }
2810 
2811 /*
2812  * ql_getmap
2813  *	Request of Arbitrated Loop (AL-PA) map.
2814  *
2815  * Input:
2816  *	fca_handle = handle setup by ql_bind_port().
2817  *	mapbuf= buffer pointer for map.
2818  *
2819  * Returns:
2820  *	FC_OLDPORT - the specified port is not operating in loop mode.
2821  *	FC_OFFLINE - the specified port is not online.
2822  *	FC_NOMAP - there is no loop map available for this port.
2823  *	FC_UNBOUND - the fca_handle specified is not bound.
2824  *	FC_SUCCESS - a valid map has been placed in mapbuf.
2825  *
2826  * Context:
2827  *	Kernel context.
2828  */
2829 static int
2830 ql_getmap(opaque_t fca_handle, fc_lilpmap_t *mapbuf)
2831 {
2832 	ql_adapter_state_t	*ha;
2833 	clock_t			timer;
2834 	int			rval = FC_SUCCESS;
2835 
2836 	ha = ql_fca_handle_to_state(fca_handle);
2837 	if (ha == NULL) {
2838 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2839 		    (void *)fca_handle);
2840 		return (FC_UNBOUND);
2841 	}
2842 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2843 
2844 	ASSERT(ha->power_level == PM_LEVEL_D0);
2845 
2846 	mapbuf->lilp_magic = (uint16_t)MAGIC_LIRP;
2847 	mapbuf->lilp_myalpa = ha->d_id.b.al_pa;
2848 
2849 	/* Wait for suspension to end. */
2850 	TASK_DAEMON_LOCK(ha);
2851 	while (ha->task_daemon_flags & QL_SUSPENDED) {
2852 		ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
2853 
2854 		/* 30 seconds from now */
2855 		timer = ddi_get_lbolt();
2856 		timer += drv_usectohz(30000000);
2857 
2858 		if (cv_timedwait(&ha->pha->cv_dr_suspended,
2859 		    &ha->pha->task_daemon_mutex, timer) == -1) {
2860 			/*
2861 			 * The timeout time 'timer' was
2862 			 * reached without the condition
2863 			 * being signaled.
2864 			 */
2865 
2866 			/* Release task daemon lock. */
2867 			TASK_DAEMON_UNLOCK(ha);
2868 
2869 			EL(ha, "QL_SUSPENDED failed, FC_TRAN_BUSY\n");
2870 			return (FC_TRAN_BUSY);
2871 		}
2872 	}
2873 	/* Release task daemon lock. */
2874 	TASK_DAEMON_UNLOCK(ha);
2875 
2876 	if (ql_get_loop_position_map(ha, LOOP_POSITION_MAP_SIZE,
2877 	    (caddr_t)&mapbuf->lilp_length) != QL_SUCCESS) {
2878 		/*
2879 		 * Now, since transport drivers cosider this as an
2880 		 * offline condition, let's wait for few seconds
2881 		 * for any loop transitions before we reset the.
2882 		 * chip and restart all over again.
2883 		 */
2884 		ql_delay(ha, 2000000);
2885 		EL(ha, "failed, FC_NOMAP\n");
2886 		rval = FC_NOMAP;
2887 	} else {
2888 		/*EMPTY*/
2889 		QL_PRINT_3(CE_CONT, "(%d): my_alpa %xh len %xh "
2890 		    "data %xh %xh %xh %xh\n", ha->instance,
2891 		    mapbuf->lilp_myalpa, mapbuf->lilp_length,
2892 		    mapbuf->lilp_alpalist[0], mapbuf->lilp_alpalist[1],
2893 		    mapbuf->lilp_alpalist[2], mapbuf->lilp_alpalist[3]);
2894 	}
2895 
2896 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2897 #if 0
2898 	QL_DUMP_3((uint8_t *)mapbuf, 8, sizeof (fc_lilpmap_t));
2899 #endif
2900 	return (rval);
2901 }
2902 
2903 /*
2904  * ql_transport
2905  *	Issue an I/O request. Handles all regular requests.
2906  *
2907  * Input:
2908  *	fca_handle = handle setup by ql_bind_port().
2909  *	pkt = pointer to fc_packet.
2910  *
2911  * Returns:
2912  *	FC_SUCCESS - the packet was accepted for transport.
2913  *	FC_TRANSPORT_ERROR - a transport error occurred.
2914  *	FC_BADPACKET - the packet to be transported had not been
2915  *			initialized by this FCA.
2916  *	FC_UNBOUND - the fca_handle specified is not bound.
2917  *
2918  * Context:
2919  *	Kernel context.
2920  */
2921 static int
2922 ql_transport(opaque_t fca_handle, fc_packet_t *pkt)
2923 {
2924 	ql_adapter_state_t	*ha;
2925 	int			rval = FC_TRANSPORT_ERROR;
2926 	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
2927 
2928 	/* Verify proper command. */
2929 	ha = ql_cmd_setup(fca_handle, pkt, &rval);
2930 	if (ha == NULL) {
2931 		QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
2932 		    rval, fca_handle);
2933 		return (rval);
2934 	}
2935 	QL_PRINT_3(CE_CONT, "(%d): started command:\n", ha->instance);
2936 #if 0
2937 	QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
2938 	    sizeof (fc_frame_hdr_t) / 4);
2939 	QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
2940 	QL_DUMP_3((uint8_t *)pkt->pkt_cmd, 8, pkt->pkt_cmdlen);
2941 #endif
2942 	if (ha->flags & ADAPTER_SUSPENDED) {
2943 		ASSERT(pkt->pkt_tran_flags & FC_TRAN_DUMPING);
2944 	}
2945 
2946 	ASSERT(ha->power_level == PM_LEVEL_D0);
2947 
2948 	/* Reset SRB flags. */
2949 	sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | SRB_RETRY |
2950 	    SRB_POLL | SRB_WATCHDOG_ENABLED | SRB_ABORT | SRB_UB_CALLBACK |
2951 	    SRB_UB_RSCN | SRB_UB_FCP | SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT |
2952 	    SRB_FCP_RSP_PKT | SRB_IP_PKT | SRB_GENERIC_SERVICES_PKT |
2953 	    SRB_COMMAND_TIMEOUT | SRB_ABORTING | SRB_IN_DEVICE_QUEUE |
2954 	    SRB_IN_TOKEN_ARRAY | SRB_UB_FREE_REQUESTED | SRB_UB_ACQUIRED |
2955 	    SRB_MS_PKT | SRB_ELS_PKT);
2956 
2957 	pkt->pkt_resp_fhdr.d_id = ha->d_id.b24;
2958 	pkt->pkt_resp_fhdr.r_ctl = R_CTL_STATUS;
2959 	pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
2960 	pkt->pkt_resp_fhdr.f_ctl = pkt->pkt_cmd_fhdr.f_ctl;
2961 	pkt->pkt_resp_fhdr.type = pkt->pkt_cmd_fhdr.type;
2962 
2963 	switch (pkt->pkt_cmd_fhdr.r_ctl) {
2964 	case R_CTL_COMMAND:
2965 		if (pkt->pkt_cmd_fhdr.type == FC_TYPE_SCSI_FCP) {
2966 			sp->flags |= SRB_FCP_CMD_PKT;
2967 			rval = ql_fcp_scsi_cmd(ha, pkt, sp);
2968 		}
2969 		break;
2970 
2971 	default:
2972 		/* Setup response header and buffer. */
2973 		if (pkt->pkt_rsplen) {
2974 			bzero((void *)pkt->pkt_resp, pkt->pkt_rsplen);
2975 		}
2976 
2977 		switch (pkt->pkt_cmd_fhdr.r_ctl) {
2978 		case R_CTL_UNSOL_DATA:
2979 			if (pkt->pkt_cmd_fhdr.type == FC_TYPE_IS8802_SNAP) {
2980 				sp->flags |= SRB_IP_PKT;
2981 				rval = ql_fcp_ip_cmd(ha, pkt, sp);
2982 			}
2983 			break;
2984 
2985 		case R_CTL_UNSOL_CONTROL:
2986 			if (pkt->pkt_cmd_fhdr.type == FC_TYPE_FC_SERVICES) {
2987 				sp->flags |= SRB_GENERIC_SERVICES_PKT;
2988 				rval = ql_fc_services(ha, pkt);
2989 			}
2990 			break;
2991 
2992 		case R_CTL_SOLICITED_DATA:
2993 		case R_CTL_STATUS:
2994 		default:
2995 			pkt->pkt_state = FC_PKT_LOCAL_RJT;
2996 			pkt->pkt_reason = FC_REASON_UNSUPPORTED;
2997 			rval = FC_TRANSPORT_ERROR;
2998 			EL(ha, "unknown, r_ctl=%xh\n",
2999 			    pkt->pkt_cmd_fhdr.r_ctl);
3000 			break;
3001 		}
3002 	}
3003 
3004 	if (rval != FC_SUCCESS) {
3005 		EL(ha, "failed, rval = %xh\n", rval);
3006 	} else {
3007 		/*EMPTY*/
3008 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3009 	}
3010 
3011 	return (rval);
3012 }
3013 
3014 /*
3015  * ql_ub_alloc
3016  *	Allocate buffers for unsolicited exchanges.
3017  *
3018  * Input:
3019  *	fca_handle = handle setup by ql_bind_port().
3020  *	tokens = token array for each buffer.
3021  *	size = size of each buffer.
3022  *	count = pointer to number of buffers.
3023  *	type = the FC-4 type the buffers are reserved for.
3024  *		1 = Extended Link Services, 5 = LLC/SNAP
3025  *
3026  * Returns:
3027  *	FC_FAILURE - buffers could not be allocated.
3028  *	FC_TOOMANY - the FCA could not allocate the requested
3029  *			number of buffers.
3030  *	FC_SUCCESS - unsolicited buffers were allocated.
3031  *	FC_UNBOUND - the fca_handle specified is not bound.
3032  *
3033  * Context:
3034  *	Kernel context.
3035  */
3036 static int
3037 ql_ub_alloc(opaque_t fca_handle, uint64_t tokens[], uint32_t size,
3038     uint32_t *count, uint32_t type)
3039 {
3040 	ql_adapter_state_t	*ha;
3041 	caddr_t			bufp = NULL;
3042 	fc_unsol_buf_t		*ubp;
3043 	ql_srb_t		*sp;
3044 	uint32_t		index;
3045 	uint32_t		cnt;
3046 	uint32_t		ub_array_index = 0;
3047 	int			rval = FC_SUCCESS;
3048 	int			ub_updated = FALSE;
3049 
3050 	/* Check handle. */
3051 	ha = ql_fca_handle_to_state(fca_handle);
3052 	if (ha == NULL) {
3053 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3054 		    (void *)fca_handle);
3055 		return (FC_UNBOUND);
3056 	}
3057 	QL_PRINT_3(CE_CONT, "(%d,%d): started, count = %xh\n",
3058 	    ha->instance, ha->vp_index, *count);
3059 
3060 	QL_PM_LOCK(ha);
3061 	if (ha->power_level != PM_LEVEL_D0) {
3062 		QL_PM_UNLOCK(ha);
3063 		QL_PRINT_3(CE_CONT, "(%d,%d): down done\n", ha->instance,
3064 		    ha->vp_index);
3065 		return (FC_FAILURE);
3066 	}
3067 	QL_PM_UNLOCK(ha);
3068 
3069 	/* Acquire adapter state lock. */
3070 	ADAPTER_STATE_LOCK(ha);
3071 
3072 	/* Check the count. */
3073 	if ((*count + ha->ub_allocated) > QL_UB_LIMIT) {
3074 		*count = 0;
3075 		EL(ha, "failed, FC_TOOMANY\n");
3076 		rval = FC_TOOMANY;
3077 	}
3078 
3079 	/*
3080 	 * reset ub_array_index
3081 	 */
3082 	ub_array_index = 0;
3083 
3084 	/*
3085 	 * Now proceed to allocate any buffers required
3086 	 */
3087 	for (index = 0; index < *count && rval == FC_SUCCESS; index++) {
3088 		/* Allocate all memory needed. */
3089 		ubp = (fc_unsol_buf_t *)kmem_zalloc(sizeof (fc_unsol_buf_t),
3090 		    KM_SLEEP);
3091 		if (ubp == NULL) {
3092 			EL(ha, "failed, FC_FAILURE\n");
3093 			rval = FC_FAILURE;
3094 		} else {
3095 			sp = kmem_zalloc(sizeof (ql_srb_t), KM_SLEEP);
3096 			if (sp == NULL) {
3097 				kmem_free(ubp, sizeof (fc_unsol_buf_t));
3098 				rval = FC_FAILURE;
3099 			} else {
3100 				if (type == FC_TYPE_IS8802_SNAP) {
3101 #ifdef	__sparc
3102 					if (ql_get_dma_mem(ha,
3103 					    &sp->ub_buffer, size,
3104 					    BIG_ENDIAN_DMA,
3105 					    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
3106 						rval = FC_FAILURE;
3107 						kmem_free(ubp,
3108 						    sizeof (fc_unsol_buf_t));
3109 						kmem_free(sp,
3110 						    sizeof (ql_srb_t));
3111 					} else {
3112 						bufp = sp->ub_buffer.bp;
3113 						sp->ub_size = size;
3114 					}
3115 #else
3116 					if (ql_get_dma_mem(ha,
3117 					    &sp->ub_buffer, size,
3118 					    LITTLE_ENDIAN_DMA,
3119 					    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
3120 						rval = FC_FAILURE;
3121 						kmem_free(ubp,
3122 						    sizeof (fc_unsol_buf_t));
3123 						kmem_free(sp,
3124 						    sizeof (ql_srb_t));
3125 					} else {
3126 						bufp = sp->ub_buffer.bp;
3127 						sp->ub_size = size;
3128 					}
3129 #endif
3130 				} else {
3131 					bufp = kmem_zalloc(size, KM_SLEEP);
3132 					if (bufp == NULL) {
3133 						rval = FC_FAILURE;
3134 						kmem_free(ubp,
3135 						    sizeof (fc_unsol_buf_t));
3136 						kmem_free(sp,
3137 						    sizeof (ql_srb_t));
3138 					} else {
3139 						sp->ub_size = size;
3140 					}
3141 				}
3142 			}
3143 		}
3144 
3145 		if (rval == FC_SUCCESS) {
3146 			/* Find next available slot. */
3147 			QL_UB_LOCK(ha);
3148 			while (ha->ub_array[ub_array_index] != NULL) {
3149 				ub_array_index++;
3150 			}
3151 
3152 			ubp->ub_fca_private = (void *)sp;
3153 
3154 			/* init cmd links */
3155 			sp->cmd.base_address = sp;
3156 			sp->cmd.prev = NULL;
3157 			sp->cmd.next = NULL;
3158 			sp->cmd.head = NULL;
3159 
3160 			/* init wdg links */
3161 			sp->wdg.base_address = sp;
3162 			sp->wdg.prev = NULL;
3163 			sp->wdg.next = NULL;
3164 			sp->wdg.head = NULL;
3165 			sp->ha = ha;
3166 
3167 			ubp->ub_buffer = bufp;
3168 			ubp->ub_bufsize = size;
3169 			ubp->ub_port_handle = fca_handle;
3170 			ubp->ub_token = ub_array_index;
3171 
3172 			/* Save the token. */
3173 			tokens[index] = ub_array_index;
3174 
3175 			/* Setup FCA private information. */
3176 			sp->ub_type = type;
3177 			sp->handle = ub_array_index;
3178 			sp->flags |= SRB_UB_IN_FCA;
3179 
3180 			ha->ub_array[ub_array_index] = ubp;
3181 			ha->ub_allocated++;
3182 			ub_updated = TRUE;
3183 			QL_UB_UNLOCK(ha);
3184 		}
3185 	}
3186 
3187 	/* Release adapter state lock. */
3188 	ADAPTER_STATE_UNLOCK(ha);
3189 
3190 	/* IP buffer. */
3191 	if (ub_updated) {
3192 		if ((type == FC_TYPE_IS8802_SNAP) &&
3193 		    (!(CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_2581))))) {
3194 
3195 			ADAPTER_STATE_LOCK(ha);
3196 			ha->flags |= IP_ENABLED;
3197 			ADAPTER_STATE_UNLOCK(ha);
3198 
3199 			if (!(ha->flags & IP_INITIALIZED)) {
3200 				if (CFG_IST(ha, CFG_CTRL_2422)) {
3201 					ha->ip_init_ctrl_blk.cb24.mtu_size[0] =
3202 					    LSB(ql_ip_mtu);
3203 					ha->ip_init_ctrl_blk.cb24.mtu_size[1] =
3204 					    MSB(ql_ip_mtu);
3205 					ha->ip_init_ctrl_blk.cb24.buf_size[0] =
3206 					    LSB(size);
3207 					ha->ip_init_ctrl_blk.cb24.buf_size[1] =
3208 					    MSB(size);
3209 
3210 					cnt = CHAR_TO_SHORT(
3211 					    ha->ip_init_ctrl_blk.cb24.cc[0],
3212 					    ha->ip_init_ctrl_blk.cb24.cc[1]);
3213 
3214 					if (cnt < *count) {
3215 						ha->ip_init_ctrl_blk.cb24.cc[0]
3216 						    = LSB(*count);
3217 						ha->ip_init_ctrl_blk.cb24.cc[1]
3218 						    = MSB(*count);
3219 					}
3220 				} else {
3221 					ha->ip_init_ctrl_blk.cb.mtu_size[0] =
3222 					    LSB(ql_ip_mtu);
3223 					ha->ip_init_ctrl_blk.cb.mtu_size[1] =
3224 					    MSB(ql_ip_mtu);
3225 					ha->ip_init_ctrl_blk.cb.buf_size[0] =
3226 					    LSB(size);
3227 					ha->ip_init_ctrl_blk.cb.buf_size[1] =
3228 					    MSB(size);
3229 
3230 					cnt = CHAR_TO_SHORT(
3231 					    ha->ip_init_ctrl_blk.cb.cc[0],
3232 					    ha->ip_init_ctrl_blk.cb.cc[1]);
3233 
3234 					if (cnt < *count) {
3235 						ha->ip_init_ctrl_blk.cb.cc[0] =
3236 						    LSB(*count);
3237 						ha->ip_init_ctrl_blk.cb.cc[1] =
3238 						    MSB(*count);
3239 					}
3240 				}
3241 
3242 				(void) ql_initialize_ip(ha);
3243 			}
3244 			ql_isp_rcvbuf(ha);
3245 		}
3246 	}
3247 
3248 	if (rval != FC_SUCCESS) {
3249 		EL(ha, "failed=%xh\n", rval);
3250 	} else {
3251 		/*EMPTY*/
3252 		QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance,
3253 		    ha->vp_index);
3254 	}
3255 	return (rval);
3256 }
3257 
3258 /*
3259  * ql_ub_free
3260  *	Free unsolicited buffers.
3261  *
3262  * Input:
3263  *	fca_handle = handle setup by ql_bind_port().
3264  *	count = number of buffers.
3265  *	tokens = token array for each buffer.
3266  *
3267  * Returns:
3268  *	FC_SUCCESS - the requested buffers have been freed.
3269  *	FC_UNBOUND - the fca_handle specified is not bound.
3270  *	FC_UB_BADTOKEN - an invalid token was encountered.
3271  *			 No buffers have been released.
3272  *
3273  * Context:
3274  *	Kernel context.
3275  */
3276 static int
3277 ql_ub_free(opaque_t fca_handle, uint32_t count, uint64_t tokens[])
3278 {
3279 	ql_adapter_state_t	*ha;
3280 	ql_srb_t		*sp;
3281 	uint32_t		index;
3282 	uint64_t		ub_array_index;
3283 	int			rval = FC_SUCCESS;
3284 
3285 	/* Check handle. */
3286 	ha = ql_fca_handle_to_state(fca_handle);
3287 	if (ha == NULL) {
3288 		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3289 		    (void *)fca_handle);
3290 		return (FC_UNBOUND);
3291 	}
3292 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3293 
3294 	/* Acquire adapter state lock. */
3295 	ADAPTER_STATE_LOCK(ha);
3296 
3297 	/* Check all returned tokens. */
3298 	for (index = 0; index < count; index++) {
3299 		fc_unsol_buf_t	*ubp;
3300 
3301 		/* Check the token range. */
3302 		if ((ub_array_index = tokens[index]) >= QL_UB_LIMIT) {
3303 			EL(ha, "failed, FC_UB_BADTOKEN\n");
3304 			rval = FC_UB_BADTOKEN;
3305 			break;
3306 		}
3307 
3308 		/* Check the unsolicited buffer array. */
3309 		QL_UB_LOCK(ha);
3310 		ubp = ha->ub_array[ub_array_index];
3311 
3312 		if (ubp == NULL) {
3313 			EL(ha, "failed, FC_UB_BADTOKEN-2\n");
3314 			rval = FC_UB_BADTOKEN;
3315 			QL_UB_UNLOCK(ha);
3316 			break;
3317 		}
3318 
3319 		/* Check the state of the unsolicited buffer. */
3320 		sp = ha->ub_array[ub_array_index]->ub_fca_private;
3321 		sp->flags |= SRB_UB_FREE_REQUESTED;
3322 
3323 		while (!(sp->flags & SRB_UB_IN_FCA) ||
3324 		    (sp->flags & (SRB_UB_CALLBACK | SRB_UB_ACQUIRED))) {
3325 			QL_UB_UNLOCK(ha);
3326 			ADAPTER_STATE_UNLOCK(ha);
3327 			delay(drv_usectohz(100000));
3328 			ADAPTER_STATE_LOCK(ha);
3329 			QL_UB_LOCK(ha);
3330 		}
3331 		ha->ub_array[ub_array_index] = NULL;
3332 		QL_UB_UNLOCK(ha);
3333 		ql_free_unsolicited_buffer(ha, ubp);
3334 	}
3335 
3336 	if (rval == FC_SUCCESS) {
3337 		/*
3338 		 * Signal any pending hardware reset when there are
3339 		 * no more unsolicited buffers in use.
3340 		 */
3341 		if (ha->ub_allocated == 0) {
3342 			cv_broadcast(&ha->pha->cv_ub);
3343 		}
3344 	}
3345 
3346 	/* Release adapter state lock. */
3347 	ADAPTER_STATE_UNLOCK(ha);
3348 
3349 	if (rval != FC_SUCCESS) {
3350 		EL(ha, "failed=%xh\n", rval);
3351 	} else {
3352 		/*EMPTY*/
3353 		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3354 	}
3355 	return (rval);
3356 }
3357 
3358 /*
3359  * ql_ub_release
3360  *	Release unsolicited buffers from FC Transport
3361  *	to FCA for future use.
3362  *
3363  * Input:
3364  *	fca_handle = handle setup by ql_bind_port().
3365  *	count = number of buffers.
3366  *	tokens = token array for each buffer.
3367  *
3368  * Returns:
3369  *	FC_SUCCESS - the requested buffers have been released.
3370  *	FC_UNBOUND - the fca_handle specified is not bound.
3371  *	FC_UB_BADTOKEN - an invalid token was encountered.
3372  *		No buffers have been released.
3373  *
3374  * Context:
3375  *	Kernel context.
3376  */
3377 static int
3378 ql_ub_release(opaque_t fca_handle, uint32_t count, uint64_t tokens[])
3379 {
3380 	ql_adapter_state_t	*ha;
3381 	ql_srb_t		*sp;
3382 	uint32_t		index;
3383 	uint64_t		ub_array_index;
3384 	int			rval = FC_SUCCESS;
3385 	int			ub_ip_updated = FALSE;
3386 
3387 	/* Check handle. */
3388 	ha = ql_fca_handle_to_state(fca_handle);
3389 	if (ha == NULL</