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