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