1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/* Copyright 2010 QLogic Corporation */
23
24/*
25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27/*
28 * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
29 * Copyright (c) 2016 by Delphix. All rights reserved.
30 */
31
32#pragma ident	"Copyright 2010 QLogic Corporation; ql_api.c"
33
34/*
35 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
36 *
37 * ***********************************************************************
38 * *									**
39 * *				NOTICE					**
40 * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
41 * *			ALL RIGHTS RESERVED				**
42 * *									**
43 * ***********************************************************************
44 *
45 */
46
47#include <ql_apps.h>
48#include <ql_api.h>
49#include <ql_debug.h>
50#include <ql_init.h>
51#include <ql_iocb.h>
52#include <ql_ioctl.h>
53#include <ql_isr.h>
54#include <ql_mbx.h>
55#include <ql_nx.h>
56#include <ql_xioctl.h>
57
58/*
59 * Solaris external defines.
60 */
61extern pri_t minclsyspri;
62extern pri_t maxclsyspri;
63
64/*
65 * dev_ops functions prototypes
66 */
67static int ql_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
68static int ql_attach(dev_info_t *, ddi_attach_cmd_t);
69static int ql_detach(dev_info_t *, ddi_detach_cmd_t);
70static int ql_power(dev_info_t *, int, int);
71static int ql_quiesce(dev_info_t *);
72
73/*
74 * FCA functions prototypes exported by means of the transport table
75 */
76static opaque_t ql_bind_port(dev_info_t *, fc_fca_port_info_t *,
77    fc_fca_bind_info_t *);
78static void ql_unbind_port(opaque_t);
79static int ql_init_pkt(opaque_t, fc_packet_t *, int);
80static int ql_un_init_pkt(opaque_t, fc_packet_t *);
81static int ql_els_send(opaque_t, fc_packet_t *);
82static int ql_get_cap(opaque_t, char *, void *);
83static int ql_set_cap(opaque_t, char *, void *);
84static int ql_getmap(opaque_t, fc_lilpmap_t *);
85static int ql_transport(opaque_t, fc_packet_t *);
86static int ql_ub_alloc(opaque_t, uint64_t *, uint32_t, uint32_t *, uint32_t);
87static int ql_ub_free(opaque_t, uint32_t, uint64_t *);
88static int ql_ub_release(opaque_t, uint32_t, uint64_t *);
89static int ql_abort(opaque_t, fc_packet_t *, int);
90static int ql_reset(opaque_t, uint32_t);
91static int ql_port_manage(opaque_t, fc_fca_pm_t *);
92static opaque_t ql_get_device(opaque_t, fc_portid_t);
93
94/*
95 * FCA Driver Support Function Prototypes.
96 */
97static uint16_t	ql_wait_outstanding(ql_adapter_state_t *);
98static void ql_task_mgmt(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
99    ql_srb_t *);
100static void ql_task_daemon(void *);
101static void ql_task_thread(ql_adapter_state_t *);
102static void ql_unsol_callback(ql_srb_t *);
103static void ql_free_unsolicited_buffer(ql_adapter_state_t *,
104    fc_unsol_buf_t *);
105static void ql_timer(void *);
106static void ql_watchdog(ql_adapter_state_t *, uint32_t *, uint32_t *);
107static void ql_cmd_timeout(ql_adapter_state_t *, ql_tgt_t *q, ql_srb_t *,
108    uint32_t *, uint32_t *);
109static void ql_halt(ql_adapter_state_t *, int);
110static int ql_els_plogi(ql_adapter_state_t *, fc_packet_t *);
111static int ql_els_flogi(ql_adapter_state_t *, fc_packet_t *);
112static int ql_els_logo(ql_adapter_state_t *, fc_packet_t *);
113static int ql_els_prli(ql_adapter_state_t *, fc_packet_t *);
114static int ql_els_prlo(ql_adapter_state_t *, fc_packet_t *);
115static int ql_els_adisc(ql_adapter_state_t *, fc_packet_t *);
116static int ql_els_linit(ql_adapter_state_t *, fc_packet_t *);
117static int ql_els_lpc(ql_adapter_state_t *, fc_packet_t *);
118static int ql_els_lsts(ql_adapter_state_t *, fc_packet_t *);
119static int ql_els_scr(ql_adapter_state_t *, fc_packet_t *);
120static int ql_els_rscn(ql_adapter_state_t *, fc_packet_t *);
121static int ql_els_farp_req(ql_adapter_state_t *, fc_packet_t *);
122static int ql_els_farp_reply(ql_adapter_state_t *, fc_packet_t *);
123static int ql_els_rls(ql_adapter_state_t *, fc_packet_t *);
124static int ql_els_rnid(ql_adapter_state_t *, fc_packet_t *);
125static int ql_login_port(ql_adapter_state_t *, port_id_t);
126static int ql_login_fabric_port(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
127static int ql_logout_port(ql_adapter_state_t *, port_id_t);
128static ql_lun_t *ql_lun_queue(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
129static int ql_fcp_scsi_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
130static int ql_fcp_ip_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
131static int ql_fc_services(ql_adapter_state_t *, fc_packet_t *);
132static int ql_poll_cmd(ql_adapter_state_t *, ql_srb_t *, time_t);
133static int ql_start_cmd(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
134    ql_srb_t *);
135static int ql_kstat_update(kstat_t *, int);
136static ql_adapter_state_t *ql_fca_handle_to_state(opaque_t);
137static ql_adapter_state_t *ql_cmd_setup(opaque_t, fc_packet_t *, int *);
138static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, uint8_t);
139static void ql_rst_aen(ql_adapter_state_t *);
140static void ql_restart_queues(ql_adapter_state_t *);
141static void ql_abort_queues(ql_adapter_state_t *);
142static void ql_abort_device_queues(ql_adapter_state_t *ha, ql_tgt_t *tq);
143static void ql_idle_check(ql_adapter_state_t *);
144static int ql_loop_resync(ql_adapter_state_t *);
145static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
146static size_t ql_2581_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
147static int ql_save_config_regs(dev_info_t *);
148static int ql_restore_config_regs(dev_info_t *);
149static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
150static int ql_handle_rscn_update(ql_adapter_state_t *);
151static int ql_send_plogi(ql_adapter_state_t *, ql_tgt_t *, ql_head_t *);
152static int ql_process_rscn_for_device(ql_adapter_state_t *, ql_tgt_t *);
153static int ql_dump_firmware(ql_adapter_state_t *);
154static int ql_process_logo_for_device(ql_adapter_state_t *, ql_tgt_t *);
155static int ql_2200_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
156static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
157static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
158static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
159static int ql_81xx_binary_fw_dump(ql_adapter_state_t *, ql_81xx_fw_dump_t *);
160static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
161    void *);
162static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
163    uint8_t);
164static int ql_busy_plogi(ql_adapter_state_t *, fc_packet_t *, ql_tgt_t *);
165static int ql_suspend_adapter(ql_adapter_state_t *);
166static int ql_bstr_to_dec(char *, uint32_t *, uint32_t);
167static void ql_update_rscn(ql_adapter_state_t *, fc_affected_id_t *);
168int ql_alloc_dma_resouce(ql_adapter_state_t *, dma_mem_t *, int);
169static int ql_bind_dma_buffer(ql_adapter_state_t *, dma_mem_t *, int);
170static void ql_unbind_dma_buffer(ql_adapter_state_t *, dma_mem_t *);
171static void ql_timeout_insert(ql_adapter_state_t *, ql_tgt_t *, ql_srb_t *);
172static int ql_setup_interrupts(ql_adapter_state_t *);
173static int ql_setup_msi(ql_adapter_state_t *);
174static int ql_setup_msix(ql_adapter_state_t *);
175static int ql_setup_fixed(ql_adapter_state_t *);
176static void ql_release_intr(ql_adapter_state_t *);
177static void ql_disable_intr(ql_adapter_state_t *);
178static int ql_legacy_intr(ql_adapter_state_t *);
179static int ql_init_mutex(ql_adapter_state_t *);
180static void ql_destroy_mutex(ql_adapter_state_t *);
181static void ql_iidma(ql_adapter_state_t *);
182
183static int ql_n_port_plogi(ql_adapter_state_t *);
184static void ql_fca_isp_els_request(ql_adapter_state_t *, fc_packet_t *,
185    els_descriptor_t *);
186static void ql_isp_els_request_ctor(els_descriptor_t *,
187    els_passthru_entry_t *);
188static int ql_p2p_plogi(ql_adapter_state_t *, fc_packet_t *);
189static int ql_wait_for_td_stop(ql_adapter_state_t *);
190static void ql_process_idc_event(ql_adapter_state_t *);
191
192/*
193 * Global data
194 */
195static uint8_t	ql_enable_pm = 1;
196static int	ql_flash_sbus_fpga = 0;
197uint32_t	ql_os_release_level;
198uint32_t	ql_disable_aif = 0;
199uint32_t	ql_disable_msi = 0;
200uint32_t	ql_disable_msix = 0;
201uint32_t	ql_enable_ets = 0;
202uint16_t	ql_osc_wait_count = 1000;
203
204/* Timer routine variables. */
205static timeout_id_t	ql_timer_timeout_id = NULL;
206static clock_t		ql_timer_ticks;
207
208/* Soft state head pointer. */
209void *ql_state = NULL;
210
211/* Head adapter link. */
212ql_head_t ql_hba = {
213	NULL,
214	NULL
215};
216
217/* Global hba index */
218uint32_t ql_gfru_hba_index = 1;
219
220/*
221 * Some IP defines and globals
222 */
223uint32_t	ql_ip_buffer_count = 128;
224uint32_t	ql_ip_low_water = 10;
225uint8_t		ql_ip_fast_post_count = 5;
226static int	ql_ip_mtu = 65280;		/* equivalent to FCIPMTU */
227
228/* Device AL_PA to Device Head Queue index array. */
229uint8_t ql_alpa_to_index[] = {
230	0x7e, 0x7d, 0x7c, 0x00, 0x7b, 0x01, 0x02, 0x03, 0x7a, 0x04,
231	0x05, 0x06, 0x07, 0x08, 0x09, 0x79, 0x78, 0x0a, 0x0b, 0x0c,
232	0x0d, 0x0e, 0x0f, 0x77, 0x76, 0x10, 0x11, 0x75, 0x12, 0x74,
233	0x73, 0x72, 0x13, 0x14, 0x15, 0x71, 0x16, 0x70, 0x6f, 0x6e,
234	0x17, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x18, 0x19, 0x67,
235	0x66, 0x65, 0x64, 0x63, 0x62, 0x20, 0x21, 0x61, 0x60, 0x23,
236	0x5f, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x5e, 0x2a, 0x5d,
237	0x5c, 0x5b, 0x2b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x2c,
238	0x2d, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x2e, 0x2f, 0x4e,
239	0x4d, 0x30, 0x4c, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x4b,
240	0x37, 0x4a, 0x49, 0x48, 0x38, 0x47, 0x46, 0x45, 0x44, 0x43,
241	0x42, 0x39, 0x3a, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b,
242	0x3c, 0x3b, 0x3a, 0x3d, 0x39, 0x3e, 0x3f, 0x40, 0x38, 0x37,
243	0x36, 0x41, 0x35, 0x42, 0x43, 0x44, 0x34, 0x45, 0x46, 0x47,
244	0x48, 0x49, 0x4a, 0x33, 0x32, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
245	0x50, 0x31, 0x30, 0x51, 0x52, 0x2f, 0x53, 0x2e, 0x2d, 0x2c,
246	0x54, 0x55, 0x56, 0x2b, 0x57, 0x2a, 0x29, 0x28, 0x58, 0x27,
247	0x26, 0x25, 0x24, 0x23, 0x22, 0x59, 0x5a, 0x21, 0x20, 0x1f,
248	0x1e, 0x1d, 0x1c, 0x5b, 0x5c, 0x1b, 0x1a, 0x5d, 0x19, 0x5e,
249	0x5f, 0x60, 0x61, 0x62, 0x63, 0x18, 0x64, 0x17, 0x16, 0x15,
250	0x65, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x66, 0x67, 0x0e,
251	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x68, 0x69, 0x08, 0x07, 0x6a,
252	0x06, 0x6b, 0x6c, 0x6d, 0x05, 0x04, 0x03, 0x6e, 0x02, 0x6f,
253	0x70, 0x71, 0x01, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x00,
254	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f, 0x80, 0x00, 0x01,
255	0x02, 0x03, 0x80, 0x7f, 0x7e, 0x04
256};
257
258/* Device loop_id to ALPA array. */
259static uint8_t ql_index_to_alpa[] = {
260	0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
261	0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
262	0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
263	0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
264	0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
265	0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
266	0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
267	0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
268	0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
269	0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
270	0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
271	0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
272	0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
273};
274
275/* 2200 register offsets */
276static reg_off_t reg_off_2200 = {
277	0x00,	/* flash_address */
278	0x02,	/* flash_data */
279	0x06,	/* ctrl_status */
280	0x08,	/* ictrl */
281	0x0a,	/* istatus */
282	0x0c,	/* semaphore */
283	0x0e,	/* nvram */
284	0x18,	/* req_in */
285	0x18,	/* req_out */
286	0x1a,	/* resp_in */
287	0x1a,	/* resp_out */
288	0xff,	/* risc2host - n/a */
289	24,	/* Number of mailboxes */
290
291	/* Mailbox in register offsets 0 - 23 */
292	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
293	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
294	0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
295	/* 2200 does not have mailbox 24-31 - n/a */
296	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
297
298	/* Mailbox out register offsets 0 - 23 */
299	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
300	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
301	0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
302	/* 2200 does not have mailbox 24-31 - n/a */
303	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
304
305	0x96,	/* fpm_diag_config */
306	0xa4,	/* pcr */
307	0xb0,	/* mctr */
308	0xb8,	/* fb_cmd */
309	0xc0,	/* hccr */
310	0xcc,	/* gpiod */
311	0xce,	/* gpioe */
312	0xff,	/* host_to_host_sema - n/a */
313	0xff,	/* pri_req_in - n/a */
314	0xff,	/* pri_req_out - n/a */
315	0xff,	/* atio_req_in - n/a */
316	0xff,	/* atio_req_out - n/a */
317	0xff,	/* io_base_addr - n/a */
318	0xff,	/* nx_host_int - n/a */
319	0xff	/* nx_risc_int - n/a */
320};
321
322/* 2300 register offsets */
323static reg_off_t reg_off_2300 = {
324	0x00,	/* flash_address */
325	0x02,	/* flash_data */
326	0x06,	/* ctrl_status */
327	0x08,	/* ictrl */
328	0x0a,	/* istatus */
329	0x0c,	/* semaphore */
330	0x0e,	/* nvram */
331	0x10,	/* req_in */
332	0x12,	/* req_out */
333	0x14,	/* resp_in */
334	0x16,	/* resp_out */
335	0x18,	/* risc2host */
336	32,	/* Number of mailboxes */
337
338	/* Mailbox in register offsets 0 - 31 */
339	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
340	0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
341	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
342	0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
343
344	/* Mailbox out register offsets 0 - 31 */
345	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
346	0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
347	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
348	0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
349
350	0x96,	/* fpm_diag_config */
351	0xa4,	/* pcr */
352	0xb0,	/* mctr */
353	0x80,	/* fb_cmd */
354	0xc0,	/* hccr */
355	0xcc,	/* gpiod */
356	0xce,	/* gpioe */
357	0x1c,	/* host_to_host_sema */
358	0xff,	/* pri_req_in - n/a */
359	0xff,	/* pri_req_out - n/a */
360	0xff,	/* atio_req_in - n/a */
361	0xff,	/* atio_req_out - n/a */
362	0xff,	/* io_base_addr - n/a */
363	0xff,	/* nx_host_int - n/a */
364	0xff	/* nx_risc_int - n/a */
365};
366
367/* 2400/2500 register offsets */
368reg_off_t reg_off_2400_2500 = {
369	0x00,	/* flash_address */
370	0x04,	/* flash_data */
371	0x08,	/* ctrl_status */
372	0x0c,	/* ictrl */
373	0x10,	/* istatus */
374	0xff,	/* semaphore - n/a */
375	0xff,	/* nvram - n/a */
376	0x1c,	/* req_in */
377	0x20,	/* req_out */
378	0x24,	/* resp_in */
379	0x28,	/* resp_out */
380	0x44,	/* risc2host */
381	32,	/* Number of mailboxes */
382
383	/* Mailbox in register offsets 0 - 31 */
384	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
385	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
386	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
387	0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
388
389	/* Mailbox out register offsets 0 - 31 */
390	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
391	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
392	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
393	0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
394
395	0xff,	/* fpm_diag_config  - n/a */
396	0xff,	/* pcr - n/a */
397	0xff,	/* mctr - n/a */
398	0xff,	/* fb_cmd - n/a */
399	0x48,	/* hccr */
400	0x4c,	/* gpiod */
401	0x50,	/* gpioe */
402	0xff,	/* host_to_host_sema - n/a */
403	0x2c,	/* pri_req_in */
404	0x30,	/* pri_req_out */
405	0x3c,	/* atio_req_in */
406	0x40,	/* atio_req_out */
407	0x54,	/* io_base_addr */
408	0xff,	/* nx_host_int - n/a */
409	0xff	/* nx_risc_int - n/a */
410};
411
412/* P3 register offsets */
413static reg_off_t reg_off_8021 = {
414	0x00,	/* flash_address */
415	0x04,	/* flash_data */
416	0x08,	/* ctrl_status */
417	0x0c,	/* ictrl */
418	0x10,	/* istatus */
419	0xff,	/* semaphore - n/a */
420	0xff,	/* nvram - n/a */
421	0xff,	/* req_in - n/a */
422	0x0,	/* req_out */
423	0x100,	/* resp_in */
424	0x200,	/* resp_out */
425	0x500,	/* risc2host */
426	32,	/* Number of mailboxes */
427
428	/* Mailbox in register offsets 0 - 31 */
429	0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e,
430	0x310, 0x312, 0x314, 0x316, 0x318, 0x31a, 0x31c, 0x31e,
431	0x320, 0x322, 0x324, 0x326, 0x328, 0x32a, 0x32c, 0x32e,
432	0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e,
433
434	/* Mailbox out register offsets 0 - 31 */
435	0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e,
436	0x410, 0x412, 0x414, 0x416, 0x418, 0x41a, 0x41c, 0x41e,
437	0x420, 0x422, 0x424, 0x426, 0x428, 0x42a, 0x42c, 0x42e,
438	0x430, 0x432, 0x434, 0x436, 0x438, 0x43a, 0x43c, 0x43e,
439
440	0xff,	/* fpm_diag_config  - n/a */
441	0xff,	/* pcr - n/a */
442	0xff,	/* mctr - n/a */
443	0xff,	/* fb_cmd - n/a */
444	0x48,	/* hccr */
445	0x4c,	/* gpiod */
446	0x50,	/* gpioe */
447	0xff,	/* host_to_host_sema - n/a */
448	0x2c,	/* pri_req_in */
449	0x30,	/* pri_req_out */
450	0x3c,	/* atio_req_in */
451	0x40,	/* atio_req_out */
452	0x54,	/* io_base_addr */
453	0x380,	/* nx_host_int */
454	0x504	/* nx_risc_int */
455};
456
457/* mutex for protecting variables shared by all instances of the driver */
458kmutex_t ql_global_mutex;
459kmutex_t ql_global_hw_mutex;
460kmutex_t ql_global_el_mutex;
461
462/* DMA access attribute structure. */
463static ddi_device_acc_attr_t ql_dev_acc_attr = {
464	DDI_DEVICE_ATTR_V0,
465	DDI_STRUCTURE_LE_ACC,
466	DDI_STRICTORDER_ACC
467};
468
469/* I/O DMA attributes structures. */
470static ddi_dma_attr_t ql_64bit_io_dma_attr = {
471	DMA_ATTR_V0,			/* dma_attr_version */
472	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
473	QL_DMA_HIGH_64BIT_ADDRESS,	/* high DMA address range */
474	QL_DMA_XFER_COUNTER,		/* DMA counter register */
475	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
476	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
477	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
478	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
479	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
480	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
481	QL_DMA_GRANULARITY,		/* granularity of device */
482	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
483};
484
485static ddi_dma_attr_t ql_32bit_io_dma_attr = {
486	DMA_ATTR_V0,			/* dma_attr_version */
487	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
488	QL_DMA_HIGH_32BIT_ADDRESS,	/* high DMA address range */
489	QL_DMA_XFER_COUNTER,		/* DMA counter register */
490	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
491	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
492	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
493	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
494	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
495	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
496	QL_DMA_GRANULARITY,		/* granularity of device */
497	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
498};
499
500/* Load the default dma attributes */
501static	ddi_dma_attr_t	ql_32fcsm_cmd_dma_attr;
502static	ddi_dma_attr_t	ql_64fcsm_cmd_dma_attr;
503static	ddi_dma_attr_t	ql_32fcsm_rsp_dma_attr;
504static	ddi_dma_attr_t	ql_64fcsm_rsp_dma_attr;
505static	ddi_dma_attr_t	ql_32fcip_cmd_dma_attr;
506static	ddi_dma_attr_t	ql_64fcip_cmd_dma_attr;
507static	ddi_dma_attr_t	ql_32fcip_rsp_dma_attr;
508static	ddi_dma_attr_t	ql_64fcip_rsp_dma_attr;
509static	ddi_dma_attr_t	ql_32fcp_cmd_dma_attr;
510static	ddi_dma_attr_t	ql_64fcp_cmd_dma_attr;
511static	ddi_dma_attr_t	ql_32fcp_rsp_dma_attr;
512static	ddi_dma_attr_t	ql_64fcp_rsp_dma_attr;
513static	ddi_dma_attr_t	ql_32fcp_data_dma_attr;
514static	ddi_dma_attr_t	ql_64fcp_data_dma_attr;
515
516/* Static declarations of cb_ops entry point functions... */
517static struct cb_ops ql_cb_ops = {
518	ql_open,			/* b/c open */
519	ql_close,			/* b/c close */
520	nodev,				/* b strategy */
521	nodev,				/* b print */
522	nodev,				/* b dump */
523	nodev,				/* c read */
524	nodev,				/* c write */
525	ql_ioctl,			/* c ioctl */
526	nodev,				/* c devmap */
527	nodev,				/* c mmap */
528	nodev,				/* c segmap */
529	nochpoll,			/* c poll */
530	nodev,				/* cb_prop_op */
531	NULL,				/* streamtab  */
532	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
533	CB_REV,				/* cb_ops revision */
534	nodev,				/* c aread */
535	nodev				/* c awrite */
536};
537
538/* Static declarations of dev_ops entry point functions... */
539static struct dev_ops ql_devops = {
540	DEVO_REV,			/* devo_rev */
541	0,				/* refcnt */
542	ql_getinfo,			/* getinfo */
543	nulldev,			/* identify */
544	nulldev,			/* probe */
545	ql_attach,			/* attach */
546	ql_detach,			/* detach */
547	nodev,				/* reset */
548	&ql_cb_ops,			/* char/block ops */
549	NULL,				/* bus operations */
550	ql_power,			/* power management */
551	ql_quiesce			/* quiesce device */
552};
553
554/* ELS command code to text converter */
555cmd_table_t els_cmd_tbl[] = ELS_CMD_TABLE();
556/* Mailbox command code to text converter */
557cmd_table_t mbox_cmd_tbl[] = MBOX_CMD_TABLE();
558
559char qlc_driver_version[] = QL_VERSION;
560
561/*
562 * Loadable Driver Interface Structures.
563 * Declare and initialize the module configuration section...
564 */
565static struct modldrv modldrv = {
566	&mod_driverops,				/* type of module: driver */
567	"SunFC Qlogic FCA v" QL_VERSION,	/* name of module */
568	&ql_devops				/* driver dev_ops */
569};
570
571static struct modlinkage modlinkage = {
572	MODREV_1,
573	&modldrv,
574	NULL
575};
576
577/* ************************************************************************ */
578/*				Loadable Module Routines.		    */
579/* ************************************************************************ */
580
581/*
582 * _init
583 *	Initializes a loadable module. It is called before any other
584 *	routine in a loadable module.
585 *
586 * Returns:
587 *	0 = success
588 *
589 * Context:
590 *	Kernel context.
591 */
592int
593_init(void)
594{
595	uint16_t	w16;
596	int		rval = 0;
597
598	/* Get OS major release level. */
599	for (w16 = 0; w16 < sizeof (utsname.release); w16++) {
600		if (utsname.release[w16] == '.') {
601			w16++;
602			break;
603		}
604	}
605	if (w16 < sizeof (utsname.release)) {
606		(void) ql_bstr_to_dec(&utsname.release[w16],
607		    &ql_os_release_level, 0);
608	} else {
609		ql_os_release_level = 0;
610	}
611	if (ql_os_release_level < 6) {
612		cmn_err(CE_WARN, "%s Unsupported OS release level = %d",
613		    QL_NAME, ql_os_release_level);
614		rval = EINVAL;
615	}
616	if (ql_os_release_level == 6) {
617		ql_32bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
618		ql_64bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
619	}
620
621	if (rval == 0) {
622		rval = ddi_soft_state_init(&ql_state,
623		    sizeof (ql_adapter_state_t), 0);
624	}
625	if (rval == 0) {
626		/* allow the FC Transport to tweak the dev_ops */
627		fc_fca_init(&ql_devops);
628
629		mutex_init(&ql_global_mutex, NULL, MUTEX_DRIVER, NULL);
630		mutex_init(&ql_global_hw_mutex, NULL, MUTEX_DRIVER, NULL);
631		mutex_init(&ql_global_el_mutex, NULL, MUTEX_DRIVER, NULL);
632		rval = mod_install(&modlinkage);
633		if (rval != 0) {
634			mutex_destroy(&ql_global_hw_mutex);
635			mutex_destroy(&ql_global_mutex);
636			mutex_destroy(&ql_global_el_mutex);
637			ddi_soft_state_fini(&ql_state);
638		} else {
639			/*EMPTY*/
640			ql_32fcsm_cmd_dma_attr = ql_32bit_io_dma_attr;
641			ql_64fcsm_cmd_dma_attr = ql_64bit_io_dma_attr;
642			ql_32fcsm_rsp_dma_attr = ql_32bit_io_dma_attr;
643			ql_64fcsm_rsp_dma_attr = ql_64bit_io_dma_attr;
644			ql_32fcip_cmd_dma_attr = ql_32bit_io_dma_attr;
645			ql_64fcip_cmd_dma_attr = ql_64bit_io_dma_attr;
646			ql_32fcip_rsp_dma_attr = ql_32bit_io_dma_attr;
647			ql_64fcip_rsp_dma_attr = ql_64bit_io_dma_attr;
648			ql_32fcp_cmd_dma_attr = ql_32bit_io_dma_attr;
649			ql_64fcp_cmd_dma_attr = ql_64bit_io_dma_attr;
650			ql_32fcp_rsp_dma_attr = ql_32bit_io_dma_attr;
651			ql_64fcp_rsp_dma_attr = ql_64bit_io_dma_attr;
652			ql_32fcp_data_dma_attr = ql_32bit_io_dma_attr;
653			ql_64fcp_data_dma_attr = ql_64bit_io_dma_attr;
654			ql_32fcsm_cmd_dma_attr.dma_attr_sgllen =
655			    ql_64fcsm_cmd_dma_attr.dma_attr_sgllen =
656			    QL_FCSM_CMD_SGLLEN;
657			ql_32fcsm_rsp_dma_attr.dma_attr_sgllen =
658			    ql_64fcsm_rsp_dma_attr.dma_attr_sgllen =
659			    QL_FCSM_RSP_SGLLEN;
660			ql_32fcip_cmd_dma_attr.dma_attr_sgllen =
661			    ql_64fcip_cmd_dma_attr.dma_attr_sgllen =
662			    QL_FCIP_CMD_SGLLEN;
663			ql_32fcip_rsp_dma_attr.dma_attr_sgllen =
664			    ql_64fcip_rsp_dma_attr.dma_attr_sgllen =
665			    QL_FCIP_RSP_SGLLEN;
666			ql_32fcp_cmd_dma_attr.dma_attr_sgllen =
667			    ql_64fcp_cmd_dma_attr.dma_attr_sgllen =
668			    QL_FCP_CMD_SGLLEN;
669			ql_32fcp_rsp_dma_attr.dma_attr_sgllen =
670			    ql_64fcp_rsp_dma_attr.dma_attr_sgllen =
671			    QL_FCP_RSP_SGLLEN;
672		}
673	}
674
675	if (rval != 0) {
676		cmn_err(CE_CONT, "?Unable to install/attach driver '%s'",
677		    QL_NAME);
678	}
679
680	return (rval);
681}
682
683/*
684 * _fini
685 *	Prepares a module for unloading. It is called when the system
686 *	wants to unload a module. If the module determines that it can
687 *	be unloaded, then _fini() returns the value returned by
688 *	mod_remove(). Upon successful return from _fini() no other
689 *	routine in the module will be called before _init() is called.
690 *
691 * Returns:
692 *	0 = success
693 *
694 * Context:
695 *	Kernel context.
696 */
697int
698_fini(void)
699{
700	int	rval;
701
702	rval = mod_remove(&modlinkage);
703	if (rval == 0) {
704		mutex_destroy(&ql_global_hw_mutex);
705		mutex_destroy(&ql_global_mutex);
706		mutex_destroy(&ql_global_el_mutex);
707		ddi_soft_state_fini(&ql_state);
708	}
709
710	return (rval);
711}
712
713/*
714 * _info
715 *	Returns information about loadable module.
716 *
717 * Input:
718 *	modinfo = pointer to module information structure.
719 *
720 * Returns:
721 *	Value returned by mod_info().
722 *
723 * Context:
724 *	Kernel context.
725 */
726int
727_info(struct modinfo *modinfop)
728{
729	return (mod_info(&modlinkage, modinfop));
730}
731
732/* ************************************************************************ */
733/*			dev_ops functions				    */
734/* ************************************************************************ */
735
736/*
737 * ql_getinfo
738 *	Returns the pointer associated with arg when cmd is
739 *	set to DDI_INFO_DEVT2DEVINFO, or it should return the
740 *	instance number associated with arg when cmd is set
741 *	to DDI_INFO_DEV2INSTANCE.
742 *
743 * Input:
744 *	dip = Do not use.
745 *	cmd = command argument.
746 *	arg = command specific argument.
747 *	resultp = pointer to where request information is stored.
748 *
749 * Returns:
750 *	DDI_SUCCESS or DDI_FAILURE.
751 *
752 * Context:
753 *	Kernel context.
754 */
755/* ARGSUSED */
756static int
757ql_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
758{
759	ql_adapter_state_t	*ha;
760	int			minor;
761	int			rval = DDI_FAILURE;
762
763	minor = (int)(getminor((dev_t)arg));
764	ha = ddi_get_soft_state(ql_state, minor);
765	if (ha == NULL) {
766		QL_PRINT_2(CE_CONT, "failed, unknown minor=%d\n",
767		    getminor((dev_t)arg));
768		*resultp = NULL;
769		return (rval);
770	}
771
772	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
773
774	switch (cmd) {
775	case DDI_INFO_DEVT2DEVINFO:
776		*resultp = ha->dip;
777		rval = DDI_SUCCESS;
778		break;
779	case DDI_INFO_DEVT2INSTANCE:
780		*resultp = (void *)(uintptr_t)(ha->instance);
781		rval = DDI_SUCCESS;
782		break;
783	default:
784		EL(ha, "failed, unsupported cmd=%d\n", cmd);
785		rval = DDI_FAILURE;
786		break;
787	}
788
789	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
790
791	return (rval);
792}
793
794/*
795 * ql_attach
796 *	Configure and attach an instance of the driver
797 *	for a port.
798 *
799 * Input:
800 *	dip = pointer to device information structure.
801 *	cmd = attach type.
802 *
803 * Returns:
804 *	DDI_SUCCESS or DDI_FAILURE.
805 *
806 * Context:
807 *	Kernel context.
808 */
809static int
810ql_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
811{
812	off_t			regsize;
813	uint32_t		size;
814	int			rval, *ptr;
815	int			instance;
816	uint_t			progress = 0;
817	char			*buf;
818	ushort_t		caps_ptr, cap;
819	fc_fca_tran_t		*tran;
820	ql_adapter_state_t	*ha = NULL;
821
822	static char *pmcomps[] = {
823		NULL,
824		PM_LEVEL_D3_STR,		/* Device OFF */
825		PM_LEVEL_D0_STR,		/* Device ON */
826	};
827
828	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n",
829	    ddi_get_instance(dip), cmd);
830
831	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
832
833	switch (cmd) {
834	case DDI_ATTACH:
835		/* first get the instance */
836		instance = ddi_get_instance(dip);
837
838		cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
839		    QL_NAME, instance, QL_VERSION);
840
841		/* Correct OS version? */
842		if (ql_os_release_level != 11) {
843			cmn_err(CE_WARN, "%s(%d): This driver is for Solaris "
844			    "11", QL_NAME, instance);
845			goto attach_failed;
846		}
847
848		/* Hardware is installed in a DMA-capable slot? */
849		if (ddi_slaveonly(dip) == DDI_SUCCESS) {
850			cmn_err(CE_WARN, "%s(%d): slave only", QL_NAME,
851			    instance);
852			goto attach_failed;
853		}
854
855		/* No support for high-level interrupts */
856		if (ddi_intr_hilevel(dip, 0) != 0) {
857			cmn_err(CE_WARN, "%s(%d): High level interrupt"
858			    " not supported", QL_NAME, instance);
859			goto attach_failed;
860		}
861
862		/* Allocate our per-device-instance structure */
863		if (ddi_soft_state_zalloc(ql_state,
864		    instance) != DDI_SUCCESS) {
865			cmn_err(CE_WARN, "%s(%d): soft state alloc failed",
866			    QL_NAME, instance);
867			goto attach_failed;
868		}
869		progress |= QL_SOFT_STATE_ALLOCED;
870
871		ha = ddi_get_soft_state(ql_state, instance);
872		if (ha == NULL) {
873			cmn_err(CE_WARN, "%s(%d): can't get soft state",
874			    QL_NAME, instance);
875			goto attach_failed;
876		}
877		ha->dip = dip;
878		ha->instance = instance;
879		ha->hba.base_address = ha;
880		ha->pha = ha;
881
882		if (ql_el_trace_desc_ctor(ha) != DDI_SUCCESS) {
883			cmn_err(CE_WARN, "%s(%d): can't setup el tracing",
884			    QL_NAME, instance);
885			goto attach_failed;
886		}
887
888		/* Get extended logging and dump flags. */
889		ql_common_properties(ha);
890
891		if (strcmp(ddi_driver_name(ddi_get_parent(dip)),
892		    "sbus") == 0) {
893			EL(ha, "%s SBUS card detected", QL_NAME);
894			ha->cfg_flags |= CFG_SBUS_CARD;
895		}
896
897		ha->dev = kmem_zalloc(sizeof (*ha->dev) *
898		    DEVICE_HEAD_LIST_SIZE, KM_SLEEP);
899
900		ha->outstanding_cmds = kmem_zalloc(
901		    sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS,
902		    KM_SLEEP);
903
904		ha->ub_array = kmem_zalloc(sizeof (*ha->ub_array) *
905		    QL_UB_LIMIT, KM_SLEEP);
906
907		ha->adapter_stats = kmem_zalloc(sizeof (*ha->adapter_stats),
908		    KM_SLEEP);
909
910		(void) ddi_pathname(dip, buf);
911		ha->devpath = kmem_zalloc(strlen(buf)+1, KM_SLEEP);
912		if (ha->devpath == NULL) {
913			EL(ha, "devpath mem alloc failed\n");
914		} else {
915			(void) strcpy(ha->devpath, buf);
916			EL(ha, "devpath is: %s\n", ha->devpath);
917		}
918
919		if (CFG_IST(ha, CFG_SBUS_CARD)) {
920			/*
921			 * For cards where PCI is mapped to sbus e.g. Ivory.
922			 *
923			 * 0x00	: 0x000 - 0x0FF PCI Config Space for 2200
924			 *	: 0x100 - 0x3FF PCI IO space for 2200
925			 * 0x01	: 0x000 - 0x0FF PCI Config Space for fpga
926			 *	: 0x100 - 0x3FF PCI IO Space for fpga
927			 */
928			if (ddi_regs_map_setup(dip, 0, (caddr_t *)&ha->iobase,
929			    0x100, 0x300, &ql_dev_acc_attr, &ha->dev_handle) !=
930			    DDI_SUCCESS) {
931				cmn_err(CE_WARN, "%s(%d): Unable to map device"
932				    " registers", QL_NAME, instance);
933				goto attach_failed;
934			}
935			if (ddi_regs_map_setup(dip, 1,
936			    (caddr_t *)&ha->sbus_fpga_iobase, 0, 0x400,
937			    &ql_dev_acc_attr, &ha->sbus_fpga_dev_handle) !=
938			    DDI_SUCCESS) {
939				/* We should not fail attach here */
940				cmn_err(CE_WARN, "%s(%d): Unable to map FPGA",
941				    QL_NAME, instance);
942				ha->sbus_fpga_iobase = NULL;
943			}
944			progress |= QL_REGS_MAPPED;
945
946			/*
947			 * We should map config space before adding interrupt
948			 * So that the chip type (2200 or 2300) can be
949			 * determined before the interrupt routine gets a
950			 * chance to execute.
951			 */
952			if (ddi_regs_map_setup(dip, 0,
953			    (caddr_t *)&ha->sbus_config_base, 0, 0x100,
954			    &ql_dev_acc_attr, &ha->sbus_config_handle) !=
955			    DDI_SUCCESS) {
956				cmn_err(CE_WARN, "%s(%d): Unable to map sbus "
957				    "config registers", QL_NAME, instance);
958				goto attach_failed;
959			}
960			progress |= QL_CONFIG_SPACE_SETUP;
961		} else {
962			/*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/
963			rval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
964			    DDI_PROP_DONTPASS, "reg", &ptr, &size);
965			if (rval != DDI_PROP_SUCCESS) {
966				cmn_err(CE_WARN, "%s(%d): Unable to get PCI "
967				    "address registers", QL_NAME, instance);
968				goto attach_failed;
969			} else {
970				ha->pci_bus_addr = ptr[0];
971				ha->function_number = (uint8_t)
972				    (ha->pci_bus_addr >> 8 & 7);
973				ddi_prop_free(ptr);
974			}
975
976			/*
977			 * We should map config space before adding interrupt
978			 * So that the chip type (2200 or 2300) can be
979			 * determined before the interrupt routine gets a
980			 * chance to execute.
981			 */
982			if (pci_config_setup(ha->dip, &ha->pci_handle) !=
983			    DDI_SUCCESS) {
984				cmn_err(CE_WARN, "%s(%d): can't setup PCI "
985				    "config space", QL_NAME, instance);
986				goto attach_failed;
987			}
988			progress |= QL_CONFIG_SPACE_SETUP;
989
990			/*
991			 * Setup the ISP2200 registers address mapping to be
992			 * accessed by this particular driver.
993			 * 0x0   Configuration Space
994			 * 0x1   I/O Space
995			 * 0x2   32-bit Memory Space address
996			 * 0x3   64-bit Memory Space address
997			 */
998			size = ql_pci_config_get32(ha, PCI_CONF_BASE0) & BIT_0 ?
999			    2 : 1;
1000			if (ddi_dev_regsize(dip, size, &regsize) !=
1001			    DDI_SUCCESS ||
1002			    ddi_regs_map_setup(dip, size, &ha->iobase,
1003			    0, regsize, &ql_dev_acc_attr, &ha->dev_handle) !=
1004			    DDI_SUCCESS) {
1005				cmn_err(CE_WARN, "%s(%d): regs_map_setup(mem) "
1006				    "failed", QL_NAME, instance);
1007				goto attach_failed;
1008			}
1009			progress |= QL_REGS_MAPPED;
1010
1011			/*
1012			 * We need I/O space mappings for 23xx HBAs for
1013			 * loading flash (FCode). The chip has a bug due to
1014			 * which loading flash fails through mem space
1015			 * mappings in PCI-X mode.
1016			 */
1017			if (size == 1) {
1018				ha->iomap_iobase = ha->iobase;
1019				ha->iomap_dev_handle = ha->dev_handle;
1020			} else {
1021				if (ddi_dev_regsize(dip, 1, &regsize) !=
1022				    DDI_SUCCESS ||
1023				    ddi_regs_map_setup(dip, 1,
1024				    &ha->iomap_iobase, 0, regsize,
1025				    &ql_dev_acc_attr, &ha->iomap_dev_handle) !=
1026				    DDI_SUCCESS) {
1027					cmn_err(CE_WARN, "%s(%d): regs_map_"
1028					    "setup(I/O) failed", QL_NAME,
1029					    instance);
1030					goto attach_failed;
1031				}
1032				progress |= QL_IOMAP_IOBASE_MAPPED;
1033			}
1034		}
1035
1036		ha->subsys_id = (uint16_t)ql_pci_config_get16(ha,
1037		    PCI_CONF_SUBSYSID);
1038		ha->subven_id = (uint16_t)ql_pci_config_get16(ha,
1039		    PCI_CONF_SUBVENID);
1040		ha->ven_id = (uint16_t)ql_pci_config_get16(ha,
1041		    PCI_CONF_VENID);
1042		ha->device_id = (uint16_t)ql_pci_config_get16(ha,
1043		    PCI_CONF_DEVID);
1044		ha->rev_id = (uint8_t)ql_pci_config_get8(ha,
1045		    PCI_CONF_REVID);
1046
1047		EL(ha, "ISP%x chip detected (RevID=%x, VenID=%x, SVenID=%x, "
1048		    "SSysID=%x)\n", ha->device_id, ha->rev_id, ha->ven_id,
1049		    ha->subven_id, ha->subsys_id);
1050
1051		switch (ha->device_id) {
1052		case 0x2300:
1053		case 0x2312:
1054		case 0x2322:
1055		case 0x6312:
1056		case 0x6322:
1057			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
1058				ha->flags |= FUNCTION_1;
1059			}
1060			if ((ha->device_id == 0x6322) ||
1061			    (ha->device_id == 0x2322)) {
1062				ha->cfg_flags |= CFG_CTRL_6322;
1063				ha->fw_class = 0x6322;
1064				ha->risc_dump_size = QL_6322_FW_DUMP_SIZE;
1065			} else {
1066				ha->cfg_flags |= CFG_CTRL_2300;
1067				ha->fw_class = 0x2300;
1068				ha->risc_dump_size = QL_2300_FW_DUMP_SIZE;
1069			}
1070			ha->reg_off = &reg_off_2300;
1071			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1072				goto attach_failed;
1073			}
1074			ha->fcp_cmd = ql_command_iocb;
1075			ha->ip_cmd = ql_ip_iocb;
1076			ha->ms_cmd = ql_ms_iocb;
1077			if (CFG_IST(ha, CFG_SBUS_CARD)) {
1078				ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS;
1079				ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS;
1080			} else {
1081				ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS;
1082				ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1083			}
1084			break;
1085
1086		case 0x2200:
1087			ha->cfg_flags |= CFG_CTRL_2200;
1088			ha->reg_off = &reg_off_2200;
1089			ha->fw_class = 0x2200;
1090			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1091				goto attach_failed;
1092			}
1093			ha->risc_dump_size = QL_2200_FW_DUMP_SIZE;
1094			ha->fcp_cmd = ql_command_iocb;
1095			ha->ip_cmd = ql_ip_iocb;
1096			ha->ms_cmd = ql_ms_iocb;
1097			if (CFG_IST(ha, CFG_SBUS_CARD)) {
1098				ha->cmd_segs = CMD_TYPE_2_DATA_SEGMENTS;
1099				ha->cmd_cont_segs = CONT_TYPE_0_DATA_SEGMENTS;
1100			} else {
1101				ha->cmd_segs = CMD_TYPE_3_DATA_SEGMENTS;
1102				ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1103			}
1104			break;
1105
1106		case 0x2422:
1107		case 0x2432:
1108		case 0x5422:
1109		case 0x5432:
1110		case 0x8432:
1111			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
1112				ha->flags |= FUNCTION_1;
1113			}
1114			ha->cfg_flags |= CFG_CTRL_2422;
1115			if (ha->device_id == 0x8432) {
1116				ha->cfg_flags |= CFG_CTRL_MENLO;
1117			} else {
1118				ha->flags |= VP_ENABLED;
1119			}
1120
1121			ha->reg_off = &reg_off_2400_2500;
1122			ha->fw_class = 0x2400;
1123			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1124				goto attach_failed;
1125			}
1126			ha->risc_dump_size = QL_24XX_FW_DUMP_SIZE;
1127			ha->fcp_cmd = ql_command_24xx_iocb;
1128			ha->ip_cmd = ql_ip_24xx_iocb;
1129			ha->ms_cmd = ql_ms_24xx_iocb;
1130			ha->els_cmd = ql_els_24xx_iocb;
1131			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1132			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1133			break;
1134
1135		case 0x2522:
1136		case 0x2532:
1137			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
1138				ha->flags |= FUNCTION_1;
1139			}
1140			ha->cfg_flags |= CFG_CTRL_25XX;
1141			ha->flags |= VP_ENABLED;
1142			ha->fw_class = 0x2500;
1143			ha->reg_off = &reg_off_2400_2500;
1144			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1145				goto attach_failed;
1146			}
1147			ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
1148			ha->fcp_cmd = ql_command_24xx_iocb;
1149			ha->ip_cmd = ql_ip_24xx_iocb;
1150			ha->ms_cmd = ql_ms_24xx_iocb;
1151			ha->els_cmd = ql_els_24xx_iocb;
1152			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1153			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1154			break;
1155
1156		case 0x8001:
1157			if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 4) {
1158				ha->flags |= FUNCTION_1;
1159			}
1160			ha->cfg_flags |= CFG_CTRL_81XX;
1161			ha->flags |= VP_ENABLED;
1162			ha->fw_class = 0x8100;
1163			ha->reg_off = &reg_off_2400_2500;
1164			if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
1165				goto attach_failed;
1166			}
1167			ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
1168			ha->fcp_cmd = ql_command_24xx_iocb;
1169			ha->ip_cmd = ql_ip_24xx_iocb;
1170			ha->ms_cmd = ql_ms_24xx_iocb;
1171			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1172			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1173			break;
1174
1175		case 0x8021:
1176			if (ha->function_number & BIT_0) {
1177				ha->flags |= FUNCTION_1;
1178			}
1179			ha->cfg_flags |= CFG_CTRL_8021;
1180			ha->reg_off = &reg_off_8021;
1181			ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
1182			ha->fcp_cmd = ql_command_24xx_iocb;
1183			ha->ms_cmd = ql_ms_24xx_iocb;
1184			ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
1185			ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
1186
1187			ha->nx_pcibase = ha->iobase;
1188			ha->iobase += 0xBC000 + (ha->function_number << 11);
1189			ha->iomap_iobase += 0xBC000 +
1190			    (ha->function_number << 11);
1191
1192			/* map doorbell */
1193			if (ddi_dev_regsize(dip, 2, &regsize) != DDI_SUCCESS ||
1194			    ddi_regs_map_setup(dip, 2, &ha->db_iobase,
1195			    0, regsize, &ql_dev_acc_attr, &ha->db_dev_handle) !=
1196			    DDI_SUCCESS) {
1197				cmn_err(CE_WARN, "%s(%d): regs_map_setup"
1198				    "(doorbell) failed", QL_NAME, instance);
1199				goto attach_failed;
1200			}
1201			progress |= QL_DB_IOBASE_MAPPED;
1202
1203			ha->nx_req_in = (uint32_t *)(ha->db_iobase +
1204			    (ha->function_number << 12));
1205			ha->db_read = ha->nx_pcibase + (512 * 1024) +
1206			    (ha->function_number * 8);
1207
1208			ql_8021_update_crb_int_ptr(ha);
1209			ql_8021_set_drv_active(ha);
1210			break;
1211
1212		default:
1213			cmn_err(CE_WARN, "%s(%d): Unsupported device id: %x",
1214			    QL_NAME, instance, ha->device_id);
1215			goto attach_failed;
1216		}
1217
1218		/* Setup hba buffer. */
1219
1220		size = CFG_IST(ha, CFG_CTRL_24258081) ?
1221		    (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE) :
1222		    (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE +
1223		    RCVBUF_QUEUE_SIZE);
1224
1225		if (ql_get_dma_mem(ha, &ha->hba_buf, size, LITTLE_ENDIAN_DMA,
1226		    QL_DMA_RING_ALIGN) != QL_SUCCESS) {
1227			cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
1228			    "alloc failed", QL_NAME, instance);
1229			goto attach_failed;
1230		}
1231		progress |= QL_HBA_BUFFER_SETUP;
1232
1233		/* Setup buffer pointers. */
1234		ha->request_dvma = ha->hba_buf.cookie.dmac_laddress +
1235		    REQUEST_Q_BUFFER_OFFSET;
1236		ha->request_ring_bp = (struct cmd_entry *)
1237		    ((caddr_t)ha->hba_buf.bp + REQUEST_Q_BUFFER_OFFSET);
1238
1239		ha->response_dvma = ha->hba_buf.cookie.dmac_laddress +
1240		    RESPONSE_Q_BUFFER_OFFSET;
1241		ha->response_ring_bp = (struct sts_entry *)
1242		    ((caddr_t)ha->hba_buf.bp + RESPONSE_Q_BUFFER_OFFSET);
1243
1244		ha->rcvbuf_dvma = ha->hba_buf.cookie.dmac_laddress +
1245		    RCVBUF_Q_BUFFER_OFFSET;
1246		ha->rcvbuf_ring_bp = (struct rcvbuf *)
1247		    ((caddr_t)ha->hba_buf.bp + RCVBUF_Q_BUFFER_OFFSET);
1248
1249		/* Allocate resource for QLogic IOCTL */
1250		(void) ql_alloc_xioctl_resource(ha);
1251
1252		/* Setup interrupts */
1253		if ((rval = ql_setup_interrupts(ha)) != DDI_SUCCESS) {
1254			cmn_err(CE_WARN, "%s(%d): Failed to add interrupt, "
1255			    "rval=%xh", QL_NAME, instance, rval);
1256			goto attach_failed;
1257		}
1258
1259		progress |= (QL_INTR_ADDED | QL_MUTEX_CV_INITED);
1260
1261		if (ql_nvram_cache_desc_ctor(ha) != DDI_SUCCESS) {
1262			cmn_err(CE_WARN, "%s(%d): can't setup nvram cache",
1263			    QL_NAME, instance);
1264			goto attach_failed;
1265		}
1266
1267		/*
1268		 * Allocate an N Port information structure
1269		 * for use when in P2P topology.
1270		 */
1271		ha->n_port = (ql_n_port_info_t *)
1272		    kmem_zalloc(sizeof (ql_n_port_info_t), KM_SLEEP);
1273		if (ha->n_port == NULL) {
1274			cmn_err(CE_WARN, "%s(%d): Failed to create N Port info",
1275			    QL_NAME, instance);
1276			goto attach_failed;
1277		}
1278
1279		progress |= QL_N_PORT_INFO_CREATED;
1280
1281		/*
1282		 * Determine support for Power Management
1283		 */
1284		caps_ptr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR);
1285
1286		while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
1287			cap = (uint8_t)ql_pci_config_get8(ha, caps_ptr);
1288			if (cap == PCI_CAP_ID_PM) {
1289				ha->pm_capable = 1;
1290				break;
1291			}
1292			caps_ptr = (uint8_t)ql_pci_config_get8(ha, caps_ptr +
1293			    PCI_CAP_NEXT_PTR);
1294		}
1295
1296		if (ha->pm_capable) {
1297			/*
1298			 * Enable PM for 2200 based HBAs only.
1299			 */
1300			if (ha->device_id != 0x2200) {
1301				ha->pm_capable = 0;
1302			}
1303		}
1304
1305		if (ha->pm_capable) {
1306			ha->pm_capable = ql_enable_pm;
1307		}
1308
1309		if (ha->pm_capable) {
1310			/*
1311			 * Initialize power management bookkeeping;
1312			 * components are created idle.
1313			 */
1314			(void) sprintf(buf, "NAME=%s(%d)", QL_NAME, instance);
1315			pmcomps[0] = buf;
1316
1317			/*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
1318			if (ddi_prop_update_string_array(DDI_DEV_T_NONE,
1319			    dip, "pm-components", pmcomps,
1320			    sizeof (pmcomps) / sizeof (pmcomps[0])) !=
1321			    DDI_PROP_SUCCESS) {
1322				cmn_err(CE_WARN, "%s(%d): failed to create"
1323				    " pm-components property", QL_NAME,
1324				    instance);
1325
1326				/* Initialize adapter. */
1327				ha->power_level = PM_LEVEL_D0;
1328				if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1329					cmn_err(CE_WARN, "%s(%d): failed to"
1330					    " initialize adapter", QL_NAME,
1331					    instance);
1332					goto attach_failed;
1333				}
1334			} else {
1335				ha->power_level = PM_LEVEL_D3;
1336				if (pm_raise_power(dip, QL_POWER_COMPONENT,
1337				    PM_LEVEL_D0) != DDI_SUCCESS) {
1338					cmn_err(CE_WARN, "%s(%d): failed to"
1339					    " raise power or initialize"
1340					    " adapter", QL_NAME, instance);
1341				}
1342			}
1343		} else {
1344			/* Initialize adapter. */
1345			ha->power_level = PM_LEVEL_D0;
1346			if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1347				cmn_err(CE_WARN, "%s(%d): failed to initialize"
1348				    " adapter", QL_NAME, instance);
1349			}
1350		}
1351
1352		if (ha->fw_major_version == 0 && ha->fw_minor_version == 0 &&
1353		    ha->fw_subminor_version == 0) {
1354			cmn_err(CE_NOTE, "!%s(%d): Firmware not loaded",
1355			    QL_NAME, ha->instance);
1356		} else {
1357			int	rval;
1358			char	ver_fmt[256];
1359
1360			rval = (int)snprintf(ver_fmt, (size_t)sizeof (ver_fmt),
1361			    "Firmware version %d.%d.%d", ha->fw_major_version,
1362			    ha->fw_minor_version, ha->fw_subminor_version);
1363
1364			if (CFG_IST(ha, CFG_CTRL_81XX)) {
1365				rval = (int)snprintf(ver_fmt + rval,
1366				    (size_t)sizeof (ver_fmt),
1367				    ", MPI fw version %d.%d.%d",
1368				    ha->mpi_fw_major_version,
1369				    ha->mpi_fw_minor_version,
1370				    ha->mpi_fw_subminor_version);
1371
1372				if (ha->subsys_id == 0x17B ||
1373				    ha->subsys_id == 0x17D) {
1374					(void) snprintf(ver_fmt + rval,
1375					    (size_t)sizeof (ver_fmt),
1376					    ", PHY fw version %d.%d.%d",
1377					    ha->phy_fw_major_version,
1378					    ha->phy_fw_minor_version,
1379					    ha->phy_fw_subminor_version);
1380				}
1381			}
1382			cmn_err(CE_NOTE, "!%s(%d): %s",
1383			    QL_NAME, ha->instance, ver_fmt);
1384		}
1385
1386		ha->k_stats = kstat_create(QL_NAME, instance, "statistics",
1387		    "controller", KSTAT_TYPE_RAW,
1388		    (uint32_t)sizeof (ql_adapter_stat_t), KSTAT_FLAG_VIRTUAL);
1389		if (ha->k_stats == NULL) {
1390			cmn_err(CE_WARN, "%s(%d): Failed to create kstat",
1391			    QL_NAME, instance);
1392			goto attach_failed;
1393		}
1394		progress |= QL_KSTAT_CREATED;
1395
1396		ha->adapter_stats->version = 1;
1397		ha->k_stats->ks_data = (void *)ha->adapter_stats;
1398		ha->k_stats->ks_private = ha;
1399		ha->k_stats->ks_update = ql_kstat_update;
1400		ha->k_stats->ks_ndata = 1;
1401		ha->k_stats->ks_data_size = sizeof (ql_adapter_stat_t);
1402		kstat_install(ha->k_stats);
1403
1404		if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
1405		    instance, DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
1406			cmn_err(CE_WARN, "%s(%d): failed to create minor node",
1407			    QL_NAME, instance);
1408			goto attach_failed;
1409		}
1410		progress |= QL_MINOR_NODE_CREATED;
1411
1412		/* Allocate a transport structure for this instance */
1413		tran = kmem_zalloc(sizeof (fc_fca_tran_t), KM_SLEEP);
1414		if (tran == NULL) {
1415			cmn_err(CE_WARN, "%s(%d): failed to allocate transport",
1416			    QL_NAME, instance);
1417			goto attach_failed;
1418		}
1419
1420		progress |= QL_FCA_TRAN_ALLOCED;
1421
1422		/* fill in the structure */
1423		tran->fca_numports = 1;
1424		tran->fca_version = FCTL_FCA_MODREV_5;
1425		if (CFG_IST(ha, CFG_CTRL_2422)) {
1426			tran->fca_num_npivports = MAX_24_VIRTUAL_PORTS;
1427		} else if (CFG_IST(ha, CFG_CTRL_2581)) {
1428			tran->fca_num_npivports = MAX_25_VIRTUAL_PORTS;
1429		}
1430		bcopy(ha->loginparams.node_ww_name.raw_wwn,
1431		    tran->fca_perm_pwwn.raw_wwn, 8);
1432
1433		EL(ha, "FCA version %d\n", tran->fca_version);
1434
1435		/* Specify the amount of space needed in each packet */
1436		tran->fca_pkt_size = sizeof (ql_srb_t);
1437
1438		/* command limits are usually dictated by hardware */
1439		tran->fca_cmd_max = MAX_OUTSTANDING_COMMANDS;
1440
1441		/* dmaattr are static, set elsewhere. */
1442		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1443			tran->fca_dma_attr = &ql_64bit_io_dma_attr;
1444			tran->fca_dma_fcp_cmd_attr = &ql_64fcp_cmd_dma_attr;
1445			tran->fca_dma_fcp_rsp_attr = &ql_64fcp_rsp_dma_attr;
1446			tran->fca_dma_fcp_data_attr = &ql_64fcp_data_dma_attr;
1447			tran->fca_dma_fcsm_cmd_attr = &ql_64fcsm_cmd_dma_attr;
1448			tran->fca_dma_fcsm_rsp_attr = &ql_64fcsm_rsp_dma_attr;
1449			tran->fca_dma_fcip_cmd_attr = &ql_64fcip_cmd_dma_attr;
1450			tran->fca_dma_fcip_rsp_attr = &ql_64fcip_rsp_dma_attr;
1451		} else {
1452			tran->fca_dma_attr = &ql_32bit_io_dma_attr;
1453			tran->fca_dma_fcp_cmd_attr = &ql_32fcp_cmd_dma_attr;
1454			tran->fca_dma_fcp_rsp_attr = &ql_32fcp_rsp_dma_attr;
1455			tran->fca_dma_fcp_data_attr = &ql_32fcp_data_dma_attr;
1456			tran->fca_dma_fcsm_cmd_attr = &ql_32fcsm_cmd_dma_attr;
1457			tran->fca_dma_fcsm_rsp_attr = &ql_32fcsm_rsp_dma_attr;
1458			tran->fca_dma_fcip_cmd_attr = &ql_32fcip_cmd_dma_attr;
1459			tran->fca_dma_fcip_rsp_attr = &ql_32fcip_rsp_dma_attr;
1460		}
1461
1462		tran->fca_acc_attr = &ql_dev_acc_attr;
1463		tran->fca_iblock = &(ha->iblock_cookie);
1464
1465		/* the remaining values are simply function vectors */
1466		tran->fca_bind_port = ql_bind_port;
1467		tran->fca_unbind_port = ql_unbind_port;
1468		tran->fca_init_pkt = ql_init_pkt;
1469		tran->fca_un_init_pkt = ql_un_init_pkt;
1470		tran->fca_els_send = ql_els_send;
1471		tran->fca_get_cap = ql_get_cap;
1472		tran->fca_set_cap = ql_set_cap;
1473		tran->fca_getmap = ql_getmap;
1474		tran->fca_transport = ql_transport;
1475		tran->fca_ub_alloc = ql_ub_alloc;
1476		tran->fca_ub_free = ql_ub_free;
1477		tran->fca_ub_release = ql_ub_release;
1478		tran->fca_abort = ql_abort;
1479		tran->fca_reset = ql_reset;
1480		tran->fca_port_manage = ql_port_manage;
1481		tran->fca_get_device = ql_get_device;
1482
1483		/* give it to the FC transport */
1484		if (fc_fca_attach(dip, tran) != DDI_SUCCESS) {
1485			cmn_err(CE_WARN, "%s(%d): FCA attach failed", QL_NAME,
1486			    instance);
1487			goto attach_failed;
1488		}
1489		progress |= QL_FCA_ATTACH_DONE;
1490
1491		/* Stash the structure so it can be freed at detach */
1492		ha->tran = tran;
1493
1494		/* Acquire global state lock. */
1495		GLOBAL_STATE_LOCK();
1496
1497		/* Add adapter structure to link list. */
1498		ql_add_link_b(&ql_hba, &ha->hba);
1499
1500		/* Start one second driver timer. */
1501		if (ql_timer_timeout_id == NULL) {
1502			ql_timer_ticks = drv_usectohz(1000000);
1503			ql_timer_timeout_id = timeout(ql_timer, (void *)0,
1504			    ql_timer_ticks);
1505		}
1506
1507		/* Release global state lock. */
1508		GLOBAL_STATE_UNLOCK();
1509
1510		/* Determine and populate HBA fru info */
1511		ql_setup_fruinfo(ha);
1512
1513		/* Setup task_daemon thread. */
1514		(void) thread_create(NULL, 0, (void (*)())ql_task_daemon, ha,
1515		    0, &p0, TS_RUN, minclsyspri);
1516
1517		progress |= QL_TASK_DAEMON_STARTED;
1518
1519		ddi_report_dev(dip);
1520
1521		/* Disable link reset in panic path */
1522		ha->lip_on_panic = 1;
1523
1524		rval = DDI_SUCCESS;
1525		break;
1526
1527attach_failed:
1528		if (progress & QL_FCA_ATTACH_DONE) {
1529			(void) fc_fca_detach(dip);
1530			progress &= ~QL_FCA_ATTACH_DONE;
1531		}
1532
1533		if (progress & QL_FCA_TRAN_ALLOCED) {
1534			kmem_free(tran, sizeof (fc_fca_tran_t));
1535			progress &= ~QL_FCA_TRAN_ALLOCED;
1536		}
1537
1538		if (progress & QL_MINOR_NODE_CREATED) {
1539			ddi_remove_minor_node(dip, "devctl");
1540			progress &= ~QL_MINOR_NODE_CREATED;
1541		}
1542
1543		if (progress & QL_KSTAT_CREATED) {
1544			kstat_delete(ha->k_stats);
1545			progress &= ~QL_KSTAT_CREATED;
1546		}
1547
1548		if (progress & QL_N_PORT_INFO_CREATED) {
1549			kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
1550			progress &= ~QL_N_PORT_INFO_CREATED;
1551		}
1552
1553		if (progress & QL_TASK_DAEMON_STARTED) {
1554			TASK_DAEMON_LOCK(ha);
1555
1556			ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
1557
1558			cv_signal(&ha->cv_task_daemon);
1559
1560			/* Release task daemon lock. */
1561			TASK_DAEMON_UNLOCK(ha);
1562
1563			/* Wait for for task daemon to stop running. */
1564			while (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
1565				ql_delay(ha, 10000);
1566			}
1567			progress &= ~QL_TASK_DAEMON_STARTED;
1568		}
1569
1570		if (progress & QL_DB_IOBASE_MAPPED) {
1571			ql_8021_clr_drv_active(ha);
1572			ddi_regs_map_free(&ha->db_dev_handle);
1573			progress &= ~QL_DB_IOBASE_MAPPED;
1574		}
1575		if (progress & QL_IOMAP_IOBASE_MAPPED) {
1576			ddi_regs_map_free(&ha->iomap_dev_handle);
1577			progress &= ~QL_IOMAP_IOBASE_MAPPED;
1578		}
1579
1580		if (progress & QL_CONFIG_SPACE_SETUP) {
1581			if (CFG_IST(ha, CFG_SBUS_CARD)) {
1582				ddi_regs_map_free(&ha->sbus_config_handle);
1583			} else {
1584				pci_config_teardown(&ha->pci_handle);
1585			}
1586			progress &= ~QL_CONFIG_SPACE_SETUP;
1587		}
1588
1589		if (progress & QL_INTR_ADDED) {
1590			ql_disable_intr(ha);
1591			ql_release_intr(ha);
1592			progress &= ~QL_INTR_ADDED;
1593		}
1594
1595		if (progress & QL_MUTEX_CV_INITED) {
1596			ql_destroy_mutex(ha);
1597			progress &= ~QL_MUTEX_CV_INITED;
1598		}
1599
1600		if (progress & QL_HBA_BUFFER_SETUP) {
1601			ql_free_phys(ha, &ha->hba_buf);
1602			progress &= ~QL_HBA_BUFFER_SETUP;
1603		}
1604
1605		if (progress & QL_REGS_MAPPED) {
1606			ddi_regs_map_free(&ha->dev_handle);
1607			if (ha->sbus_fpga_iobase != NULL) {
1608				ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
1609			}
1610			progress &= ~QL_REGS_MAPPED;
1611		}
1612
1613		if (progress & QL_SOFT_STATE_ALLOCED) {
1614
1615			ql_fcache_rel(ha->fcache);
1616
1617			kmem_free(ha->adapter_stats,
1618			    sizeof (*ha->adapter_stats));
1619
1620			kmem_free(ha->ub_array, sizeof (*ha->ub_array) *
1621			    QL_UB_LIMIT);
1622
1623			kmem_free(ha->outstanding_cmds,
1624			    sizeof (*ha->outstanding_cmds) *
1625			    MAX_OUTSTANDING_COMMANDS);
1626
1627			if (ha->devpath != NULL) {
1628				kmem_free(ha->devpath,
1629				    strlen(ha->devpath) + 1);
1630			}
1631
1632			kmem_free(ha->dev, sizeof (*ha->dev) *
1633			    DEVICE_HEAD_LIST_SIZE);
1634
1635			if (ha->xioctl != NULL) {
1636				ql_free_xioctl_resource(ha);
1637			}
1638
1639			if (ha->fw_module != NULL) {
1640				(void) ddi_modclose(ha->fw_module);
1641			}
1642			(void) ql_el_trace_desc_dtor(ha);
1643			(void) ql_nvram_cache_desc_dtor(ha);
1644
1645			ddi_soft_state_free(ql_state, instance);
1646			progress &= ~QL_SOFT_STATE_ALLOCED;
1647		}
1648
1649		ddi_prop_remove_all(dip);
1650		rval = DDI_FAILURE;
1651		break;
1652
1653	case DDI_RESUME:
1654		rval = DDI_FAILURE;
1655
1656		ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
1657		if (ha == NULL) {
1658			cmn_err(CE_WARN, "%s(%d): can't get soft state",
1659			    QL_NAME, instance);
1660			break;
1661		}
1662
1663		ha->power_level = PM_LEVEL_D3;
1664		if (ha->pm_capable) {
1665			/*
1666			 * Get ql_power to do power on initialization
1667			 */
1668			if (pm_raise_power(dip, QL_POWER_COMPONENT,
1669			    PM_LEVEL_D0) != DDI_SUCCESS) {
1670				cmn_err(CE_WARN, "%s(%d): can't raise adapter"
1671				    " power", QL_NAME, instance);
1672			}
1673		}
1674
1675		/*
1676		 * There is a bug in DR that prevents PM framework
1677		 * from calling ql_power.
1678		 */
1679		if (ha->power_level == PM_LEVEL_D3) {
1680			ha->power_level = PM_LEVEL_D0;
1681
1682			if (ql_initialize_adapter(ha) != QL_SUCCESS) {
1683				cmn_err(CE_WARN, "%s(%d): can't initialize the"
1684				    " adapter", QL_NAME, instance);
1685			}
1686
1687			/* Wake up task_daemon. */
1688			ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG,
1689			    0);
1690		}
1691
1692		/* Acquire global state lock. */
1693		GLOBAL_STATE_LOCK();
1694
1695		/* Restart driver timer. */
1696		if (ql_timer_timeout_id == NULL) {
1697			ql_timer_timeout_id = timeout(ql_timer, (void *)0,
1698			    ql_timer_ticks);
1699		}
1700
1701		/* Release global state lock. */
1702		GLOBAL_STATE_UNLOCK();
1703
1704		/* Wake up command start routine. */
1705		ADAPTER_STATE_LOCK(ha);
1706		ha->flags &= ~ADAPTER_SUSPENDED;
1707		ADAPTER_STATE_UNLOCK(ha);
1708
1709		/*
1710		 * Transport doesn't make FC discovery in polled
1711		 * mode; So we need the daemon thread's services
1712		 * right here.
1713		 */
1714		(void) callb_generic_cpr(&ha->cprinfo, CB_CODE_CPR_RESUME);
1715
1716		rval = DDI_SUCCESS;
1717
1718		/* Restart IP if it was running. */
1719		if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
1720			(void) ql_initialize_ip(ha);
1721			ql_isp_rcvbuf(ha);
1722		}
1723		break;
1724
1725	default:
1726		cmn_err(CE_WARN, "%s(%d): attach, unknown code:"
1727		    " %x", QL_NAME, ddi_get_instance(dip), cmd);
1728		rval = DDI_FAILURE;
1729		break;
1730	}
1731
1732	kmem_free(buf, MAXPATHLEN);
1733
1734	if (rval != DDI_SUCCESS) {
1735		/*EMPTY*/
1736		QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
1737		    ddi_get_instance(dip), rval);
1738	} else {
1739		/*EMPTY*/
1740		QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
1741	}
1742
1743	return (rval);
1744}
1745
1746/*
1747 * ql_detach
1748 *	Used to remove all the states associated with a given
1749 *	instances of a device node prior to the removal of that
1750 *	instance from the system.
1751 *
1752 * Input:
1753 *	dip = pointer to device information structure.
1754 *	cmd = type of detach.
1755 *
1756 * Returns:
1757 *	DDI_SUCCESS or DDI_FAILURE.
1758 *
1759 * Context:
1760 *	Kernel context.
1761 */
1762static int
1763ql_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1764{
1765	ql_adapter_state_t	*ha, *vha;
1766	ql_tgt_t		*tq;
1767	int			delay_cnt;
1768	uint16_t		index;
1769	ql_link_t		*link;
1770	char			*buf;
1771	timeout_id_t		timer_id = NULL;
1772	int			suspend, rval = DDI_SUCCESS;
1773
1774	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
1775	if (ha == NULL) {
1776		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
1777		    ddi_get_instance(dip));
1778		return (DDI_FAILURE);
1779	}
1780
1781	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, cmd);
1782
1783	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
1784
1785	switch (cmd) {
1786	case DDI_DETACH:
1787		ADAPTER_STATE_LOCK(ha);
1788		ha->flags |= (ADAPTER_SUSPENDED | ABORT_CMDS_LOOP_DOWN_TMO);
1789		ADAPTER_STATE_UNLOCK(ha);
1790
1791		TASK_DAEMON_LOCK(ha);
1792
1793		if (ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) {
1794			ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
1795			cv_signal(&ha->cv_task_daemon);
1796
1797			TASK_DAEMON_UNLOCK(ha);
1798
1799			(void) ql_wait_for_td_stop(ha);
1800
1801			TASK_DAEMON_LOCK(ha);
1802			if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
1803				ha->task_daemon_flags &= ~TASK_DAEMON_STOP_FLG;
1804				EL(ha, "failed, could not stop task daemon\n");
1805			}
1806		}
1807		TASK_DAEMON_UNLOCK(ha);
1808
1809		GLOBAL_STATE_LOCK();
1810
1811		/* Disable driver timer if no adapters. */
1812		if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
1813		    ql_hba.last == &ha->hba) {
1814			timer_id = ql_timer_timeout_id;
1815			ql_timer_timeout_id = NULL;
1816		}
1817		ql_remove_link(&ql_hba, &ha->hba);
1818
1819		GLOBAL_STATE_UNLOCK();
1820
1821		if (timer_id) {
1822			(void) untimeout(timer_id);
1823		}
1824
1825		if (ha->pm_capable) {
1826			if (pm_lower_power(dip, QL_POWER_COMPONENT,
1827			    PM_LEVEL_D3) != DDI_SUCCESS) {
1828				cmn_err(CE_WARN, "%s(%d): failed to lower the"
1829				    " power", QL_NAME, ha->instance);
1830			}
1831		}
1832
1833		/*
1834		 * If pm_lower_power shutdown the adapter, there
1835		 * isn't much else to do
1836		 */
1837		if (ha->power_level != PM_LEVEL_D3) {
1838			ql_halt(ha, PM_LEVEL_D3);
1839		}
1840
1841		/* Remove virtual ports. */
1842		while ((vha = ha->vp_next) != NULL) {
1843			ql_vport_destroy(vha);
1844		}
1845
1846		/* Free target queues. */
1847		for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
1848			link = ha->dev[index].first;
1849			while (link != NULL) {
1850				tq = link->base_address;
1851				link = link->next;
1852				ql_dev_free(ha, tq);
1853			}
1854		}
1855
1856		/*
1857		 * Free unsolicited buffers.
1858		 * If we are here then there are no ULPs still
1859		 * alive that wish to talk to ql so free up
1860		 * any SRB_IP_UB_UNUSED buffers that are
1861		 * lingering around
1862		 */
1863		QL_UB_LOCK(ha);
1864		for (index = 0; index < QL_UB_LIMIT; index++) {
1865			fc_unsol_buf_t *ubp = ha->ub_array[index];
1866
1867			if (ubp != NULL) {
1868				ql_srb_t *sp = ubp->ub_fca_private;
1869
1870				sp->flags |= SRB_UB_FREE_REQUESTED;
1871
1872				while (!(sp->flags & SRB_UB_IN_FCA) ||
1873				    (sp->flags & (SRB_UB_CALLBACK |
1874				    SRB_UB_ACQUIRED))) {
1875					QL_UB_UNLOCK(ha);
1876					delay(drv_usectohz(100000));
1877					QL_UB_LOCK(ha);
1878				}
1879				ha->ub_array[index] = NULL;
1880
1881				QL_UB_UNLOCK(ha);
1882				ql_free_unsolicited_buffer(ha, ubp);
1883				QL_UB_LOCK(ha);
1884			}
1885		}
1886		QL_UB_UNLOCK(ha);
1887
1888		/* Free any saved RISC code. */
1889		if (ha->risc_code != NULL) {
1890			kmem_free(ha->risc_code, ha->risc_code_size);
1891			ha->risc_code = NULL;
1892			ha->risc_code_size = 0;
1893		}
1894
1895		if (ha->fw_module != NULL) {
1896			(void) ddi_modclose(ha->fw_module);
1897			ha->fw_module = NULL;
1898		}
1899
1900		/* Free resources. */
1901		ddi_prop_remove_all(dip);
1902		(void) fc_fca_detach(dip);
1903		kmem_free(ha->tran, sizeof (fc_fca_tran_t));
1904		ddi_remove_minor_node(dip, "devctl");
1905		if (ha->k_stats != NULL) {
1906			kstat_delete(ha->k_stats);
1907		}
1908
1909		if (CFG_IST(ha, CFG_SBUS_CARD)) {
1910			ddi_regs_map_free(&ha->sbus_config_handle);
1911		} else {
1912			if (CFG_IST(ha, CFG_CTRL_8021)) {
1913				ql_8021_clr_drv_active(ha);
1914				ddi_regs_map_free(&ha->db_dev_handle);
1915			}
1916			if (ha->iomap_dev_handle != ha->dev_handle) {
1917				ddi_regs_map_free(&ha->iomap_dev_handle);
1918			}
1919			pci_config_teardown(&ha->pci_handle);
1920		}
1921
1922		ql_disable_intr(ha);
1923		ql_release_intr(ha);
1924
1925		ql_free_xioctl_resource(ha);
1926
1927		ql_destroy_mutex(ha);
1928
1929		ql_free_phys(ha, &ha->hba_buf);
1930		ql_free_phys(ha, &ha->fwexttracebuf);
1931		ql_free_phys(ha, &ha->fwfcetracebuf);
1932
1933		ddi_regs_map_free(&ha->dev_handle);
1934		if (ha->sbus_fpga_iobase != NULL) {
1935			ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
1936		}
1937
1938		ql_fcache_rel(ha->fcache);
1939		if (ha->vcache != NULL) {
1940			kmem_free(ha->vcache, QL_24XX_VPD_SIZE);
1941		}
1942
1943		if (ha->pi_attrs != NULL) {
1944			kmem_free(ha->pi_attrs, sizeof (fca_port_attrs_t));
1945		}
1946
1947		kmem_free(ha->adapter_stats, sizeof (*ha->adapter_stats));
1948
1949		kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
1950
1951		kmem_free(ha->outstanding_cmds,
1952		    sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS);
1953
1954		if (ha->n_port != NULL) {
1955			kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
1956		}
1957
1958		if (ha->devpath != NULL) {
1959			kmem_free(ha->devpath, strlen(ha->devpath) + 1);
1960		}
1961
1962		kmem_free(ha->dev, sizeof (*ha->dev) * DEVICE_HEAD_LIST_SIZE);
1963
1964		EL(ha, "detached\n");
1965
1966		ddi_soft_state_free(ql_state, (int)ha->instance);
1967
1968		break;
1969
1970	case DDI_SUSPEND:
1971		ADAPTER_STATE_LOCK(ha);
1972
1973		delay_cnt = 0;
1974		ha->flags |= ADAPTER_SUSPENDED;
1975		while (ha->flags & ADAPTER_TIMER_BUSY && delay_cnt++ < 10) {
1976			ADAPTER_STATE_UNLOCK(ha);
1977			delay(drv_usectohz(1000000));
1978			ADAPTER_STATE_LOCK(ha);
1979		}
1980		if (ha->busy || ha->flags & ADAPTER_TIMER_BUSY) {
1981			ha->flags &= ~ADAPTER_SUSPENDED;
1982			ADAPTER_STATE_UNLOCK(ha);
1983			rval = DDI_FAILURE;
1984			cmn_err(CE_WARN, "!%s(%d): Fail suspend"
1985			    " busy %xh flags %xh", QL_NAME, ha->instance,
1986			    ha->busy, ha->flags);
1987			break;
1988		}
1989
1990		ADAPTER_STATE_UNLOCK(ha);
1991
1992		if (ha->flags & IP_INITIALIZED) {
1993			(void) ql_shutdown_ip(ha);
1994		}
1995
1996		if ((suspend = ql_suspend_adapter(ha)) != QL_SUCCESS) {
1997			ADAPTER_STATE_LOCK(ha);
1998			ha->flags &= ~ADAPTER_SUSPENDED;
1999			ADAPTER_STATE_UNLOCK(ha);
2000			cmn_err(CE_WARN, "%s(%d): Fail suspend rval %xh",
2001			    QL_NAME, ha->instance, suspend);
2002
2003			/* Restart IP if it was running. */
2004			if (ha->flags & IP_ENABLED &&
2005			    !(ha->flags & IP_INITIALIZED)) {
2006				(void) ql_initialize_ip(ha);
2007				ql_isp_rcvbuf(ha);
2008			}
2009			rval = DDI_FAILURE;
2010			break;
2011		}
2012
2013		/* Acquire global state lock. */
2014		GLOBAL_STATE_LOCK();
2015
2016		/* Disable driver timer if last adapter. */
2017		if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
2018		    ql_hba.last == &ha->hba) {
2019			timer_id = ql_timer_timeout_id;
2020			ql_timer_timeout_id = NULL;
2021		}
2022		GLOBAL_STATE_UNLOCK();
2023
2024		if (timer_id) {
2025			(void) untimeout(timer_id);
2026		}
2027
2028		EL(ha, "suspended\n");
2029
2030		break;
2031
2032	default:
2033		rval = DDI_FAILURE;
2034		break;
2035	}
2036
2037	kmem_free(buf, MAXPATHLEN);
2038
2039	if (rval != DDI_SUCCESS) {
2040		if (ha != NULL) {
2041			EL(ha, "failed, rval = %xh\n", rval);
2042		} else {
2043			/*EMPTY*/
2044			QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
2045			    ddi_get_instance(dip), rval);
2046		}
2047	} else {
2048		/*EMPTY*/
2049		QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
2050	}
2051
2052	return (rval);
2053}
2054
2055
2056/*
2057 * ql_power
2058 *	Power a device attached to the system.
2059 *
2060 * Input:
2061 *	dip = pointer to device information structure.
2062 *	component = device.
2063 *	level = power level.
2064 *
2065 * Returns:
2066 *	DDI_SUCCESS or DDI_FAILURE.
2067 *
2068 * Context:
2069 *	Kernel context.
2070 */
2071/* ARGSUSED */
2072static int
2073ql_power(dev_info_t *dip, int component, int level)
2074{
2075	int			rval = DDI_FAILURE;
2076	off_t			csr;
2077	uint8_t			saved_pm_val;
2078	ql_adapter_state_t	*ha;
2079	char			*buf;
2080	char			*path;
2081
2082	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
2083	if (ha == NULL || ha->pm_capable == 0) {
2084		QL_PRINT_2(CE_CONT, "(%d): no hba or PM not supported\n",
2085		    ddi_get_instance(dip));
2086		return (rval);
2087	}
2088
2089	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
2090
2091	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
2092	path = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
2093
2094	if (component != QL_POWER_COMPONENT || (level != PM_LEVEL_D0 &&
2095	    level != PM_LEVEL_D3)) {
2096		EL(ha, "invalid, component=%xh or level=%xh\n",
2097		    component, level);
2098		return (rval);
2099	}
2100
2101	GLOBAL_HW_LOCK();
2102	csr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR) + PCI_PMCSR;
2103	GLOBAL_HW_UNLOCK();
2104
2105	(void) snprintf(buf, sizeof (buf),
2106	    "Qlogic %s(%d): %s\n\t", QL_NAME, ddi_get_instance(dip),
2107	    ddi_pathname(dip, path));
2108
2109	switch (level) {
2110	case PM_LEVEL_D0:	/* power up to D0 state - fully on */
2111
2112		QL_PM_LOCK(ha);
2113		if (ha->power_level == PM_LEVEL_D0) {
2114			QL_PM_UNLOCK(ha);
2115			rval = DDI_SUCCESS;
2116			break;
2117		}
2118
2119		/*
2120		 * Enable interrupts now
2121		 */
2122		saved_pm_val = ha->power_level;
2123		ha->power_level = PM_LEVEL_D0;
2124		QL_PM_UNLOCK(ha);
2125
2126		GLOBAL_HW_LOCK();
2127
2128		ql_pci_config_put16(ha, csr, PCI_PMCSR_D0);
2129
2130		/*
2131		 * Delay after reset, for chip to recover.
2132		 * Otherwise causes system PANIC
2133		 */
2134		drv_usecwait(200000);
2135
2136		GLOBAL_HW_UNLOCK();
2137
2138		if (ha->config_saved) {
2139			ha->config_saved = 0;
2140			if (QL_RESTORE_CONFIG_REGS(dip) != DDI_SUCCESS) {
2141				QL_PM_LOCK(ha);
2142				ha->power_level = saved_pm_val;
2143				QL_PM_UNLOCK(ha);
2144				cmn_err(CE_WARN, "%s failed to restore "
2145				    "config regs", buf);
2146				break;
2147			}
2148		}
2149
2150		if (ql_initialize_adapter(ha) != QL_SUCCESS) {
2151			cmn_err(CE_WARN, "%s adapter initialization failed",
2152			    buf);
2153		}
2154
2155		/* Wake up task_daemon. */
2156		ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG |
2157		    TASK_DAEMON_SLEEPING_FLG, 0);
2158
2159		/* Restart IP if it was running. */
2160		if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
2161			(void) ql_initialize_ip(ha);
2162			ql_isp_rcvbuf(ha);
2163		}
2164
2165		cmn_err(CE_NOTE, QL_BANG "ql_power(%d): %s is powered ON\n",
2166		    ha->instance, QL_NAME);
2167
2168		rval = DDI_SUCCESS;
2169		break;
2170
2171	case PM_LEVEL_D3:	/* power down to D3 state - off */
2172
2173		QL_PM_LOCK(ha);
2174
2175		if (ha->busy || ((ha->task_daemon_flags &
2176		    TASK_DAEMON_SLEEPING_FLG) == 0)) {
2177			QL_PM_UNLOCK(ha);
2178			break;
2179		}
2180
2181		if (ha->power_level == PM_LEVEL_D3) {
2182			rval = DDI_SUCCESS;
2183			QL_PM_UNLOCK(ha);
2184			break;
2185		}
2186		QL_PM_UNLOCK(ha);
2187
2188		if (QL_SAVE_CONFIG_REGS(dip) != DDI_SUCCESS) {
2189			cmn_err(CE_WARN, "!Qlogic %s(%d): %s failed to save"
2190			    " config regs", QL_NAME, ha->instance, buf);
2191			break;
2192		}
2193		ha->config_saved = 1;
2194
2195		/*
2196		 * Don't enable interrupts. Running mailbox commands with
2197		 * interrupts enabled could cause hangs since pm_run_scan()
2198		 * runs out of a callout thread and on single cpu systems
2199		 * cv_reltimedwait_sig(), called from ql_mailbox_command(),
2200		 * would not get to run.
2201		 */
2202		TASK_DAEMON_LOCK(ha);
2203		ha->task_daemon_flags |= TASK_DAEMON_POWERING_DOWN;
2204		TASK_DAEMON_UNLOCK(ha);
2205
2206		ql_halt(ha, PM_LEVEL_D3);
2207
2208		/*
2209		 * Setup ql_intr to ignore interrupts from here on.
2210		 */
2211		QL_PM_LOCK(ha);
2212		ha->power_level = PM_LEVEL_D3;
2213		QL_PM_UNLOCK(ha);
2214
2215		/*
2216		 * Wait for ISR to complete.
2217		 */
2218		INTR_LOCK(ha);
2219		ql_pci_config_put16(ha, csr, PCI_PMCSR_D3HOT);
2220		INTR_UNLOCK(ha);
2221
2222		cmn_err(CE_NOTE, QL_BANG "ql_power(%d): %s is powered OFF\n",
2223		    ha->instance, QL_NAME);
2224
2225		rval = DDI_SUCCESS;
2226		break;
2227	}
2228
2229	kmem_free(buf, MAXPATHLEN);
2230	kmem_free(path, MAXPATHLEN);
2231
2232	QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
2233
2234	return (rval);
2235}
2236
2237/*
2238 * ql_quiesce
2239 *	quiesce a device attached to the system.
2240 *
2241 * Input:
2242 *	dip = pointer to device information structure.
2243 *
2244 * Returns:
2245 *	DDI_SUCCESS
2246 *
2247 * Context:
2248 *	Kernel context.
2249 */
2250static int
2251ql_quiesce(dev_info_t *dip)
2252{
2253	ql_adapter_state_t	*ha;
2254	uint32_t		timer;
2255	uint32_t		stat;
2256
2257	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
2258	if (ha == NULL) {
2259		/* Oh well.... */
2260		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
2261		    ddi_get_instance(dip));
2262		return (DDI_SUCCESS);
2263	}
2264
2265	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2266
2267	if (CFG_IST(ha, CFG_CTRL_8021)) {
2268		(void) ql_stop_firmware(ha);
2269	} else if (CFG_IST(ha, CFG_CTRL_242581)) {
2270		WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
2271		WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
2272		WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
2273		for (timer = 0; timer < 30000; timer++) {
2274			stat = RD32_IO_REG(ha, risc2host);
2275			if (stat & BIT_15) {
2276				if ((stat & 0xff) < 0x12) {
2277					WRT32_IO_REG(ha, hccr,
2278					    HC24_CLR_RISC_INT);
2279					break;
2280				}
2281				WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
2282			}
2283			drv_usecwait(100);
2284		}
2285		/* Reset the chip. */
2286		WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
2287		    MWB_4096_BYTES);
2288		drv_usecwait(100);
2289
2290	} else {
2291		/* Disable ISP interrupts. */
2292		WRT16_IO_REG(ha, ictrl, 0);
2293		/* Select RISC module registers. */
2294		WRT16_IO_REG(ha, ctrl_status, 0);
2295		/* Reset ISP semaphore. */
2296		WRT16_IO_REG(ha, semaphore, 0);
2297		/* Reset RISC module. */
2298		WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
2299		/* Release RISC module. */
2300		WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
2301	}
2302
2303	ql_disable_intr(ha);
2304
2305	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2306
2307	return (DDI_SUCCESS);
2308}
2309
2310/* ************************************************************************ */
2311/*		Fibre Channel Adapter (FCA) Transport Functions.	    */
2312/* ************************************************************************ */
2313
2314/*
2315 * ql_bind_port
2316 *	Handling port binding. The FC Transport attempts to bind an FCA port
2317 *	when it is ready to start transactions on the port. The FC Transport
2318 *	will call the fca_bind_port() function specified in the fca_transport
2319 *	structure it receives. The FCA must fill in the port_info structure
2320 *	passed in the call and also stash the information for future calls.
2321 *
2322 * Input:
2323 *	dip = pointer to FCA information structure.
2324 *	port_info = pointer to port information structure.
2325 *	bind_info = pointer to bind information structure.
2326 *
2327 * Returns:
2328 *	NULL = failure
2329 *
2330 * Context:
2331 *	Kernel context.
2332 */
2333static opaque_t
2334ql_bind_port(dev_info_t *dip, fc_fca_port_info_t *port_info,
2335    fc_fca_bind_info_t *bind_info)
2336{
2337	ql_adapter_state_t	*ha, *vha;
2338	opaque_t		fca_handle = NULL;
2339	port_id_t		d_id;
2340	int			port_npiv = bind_info->port_npiv;
2341	uchar_t			*port_nwwn = bind_info->port_nwwn.raw_wwn;
2342	uchar_t			*port_pwwn = bind_info->port_pwwn.raw_wwn;
2343
2344	/* get state info based on the dip */
2345	ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
2346	if (ha == NULL) {
2347		QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
2348		    ddi_get_instance(dip));
2349		return (NULL);
2350	}
2351	QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
2352
2353	/* Verify port number is supported. */
2354	if (port_npiv != 0) {
2355		if (!(ha->flags & VP_ENABLED)) {
2356			QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_NOT_SUPPORTED\n",
2357			    ha->instance);
2358			port_info->pi_error = FC_NPIV_NOT_SUPPORTED;
2359			return (NULL);
2360		}
2361		if (!(ha->flags & POINT_TO_POINT)) {
2362			QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_WRONG_TOPOLOGY\n",
2363			    ha->instance);
2364			port_info->pi_error = FC_NPIV_WRONG_TOPOLOGY;
2365			return (NULL);
2366		}
2367		if (!(ha->flags & FDISC_ENABLED)) {
2368			QL_PRINT_2(CE_CONT, "(%d): switch does not support "
2369			    "FDISC\n", ha->instance);
2370			port_info->pi_error = FC_NPIV_FDISC_FAILED;
2371			return (NULL);
2372		}
2373		if (bind_info->port_num > (CFG_IST(ha, CFG_CTRL_2422) ?
2374		    MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS)) {
2375			QL_PRINT_2(CE_CONT, "(%d): port number=%d "
2376			    "FC_OUTOFBOUNDS\n", ha->instance);
2377			port_info->pi_error = FC_OUTOFBOUNDS;
2378			return (NULL);
2379		}
2380	} else if (bind_info->port_num != 0) {
2381		QL_PRINT_2(CE_CONT, "(%d): failed, port number=%d is not "
2382		    "supported\n", ha->instance, bind_info->port_num);
2383		port_info->pi_error = FC_OUTOFBOUNDS;
2384		return (NULL);
2385	}
2386
2387	/* Locate port context. */
2388	for (vha = ha; vha != NULL; vha = vha->vp_next) {
2389		if (vha->vp_index == bind_info->port_num) {
2390			break;
2391		}
2392	}
2393
2394	/* If virtual port does not exist. */
2395	if (vha == NULL) {
2396		vha = ql_vport_create(ha, (uint8_t)bind_info->port_num);
2397	}
2398
2399	/* make sure this port isn't already bound */
2400	if (vha->flags & FCA_BOUND) {
2401		port_info->pi_error = FC_ALREADY;
2402	} else {
2403		if (vha->vp_index != 0) {
2404			bcopy(port_nwwn,
2405			    vha->loginparams.node_ww_name.raw_wwn, 8);
2406			bcopy(port_pwwn,
2407			    vha->loginparams.nport_ww_name.raw_wwn, 8);
2408		}
2409		if (vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
2410			if (ql_vport_enable(vha) != QL_SUCCESS) {
2411				QL_PRINT_2(CE_CONT, "(%d): failed to enable "
2412				    "virtual port=%d\n", ha->instance,
2413				    vha->vp_index);
2414				port_info->pi_error = FC_NPIV_FDISC_FAILED;
2415				return (NULL);
2416			}
2417			cmn_err(CE_CONT, "!Qlogic %s(%d) NPIV(%d) "
2418			    "WWPN=%02x%02x%02x%02x%02x%02x%02x%02x : "
2419			    "WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
2420			    QL_NAME, ha->instance, vha->vp_index,
2421			    port_pwwn[0], port_pwwn[1], port_pwwn[2],
2422			    port_pwwn[3], port_pwwn[4], port_pwwn[5],
2423			    port_pwwn[6], port_pwwn[7],
2424			    port_nwwn[0], port_nwwn[1], port_nwwn[2],
2425			    port_nwwn[3], port_nwwn[4], port_nwwn[5],
2426			    port_nwwn[6], port_nwwn[7]);
2427		}
2428
2429		/* stash the bind_info supplied by the FC Transport */
2430		vha->bind_info.port_handle = bind_info->port_handle;
2431		vha->bind_info.port_statec_cb =
2432		    bind_info->port_statec_cb;
2433		vha->bind_info.port_unsol_cb = bind_info->port_unsol_cb;
2434
2435		/* Set port's source ID. */
2436		port_info->pi_s_id.port_id = vha->d_id.b24;
2437
2438		/* copy out the default login parameters */
2439		bcopy((void *)&vha->loginparams,
2440		    (void *)&port_info->pi_login_params,
2441		    sizeof (la_els_logi_t));
2442
2443		/* Set port's hard address if enabled. */
2444		port_info->pi_hard_addr.hard_addr = 0;
2445		if (bind_info->port_num == 0) {
2446			d_id.b24 = ha->d_id.b24;
2447			if (CFG_IST(ha, CFG_CTRL_24258081)) {
2448				if (ha->init_ctrl_blk.cb24.
2449				    firmware_options_1[0] & BIT_0) {
2450					d_id.b.al_pa = ql_index_to_alpa[ha->
2451					    init_ctrl_blk.cb24.
2452					    hard_address[0]];
2453					port_info->pi_hard_addr.hard_addr =
2454					    d_id.b24;
2455				}
2456			} else if (ha->init_ctrl_blk.cb.firmware_options[0] &
2457			    BIT_0) {
2458				d_id.b.al_pa = ql_index_to_alpa[ha->
2459				    init_ctrl_blk.cb.hard_address[0]];
2460				port_info->pi_hard_addr.hard_addr = d_id.b24;
2461			}
2462
2463			/* Set the node id data */
2464			if (ql_get_rnid_params(ha,
2465			    sizeof (port_info->pi_rnid_params.params),
2466			    (caddr_t)&port_info->pi_rnid_params.params) ==
2467			    QL_SUCCESS) {
2468				port_info->pi_rnid_params.status = FC_SUCCESS;
2469			} else {
2470				port_info->pi_rnid_params.status = FC_FAILURE;
2471			}
2472
2473			/* Populate T11 FC-HBA details */
2474			ql_populate_hba_fru_details(ha, port_info);
2475			ha->pi_attrs = kmem_zalloc(sizeof (fca_port_attrs_t),
2476			    KM_SLEEP);
2477			if (ha->pi_attrs != NULL) {
2478				bcopy(&port_info->pi_attrs, ha->pi_attrs,
2479				    sizeof (fca_port_attrs_t));
2480			}
2481		} else {
2482			port_info->pi_rnid_params.status = FC_FAILURE;
2483			if (ha->pi_attrs != NULL) {
2484				bcopy(ha->pi_attrs, &port_info->pi_attrs,
2485				    sizeof (fca_port_attrs_t));
2486			}
2487		}
2488
2489		/* Generate handle for this FCA. */
2490		fca_handle = (opaque_t)vha;
2491
2492		ADAPTER_STATE_LOCK(ha);
2493		vha->flags |= FCA_BOUND;
2494		ADAPTER_STATE_UNLOCK(ha);
2495		/* Set port's current state. */
2496		port_info->pi_port_state = vha->state;
2497	}
2498
2499	QL_PRINT_10(CE_CONT, "(%d,%d): done, pi_port_state=%xh, "
2500	    "pi_s_id.port_id=%xh\n", ha->instance, ha->vp_index,
2501	    port_info->pi_port_state, port_info->pi_s_id.port_id);
2502
2503	return (fca_handle);
2504}
2505
2506/*
2507 * ql_unbind_port
2508 *	To unbind a Fibre Channel Adapter from an FC Port driver.
2509 *
2510 * Input:
2511 *	fca_handle = handle setup by ql_bind_port().
2512 *
2513 * Context:
2514 *	Kernel context.
2515 */
2516static void
2517ql_unbind_port(opaque_t fca_handle)
2518{
2519	ql_adapter_state_t	*ha;
2520	ql_tgt_t		*tq;
2521	uint32_t		flgs;
2522
2523	ha = ql_fca_handle_to_state(fca_handle);
2524	if (ha == NULL) {
2525		/*EMPTY*/
2526		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2527		    (void *)fca_handle);
2528	} else {
2529		QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance,
2530		    ha->vp_index);
2531
2532		if (!(ha->flags & FCA_BOUND)) {
2533			/*EMPTY*/
2534			QL_PRINT_2(CE_CONT, "(%d): port=%d already unbound\n",
2535			    ha->instance, ha->vp_index);
2536		} else {
2537			if (ha->vp_index != 0 && ha->flags & VP_ENABLED) {
2538				if ((tq = ql_loop_id_to_queue(ha,
2539				    FL_PORT_24XX_HDL)) != NULL) {
2540					(void) ql_logout_fabric_port(ha, tq);
2541				}
2542				(void) ql_vport_control(ha, (uint8_t)
2543				    (CFG_IST(ha, CFG_CTRL_2425) ?
2544				    VPC_DISABLE_INIT : VPC_DISABLE_LOGOUT));
2545				flgs = FCA_BOUND | VP_ENABLED;
2546			} else {
2547				flgs = FCA_BOUND;
2548			}
2549			ADAPTER_STATE_LOCK(ha);
2550			ha->flags &= ~flgs;
2551			ADAPTER_STATE_UNLOCK(ha);
2552		}
2553
2554		QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
2555		    ha->vp_index);
2556	}
2557}
2558
2559/*
2560 * ql_init_pkt
2561 *	Initialize FCA portion of packet.
2562 *
2563 * Input:
2564 *	fca_handle = handle setup by ql_bind_port().
2565 *	pkt = pointer to fc_packet.
2566 *
2567 * Returns:
2568 *	FC_SUCCESS - the packet has successfully been initialized.
2569 *	FC_UNBOUND - the fca_handle specified is not bound.
2570 *	FC_NOMEM - the FCA failed initialization due to an allocation error.
2571 *	FC_FAILURE - the FCA failed initialization for undisclosed reasons
2572 *
2573 * Context:
2574 *	Kernel context.
2575 */
2576/* ARGSUSED */
2577static int
2578ql_init_pkt(opaque_t fca_handle, fc_packet_t *pkt, int sleep)
2579{
2580	ql_adapter_state_t	*ha;
2581	ql_srb_t		*sp;
2582	int			rval = FC_SUCCESS;
2583
2584	ha = ql_fca_handle_to_state(fca_handle);
2585	if (ha == NULL) {
2586		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2587		    (void *)fca_handle);
2588		return (FC_UNBOUND);
2589	}
2590	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2591
2592	sp = (ql_srb_t *)pkt->pkt_fca_private;
2593	sp->flags = 0;
2594
2595	/* init cmd links */
2596	sp->cmd.base_address = sp;
2597	sp->cmd.prev = NULL;
2598	sp->cmd.next = NULL;
2599	sp->cmd.head = NULL;
2600
2601	/* init watchdog links */
2602	sp->wdg.base_address = sp;
2603	sp->wdg.prev = NULL;
2604	sp->wdg.next = NULL;
2605	sp->wdg.head = NULL;
2606	sp->pkt = pkt;
2607	sp->ha = ha;
2608	sp->magic_number = QL_FCA_BRAND;
2609	sp->sg_dma.dma_handle = NULL;
2610#ifndef __sparc
2611	if (CFG_IST(ha, CFG_CTRL_8021)) {
2612		/* Setup DMA for scatter gather list. */
2613		sp->sg_dma.size = sizeof (cmd6_2400_dma_t);
2614		sp->sg_dma.type = LITTLE_ENDIAN_DMA;
2615		sp->sg_dma.cookie_count = 1;
2616		sp->sg_dma.alignment = 64;
2617		if (ql_alloc_phys(ha, &sp->sg_dma, KM_SLEEP) != QL_SUCCESS) {
2618			rval = FC_NOMEM;
2619		}
2620	}
2621#endif	/* __sparc */
2622
2623	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2624
2625	return (rval);
2626}
2627
2628/*
2629 * ql_un_init_pkt
2630 *	Release all local resources bound to packet.
2631 *
2632 * Input:
2633 *	fca_handle = handle setup by ql_bind_port().
2634 *	pkt = pointer to fc_packet.
2635 *
2636 * Returns:
2637 *	FC_SUCCESS - the packet has successfully been invalidated.
2638 *	FC_UNBOUND - the fca_handle specified is not bound.
2639 *	FC_BADPACKET - the packet has not been initialized or has
2640 *			already been freed by this FCA.
2641 *
2642 * Context:
2643 *	Kernel context.
2644 */
2645static int
2646ql_un_init_pkt(opaque_t fca_handle, fc_packet_t *pkt)
2647{
2648	ql_adapter_state_t *ha;
2649	int rval;
2650	ql_srb_t *sp;
2651
2652	ha = ql_fca_handle_to_state(fca_handle);
2653	if (ha == NULL) {
2654		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2655		    (void *)fca_handle);
2656		return (FC_UNBOUND);
2657	}
2658	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2659
2660	sp = (ql_srb_t *)pkt->pkt_fca_private;
2661
2662	if (sp->magic_number != QL_FCA_BRAND) {
2663		EL(ha, "failed, FC_BADPACKET\n");
2664		rval = FC_BADPACKET;
2665	} else {
2666		sp->magic_number = 0;
2667		ql_free_phys(ha, &sp->sg_dma);
2668		rval = FC_SUCCESS;
2669	}
2670
2671	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2672
2673	return (rval);
2674}
2675
2676/*
2677 * ql_els_send
2678 *	Issue a extended link service request.
2679 *
2680 * Input:
2681 *	fca_handle = handle setup by ql_bind_port().
2682 *	pkt = pointer to fc_packet.
2683 *
2684 * Returns:
2685 *	FC_SUCCESS - the command was successful.
2686 *	FC_ELS_FREJECT - the command was rejected by a Fabric.
2687 *	FC_ELS_PREJECT - the command was rejected by an N-port.
2688 *	FC_TRANSPORT_ERROR - a transport error occurred.
2689 *	FC_UNBOUND - the fca_handle specified is not bound.
2690 *	FC_ELS_BAD - the FCA can not issue the requested ELS.
2691 *
2692 * Context:
2693 *	Kernel context.
2694 */
2695static int
2696ql_els_send(opaque_t fca_handle, fc_packet_t *pkt)
2697{
2698	ql_adapter_state_t	*ha;
2699	int			rval;
2700	clock_t			timer = drv_usectohz(30000000);
2701	ls_code_t		els;
2702	la_els_rjt_t		rjt;
2703	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
2704
2705	/* Verify proper command. */
2706	ha = ql_cmd_setup(fca_handle, pkt, &rval);
2707	if (ha == NULL) {
2708		QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
2709		    rval, fca_handle);
2710		return (FC_INVALID_REQUEST);
2711	}
2712	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2713
2714	/* Wait for suspension to end. */
2715	TASK_DAEMON_LOCK(ha);
2716	while (ha->task_daemon_flags & QL_SUSPENDED) {
2717		ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
2718
2719		/* 30 seconds from now */
2720		if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
2721		    &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
2722			/*
2723			 * The timeout time 'timer' was
2724			 * reached without the condition
2725			 * being signaled.
2726			 */
2727			pkt->pkt_state = FC_PKT_TRAN_BSY;
2728			pkt->pkt_reason = FC_REASON_XCHG_BSY;
2729
2730			/* Release task daemon lock. */
2731			TASK_DAEMON_UNLOCK(ha);
2732
2733			EL(ha, "QL_SUSPENDED failed=%xh\n",
2734			    QL_FUNCTION_TIMEOUT);
2735			return (FC_TRAN_BUSY);
2736		}
2737	}
2738	/* Release task daemon lock. */
2739	TASK_DAEMON_UNLOCK(ha);
2740
2741	/* Setup response header. */
2742	bcopy((void *)&pkt->pkt_cmd_fhdr, (void *)&pkt->pkt_resp_fhdr,
2743	    sizeof (fc_frame_hdr_t));
2744
2745	if (pkt->pkt_rsplen) {
2746		bzero((void *)pkt->pkt_resp, pkt->pkt_rsplen);
2747	}
2748
2749	pkt->pkt_resp_fhdr.d_id = ha->d_id.b24;
2750	pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
2751	pkt->pkt_resp_fhdr.r_ctl = R_CTL_EXTENDED_SVC |
2752	    R_CTL_SOLICITED_CONTROL;
2753	pkt->pkt_resp_fhdr.f_ctl = F_CTL_XCHG_CONTEXT | F_CTL_LAST_SEQ |
2754	    F_CTL_END_SEQ;
2755
2756	sp->flags &= ~(SRB_UB_CALLBACK | SRB_UB_RSCN | SRB_UB_FCP |
2757	    SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT | SRB_FCP_RSP_PKT |
2758	    SRB_IP_PKT | SRB_COMMAND_TIMEOUT | SRB_UB_ACQUIRED | SRB_MS_PKT);
2759
2760	sp->flags |= SRB_ELS_PKT;
2761
2762	/* map the type of ELS to a function */
2763	ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
2764	    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
2765
2766#if 0
2767	QL_PRINT_3(CE_CONT, "(%d): command fhdr:\n", ha->instance);
2768	QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
2769	    sizeof (fc_frame_hdr_t) / 4);
2770	QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
2771	QL_DUMP_3((uint8_t *)&els, 32, sizeof (els) / 4);
2772#endif
2773
2774	sp->iocb = ha->els_cmd;
2775	sp->req_cnt = 1;
2776
2777	switch (els.ls_code) {
2778	case LA_ELS_RJT:
2779	case LA_ELS_ACC:
2780		EL(ha, "LA_ELS_RJT\n");
2781		pkt->pkt_state = FC_PKT_SUCCESS;
2782		rval = FC_SUCCESS;
2783		break;
2784	case LA_ELS_PLOGI:
2785	case LA_ELS_PDISC:
2786		rval = ql_els_plogi(ha, pkt);
2787		break;
2788	case LA_ELS_FLOGI:
2789	case LA_ELS_FDISC:
2790		rval = ql_els_flogi(ha, pkt);
2791		break;
2792	case LA_ELS_LOGO:
2793		rval = ql_els_logo(ha, pkt);
2794		break;
2795	case LA_ELS_PRLI:
2796		rval = ql_els_prli(ha, pkt);
2797		break;
2798	case LA_ELS_PRLO:
2799		rval = ql_els_prlo(ha, pkt);
2800		break;
2801	case LA_ELS_ADISC:
2802		rval = ql_els_adisc(ha, pkt);
2803		break;
2804	case LA_ELS_LINIT:
2805		rval = ql_els_linit(ha, pkt);
2806		break;
2807	case LA_ELS_LPC:
2808		rval = ql_els_lpc(ha, pkt);
2809		break;
2810	case LA_ELS_LSTS:
2811		rval = ql_els_lsts(ha, pkt);
2812		break;
2813	case LA_ELS_SCR:
2814		rval = ql_els_scr(ha, pkt);
2815		break;
2816	case LA_ELS_RSCN:
2817		rval = ql_els_rscn(ha, pkt);
2818		break;
2819	case LA_ELS_FARP_REQ:
2820		rval = ql_els_farp_req(ha, pkt);
2821		break;
2822	case LA_ELS_FARP_REPLY:
2823		rval = ql_els_farp_reply(ha, pkt);
2824		break;
2825	case LA_ELS_RLS:
2826		rval = ql_els_rls(ha, pkt);
2827		break;
2828	case LA_ELS_RNID:
2829		rval = ql_els_rnid(ha, pkt);
2830		break;
2831	default:
2832		EL(ha, "LA_ELS_RJT, FC_REASON_CMD_UNSUPPORTED=%xh\n",
2833		    els.ls_code);
2834		/* Build RJT. */
2835		bzero(&rjt, sizeof (rjt));
2836		rjt.ls_code.ls_code = LA_ELS_RJT;
2837		rjt.reason = FC_REASON_CMD_UNSUPPORTED;
2838
2839		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
2840		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
2841
2842		pkt->pkt_state = FC_PKT_LOCAL_RJT;
2843		pkt->pkt_reason = FC_REASON_UNSUPPORTED;
2844		rval = FC_SUCCESS;
2845		break;
2846	}
2847
2848#if 0
2849	QL_PRINT_3(CE_CONT, "(%d): response fhdr:\n", ha->instance);
2850	QL_DUMP_3((uint8_t *)&pkt->pkt_resp_fhdr, 32,
2851	    sizeof (fc_frame_hdr_t) / 4);
2852#endif
2853	/*
2854	 * Return success if the srb was consumed by an iocb. The packet
2855	 * completion callback will be invoked by the response handler.
2856	 */
2857	if (rval == QL_CONSUMED) {
2858		rval = FC_SUCCESS;
2859	} else if (rval == FC_SUCCESS &&
2860	    !(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
2861		/* Do command callback only if no error */
2862		ql_awaken_task_daemon(ha, sp, 0, 0);
2863	}
2864
2865	if (rval != FC_SUCCESS) {
2866		EL(ha, "failed, rval = %xh\n", rval);
2867	} else {
2868		/*EMPTY*/
2869		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2870	}
2871	return (rval);
2872}
2873
2874/*
2875 * ql_get_cap
2876 *	Export FCA hardware and software capabilities.
2877 *
2878 * Input:
2879 *	fca_handle = handle setup by ql_bind_port().
2880 *	cap = pointer to the capabilities string.
2881 *	ptr = buffer pointer for return capability.
2882 *
2883 * Returns:
2884 *	FC_CAP_ERROR - no such capability
2885 *	FC_CAP_FOUND - the capability was returned and cannot be set
2886 *	FC_CAP_SETTABLE - the capability was returned and can be set
2887 *	FC_UNBOUND - the fca_handle specified is not bound.
2888 *
2889 * Context:
2890 *	Kernel context.
2891 */
2892static int
2893ql_get_cap(opaque_t fca_handle, char *cap, void *ptr)
2894{
2895	ql_adapter_state_t	*ha;
2896	int			rval;
2897	uint32_t		*rptr = (uint32_t *)ptr;
2898
2899	ha = ql_fca_handle_to_state(fca_handle);
2900	if (ha == NULL) {
2901		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
2902		    (void *)fca_handle);
2903		return (FC_UNBOUND);
2904	}
2905	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2906
2907	if (strcmp(cap, FC_NODE_WWN) == 0) {
2908		bcopy((void *)&ha->loginparams.node_ww_name.raw_wwn[0],
2909		    ptr, 8);
2910		rval = FC_CAP_FOUND;
2911	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
2912		bcopy((void *)&ha->loginparams, ptr,
2913		    sizeof (la_els_logi_t));
2914		rval = FC_CAP_FOUND;
2915	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
2916		*rptr = (uint32_t)QL_UB_LIMIT;
2917		rval = FC_CAP_FOUND;
2918	} else if (strcmp(cap, FC_CAP_NOSTREAM_ON_UNALIGN_BUF) == 0) {
2919
2920		dev_info_t	*psydip = NULL;
2921#ifdef __sparc
2922		/*
2923		 * Disable streaming for certain 2 chip adapters
2924		 * below Psycho to handle Psycho byte hole issue.
2925		 */
2926		if ((CFG_IST(ha, CFG_MULTI_CHIP_ADAPTER)) &&
2927		    (!CFG_IST(ha, CFG_SBUS_CARD))) {
2928			for (psydip = ddi_get_parent(ha->dip); psydip;
2929			    psydip = ddi_get_parent(psydip)) {
2930				if (strcmp(ddi_driver_name(psydip),
2931				    "pcipsy") == 0) {
2932					break;
2933				}
2934			}
2935		}
2936#endif	/* __sparc */
2937
2938		if (psydip) {
2939			*rptr = (uint32_t)FC_NO_STREAMING;
2940			EL(ha, "No Streaming\n");
2941		} else {
2942			*rptr = (uint32_t)FC_ALLOW_STREAMING;
2943			EL(ha, "Allow Streaming\n");
2944		}
2945		rval = FC_CAP_FOUND;
2946	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
2947		if (CFG_IST(ha, CFG_CTRL_24258081)) {
2948			*rptr = (uint32_t)CHAR_TO_SHORT(
2949			    ha->init_ctrl_blk.cb24.max_frame_length[0],
2950			    ha->init_ctrl_blk.cb24.max_frame_length[1]);
2951		} else {
2952			*rptr = (uint32_t)CHAR_TO_SHORT(
2953			    ha->init_ctrl_blk.cb.max_frame_length[0],
2954			    ha->init_ctrl_blk.cb.max_frame_length[1]);
2955		}
2956		rval = FC_CAP_FOUND;
2957	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
2958		*rptr = FC_RESET_RETURN_ALL;
2959		rval = FC_CAP_FOUND;
2960	} else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
2961		*rptr = FC_NO_DVMA_SPACE;
2962		rval = FC_CAP_FOUND;
2963	} else {
2964		EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
2965		rval = FC_CAP_ERROR;
2966	}
2967
2968	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
2969
2970	return (rval);
2971}
2972
2973/*
2974 * ql_set_cap
2975 *	Allow the FC Transport to set FCA capabilities if possible.
2976 *
2977 * Input:
2978 *	fca_handle = handle setup by ql_bind_port().
2979 *	cap = pointer to the capabilities string.
2980 *	ptr = buffer pointer for capability.
2981 *
2982 * Returns:
2983 *	FC_CAP_ERROR - no such capability
2984 *	FC_CAP_FOUND - the capability cannot be set by the FC Transport.
2985 *	FC_CAP_SETTABLE - the capability was successfully set.
2986 *	FC_UNBOUND - the fca_handle specified is not bound.
2987 *
2988 * Context:
2989 *	Kernel context.
2990 */
2991/* ARGSUSED */
2992static int
2993ql_set_cap(opaque_t fca_handle, char *cap, void *ptr)
2994{
2995	ql_adapter_state_t	*ha;
2996	int			rval;
2997
2998	ha = ql_fca_handle_to_state(fca_handle);
2999	if (ha == NULL) {
3000		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3001		    (void *)fca_handle);
3002		return (FC_UNBOUND);
3003	}
3004	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3005
3006	if (strcmp(cap, FC_NODE_WWN) == 0) {
3007		rval = FC_CAP_FOUND;
3008	} else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
3009		rval = FC_CAP_FOUND;
3010	} else if (strcmp(cap, FC_CAP_UNSOL_BUF) == 0) {
3011		rval = FC_CAP_FOUND;
3012	} else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
3013		rval = FC_CAP_FOUND;
3014	} else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
3015		rval = FC_CAP_FOUND;
3016	} else {
3017		EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
3018		rval = FC_CAP_ERROR;
3019	}
3020
3021	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3022
3023	return (rval);
3024}
3025
3026/*
3027 * ql_getmap
3028 *	Request of Arbitrated Loop (AL-PA) map.
3029 *
3030 * Input:
3031 *	fca_handle = handle setup by ql_bind_port().
3032 *	mapbuf= buffer pointer for map.
3033 *
3034 * Returns:
3035 *	FC_OLDPORT - the specified port is not operating in loop mode.
3036 *	FC_OFFLINE - the specified port is not online.
3037 *	FC_NOMAP - there is no loop map available for this port.
3038 *	FC_UNBOUND - the fca_handle specified is not bound.
3039 *	FC_SUCCESS - a valid map has been placed in mapbuf.
3040 *
3041 * Context:
3042 *	Kernel context.
3043 */
3044static int
3045ql_getmap(opaque_t fca_handle, fc_lilpmap_t *mapbuf)
3046{
3047	ql_adapter_state_t	*ha;
3048	clock_t			timer = drv_usectohz(30000000);
3049	int			rval = FC_SUCCESS;
3050
3051	ha = ql_fca_handle_to_state(fca_handle);
3052	if (ha == NULL) {
3053		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3054		    (void *)fca_handle);
3055		return (FC_UNBOUND);
3056	}
3057	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3058
3059	mapbuf->lilp_magic = (uint16_t)MAGIC_LIRP;
3060	mapbuf->lilp_myalpa = ha->d_id.b.al_pa;
3061
3062	/* Wait for suspension to end. */
3063	TASK_DAEMON_LOCK(ha);
3064	while (ha->task_daemon_flags & QL_SUSPENDED) {
3065		ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
3066
3067		/* 30 seconds from now */
3068		if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
3069		    &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
3070			/*
3071			 * The timeout time 'timer' was
3072			 * reached without the condition
3073			 * being signaled.
3074			 */
3075
3076			/* Release task daemon lock. */
3077			TASK_DAEMON_UNLOCK(ha);
3078
3079			EL(ha, "QL_SUSPENDED failed, FC_TRAN_BUSY\n");
3080			return (FC_TRAN_BUSY);
3081		}
3082	}
3083	/* Release task daemon lock. */
3084	TASK_DAEMON_UNLOCK(ha);
3085
3086	if (ql_get_loop_position_map(ha, LOOP_POSITION_MAP_SIZE,
3087	    (caddr_t)&mapbuf->lilp_length) != QL_SUCCESS) {
3088		/*
3089		 * Now, since transport drivers cosider this as an
3090		 * offline condition, let's wait for few seconds
3091		 * for any loop transitions before we reset the.
3092		 * chip and restart all over again.
3093		 */
3094		ql_delay(ha, 2000000);
3095		EL(ha, "failed, FC_NOMAP\n");
3096		rval = FC_NOMAP;
3097	} else {
3098		/*EMPTY*/
3099		QL_PRINT_3(CE_CONT, "(%d): my_alpa %xh len %xh "
3100		    "data %xh %xh %xh %xh\n", ha->instance,
3101		    mapbuf->lilp_myalpa, mapbuf->lilp_length,
3102		    mapbuf->lilp_alpalist[0], mapbuf->lilp_alpalist[1],
3103		    mapbuf->lilp_alpalist[2], mapbuf->lilp_alpalist[3]);
3104	}
3105
3106	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3107#if 0
3108	QL_DUMP_3((uint8_t *)mapbuf, 8, sizeof (fc_lilpmap_t));
3109#endif
3110	return (rval);
3111}
3112
3113/*
3114 * ql_transport
3115 *	Issue an I/O request. Handles all regular requests.
3116 *
3117 * Input:
3118 *	fca_handle = handle setup by ql_bind_port().
3119 *	pkt = pointer to fc_packet.
3120 *
3121 * Returns:
3122 *	FC_SUCCESS - the packet was accepted for transport.
3123 *	FC_TRANSPORT_ERROR - a transport error occurred.
3124 *	FC_BADPACKET - the packet to be transported had not been
3125 *			initialized by this FCA.
3126 *	FC_UNBOUND - the fca_handle specified is not bound.
3127 *
3128 * Context:
3129 *	Kernel context.
3130 */
3131static int
3132ql_transport(opaque_t fca_handle, fc_packet_t *pkt)
3133{
3134	ql_adapter_state_t	*ha;
3135	int			rval = FC_TRANSPORT_ERROR;
3136	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
3137
3138	/* Verify proper command. */
3139	ha = ql_cmd_setup(fca_handle, pkt, &rval);
3140	if (ha == NULL) {
3141		QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
3142		    rval, fca_handle);
3143		return (rval);
3144	}
3145	QL_PRINT_3(CE_CONT, "(%d): started command:\n", ha->instance);
3146#if 0
3147	QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
3148	    sizeof (fc_frame_hdr_t) / 4);
3149	QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
3150	QL_DUMP_3((uint8_t *)pkt->pkt_cmd, 8, pkt->pkt_cmdlen);
3151#endif
3152
3153	/* Reset SRB flags. */
3154	sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | SRB_RETRY |
3155	    SRB_POLL | SRB_WATCHDOG_ENABLED | SRB_ABORT | SRB_UB_CALLBACK |
3156	    SRB_UB_RSCN | SRB_UB_FCP | SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT |
3157	    SRB_FCP_RSP_PKT | SRB_IP_PKT | SRB_GENERIC_SERVICES_PKT |
3158	    SRB_COMMAND_TIMEOUT | SRB_ABORTING | SRB_IN_DEVICE_QUEUE |
3159	    SRB_IN_TOKEN_ARRAY | SRB_UB_FREE_REQUESTED | SRB_UB_ACQUIRED |
3160	    SRB_MS_PKT | SRB_ELS_PKT);
3161
3162	pkt->pkt_resp_fhdr.d_id = ha->d_id.b24;
3163	pkt->pkt_resp_fhdr.r_ctl = R_CTL_STATUS;
3164	pkt->pkt_resp_fhdr.s_id = pkt->pkt_cmd_fhdr.d_id;
3165	pkt->pkt_resp_fhdr.f_ctl = pkt->pkt_cmd_fhdr.f_ctl;
3166	pkt->pkt_resp_fhdr.type = pkt->pkt_cmd_fhdr.type;
3167
3168	switch (pkt->pkt_cmd_fhdr.r_ctl) {
3169	case R_CTL_COMMAND:
3170		if (pkt->pkt_cmd_fhdr.type == FC_TYPE_SCSI_FCP) {
3171			sp->flags |= SRB_FCP_CMD_PKT;
3172			rval = ql_fcp_scsi_cmd(ha, pkt, sp);
3173		}
3174		break;
3175
3176	default:
3177		/* Setup response header and buffer. */
3178		if (pkt->pkt_rsplen) {
3179			bzero((void *)pkt->pkt_resp, pkt->pkt_rsplen);
3180		}
3181
3182		switch (pkt->pkt_cmd_fhdr.r_ctl) {
3183		case R_CTL_UNSOL_DATA:
3184			if (pkt->pkt_cmd_fhdr.type == FC_TYPE_IS8802_SNAP) {
3185				sp->flags |= SRB_IP_PKT;
3186				rval = ql_fcp_ip_cmd(ha, pkt, sp);
3187			}
3188			break;
3189
3190		case R_CTL_UNSOL_CONTROL:
3191			if (pkt->pkt_cmd_fhdr.type == FC_TYPE_FC_SERVICES) {
3192				sp->flags |= SRB_GENERIC_SERVICES_PKT;
3193				rval = ql_fc_services(ha, pkt);
3194			}
3195			break;
3196
3197		case R_CTL_SOLICITED_DATA:
3198		case R_CTL_STATUS:
3199		default:
3200			pkt->pkt_state = FC_PKT_LOCAL_RJT;
3201			pkt->pkt_reason = FC_REASON_UNSUPPORTED;
3202			rval = FC_TRANSPORT_ERROR;
3203			EL(ha, "unknown, r_ctl=%xh\n",
3204			    pkt->pkt_cmd_fhdr.r_ctl);
3205			break;
3206		}
3207	}
3208
3209	if (rval != FC_SUCCESS) {
3210		EL(ha, "failed, rval = %xh\n", rval);
3211	} else {
3212		/*EMPTY*/
3213		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3214	}
3215
3216	return (rval);
3217}
3218
3219/*
3220 * ql_ub_alloc
3221 *	Allocate buffers for unsolicited exchanges.
3222 *
3223 * Input:
3224 *	fca_handle = handle setup by ql_bind_port().
3225 *	tokens = token array for each buffer.
3226 *	size = size of each buffer.
3227 *	count = pointer to number of buffers.
3228 *	type = the FC-4 type the buffers are reserved for.
3229 *		1 = Extended Link Services, 5 = LLC/SNAP
3230 *
3231 * Returns:
3232 *	FC_FAILURE - buffers could not be allocated.
3233 *	FC_TOOMANY - the FCA could not allocate the requested
3234 *			number of buffers.
3235 *	FC_SUCCESS - unsolicited buffers were allocated.
3236 *	FC_UNBOUND - the fca_handle specified is not bound.
3237 *
3238 * Context:
3239 *	Kernel context.
3240 */
3241static int
3242ql_ub_alloc(opaque_t fca_handle, uint64_t tokens[], uint32_t size,
3243    uint32_t *count, uint32_t type)
3244{
3245	ql_adapter_state_t	*ha;
3246	caddr_t			bufp = NULL;
3247	fc_unsol_buf_t		*ubp;
3248	ql_srb_t		*sp;
3249	uint32_t		index;
3250	uint32_t		cnt;
3251	uint32_t		ub_array_index = 0;
3252	int			rval = FC_SUCCESS;
3253	int			ub_updated = FALSE;
3254
3255	/* Check handle. */
3256	ha = ql_fca_handle_to_state(fca_handle);
3257	if (ha == NULL) {
3258		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3259		    (void *)fca_handle);
3260		return (FC_UNBOUND);
3261	}
3262	QL_PRINT_3(CE_CONT, "(%d,%d): started, count = %xh\n",
3263	    ha->instance, ha->vp_index, *count);
3264
3265	QL_PM_LOCK(ha);
3266	if (ha->power_level != PM_LEVEL_D0) {
3267		QL_PM_UNLOCK(ha);
3268		QL_PRINT_3(CE_CONT, "(%d,%d): down done\n", ha->instance,
3269		    ha->vp_index);
3270		return (FC_FAILURE);
3271	}
3272	QL_PM_UNLOCK(ha);
3273
3274	/* Acquire adapter state lock. */
3275	ADAPTER_STATE_LOCK(ha);
3276
3277	/* Check the count. */
3278	if ((*count + ha->ub_allocated) > QL_UB_LIMIT) {
3279		*count = 0;
3280		EL(ha, "failed, FC_TOOMANY\n");
3281		rval = FC_TOOMANY;
3282	}
3283
3284	/*
3285	 * reset ub_array_index
3286	 */
3287	ub_array_index = 0;
3288
3289	/*
3290	 * Now proceed to allocate any buffers required
3291	 */
3292	for (index = 0; index < *count && rval == FC_SUCCESS; index++) {
3293		/* Allocate all memory needed. */
3294		ubp = (fc_unsol_buf_t *)kmem_zalloc(sizeof (fc_unsol_buf_t),
3295		    KM_SLEEP);
3296		if (ubp == NULL) {
3297			EL(ha, "failed, FC_FAILURE\n");
3298			rval = FC_FAILURE;
3299		} else {
3300			sp = kmem_zalloc(sizeof (ql_srb_t), KM_SLEEP);
3301			if (sp == NULL) {
3302				kmem_free(ubp, sizeof (fc_unsol_buf_t));
3303				rval = FC_FAILURE;
3304			} else {
3305				if (type == FC_TYPE_IS8802_SNAP) {
3306#ifdef	__sparc
3307					if (ql_get_dma_mem(ha,
3308					    &sp->ub_buffer, size,
3309					    BIG_ENDIAN_DMA,
3310					    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
3311						rval = FC_FAILURE;
3312						kmem_free(ubp,
3313						    sizeof (fc_unsol_buf_t));
3314						kmem_free(sp,
3315						    sizeof (ql_srb_t));
3316					} else {
3317						bufp = sp->ub_buffer.bp;
3318						sp->ub_size = size;
3319					}
3320#else
3321					if (ql_get_dma_mem(ha,
3322					    &sp->ub_buffer, size,
3323					    LITTLE_ENDIAN_DMA,
3324					    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
3325						rval = FC_FAILURE;
3326						kmem_free(ubp,
3327						    sizeof (fc_unsol_buf_t));
3328						kmem_free(sp,
3329						    sizeof (ql_srb_t));
3330					} else {
3331						bufp = sp->ub_buffer.bp;
3332						sp->ub_size = size;
3333					}
3334#endif
3335				} else {
3336					bufp = kmem_zalloc(size, KM_SLEEP);
3337					if (bufp == NULL) {
3338						rval = FC_FAILURE;
3339						kmem_free(ubp,
3340						    sizeof (fc_unsol_buf_t));
3341						kmem_free(sp,
3342						    sizeof (ql_srb_t));
3343					} else {
3344						sp->ub_size = size;
3345					}
3346				}
3347			}
3348		}
3349
3350		if (rval == FC_SUCCESS) {
3351			/* Find next available slot. */
3352			QL_UB_LOCK(ha);
3353			while (ha->ub_array[ub_array_index] != NULL) {
3354				ub_array_index++;
3355			}
3356
3357			ubp->ub_fca_private = (void *)sp;
3358
3359			/* init cmd links */
3360			sp->cmd.base_address = sp;
3361			sp->cmd.prev = NULL;
3362			sp->cmd.next = NULL;
3363			sp->cmd.head = NULL;
3364
3365			/* init wdg links */
3366			sp->wdg.base_address = sp;
3367			sp->wdg.prev = NULL;
3368			sp->wdg.next = NULL;
3369			sp->wdg.head = NULL;
3370			sp->ha = ha;
3371
3372			ubp->ub_buffer = bufp;
3373			ubp->ub_bufsize = size;
3374			ubp->ub_port_handle = fca_handle;
3375			ubp->ub_token = ub_array_index;
3376
3377			/* Save the token. */
3378			tokens[index] = ub_array_index;
3379
3380			/* Setup FCA private information. */
3381			sp->ub_type = type;
3382			sp->handle = ub_array_index;
3383			sp->flags |= SRB_UB_IN_FCA;
3384
3385			ha->ub_array[ub_array_index] = ubp;
3386			ha->ub_allocated++;
3387			ub_updated = TRUE;
3388			QL_UB_UNLOCK(ha);
3389		}
3390	}
3391
3392	/* Release adapter state lock. */
3393	ADAPTER_STATE_UNLOCK(ha);
3394
3395	/* IP buffer. */
3396	if (ub_updated) {
3397		if ((type == FC_TYPE_IS8802_SNAP) &&
3398		    (!(CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_2581))))) {
3399
3400			ADAPTER_STATE_LOCK(ha);
3401			ha->flags |= IP_ENABLED;
3402			ADAPTER_STATE_UNLOCK(ha);
3403
3404			if (!(ha->flags & IP_INITIALIZED)) {
3405				if (CFG_IST(ha, CFG_CTRL_2422)) {
3406					ha->ip_init_ctrl_blk.cb24.mtu_size[0] =
3407					    LSB(ql_ip_mtu);
3408					ha->ip_init_ctrl_blk.cb24.mtu_size[1] =
3409					    MSB(ql_ip_mtu);
3410					ha->ip_init_ctrl_blk.cb24.buf_size[0] =
3411					    LSB(size);
3412					ha->ip_init_ctrl_blk.cb24.buf_size[1] =
3413					    MSB(size);
3414
3415					cnt = CHAR_TO_SHORT(
3416					    ha->ip_init_ctrl_blk.cb24.cc[0],
3417					    ha->ip_init_ctrl_blk.cb24.cc[1]);
3418
3419					if (cnt < *count) {
3420						ha->ip_init_ctrl_blk.cb24.cc[0]
3421						    = LSB(*count);
3422						ha->ip_init_ctrl_blk.cb24.cc[1]
3423						    = MSB(*count);
3424					}
3425				} else {
3426					ha->ip_init_ctrl_blk.cb.mtu_size[0] =
3427					    LSB(ql_ip_mtu);
3428					ha->ip_init_ctrl_blk.cb.mtu_size[1] =
3429					    MSB(ql_ip_mtu);
3430					ha->ip_init_ctrl_blk.cb.buf_size[0] =
3431					    LSB(size);
3432					ha->ip_init_ctrl_blk.cb.buf_size[1] =
3433					    MSB(size);
3434
3435					cnt = CHAR_TO_SHORT(
3436					    ha->ip_init_ctrl_blk.cb.cc[0],
3437					    ha->ip_init_ctrl_blk.cb.cc[1]);
3438
3439					if (cnt < *count) {
3440						ha->ip_init_ctrl_blk.cb.cc[0] =
3441						    LSB(*count);
3442						ha->ip_init_ctrl_blk.cb.cc[1] =
3443						    MSB(*count);
3444					}
3445				}
3446
3447				(void) ql_initialize_ip(ha);
3448			}
3449			ql_isp_rcvbuf(ha);
3450		}
3451	}
3452
3453	if (rval != FC_SUCCESS) {
3454		EL(ha, "failed=%xh\n", rval);
3455	} else {
3456		/*EMPTY*/
3457		QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance,
3458		    ha->vp_index);
3459	}
3460	return (rval);
3461}
3462
3463/*
3464 * ql_ub_free
3465 *	Free unsolicited buffers.
3466 *
3467 * Input:
3468 *	fca_handle = handle setup by ql_bind_port().
3469 *	count = number of buffers.
3470 *	tokens = token array for each buffer.
3471 *
3472 * Returns:
3473 *	FC_SUCCESS - the requested buffers have been freed.
3474 *	FC_UNBOUND - the fca_handle specified is not bound.
3475 *	FC_UB_BADTOKEN - an invalid token was encountered.
3476 *			 No buffers have been released.
3477 *
3478 * Context:
3479 *	Kernel context.
3480 */
3481static int
3482ql_ub_free(opaque_t fca_handle, uint32_t count, uint64_t tokens[])
3483{
3484	ql_adapter_state_t	*ha;
3485	ql_srb_t		*sp;
3486	uint32_t		index;
3487	uint64_t		ub_array_index;
3488	int			rval = FC_SUCCESS;
3489
3490	/* Check handle. */
3491	ha = ql_fca_handle_to_state(fca_handle);
3492	if (ha == NULL) {
3493		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3494		    (void *)fca_handle);
3495		return (FC_UNBOUND);
3496	}
3497	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3498
3499	/* Acquire adapter state lock. */
3500	ADAPTER_STATE_LOCK(ha);
3501
3502	/* Check all returned tokens. */
3503	for (index = 0; index < count; index++) {
3504		fc_unsol_buf_t	*ubp;
3505
3506		/* Check the token range. */
3507		if ((ub_array_index = tokens[index]) >= QL_UB_LIMIT) {
3508			EL(ha, "failed, FC_UB_BADTOKEN\n");
3509			rval = FC_UB_BADTOKEN;
3510			break;
3511		}
3512
3513		/* Check the unsolicited buffer array. */
3514		QL_UB_LOCK(ha);
3515		ubp = ha->ub_array[ub_array_index];
3516
3517		if (ubp == NULL) {
3518			EL(ha, "failed, FC_UB_BADTOKEN-2\n");
3519			rval = FC_UB_BADTOKEN;
3520			QL_UB_UNLOCK(ha);
3521			break;
3522		}
3523
3524		/* Check the state of the unsolicited buffer. */
3525		sp = ha->ub_array[ub_array_index]->ub_fca_private;
3526		sp->flags |= SRB_UB_FREE_REQUESTED;
3527
3528		while (!(sp->flags & SRB_UB_IN_FCA) ||
3529		    (sp->flags & (SRB_UB_CALLBACK | SRB_UB_ACQUIRED))) {
3530			QL_UB_UNLOCK(ha);
3531			ADAPTER_STATE_UNLOCK(ha);
3532			delay(drv_usectohz(100000));
3533			ADAPTER_STATE_LOCK(ha);
3534			QL_UB_LOCK(ha);
3535		}
3536		ha->ub_array[ub_array_index] = NULL;
3537		QL_UB_UNLOCK(ha);
3538		ql_free_unsolicited_buffer(ha, ubp);
3539	}
3540
3541	if (rval == FC_SUCCESS) {
3542		/*
3543		 * Signal any pending hardware reset when there are
3544		 * no more unsolicited buffers in use.
3545		 */
3546		if (ha->ub_allocated == 0) {
3547			cv_broadcast(&ha->pha->cv_ub);
3548		}
3549	}
3550
3551	/* Release adapter state lock. */
3552	ADAPTER_STATE_UNLOCK(ha);
3553
3554	if (rval != FC_SUCCESS) {
3555		EL(ha, "failed=%xh\n", rval);
3556	} else {
3557		/*EMPTY*/
3558		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3559	}
3560	return (rval);
3561}
3562
3563/*
3564 * ql_ub_release
3565 *	Release unsolicited buffers from FC Transport
3566 *	to FCA for future use.
3567 *
3568 * Input:
3569 *	fca_handle = handle setup by ql_bind_port().
3570 *	count = number of buffers.
3571 *	tokens = token array for each buffer.
3572 *
3573 * Returns:
3574 *	FC_SUCCESS - the requested buffers have been released.
3575 *	FC_UNBOUND - the fca_handle specified is not bound.
3576 *	FC_UB_BADTOKEN - an invalid token was encountered.
3577 *		No buffers have been released.
3578 *
3579 * Context:
3580 *	Kernel context.
3581 */
3582static int
3583ql_ub_release(opaque_t fca_handle, uint32_t count, uint64_t tokens[])
3584{
3585	ql_adapter_state_t	*ha;
3586	ql_srb_t		*sp;
3587	uint32_t		index;
3588	uint64_t		ub_array_index;
3589	int			rval = FC_SUCCESS;
3590	int			ub_ip_updated = FALSE;
3591
3592	/* Check handle. */
3593	ha = ql_fca_handle_to_state(fca_handle);
3594	if (ha == NULL) {
3595		QL_PRINT_2(CE_CONT, ": failed, no adapter=%ph\n",
3596		    (void *)fca_handle);
3597		return (FC_UNBOUND);
3598	}
3599	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
3600
3601	/* Acquire adapter state lock. */
3602	ADAPTER_STATE_LOCK(ha);
3603	QL_UB_LOCK(ha);
3604
3605	/* Check all returned tokens. */
3606	for (index = 0; index < count; index++) {
3607		/* Check the token range. */
3608		if ((ub_array_index = tokens[index]) >= QL_UB_LIMIT) {
3609			EL(ha, "failed, FC_UB_BADTOKEN\n");
3610			rval = FC_UB_BADTOKEN;
3611			break;
3612		}
3613
3614		/* Check the unsolicited buffer array. */
3615		if (ha->ub_array[ub_array_index] == NULL) {
3616			EL(ha, "failed, FC_UB_BADTOKEN-2\n");
3617			rval = FC_UB_BADTOKEN;
3618			break;
3619		}
3620
3621		/* Check the state of the unsolicited buffer. */
3622		sp = ha->ub_array[ub_array_index]->ub_fca_private;
3623		if (sp->flags & SRB_UB_IN_FCA) {
3624			EL(ha, "failed, FC_UB_BADTOKEN-3\n");
3625			rval = FC_UB_BADTOKEN;
3626			break;
3627		}
3628	}
3629
3630	/* If all tokens checkout, release the buffers. */
3631	if (rval == FC_SUCCESS) {
3632		/* Check all returned tokens. */
3633		for (index = 0; index < count; index++) {
3634			fc_unsol_buf_t	*ubp;
3635
3636			ub_array_index = tokens[index];
3637			ubp = ha->ub_array[ub_array_index];
3638			sp = ubp->ub_fca_private;
3639
3640			ubp->ub_resp_flags = 0;
3641			sp->flags &= ~(SRB_UB_ACQUIRED | SRB_UB_CALLBACK);
3642			sp->flags |= SRB_UB_IN_FCA;
3643
3644			/* IP buffer. */
3645			if (sp->ub_type == FC_TYPE_IS8802_SNAP) {
3646				ub_ip_updated = TRUE;
3647			}
3648		}
3649	}
3650
3651	QL_UB_UNLOCK(ha);
3652	/* Release adapter state lock. */
3653	ADAPTER_STATE_UNLOCK(ha);
3654
3655	/*
3656	 * XXX: We should call ql_isp_rcvbuf() to return a
3657	 * buffer to ISP only if the number of buffers fall below
3658	 * the low water mark.
3659	 */
3660	if (ub_ip_updated) {
3661		ql_isp_rcvbuf(ha);
3662	}
3663
3664	if (rval != FC_SUCCESS) {
3665		EL(ha, "failed, rval = %xh\n", rval);
3666	} else {
3667		/*EMPTY*/
3668		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
3669	}
3670	return (rval);
3671}
3672
3673/*
3674 * ql_abort
3675 *	Abort a packet.
3676 *
3677 * Input:
3678 *	fca_handle = handle setup by ql_bind_port().
3679 *	pkt = pointer to fc_packet.
3680 *	flags = KM_SLEEP flag.
3681 *
3682 * Returns:
3683 *	FC_SUCCESS - the packet has successfully aborted.
3684 *	FC_ABORTED - the packet has successfully aborted.
3685 *	FC_ABORTING - the packet is being aborted.
3686 *	FC_ABORT_FAILED - the packet could not be aborted.
3687 *	FC_TRANSPORT_ERROR - a transport error occurred while attempting
3688 *		to abort the packet.
3689 *	FC_BADEXCHANGE - no packet found.
3690 *	FC_UNBOUND - the fca_handle specified is not bound.
3691 *
3692 * Context:
3693 *	Kernel context.
3694 */
3695static int
3696ql_abort(opaque_t fca_handle, fc_packet_t *pkt, int flags)
3697{
3698	port_id_t		d_id;
3699	ql_link_t		*link;
3700	ql_adapter_state_t	*ha, *pha;
3701	ql_srb_t		*sp;
3702	ql_tgt_t		*tq;
3703	ql_lun_t		*lq;
3704	int			rval = FC_ABORTED;
3705
3706	ha = ql_fca_handle_to_state(fca_handle);
3707	if (ha == NULL) {
3708		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3709		    (void *)fca_handle);
3710		return (FC_UNBOUND);
3711	}
3712
3713	pha = ha->pha;
3714
3715	QL_PRINT_3(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
3716
3717	/* Get target queue pointer. */
3718	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
3719	tq = ql_d_id_to_queue(ha, d_id);
3720
3721	if ((tq == NULL) || (pha->task_daemon_flags & LOOP_DOWN)) {
3722		if (tq == NULL) {
3723			EL(ha, "failed, FC_TRANSPORT_ERROR\n");
3724			rval = FC_TRANSPORT_ERROR;
3725		} else {
3726			EL(ha, "failed, FC_OFFLINE\n");
3727			rval = FC_OFFLINE;
3728		}
3729		return (rval);
3730	}
3731
3732	sp = (ql_srb_t *)pkt->pkt_fca_private;
3733	lq = sp->lun_queue;
3734
3735	/* Set poll flag if sleep wanted. */
3736	if (flags == KM_SLEEP) {
3737		sp->flags |= SRB_POLL;
3738	}
3739
3740	/* Acquire target queue lock. */
3741	DEVICE_QUEUE_LOCK(tq);
3742	REQUEST_RING_LOCK(ha);
3743
3744	/* If command not already started. */
3745	if (!(sp->flags & SRB_ISP_STARTED)) {
3746		/* Check pending queue for command. */
3747		sp = NULL;
3748		for (link = pha->pending_cmds.first; link != NULL;
3749		    link = link->next) {
3750			sp = link->base_address;
3751			if (sp == (ql_srb_t *)pkt->pkt_fca_private) {
3752				/* Remove srb from q. */
3753				ql_remove_link(&pha->pending_cmds, &sp->cmd);
3754				break;
3755			} else {
3756				sp = NULL;
3757			}
3758		}
3759		REQUEST_RING_UNLOCK(ha);
3760
3761		if (sp == NULL) {
3762			/* Check for cmd on device queue. */
3763			for (link = lq->cmd.first; link != NULL;
3764			    link = link->next) {
3765				sp = link->base_address;
3766				if (sp == (ql_srb_t *)pkt->pkt_fca_private) {
3767					/* Remove srb from q. */
3768					ql_remove_link(&lq->cmd, &sp->cmd);
3769					break;
3770				} else {
3771					sp = NULL;
3772				}
3773			}
3774		}
3775		/* Release device lock */
3776		DEVICE_QUEUE_UNLOCK(tq);
3777
3778		/* If command on target queue. */
3779		if (sp != NULL) {
3780			sp->flags &= ~SRB_IN_DEVICE_QUEUE;
3781
3782			/* Set return status */
3783			pkt->pkt_reason = CS_ABORTED;
3784
3785			sp->cmd.next = NULL;
3786			ql_done(&sp->cmd);
3787			rval = FC_ABORTED;
3788		} else {
3789			EL(ha, "failed, FC_BADEXCHANGE\n");
3790			rval = FC_BADEXCHANGE;
3791		}
3792	} else if (sp->flags & SRB_ISP_COMPLETED) {
3793		/* Release device queue lock. */
3794		REQUEST_RING_UNLOCK(ha);
3795		DEVICE_QUEUE_UNLOCK(tq);
3796		EL(ha, "failed, already done, FC_FAILURE\n");
3797		rval = FC_FAILURE;
3798	} else if ((sp->pkt->pkt_cmd_fhdr.r_ctl == R_CTL_SOLICITED_DATA) ||
3799	    (sp->pkt->pkt_cmd_fhdr.r_ctl == R_CTL_STATUS)) {
3800		/*
3801		 * If here, target data/resp ctio is with Fw.
3802		 * Since firmware is supposed to terminate such I/Os
3803		 * with an error, we need not do any thing. If FW
3804		 * decides not to terminate those IOs and simply keep
3805		 * quite then we need to initiate cleanup here by
3806		 * calling ql_done.
3807		 */
3808		REQUEST_RING_UNLOCK(ha);
3809		DEVICE_QUEUE_UNLOCK(tq);
3810		rval = FC_ABORTED;
3811	} else {
3812		request_t	*ep = pha->request_ring_bp;
3813		uint16_t	cnt;
3814
3815		if (sp->handle != 0) {
3816			for (cnt = 0; cnt < REQUEST_ENTRY_CNT; cnt++) {
3817				if (sp->handle == ddi_get32(
3818				    pha->hba_buf.acc_handle, &ep->handle)) {
3819					ep->entry_type = INVALID_ENTRY_TYPE;
3820					break;
3821				}
3822				ep++;
3823			}
3824		}
3825
3826		/* Release device queue lock. */
3827		REQUEST_RING_UNLOCK(ha);
3828		DEVICE_QUEUE_UNLOCK(tq);
3829
3830		sp->flags |= SRB_ABORTING;
3831		(void) ql_abort_command(ha, sp);
3832		pkt->pkt_reason = CS_ABORTED;
3833		rval = FC_ABORTED;
3834	}
3835
3836	QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
3837
3838	return (rval);
3839}
3840
3841/*
3842 * ql_reset
3843 *	Reset link or hardware.
3844 *
3845 * Input:
3846 *	fca_handle = handle setup by ql_bind_port().
3847 *	cmd = reset type command.
3848 *
3849 * Returns:
3850 *	FC_SUCCESS - reset has successfully finished.
3851 *	FC_UNBOUND - the fca_handle specified is not bound.
3852 *	FC_FAILURE - reset failed.
3853 *
3854 * Context:
3855 *	Kernel context.
3856 */
3857static int
3858ql_reset(opaque_t fca_handle, uint32_t cmd)
3859{
3860	ql_adapter_state_t	*ha;
3861	int			rval = FC_SUCCESS, rval2;
3862
3863	ha = ql_fca_handle_to_state(fca_handle);
3864	if (ha == NULL) {
3865		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
3866		    (void *)fca_handle);
3867		return (FC_UNBOUND);
3868	}
3869
3870	QL_PRINT_3(CE_CONT, "(%d,%d): started, cmd=%d\n", ha->instance,
3871	    ha->vp_index, cmd);
3872
3873	switch (cmd) {
3874	case FC_FCA_CORE:
3875		/* dump firmware core if specified. */
3876		if (ha->vp_index == 0) {
3877			if (ql_dump_firmware(ha) != QL_SUCCESS) {
3878				EL(ha, "failed, FC_FAILURE\n");
3879				rval = FC_FAILURE;
3880			}
3881		}
3882		break;
3883	case FC_FCA_LINK_RESET:
3884		if (!(ha->pha->task_daemon_flags & LOOP_DOWN)) {
3885			if (ql_loop_reset(ha) != QL_SUCCESS) {
3886				EL(ha, "failed, FC_FAILURE-2\n");
3887				rval = FC_FAILURE;
3888			}
3889		}
3890		break;
3891	case FC_FCA_RESET_CORE:
3892	case FC_FCA_RESET:
3893		/* if dump firmware core if specified. */
3894		if (cmd == FC_FCA_RESET_CORE) {
3895			if (ha->vp_index != 0) {
3896				rval2 = ha->pha->task_daemon_flags & LOOP_DOWN
3897				    ? QL_SUCCESS : ql_loop_reset(ha);
3898			} else {
3899				rval2 = ql_dump_firmware(ha);
3900			}
3901			if (rval2 != QL_SUCCESS) {
3902				EL(ha, "failed, FC_FAILURE-3\n");
3903				rval = FC_FAILURE;
3904			}
3905		}
3906
3907		/* Free up all unsolicited buffers. */
3908		if (ha->ub_allocated != 0) {
3909			/* Inform to release buffers. */
3910			ha->state = FC_PORT_SPEED_MASK(ha->state);
3911			ha->state |= FC_STATE_RESET_REQUESTED;
3912			if (ha->flags & FCA_BOUND) {
3913				(ha->bind_info.port_statec_cb)
3914				    (ha->bind_info.port_handle,
3915				    ha->state);
3916			}
3917		}
3918
3919		ha->state = FC_PORT_SPEED_MASK(ha->state);
3920
3921		/* All buffers freed */
3922		if (ha->ub_allocated == 0) {
3923			/* Hardware reset. */
3924			if (cmd == FC_FCA_RESET) {
3925				if (ha->vp_index == 0) {
3926					(void) ql_abort_isp(ha);
3927				} else if (!(ha->pha->task_daemon_flags &
3928				    LOOP_DOWN)) {
3929					(void) ql_loop_reset(ha);
3930				}
3931			}
3932
3933			/* Inform that the hardware has been reset */
3934			ha->state |= FC_STATE_RESET;
3935		} else {
3936			/*
3937			 * the port driver expects an online if
3938			 * buffers are not freed.
3939			 */
3940			if (ha->topology & QL_LOOP_CONNECTION) {
3941				ha->state |= FC_STATE_LOOP;
3942			} else {
3943				ha->state |= FC_STATE_ONLINE;
3944			}
3945		}
3946
3947		TASK_DAEMON_LOCK(ha);
3948		ha->task_daemon_flags |= FC_STATE_CHANGE;
3949		TASK_DAEMON_UNLOCK(ha);
3950
3951		ql_awaken_task_daemon(ha, NULL, FC_STATE_CHANGE, 0);
3952
3953		break;
3954	default:
3955		EL(ha, "unknown cmd=%xh\n", cmd);
3956		break;
3957	}
3958
3959	if (rval != FC_SUCCESS) {
3960		EL(ha, "cmd=%xh, failed=%xh\n", cmd, rval);
3961	} else {
3962		/*EMPTY*/
3963		QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance,
3964		    ha->vp_index);
3965	}
3966
3967	return (rval);
3968}
3969
3970/*
3971 * ql_port_manage
3972 *	Perform port management or diagnostics.
3973 *
3974 * Input:
3975 *	fca_handle = handle setup by ql_bind_port().
3976 *	cmd = pointer to command structure.
3977 *
3978 * Returns:
3979 *	FC_SUCCESS - the request completed successfully.
3980 *	FC_FAILURE - the request did not complete successfully.
3981 *	FC_UNBOUND - the fca_handle specified is not bound.
3982 *
3983 * Context:
3984 *	Kernel context.
3985 */
3986static int
3987ql_port_manage(opaque_t fca_handle, fc_fca_pm_t *cmd)
3988{
3989	clock_t			timer;
3990	uint16_t		index;
3991	uint32_t		*bp;
3992	port_id_t		d_id;
3993	ql_link_t		*link;
3994	ql_adapter_state_t	*ha, *pha;
3995	ql_tgt_t		*tq;
3996	dma_mem_t		buffer_xmt, buffer_rcv;
3997	size_t			length;
3998	uint32_t		cnt;
3999	char			buf[80];
4000	lbp_t			*lb;
4001	ql_mbx_data_t		mr;
4002	app_mbx_cmd_t		*mcp;
4003	int			i0;
4004	uint8_t			*bptr;
4005	int			rval2, rval = FC_SUCCESS;
4006	uint32_t		opcode;
4007	uint32_t		set_flags = 0;
4008
4009	ha = ql_fca_handle_to_state(fca_handle);
4010	if (ha == NULL) {
4011		QL_PRINT_2(CE_CONT, ": failed, no adapter=%ph\n",
4012		    (void *)fca_handle);
4013		return (FC_UNBOUND);
4014	}
4015	pha = ha->pha;
4016
4017	QL_PRINT_3(CE_CONT, "(%d): started=%xh\n", ha->instance,
4018	    cmd->pm_cmd_code);
4019
4020	ql_awaken_task_daemon(ha, NULL, DRIVER_STALL, 0);
4021
4022	/*
4023	 * Wait for all outstanding commands to complete
4024	 */
4025	index = (uint16_t)ql_wait_outstanding(ha);
4026
4027	if (index != MAX_OUTSTANDING_COMMANDS) {
4028		ql_awaken_task_daemon(ha, NULL, 0, DRIVER_STALL);
4029		ql_restart_queues(ha);
4030		EL(ha, "failed, FC_TRAN_BUSY\n");
4031		return (FC_TRAN_BUSY);
4032	}
4033
4034	switch (cmd->pm_cmd_code) {
4035	case FC_PORT_BYPASS:
4036		d_id.b24 = *cmd->pm_cmd_buf;
4037		tq = ql_d_id_to_queue(ha, d_id);
4038		if (tq == NULL || ql_loop_port_bypass(ha, tq) != QL_SUCCESS) {
4039			EL(ha, "failed, FC_PORT_BYPASS FC_FAILURE\n");
4040			rval = FC_FAILURE;
4041		}
4042		break;
4043	case FC_PORT_UNBYPASS:
4044		d_id.b24 = *cmd->pm_cmd_buf;
4045		tq = ql_d_id_to_queue(ha, d_id);
4046		if (tq == NULL || ql_loop_port_enable(ha, tq) != QL_SUCCESS) {
4047			EL(ha, "failed, FC_PORT_UNBYPASS FC_FAILURE\n");
4048			rval = FC_FAILURE;
4049		}
4050		break;
4051	case FC_PORT_GET_FW_REV:
4052		(void) sprintf(buf, "%d.%d.%d", pha->fw_major_version,
4053		    pha->fw_minor_version, pha->fw_subminor_version);
4054		length = strlen(buf) + 1;
4055		if (cmd->pm_data_len < length) {
4056			cmd->pm_data_len = length;
4057			EL(ha, "failed, FC_PORT_GET_FW_REV FC_FAILURE\n");
4058			rval = FC_FAILURE;
4059		} else {
4060			(void) strcpy(cmd->pm_data_buf, buf);
4061		}
4062		break;
4063
4064	case FC_PORT_GET_FCODE_REV: {
4065		caddr_t		fcode_ver_buf = NULL;
4066
4067		i0 = 0;
4068		/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
4069		rval2 = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
4070		    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version",
4071		    (caddr_t)&fcode_ver_buf, &i0);
4072		length = (uint_t)i0;
4073
4074		if (rval2 != DDI_PROP_SUCCESS) {
4075			EL(ha, "failed, getting version = %xh\n", rval2);
4076			length = 20;
4077			fcode_ver_buf = kmem_alloc(length, KM_SLEEP);
4078			if (fcode_ver_buf != NULL) {
4079				(void) sprintf(fcode_ver_buf,
4080				    "NO FCODE FOUND");
4081			}
4082		}
4083
4084		if (cmd->pm_data_len < length) {
4085			EL(ha, "length error, FC_PORT_GET_FCODE_REV "
4086			    "dst=%ld, src=%ld\n", cmd->pm_data_len, length);
4087			cmd->pm_data_len = length;
4088			rval = FC_FAILURE;
4089		} else if (fcode_ver_buf != NULL) {
4090			bcopy((void *)fcode_ver_buf, (void *)cmd->pm_data_buf,
4091			    length);
4092		}
4093
4094		if (fcode_ver_buf != NULL) {
4095			kmem_free(fcode_ver_buf, length);
4096		}
4097		break;
4098	}
4099
4100	case FC_PORT_GET_DUMP:
4101		QL_DUMP_LOCK(pha);
4102		if (cmd->pm_data_len < (size_t)pha->risc_dump_size) {
4103			EL(ha, "failed, FC_PORT_GET_DUMP incorrect "
4104			    "length=%lxh\n", cmd->pm_data_len);
4105			cmd->pm_data_len = pha->risc_dump_size;
4106			rval = FC_FAILURE;
4107		} else if (pha->ql_dump_state & QL_DUMPING) {
4108			EL(ha, "failed, FC_PORT_GET_DUMP FC_TRAN_BUSY\n");
4109			rval = FC_TRAN_BUSY;
4110		} else if (pha->ql_dump_state & QL_DUMP_VALID) {
4111			(void) ql_ascii_fw_dump(ha, cmd->pm_data_buf);
4112			pha->ql_dump_state |= QL_DUMP_UPLOADED;
4113		} else {
4114			EL(ha, "failed, FC_PORT_GET_DUMP no dump file\n");
4115			rval = FC_FAILURE;
4116		}
4117		QL_DUMP_UNLOCK(pha);
4118		break;
4119	case FC_PORT_FORCE_DUMP:
4120		PORTMANAGE_LOCK(ha);
4121		if (ql_dump_firmware(ha) != QL_SUCCESS) {
4122			EL(ha, "failed, FC_PORT_FORCE_DUMP FC_FAILURE\n");
4123			rval = FC_FAILURE;
4124		}
4125		PORTMANAGE_UNLOCK(ha);
4126		break;
4127	case FC_PORT_DOWNLOAD_FW:
4128		PORTMANAGE_LOCK(ha);
4129		if (CFG_IST(ha, CFG_CTRL_24258081)) {
4130			if (ql_24xx_load_flash(ha, (uint8_t *)cmd->pm_data_buf,
4131			    (uint32_t)cmd->pm_data_len,
4132			    ha->flash_fw_addr << 2) != QL_SUCCESS) {
4133				EL(ha, "failed, FC_PORT_DOWNLOAD_FW\n");
4134				rval = FC_FAILURE;
4135			}
4136			ql_reset_chip(ha);
4137			set_flags |= ISP_ABORT_NEEDED;
4138		} else {
4139			/* Save copy of the firmware. */
4140			if (pha->risc_code != NULL) {
4141				kmem_free(pha->risc_code, pha->risc_code_size);
4142				pha->risc_code = NULL;
4143				pha->risc_code_size = 0;
4144			}
4145
4146			pha->risc_code = kmem_alloc(cmd->pm_data_len,
4147			    KM_SLEEP);
4148			if (pha->risc_code != NULL) {
4149				pha->risc_code_size =
4150				    (uint32_t)cmd->pm_data_len;
4151				bcopy(cmd->pm_data_buf, pha->risc_code,
4152				    cmd->pm_data_len);
4153
4154				/* Do abort to force reload. */
4155				ql_reset_chip(ha);
4156				if (ql_abort_isp(ha) != QL_SUCCESS) {
4157					kmem_free(pha->risc_code,
4158					    pha->risc_code_size);
4159					pha->risc_code = NULL;
4160					pha->risc_code_size = 0;
4161					ql_reset_chip(ha);
4162					(void) ql_abort_isp(ha);
4163					EL(ha, "failed, FC_PORT_DOWNLOAD_FW"
4164					    " FC_FAILURE\n");
4165					rval = FC_FAILURE;
4166				}
4167			}
4168		}
4169		PORTMANAGE_UNLOCK(ha);
4170		break;
4171	case FC_PORT_GET_DUMP_SIZE:
4172		bp = (uint32_t *)cmd->pm_data_buf;
4173		*bp = pha->risc_dump_size;
4174		break;
4175	case FC_PORT_DIAG:
4176		/*
4177		 * Prevents concurrent diags
4178		 */
4179		PORTMANAGE_LOCK(ha);
4180
4181		/* Wait for suspension to end. */
4182		for (timer = 0; timer < 3000 &&
4183		    pha->task_daemon_flags & QL_LOOP_TRANSITION; timer++) {
4184			ql_delay(ha, 10000);
4185		}
4186
4187		if (pha->task_daemon_flags & QL_LOOP_TRANSITION) {
4188			EL(ha, "failed, FC_TRAN_BUSY-2\n");
4189			rval = FC_TRAN_BUSY;
4190			PORTMANAGE_UNLOCK(ha);
4191			break;
4192		}
4193
4194		switch (cmd->pm_cmd_flags) {
4195		case QL_DIAG_EXEFMW:
4196			if (ql_start_firmware(ha) != QL_SUCCESS) {
4197				EL(ha, "failed, QL_DIAG_EXEFMW FC_FAILURE\n");
4198				rval = FC_FAILURE;
4199			}
4200			break;
4201		case QL_DIAG_CHKCMDQUE:
4202			for (i0 = 1, cnt = 0; i0 < MAX_OUTSTANDING_COMMANDS;
4203			    i0++) {
4204				cnt += (pha->outstanding_cmds[i0] != NULL);
4205			}
4206			if (cnt != 0) {
4207				EL(ha, "failed, QL_DIAG_CHKCMDQUE "
4208				    "FC_FAILURE\n");
4209				rval = FC_FAILURE;
4210			}
4211			break;
4212		case QL_DIAG_FMWCHKSUM:
4213			if (ql_verify_checksum(ha) != QL_SUCCESS) {
4214				EL(ha, "failed, QL_DIAG_FMWCHKSUM "
4215				    "FC_FAILURE\n");
4216				rval = FC_FAILURE;
4217			}
4218			break;
4219		case QL_DIAG_SLFTST:
4220			if (ql_online_selftest(ha) != QL_SUCCESS) {
4221				EL(ha, "failed, QL_DIAG_SLFTST FC_FAILURE\n");
4222				rval = FC_FAILURE;
4223			}
4224			ql_reset_chip(ha);
4225			set_flags |= ISP_ABORT_NEEDED;
4226			break;
4227		case QL_DIAG_REVLVL:
4228			if (cmd->pm_stat_len <
4229			    sizeof (ql_adapter_revlvl_t)) {
4230				EL(ha, "failed, QL_DIAG_REVLVL FC_NOMEM, "
4231				    "slen=%lxh, rlvllen=%lxh\n",
4232				    cmd->pm_stat_len,
4233				    sizeof (ql_adapter_revlvl_t));
4234				rval = FC_NOMEM;
4235			} else {
4236				bcopy((void *)&(pha->adapter_stats->revlvl),
4237				    cmd->pm_stat_buf,
4238				    (size_t)cmd->pm_stat_len);
4239				cmd->pm_stat_len =
4240				    sizeof (ql_adapter_revlvl_t);
4241			}
4242			break;
4243		case QL_DIAG_LPBMBX:
4244
4245			if (cmd->pm_data_len != sizeof (struct app_mbx_cmd)) {
4246				EL(ha, "failed, QL_DIAG_LPBMBX "
4247				    "FC_INVALID_REQUEST, pmlen=%lxh, "
4248				    "reqd=%lxh\n", cmd->pm_data_len,
4249				    sizeof (struct app_mbx_cmd));
4250				rval = FC_INVALID_REQUEST;
4251				break;
4252			}
4253			/*
4254			 * Don't do the wrap test on a 2200 when the
4255			 * firmware is running.
4256			 */
4257			if (!CFG_IST(ha, CFG_CTRL_2200)) {
4258				mcp = (app_mbx_cmd_t *)cmd->pm_data_buf;
4259				mr.mb[1] = mcp->mb[1];
4260				mr.mb[2] = mcp->mb[2];
4261				mr.mb[3] = mcp->mb[3];
4262				mr.mb[4] = mcp->mb[4];
4263				mr.mb[5] = mcp->mb[5];
4264				mr.mb[6] = mcp->mb[6];
4265				mr.mb[7] = mcp->mb[7];
4266
4267				bcopy(&mr.mb[0], &mr.mb[10],
4268				    sizeof (uint16_t) * 8);
4269
4270				if (ql_mbx_wrap_test(ha, &mr) != QL_SUCCESS) {
4271					EL(ha, "failed, QL_DIAG_LPBMBX "
4272					    "FC_FAILURE\n");
4273					rval = FC_FAILURE;
4274					break;
4275				} else {
4276					for (i0 = 1; i0 < 8; i0++) {
4277						if (mr.mb[i0] !=
4278						    mr.mb[i0 + 10]) {
4279							EL(ha, "failed, "
4280							    "QL_DIAG_LPBMBX "
4281							    "FC_FAILURE-2\n");
4282							rval = FC_FAILURE;
4283							break;
4284						}
4285					}
4286				}
4287
4288				if (rval == FC_FAILURE) {
4289					(void) ql_flash_errlog(ha,
4290					    FLASH_ERRLOG_ISP_ERR, 0,
4291					    RD16_IO_REG(ha, hccr),
4292					    RD16_IO_REG(ha, istatus));
4293					set_flags |= ISP_ABORT_NEEDED;
4294				}
4295			}
4296			break;
4297		case QL_DIAG_LPBDTA:
4298			/*
4299			 * For loopback data, we receive the
4300			 * data back in pm_stat_buf. This provides
4301			 * the user an opportunity to compare the
4302			 * transmitted and received data.
4303			 *
4304			 * NB: lb->options are:
4305			 *	0 --> Ten bit loopback
4306			 *	1 --> One bit loopback
4307			 *	2 --> External loopback
4308			 */
4309			if (cmd->pm_data_len > 65536) {
4310				rval = FC_TOOMANY;
4311				EL(ha, "failed, QL_DIAG_LPBDTA "
4312				    "FC_TOOMANY=%lxh\n", cmd->pm_data_len);
4313				break;
4314			}
4315			if (ql_get_dma_mem(ha, &buffer_xmt,
4316			    (uint32_t)cmd->pm_data_len, LITTLE_ENDIAN_DMA,
4317			    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
4318				EL(ha, "failed, QL_DIAG_LPBDTA FC_NOMEM\n");
4319				rval = FC_NOMEM;
4320				break;
4321			}
4322			if (ql_get_dma_mem(ha, &buffer_rcv,
4323			    (uint32_t)cmd->pm_data_len, LITTLE_ENDIAN_DMA,
4324			    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
4325				EL(ha, "failed, QL_DIAG_LPBDTA FC_NOMEM-2\n");
4326				rval = FC_NOMEM;
4327				break;
4328			}
4329			ddi_rep_put8(buffer_xmt.acc_handle,
4330			    (uint8_t *)cmd->pm_data_buf,
4331			    (uint8_t *)buffer_xmt.bp,
4332			    cmd->pm_data_len, DDI_DEV_AUTOINCR);
4333
4334			/* 22xx's adapter must be in loop mode for test. */
4335			if (CFG_IST(ha, CFG_CTRL_2200)) {
4336				bptr = &ha->init_ctrl_blk.cb.add_fw_opt[0];
4337				if (ha->flags & POINT_TO_POINT ||
4338				    (ha->task_daemon_flags & LOOP_DOWN &&
4339				    *bptr & (BIT_6 | BIT_5 | BIT_4))) {
4340					cnt = *bptr;
4341					*bptr = (uint8_t)
4342					    (*bptr & ~(BIT_6|BIT_5|BIT_4));
4343					(void) ql_abort_isp(ha);
4344					*bptr = (uint8_t)cnt;
4345				}
4346			}
4347
4348			/* Shutdown IP. */
4349			if (pha->flags & IP_INITIALIZED) {
4350				(void) ql_shutdown_ip(pha);
4351			}
4352
4353			lb = (lbp_t *)cmd->pm_cmd_buf;
4354			lb->transfer_count =
4355			    (uint32_t)cmd->pm_data_len;
4356			lb->transfer_segment_count = 0;
4357			lb->receive_segment_count = 0;
4358			lb->transfer_data_address =
4359			    buffer_xmt.cookie.dmac_address;
4360			lb->receive_data_address =
4361			    buffer_rcv.cookie.dmac_address;
4362
4363			if (ql_loop_back(ha, 0, lb,
4364			    buffer_xmt.cookie.dmac_notused,
4365			    buffer_rcv.cookie.dmac_notused) == QL_SUCCESS) {
4366				bzero((void *)cmd->pm_stat_buf,
4367				    cmd->pm_stat_len);
4368				ddi_rep_get8(buffer_rcv.acc_handle,
4369				    (uint8_t *)cmd->pm_stat_buf,
4370				    (uint8_t *)buffer_rcv.bp,
4371				    cmd->pm_stat_len, DDI_DEV_AUTOINCR);
4372				rval = FC_SUCCESS;
4373			} else {
4374				EL(ha, "failed, QL_DIAG_LPBDTA FC_FAILURE\n");
4375				rval = FC_FAILURE;
4376			}
4377
4378			ql_free_phys(ha, &buffer_xmt);
4379			ql_free_phys(ha, &buffer_rcv);
4380
4381			/* Needed to recover the f/w */
4382			set_flags |= ISP_ABORT_NEEDED;
4383
4384			/* Restart IP if it was shutdown. */
4385			if (pha->flags & IP_ENABLED &&
4386			    !(pha->flags & IP_INITIALIZED)) {
4387				(void) ql_initialize_ip(pha);
4388				ql_isp_rcvbuf(pha);
4389			}
4390
4391			break;
4392		case QL_DIAG_ECHO: {
4393			/*
4394			 * issue an echo command with a user supplied
4395			 * data pattern and destination address
4396			 */
4397			echo_t		echo;		/* temp echo struct */
4398
4399			/* Setup echo cmd & adjust for platform */
4400			opcode = QL_ECHO_CMD;
4401			BIG_ENDIAN_32(&opcode);
4402
4403			/*
4404			 * due to limitations in the ql
4405			 * firmaware the echo data field is
4406			 * limited to 220
4407			 */
4408			if ((cmd->pm_cmd_len > QL_ECHO_CMD_LENGTH) ||
4409			    (cmd->pm_stat_len > QL_ECHO_CMD_LENGTH)) {
4410				EL(ha, "failed, QL_DIAG_ECHO FC_TOOMANY, "
4411				    "cmdl1=%lxh, statl2=%lxh\n",
4412				    cmd->pm_cmd_len, cmd->pm_stat_len);
4413				rval = FC_TOOMANY;
4414				break;
4415			}
4416
4417			/*
4418			 * the input data buffer has the user
4419			 * supplied data pattern.  The "echoed"
4420			 * data will be DMAed into the output
4421			 * data buffer.  Therefore the length
4422			 * of the output buffer must be equal
4423			 * to or greater then the input buffer
4424			 * length
4425			 */
4426			if (cmd->pm_cmd_len > cmd->pm_stat_len) {
4427				EL(ha, "failed, QL_DIAG_ECHO FC_TOOMANY-2,"
4428				    " cmdl1=%lxh, statl2=%lxh\n",
4429				    cmd->pm_cmd_len, cmd->pm_stat_len);
4430				rval = FC_TOOMANY;
4431				break;
4432			}
4433			/* add four bytes for the opcode */
4434			echo.transfer_count = (uint32_t)(cmd->pm_cmd_len + 4);
4435
4436			/*
4437			 * are we 32 or 64 bit addressed???
4438			 * We need to get the appropriate
4439			 * DMA and set the command options;
4440			 * 64 bit (bit 6) or 32 bit
4441			 * (no bit 6) addressing.
4442			 * while we are at it lets ask for
4443			 * real echo (bit 15)
4444			 */
4445			echo.options = BIT_15;
4446			if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING) &&
4447			    !(CFG_IST(ha, CFG_CTRL_8081))) {
4448				echo.options = (uint16_t)
4449				    (echo.options | BIT_6);
4450			}
4451
4452			/*
4453			 * Set up the DMA mappings for the
4454			 * output and input data buffers.
4455			 * First the output buffer
4456			 */
4457			if (ql_get_dma_mem(ha, &buffer_xmt,
4458			    (uint32_t)(cmd->pm_data_len + 4),
4459			    LITTLE_ENDIAN_DMA,
4460			    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
4461				EL(ha, "failed, QL_DIAG_ECHO FC_NOMEM\n");
4462				rval = FC_NOMEM;
4463				break;
4464			}
4465			echo.transfer_data_address = buffer_xmt.cookie;
4466
4467			/* Next the input buffer */
4468			if (ql_get_dma_mem(ha, &buffer_rcv,
4469			    (uint32_t)(cmd->pm_data_len + 4),
4470			    LITTLE_ENDIAN_DMA,
4471			    QL_DMA_DATA_ALIGN) != QL_SUCCESS) {
4472				/*
4473				 * since we could not allocate
4474				 * DMA space for the input
4475				 * buffer we need to clean up
4476				 * by freeing the DMA space
4477				 * we allocated for the output
4478				 * buffer
4479				 */
4480				ql_free_phys(ha, &buffer_xmt);
4481				EL(ha, "failed, QL_DIAG_ECHO FC_NOMEM-2\n");
4482				rval = FC_NOMEM;
4483				break;
4484			}
4485			echo.receive_data_address = buffer_rcv.cookie;
4486
4487			/*
4488			 * copy the 4 byte ECHO op code to the
4489			 * allocated DMA space
4490			 */
4491			ddi_rep_put8(buffer_xmt.acc_handle, (uint8_t *)&opcode,
4492			    (uint8_t *)buffer_xmt.bp, 4, DDI_DEV_AUTOINCR);
4493
4494			/*
4495			 * copy the user supplied data to the
4496			 * allocated DMA space
4497			 */
4498			ddi_rep_put8(buffer_xmt.acc_handle,
4499			    (uint8_t *)cmd->pm_cmd_buf,
4500			    (uint8_t *)buffer_xmt.bp + 4, cmd->pm_cmd_len,
4501			    DDI_DEV_AUTOINCR);
4502
4503			/* Shutdown IP. */
4504			if (pha->flags & IP_INITIALIZED) {
4505				(void) ql_shutdown_ip(pha);
4506			}
4507
4508			/* send the echo */
4509			if (ql_echo(ha, 0, &echo) == QL_SUCCESS) {
4510				ddi_rep_put8(buffer_rcv.acc_handle,
4511				    (uint8_t *)buffer_rcv.bp + 4,
4512				    (uint8_t *)cmd->pm_stat_buf,
4513				    cmd->pm_stat_len, DDI_DEV_AUTOINCR);
4514			} else {
4515				EL(ha, "failed, QL_DIAG_ECHO FC_FAILURE\n");
4516				rval = FC_FAILURE;
4517			}
4518
4519			/* Restart IP if it was shutdown. */
4520			if (pha->flags & IP_ENABLED &&
4521			    !(pha->flags & IP_INITIALIZED)) {
4522				(void) ql_initialize_ip(pha);
4523				ql_isp_rcvbuf(pha);
4524			}
4525			/* free up our DMA buffers */
4526			ql_free_phys(ha, &buffer_xmt);
4527			ql_free_phys(ha, &buffer_rcv);
4528			break;
4529		}
4530		default:
4531			EL(ha, "unknown=%xh, FC_PORT_DIAG "
4532			    "FC_INVALID_REQUEST\n", cmd->pm_cmd_flags);
4533			rval = FC_INVALID_REQUEST;
4534			break;
4535		}
4536		PORTMANAGE_UNLOCK(ha);
4537		break;
4538	case FC_PORT_LINK_STATE:
4539		/* Check for name equal to null. */
4540		for (index = 0; index < 8 && index < cmd->pm_cmd_len;
4541		    index++) {
4542			if (cmd->pm_cmd_buf[index] != 0) {
4543				break;
4544			}
4545		}
4546
4547		/* If name not null. */
4548		if (index < 8 && cmd->pm_cmd_len >= 8) {
4549			/* Locate device queue. */
4550			tq = NULL;
4551			for (index = 0; index < DEVICE_HEAD_LIST_SIZE &&
4552			    tq == NULL; index++) {
4553				for (link = ha->dev[index].first; link != NULL;
4554				    link = link->next) {
4555					tq = link->base_address;
4556
4557					if (bcmp((void *)&tq->port_name[0],
4558					    (void *)cmd->pm_cmd_buf, 8) == 0) {
4559						break;
4560					} else {
4561						tq = NULL;
4562					}
4563				}
4564			}
4565
4566			if (tq != NULL && VALID_DEVICE_ID(ha, tq->loop_id)) {
4567				cmd->pm_stat_buf[0] = (int8_t)LSB(ha->state);
4568				cmd->pm_stat_buf[1] = (int8_t)MSB(ha->state);
4569			} else {
4570				cnt = FC_PORT_SPEED_MASK(ha->state) |
4571				    FC_STATE_OFFLINE;
4572				cmd->pm_stat_buf[0] = (int8_t)LSB(cnt);
4573				cmd->pm_stat_buf[1] = (int8_t)MSB(cnt);
4574			}
4575		} else {
4576			cmd->pm_stat_buf[0] = (int8_t)LSB(ha->state);
4577			cmd->pm_stat_buf[1] = (int8_t)MSB(ha->state);
4578		}
4579		break;
4580	case FC_PORT_INITIALIZE:
4581		if (cmd->pm_cmd_len >= 8) {
4582			tq = NULL;
4583			for (index = 0; index < DEVICE_HEAD_LIST_SIZE &&
4584			    tq == NULL; index++) {
4585				for (link = ha->dev[index].first; link != NULL;
4586				    link = link->next) {
4587					tq = link->base_address;
4588
4589					if (bcmp((void *)&tq->port_name[0],
4590					    (void *)cmd->pm_cmd_buf, 8) == 0) {
4591						if (!VALID_DEVICE_ID(ha,
4592						    tq->loop_id)) {
4593							tq = NULL;
4594						}
4595						break;
4596					} else {
4597						tq = NULL;
4598					}
4599				}
4600			}
4601
4602			if (tq == NULL || ql_target_reset(ha, tq,
4603			    ha->loop_reset_delay) != QL_SUCCESS) {
4604				EL(ha, "failed, FC_PORT_INITIALIZE "
4605				    "FC_FAILURE\n");
4606				rval = FC_FAILURE;
4607			}
4608		} else {
4609			EL(ha, "failed, FC_PORT_INITIALIZE FC_FAILURE-2, "
4610			    "clen=%lxh\n", cmd->pm_cmd_len);
4611
4612			rval = FC_FAILURE;
4613		}
4614		break;
4615	case FC_PORT_RLS:
4616		if (cmd->pm_data_len < sizeof (fc_rls_acc_t)) {
4617			EL(ha, "failed, buffer size passed: %lxh, "
4618			    "req: %lxh\n", cmd->pm_data_len,
4619			    (sizeof (fc_rls_acc_t)));
4620			rval = FC_FAILURE;
4621		} else if (LOOP_NOT_READY(pha)) {
4622			EL(ha, "loop NOT ready\n");
4623			bzero(cmd->pm_data_buf, cmd->pm_data_len);
4624		} else if (ql_get_link_status(ha, ha->loop_id,
4625		    cmd->pm_data_len, cmd->pm_data_buf, 0) != QL_SUCCESS) {
4626			EL(ha, "failed, FC_PORT_RLS FC_FAILURE\n");
4627			rval = FC_FAILURE;
4628#ifdef _BIG_ENDIAN
4629		} else {
4630			fc_rls_acc_t		*rls;
4631
4632			rls = (fc_rls_acc_t *)cmd->pm_data_buf;
4633			LITTLE_ENDIAN_32(&rls->rls_link_fail);
4634			LITTLE_ENDIAN_32(&rls->rls_sync_loss);
4635			LITTLE_ENDIAN_32(&rls->rls_sig_loss);
4636			LITTLE_ENDIAN_32(&rls->rls_invalid_crc);
4637#endif /* _BIG_ENDIAN */
4638		}
4639		break;
4640	case FC_PORT_GET_NODE_ID:
4641		if (ql_get_rnid_params(ha, cmd->pm_data_len,
4642		    cmd->pm_data_buf) != QL_SUCCESS) {
4643			EL(ha, "failed, FC_PORT_GET_NODE_ID FC_FAILURE\n");
4644			rval = FC_FAILURE;
4645		}
4646		break;
4647	case FC_PORT_SET_NODE_ID:
4648		if (ql_set_rnid_params(ha, cmd->pm_data_len,
4649		    cmd->pm_data_buf) != QL_SUCCESS) {
4650			EL(ha, "failed, FC_PORT_SET_NODE_ID FC_FAILURE\n");
4651			rval = FC_FAILURE;
4652		}
4653		break;
4654	case FC_PORT_DOWNLOAD_FCODE:
4655		PORTMANAGE_LOCK(ha);
4656		if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
4657			rval = ql_load_flash(ha, (uint8_t *)cmd->pm_data_buf,
4658			    (uint32_t)cmd->pm_data_len);
4659		} else {
4660			if (cmd->pm_data_buf[0] == 4 &&
4661			    cmd->pm_data_buf[8] == 0 &&
4662			    cmd->pm_data_buf[9] == 0x10 &&
4663			    cmd->pm_data_buf[10] == 0 &&
4664			    cmd->pm_data_buf[11] == 0) {
4665				rval = ql_24xx_load_flash(ha,
4666				    (uint8_t *)cmd->pm_data_buf,
4667				    (uint32_t)cmd->pm_data_len,
4668				    ha->flash_fw_addr << 2);
4669			} else {
4670				rval = ql_24xx_load_flash(ha,
4671				    (uint8_t *)cmd->pm_data_buf,
4672				    (uint32_t)cmd->pm_data_len, 0);
4673			}
4674		}
4675
4676		if (rval != QL_SUCCESS) {
4677			EL(ha, "failed, FC_PORT_DOWNLOAD_FCODE FC_FAILURE\n");
4678			rval = FC_FAILURE;
4679		} else {
4680			rval = FC_SUCCESS;
4681		}
4682		ql_reset_chip(ha);
4683		set_flags |= ISP_ABORT_NEEDED;
4684		PORTMANAGE_UNLOCK(ha);
4685		break;
4686	default:
4687		EL(ha, "unknown=%xh, FC_BADCMD\n", cmd->pm_cmd_code);
4688		rval = FC_BADCMD;
4689		break;
4690	}
4691
4692	/* Wait for suspension to end. */
4693	ql_awaken_task_daemon(ha, NULL, set_flags, DRIVER_STALL);
4694	timer = 0;
4695
4696	while (timer++ < 3000 &&
4697	    ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) {
4698		ql_delay(ha, 10000);
4699	}
4700
4701	ql_restart_queues(ha);
4702
4703	if (rval != FC_SUCCESS) {
4704		EL(ha, "failed, rval = %xh\n", rval);
4705	} else {
4706		/*EMPTY*/
4707		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4708	}
4709
4710	return (rval);
4711}
4712
4713static opaque_t
4714ql_get_device(opaque_t fca_handle, fc_portid_t d_id)
4715{
4716	port_id_t		id;
4717	ql_adapter_state_t	*ha;
4718	ql_tgt_t		*tq;
4719
4720	id.r.rsvd_1 = 0;
4721	id.b24 = d_id.port_id;
4722
4723	ha = ql_fca_handle_to_state(fca_handle);
4724	if (ha == NULL) {
4725		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
4726		    (void *)fca_handle);
4727		return (NULL);
4728	}
4729	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance, id.b24);
4730
4731	tq = ql_d_id_to_queue(ha, id);
4732
4733	if (tq == NULL) {
4734		EL(ha, "failed, tq=NULL\n");
4735	} else {
4736		/*EMPTY*/
4737		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4738	}
4739	return (tq);
4740}
4741
4742/* ************************************************************************ */
4743/*			FCA Driver Local Support Functions.		    */
4744/* ************************************************************************ */
4745
4746/*
4747 * ql_cmd_setup
4748 *	Verifies proper command.
4749 *
4750 * Input:
4751 *	fca_handle = handle setup by ql_bind_port().
4752 *	pkt = pointer to fc_packet.
4753 *	rval = pointer for return value.
4754 *
4755 * Returns:
4756 *	Adapter state pointer, NULL = failure.
4757 *
4758 * Context:
4759 *	Kernel context.
4760 */
4761static ql_adapter_state_t *
4762ql_cmd_setup(opaque_t fca_handle, fc_packet_t *pkt, int *rval)
4763{
4764	ql_adapter_state_t	*ha, *pha;
4765	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
4766	ql_tgt_t		*tq;
4767	port_id_t		d_id;
4768
4769	pkt->pkt_resp_resid = 0;
4770	pkt->pkt_data_resid = 0;
4771
4772	/* check that the handle is assigned by this FCA */
4773	ha = ql_fca_handle_to_state(fca_handle);
4774	if (ha == NULL) {
4775		*rval = FC_UNBOUND;
4776		QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
4777		    (void *)fca_handle);
4778		return (NULL);
4779	}
4780	pha = ha->pha;
4781
4782	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
4783
4784	if (ddi_in_panic() || pkt->pkt_tran_flags & FC_TRAN_DUMPING) {
4785		return (ha);
4786	}
4787
4788	if (!(pha->flags & ONLINE)) {
4789		pkt->pkt_state = FC_PKT_LOCAL_RJT;
4790		pkt->pkt_reason = FC_REASON_HW_ERROR;
4791		*rval = FC_TRANSPORT_ERROR;
4792		EL(ha, "failed, not online hf=%xh\n", pha->flags);
4793		return (NULL);
4794	}
4795
4796	/* Exit on loop down. */
4797	if (CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING) &&
4798	    pha->task_daemon_flags & LOOP_DOWN &&
4799	    pha->loop_down_timer <= pha->loop_down_abort_time) {
4800		pkt->pkt_state = FC_PKT_PORT_OFFLINE;
4801		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
4802		*rval = FC_OFFLINE;
4803		EL(ha, "failed, loop down tdf=%xh\n", pha->task_daemon_flags);
4804		return (NULL);
4805	}
4806
4807	if (pkt->pkt_cmd_fhdr.r_ctl == R_CTL_COMMAND &&
4808	    pkt->pkt_cmd_fhdr.type == FC_TYPE_SCSI_FCP) {
4809		tq = (ql_tgt_t *)pkt->pkt_fca_device;
4810		if ((tq == NULL) || (!VALID_DEVICE_ID(ha, tq->loop_id))) {
4811			d_id.r.rsvd_1 = 0;
4812			d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
4813			tq = ql_d_id_to_queue(ha, d_id);
4814
4815			pkt->pkt_fca_device = (opaque_t)tq;
4816		}
4817
4818		if (tq != NULL) {
4819			DEVICE_QUEUE_LOCK(tq);
4820			if (tq->flags & (TQF_RSCN_RCVD |
4821			    TQF_NEED_AUTHENTICATION)) {
4822				*rval = FC_DEVICE_BUSY;
4823				DEVICE_QUEUE_UNLOCK(tq);
4824				EL(ha, "failed, busy qf=%xh, d_id=%xh\n",
4825				    tq->flags, tq->d_id.b24);
4826				return (NULL);
4827			}
4828			DEVICE_QUEUE_UNLOCK(tq);
4829		}
4830	}
4831
4832	/*
4833	 * Check DMA pointers.
4834	 */
4835	*rval = DDI_SUCCESS;
4836	if (pkt->pkt_cmd_acc != NULL && pkt->pkt_cmdlen) {
4837		QL_CLEAR_DMA_HANDLE(pkt->pkt_cmd_dma);
4838		*rval = ddi_check_dma_handle(pkt->pkt_cmd_dma);
4839		if (*rval == DDI_SUCCESS) {
4840			*rval = ddi_check_acc_handle(pkt->pkt_cmd_acc);
4841		}
4842	}
4843
4844	if (pkt->pkt_resp_acc != NULL && *rval == DDI_SUCCESS &&
4845	    pkt->pkt_rsplen != 0) {
4846		QL_CLEAR_DMA_HANDLE(pkt->pkt_resp_dma);
4847		*rval = ddi_check_dma_handle(pkt->pkt_resp_dma);
4848		if (*rval == DDI_SUCCESS) {
4849			*rval = ddi_check_acc_handle(pkt->pkt_resp_acc);
4850		}
4851	}
4852
4853	/*
4854	 * Minimum branch conditional; Change it with care.
4855	 */
4856	if (((pkt->pkt_data_acc != NULL) & (*rval == DDI_SUCCESS) &
4857	    (pkt->pkt_datalen != 0)) != 0) {
4858		QL_CLEAR_DMA_HANDLE(pkt->pkt_data_dma);
4859		*rval = ddi_check_dma_handle(pkt->pkt_data_dma);
4860		if (*rval == DDI_SUCCESS) {
4861			*rval = ddi_check_acc_handle(pkt->pkt_data_acc);
4862		}
4863	}
4864
4865	if (*rval != DDI_SUCCESS) {
4866		pkt->pkt_state = FC_PKT_TRAN_ERROR;
4867		pkt->pkt_reason = FC_REASON_DMA_ERROR;
4868
4869		/* Do command callback. */
4870		if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
4871			ql_awaken_task_daemon(ha, sp, 0, 0);
4872		}
4873		*rval = FC_BADPACKET;
4874		EL(ha, "failed, bad DMA pointers\n");
4875		return (NULL);
4876	}
4877
4878	if (sp->magic_number != QL_FCA_BRAND) {
4879		*rval = FC_BADPACKET;
4880		EL(ha, "failed, magic number=%xh\n", sp->magic_number);
4881		return (NULL);
4882	}
4883	*rval = FC_SUCCESS;
4884
4885	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
4886
4887	return (ha);
4888}
4889
4890/*
4891 * ql_els_plogi
4892 *	Issue a extended link service port login request.
4893 *
4894 * Input:
4895 *	ha = adapter state pointer.
4896 *	pkt = pointer to fc_packet.
4897 *
4898 * Returns:
4899 *	FC_SUCCESS - the packet was accepted for transport.
4900 *	FC_TRANSPORT_ERROR - a transport error occurred.
4901 *
4902 * Context:
4903 *	Kernel context.
4904 */
4905static int
4906ql_els_plogi(ql_adapter_state_t *ha, fc_packet_t *pkt)
4907{
4908	ql_tgt_t		*tq = NULL;
4909	port_id_t		d_id;
4910	la_els_logi_t		acc;
4911	class_svc_param_t	*class3_param;
4912	int			ret;
4913	int			rval = FC_SUCCESS;
4914
4915	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
4916	    pkt->pkt_cmd_fhdr.d_id);
4917
4918	TASK_DAEMON_LOCK(ha);
4919	if (!(ha->task_daemon_flags & STATE_ONLINE)) {
4920		TASK_DAEMON_UNLOCK(ha);
4921		QL_PRINT_3(CE_CONT, "(%d): offline done\n", ha->instance);
4922		return (FC_OFFLINE);
4923	}
4924	TASK_DAEMON_UNLOCK(ha);
4925
4926	bzero(&acc, sizeof (acc));
4927	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
4928
4929	ret = QL_SUCCESS;
4930
4931	if (CFG_IST(ha, CFG_CTRL_2425) && ha->topology & QL_N_PORT) {
4932		/*
4933		 * In p2p topology it sends a PLOGI after determining
4934		 * it has the N_Port login initiative.
4935		 */
4936		ret = ql_p2p_plogi(ha, pkt);
4937	}
4938	if (ret == QL_CONSUMED) {
4939		return (ret);
4940	}
4941
4942	switch (ret = ql_login_port(ha, d_id)) {
4943	case QL_SUCCESS:
4944		tq = ql_d_id_to_queue(ha, d_id);
4945		break;
4946
4947	case QL_LOOP_ID_USED:
4948		if ((ret = ql_login_port(ha, d_id)) == QL_SUCCESS) {
4949			tq = ql_d_id_to_queue(ha, d_id);
4950		}
4951		break;
4952
4953	default:
4954		break;
4955	}
4956
4957	if (ret != QL_SUCCESS) {
4958		/*
4959		 * Invalidate this entry so as to seek a fresh loop ID
4960		 * in case firmware reassigns it to something else
4961		 */
4962		tq = ql_d_id_to_queue(ha, d_id);
4963		if (tq && (ret != QL_MEMORY_ALLOC_FAILED)) {
4964			tq->loop_id = PORT_NO_LOOP_ID;
4965		}
4966	} else if (tq) {
4967		(void) ql_get_port_database(ha, tq, PDF_ADISC);
4968	}
4969
4970	if (tq != NULL && VALID_DEVICE_ID(ha, tq->loop_id) &&
4971	    (ret != QL_MEMORY_ALLOC_FAILED) && PD_PORT_LOGIN(tq)) {
4972
4973		/* Build ACC. */
4974		acc.ls_code.ls_code = LA_ELS_ACC;
4975		acc.common_service.fcph_version = 0x2006;
4976		acc.common_service.cmn_features = 0x8800;
4977		acc.common_service.rx_bufsize = QL_MAX_FRAME_SIZE(ha);
4978		acc.common_service.conc_sequences = 0xff;
4979		acc.common_service.relative_offset = 0x03;
4980		acc.common_service.e_d_tov = 0x7d0;
4981
4982		bcopy((void *)&tq->port_name[0],
4983		    (void *)&acc.nport_ww_name.raw_wwn[0], 8);
4984		bcopy((void *)&tq->node_name[0],
4985		    (void *)&acc.node_ww_name.raw_wwn[0], 8);
4986
4987		class3_param = (class_svc_param_t *)&acc.class_3;
4988		class3_param->class_valid_svc_opt = 0x8000;
4989		class3_param->recipient_ctl = tq->class3_recipient_ctl;
4990		class3_param->rcv_data_size = tq->class3_rcv_data_size;
4991		class3_param->conc_sequences = tq->class3_conc_sequences;
4992		class3_param->open_sequences_per_exch =
4993		    tq->class3_open_sequences_per_exch;
4994
4995		if ((ql_busy_plogi(ha, pkt, tq) == FC_TRAN_BUSY)) {
4996			acc.ls_code.ls_code = LA_ELS_RJT;
4997			pkt->pkt_state = FC_PKT_TRAN_BSY;
4998			pkt->pkt_reason = FC_REASON_XCHG_BSY;
4999			EL(ha, "LA_ELS_RJT, FC_REASON_XCHG_BSY\n");
5000			rval = FC_TRAN_BUSY;
5001		} else {
5002			DEVICE_QUEUE_LOCK(tq);
5003			tq->logout_sent = 0;
5004			tq->flags &= ~TQF_NEED_AUTHENTICATION;
5005			if (CFG_IST(ha, CFG_CTRL_242581)) {
5006				tq->flags |= TQF_IIDMA_NEEDED;
5007			}
5008			DEVICE_QUEUE_UNLOCK(tq);
5009
5010			if (CFG_IST(ha, CFG_CTRL_242581)) {
5011				TASK_DAEMON_LOCK(ha);
5012				ha->task_daemon_flags |= TD_IIDMA_NEEDED;
5013				TASK_DAEMON_UNLOCK(ha);
5014			}
5015
5016			pkt->pkt_state = FC_PKT_SUCCESS;
5017		}
5018	} else {
5019		/* Build RJT. */
5020		acc.ls_code.ls_code = LA_ELS_RJT;
5021
5022		switch (ret) {
5023		case QL_FUNCTION_TIMEOUT:
5024			pkt->pkt_state = FC_PKT_TIMEOUT;
5025			pkt->pkt_reason = FC_REASON_HW_ERROR;
5026			break;
5027
5028		case QL_MEMORY_ALLOC_FAILED:
5029			pkt->pkt_state = FC_PKT_LOCAL_BSY;
5030			pkt->pkt_reason = FC_REASON_NOMEM;
5031			rval = FC_TRAN_BUSY;
5032			break;
5033
5034		case QL_FABRIC_NOT_INITIALIZED:
5035			pkt->pkt_state = FC_PKT_FABRIC_BSY;
5036			pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5037			rval = FC_TRAN_BUSY;
5038			break;
5039
5040		default:
5041			pkt->pkt_state = FC_PKT_TRAN_ERROR;
5042			pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5043			break;
5044		}
5045
5046		EL(ha, "Plogi unsuccess for %xh state %xh reason %xh "
5047		    "ret %xh rval %xh\n", d_id.b24, pkt->pkt_state,
5048		    pkt->pkt_reason, ret, rval);
5049	}
5050
5051	if (tq != NULL) {
5052		DEVICE_QUEUE_LOCK(tq);
5053		tq->flags &= ~(TQF_PLOGI_PROGRS | TQF_QUEUE_SUSPENDED);
5054		if (rval == FC_TRAN_BUSY) {
5055			if (tq->d_id.b24 != BROADCAST_ADDR) {
5056				tq->flags |= TQF_NEED_AUTHENTICATION;
5057			}
5058		}
5059		DEVICE_QUEUE_UNLOCK(tq);
5060	}
5061
5062	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5063	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5064
5065	if (rval != FC_SUCCESS) {
5066		EL(ha, "failed, rval = %xh\n", rval);
5067	} else {
5068		/*EMPTY*/
5069		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5070	}
5071	return (rval);
5072}
5073
5074/*
5075 * ql_p2p_plogi
5076 *	Start an extended link service port login request using
5077 *	an ELS Passthru iocb.
5078 *
5079 * Input:
5080 *	ha = adapter state pointer.
5081 *	pkt = pointer to fc_packet.
5082 *
5083 * Returns:
5084 *	QL_CONSUMMED - the iocb was queued for transport.
5085 *
5086 * Context:
5087 *	Kernel context.
5088 */
5089static int
5090ql_p2p_plogi(ql_adapter_state_t *ha, fc_packet_t *pkt)
5091{
5092	uint16_t	id;
5093	ql_tgt_t	tmp;
5094	ql_tgt_t	*tq = &tmp;
5095	int		rval;
5096	port_id_t	d_id;
5097	ql_srb_t	*sp = (ql_srb_t *)pkt->pkt_fca_private;
5098
5099	tq->d_id.b.al_pa = 0;
5100	tq->d_id.b.area = 0;
5101	tq->d_id.b.domain = 0;
5102
5103	/*
5104	 * Verify that the port database hasn't moved beneath our feet by
5105	 * switching to the appropriate n_port_handle if necessary.  This is
5106	 * less unplesant than the error recovery if the wrong one is used.
5107	 */
5108	for (id = 0; id <= LAST_LOCAL_LOOP_ID; id++) {
5109		tq->loop_id = id;
5110		rval = ql_get_port_database(ha, tq, PDF_NONE);
5111		EL(ha, "rval=%xh\n", rval);
5112		/* check all the ones not logged in for possible use */
5113		if (rval == QL_NOT_LOGGED_IN) {
5114			if (tq->master_state == PD_STATE_PLOGI_PENDING) {
5115				ha->n_port->n_port_handle = tq->loop_id;
5116				EL(ha, "n_port_handle =%xh, master state=%x\n",
5117				    tq->loop_id, tq->master_state);
5118				break;
5119			}
5120			/*
5121			 * Use a 'port unavailable' entry only
5122			 * if we used it before.
5123			 */
5124			if (tq->master_state == PD_STATE_PORT_UNAVAILABLE) {
5125				/* if the port_id matches, reuse it */
5126				if (pkt->pkt_cmd_fhdr.d_id == tq->d_id.b24) {
5127					EL(ha, "n_port_handle =%xh,"
5128					    "master state=%xh\n",
5129					    tq->loop_id, tq->master_state);
5130					break;
5131				} else if (tq->loop_id ==
5132				    ha->n_port->n_port_handle) {
5133				    // avoid a lint error
5134					uint16_t *hndl;
5135					uint16_t val;
5136
5137					hndl = &ha->n_port->n_port_handle;
5138					val = *hndl;
5139					val++;
5140					val++;
5141					*hndl = val;
5142				}
5143			EL(ha, "rval=%xh, id=%d, n_port_handle =%xh, "
5144			    "master state=%x\n", rval, id, tq->loop_id,
5145			    tq->master_state);
5146			}
5147
5148		}
5149		if (rval == QL_SUCCESS) {
5150			if ((tq->flags & TQF_INITIATOR_DEVICE) == 0) {
5151				ha->n_port->n_port_handle = tq->loop_id;
5152				EL(ha, "n_port_handle =%xh, master state=%x\n",
5153				    tq->loop_id, tq->master_state);
5154				break;
5155			}
5156			EL(ha, "rval=%xh, id=%d, n_port_handle =%xh, "
5157			    "master state=%x\n", rval, id, tq->loop_id,
5158			    tq->master_state);
5159		}
5160	}
5161	(void) ddi_dma_sync(pkt->pkt_cmd_dma, 0, 0, DDI_DMA_SYNC_FORDEV);
5162
5163	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5164	tq = ql_d_id_to_queue(ha, d_id);
5165	ql_timeout_insert(ha, tq, sp);
5166	ql_start_iocb(ha, sp);
5167
5168	return (QL_CONSUMED);
5169}
5170
5171
5172/*
5173 * ql_els_flogi
5174 *	Issue a extended link service fabric login request.
5175 *
5176 * Input:
5177 *	ha = adapter state pointer.
5178 *	pkt = pointer to fc_packet.
5179 *
5180 * Returns:
5181 *	FC_SUCCESS - the packet was accepted for transport.
5182 *	FC_TRANSPORT_ERROR - a transport error occurred.
5183 *
5184 * Context:
5185 *	Kernel context.
5186 */
5187static int
5188ql_els_flogi(ql_adapter_state_t *ha, fc_packet_t *pkt)
5189{
5190	ql_tgt_t		*tq = NULL;
5191	port_id_t		d_id;
5192	la_els_logi_t		acc;
5193	class_svc_param_t	*class3_param;
5194	int			rval = FC_SUCCESS;
5195	int			accept = 0;
5196
5197	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
5198	    pkt->pkt_cmd_fhdr.d_id);
5199
5200	bzero(&acc, sizeof (acc));
5201	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5202
5203	if (CFG_IST(ha, CFG_CTRL_2425) && ha->topology & QL_N_PORT) {
5204		/*
5205		 * d_id of zero in a FLOGI accept response in a point to point
5206		 * topology triggers evaluation of N Port login initiative.
5207		 */
5208		pkt->pkt_resp_fhdr.d_id = 0;
5209		/*
5210		 * An N_Port already logged in with the firmware
5211		 * will have the only database entry.
5212		 */
5213		if (LOCAL_LOOP_ID(ha->n_port->n_port_handle)) {
5214			tq = ql_loop_id_to_queue(ha, ha->n_port->n_port_handle);
5215		}
5216
5217		if (tq != NULL) {
5218			/*
5219			 * If the target port has initiative send
5220			 * up a PLOGI about the new device.
5221			 */
5222			if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0],
5223			    (la_wwn_t *)(CFG_IST(ha, CFG_CTRL_2425) ?
5224			    &ha->init_ctrl_blk.cb24.port_name[0] :
5225			    &ha->init_ctrl_blk.cb.port_name[0])) == 1)) {
5226				ha->send_plogi_timer = 3;
5227			} else {
5228				ha->send_plogi_timer = 0;
5229			}
5230			pkt->pkt_resp_fhdr.s_id = tq->d_id.b24;
5231		} else {
5232			/*
5233			 * An N_Port not logged in with the firmware will not
5234			 * have a database entry.  We accept anyway and rely
5235			 * on a PLOGI from the upper layers to set the d_id
5236			 * and s_id.
5237			 */
5238			accept = 1;
5239		}
5240	} else {
5241		tq = ql_d_id_to_queue(ha, d_id);
5242	}
5243	if ((tq != NULL) || (accept != 0)) {
5244		/* Build ACC. */
5245		pkt->pkt_state = FC_PKT_SUCCESS;
5246		class3_param = (class_svc_param_t *)&acc.class_3;
5247
5248		acc.ls_code.ls_code = LA_ELS_ACC;
5249		acc.common_service.fcph_version = 0x2006;
5250		if (ha->topology & QL_N_PORT) {
5251			/* clear F_Port indicator */
5252			acc.common_service.cmn_features = 0x0800;
5253		} else {
5254			acc.common_service.cmn_features = 0x1b00;
5255		}
5256		CFG_IST(ha, CFG_CTRL_24258081) ?
5257		    (acc.common_service.rx_bufsize = CHAR_TO_SHORT(
5258		    ha->init_ctrl_blk.cb24.max_frame_length[0],
5259		    ha->init_ctrl_blk.cb24.max_frame_length[1])) :
5260		    (acc.common_service.rx_bufsize = CHAR_TO_SHORT(
5261		    ha->init_ctrl_blk.cb.max_frame_length[0],
5262		    ha->init_ctrl_blk.cb.max_frame_length[1]));
5263		acc.common_service.conc_sequences = 0xff;
5264		acc.common_service.relative_offset = 0x03;
5265		acc.common_service.e_d_tov = 0x7d0;
5266		if (accept) {
5267			/* Use the saved N_Port WWNN and WWPN */
5268			if (ha->n_port != NULL) {
5269				bcopy((void *)&ha->n_port->port_name[0],
5270				    (void *)&acc.nport_ww_name.raw_wwn[0], 8);
5271				bcopy((void *)&ha->n_port->node_name[0],
5272				    (void *)&acc.node_ww_name.raw_wwn[0], 8);
5273				/* mark service options invalid */
5274				class3_param->class_valid_svc_opt = 0x0800;
5275			} else {
5276				EL(ha, "ha->n_port is NULL\n");
5277				/* Build RJT. */
5278				acc.ls_code.ls_code = LA_ELS_RJT;
5279
5280				pkt->pkt_state = FC_PKT_TRAN_ERROR;
5281				pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5282			}
5283		} else {
5284			bcopy((void *)&tq->port_name[0],
5285			    (void *)&acc.nport_ww_name.raw_wwn[0], 8);
5286			bcopy((void *)&tq->node_name[0],
5287			    (void *)&acc.node_ww_name.raw_wwn[0], 8);
5288
5289			class3_param = (class_svc_param_t *)&acc.class_3;
5290			class3_param->class_valid_svc_opt = 0x8800;
5291			class3_param->recipient_ctl = tq->class3_recipient_ctl;
5292			class3_param->rcv_data_size = tq->class3_rcv_data_size;
5293			class3_param->conc_sequences =
5294			    tq->class3_conc_sequences;
5295			class3_param->open_sequences_per_exch =
5296			    tq->class3_open_sequences_per_exch;
5297		}
5298	} else {
5299		/* Build RJT. */
5300		acc.ls_code.ls_code = LA_ELS_RJT;
5301
5302		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5303		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5304		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5305	}
5306
5307	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5308	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5309
5310	if (rval != FC_SUCCESS) {
5311		EL(ha, "failed, rval = %xh\n", rval);
5312	} else {
5313		/*EMPTY*/
5314		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5315	}
5316	return (rval);
5317}
5318
5319/*
5320 * ql_els_logo
5321 *	Issue a extended link service logout request.
5322 *
5323 * Input:
5324 *	ha = adapter state pointer.
5325 *	pkt = pointer to fc_packet.
5326 *
5327 * Returns:
5328 *	FC_SUCCESS - the packet was accepted for transport.
5329 *	FC_TRANSPORT_ERROR - a transport error occurred.
5330 *
5331 * Context:
5332 *	Kernel context.
5333 */
5334static int
5335ql_els_logo(ql_adapter_state_t *ha, fc_packet_t *pkt)
5336{
5337	port_id_t	d_id;
5338	ql_tgt_t	*tq;
5339	la_els_logo_t	acc;
5340	int		rval = FC_SUCCESS;
5341
5342	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
5343	    pkt->pkt_cmd_fhdr.d_id);
5344
5345	bzero(&acc, sizeof (acc));
5346	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5347
5348	tq = ql_d_id_to_queue(ha, d_id);
5349	if (tq) {
5350		DEVICE_QUEUE_LOCK(tq);
5351		if (tq->d_id.b24 == BROADCAST_ADDR) {
5352			DEVICE_QUEUE_UNLOCK(tq);
5353			return (FC_SUCCESS);
5354		}
5355
5356		tq->flags |= TQF_NEED_AUTHENTICATION;
5357
5358		do {
5359			DEVICE_QUEUE_UNLOCK(tq);
5360			(void) ql_abort_device(ha, tq, 1);
5361
5362			/*
5363			 * Wait for commands to drain in F/W (doesn't
5364			 * take more than a few milliseconds)
5365			 */
5366			ql_delay(ha, 10000);
5367
5368			DEVICE_QUEUE_LOCK(tq);
5369		} while (tq->outcnt);
5370
5371		DEVICE_QUEUE_UNLOCK(tq);
5372	}
5373
5374	if (ql_logout_port(ha, d_id) == QL_SUCCESS) {
5375		/* Build ACC. */
5376		acc.ls_code.ls_code = LA_ELS_ACC;
5377
5378		pkt->pkt_state = FC_PKT_SUCCESS;
5379	} else {
5380		/* Build RJT. */
5381		acc.ls_code.ls_code = LA_ELS_RJT;
5382
5383		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5384		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5385		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5386	}
5387
5388	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5389	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5390
5391	if (rval != FC_SUCCESS) {
5392		EL(ha, "failed, rval = %xh\n", rval);
5393	} else {
5394		/*EMPTY*/
5395		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5396	}
5397	return (rval);
5398}
5399
5400/*
5401 * ql_els_prli
5402 *	Issue a extended link service process login request.
5403 *
5404 * Input:
5405 *	ha = adapter state pointer.
5406 *	pkt = pointer to fc_packet.
5407 *
5408 * Returns:
5409 *	FC_SUCCESS - the packet was accepted for transport.
5410 *	FC_TRANSPORT_ERROR - a transport error occurred.
5411 *
5412 * Context:
5413 *	Kernel context.
5414 */
5415static int
5416ql_els_prli(ql_adapter_state_t *ha, fc_packet_t *pkt)
5417{
5418	ql_tgt_t		*tq;
5419	port_id_t		d_id;
5420	la_els_prli_t		acc;
5421	prli_svc_param_t	*param;
5422	ql_srb_t		*sp = (ql_srb_t *)pkt->pkt_fca_private;
5423	int			rval = FC_SUCCESS;
5424
5425	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
5426	    pkt->pkt_cmd_fhdr.d_id);
5427
5428	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5429
5430	tq = ql_d_id_to_queue(ha, d_id);
5431	if (tq != NULL) {
5432		(void) ql_get_port_database(ha, tq, PDF_NONE);
5433
5434		if ((ha->topology & QL_N_PORT) &&
5435		    (tq->master_state == PD_STATE_PLOGI_COMPLETED)) {
5436			ql_timeout_insert(ha, tq, sp);
5437			ql_start_iocb(ha, sp);
5438			rval = QL_CONSUMED;
5439		} else {
5440			/* Build ACC. */
5441			bzero(&acc, sizeof (acc));
5442			acc.ls_code = LA_ELS_ACC;
5443			acc.page_length = 0x10;
5444			acc.payload_length = tq->prli_payload_length;
5445
5446			param = (prli_svc_param_t *)&acc.service_params[0];
5447			param->type = 0x08;
5448			param->rsvd = 0x00;
5449			param->process_assoc_flags = tq->prli_svc_param_word_0;
5450			param->process_flags = tq->prli_svc_param_word_3;
5451
5452			ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5453			    (uint8_t *)pkt->pkt_resp, sizeof (acc),
5454			    DDI_DEV_AUTOINCR);
5455
5456			pkt->pkt_state = FC_PKT_SUCCESS;
5457		}
5458	} else {
5459		la_els_rjt_t rjt;
5460
5461		/* Build RJT. */
5462		bzero(&rjt, sizeof (rjt));
5463		rjt.ls_code.ls_code = LA_ELS_RJT;
5464
5465		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
5466		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
5467
5468		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5469		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5470		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5471	}
5472
5473	if ((rval != FC_SUCCESS) && (rval != QL_CONSUMED)) {
5474		EL(ha, "failed, rval = %xh\n", rval);
5475	} else {
5476		/*EMPTY*/
5477		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5478	}
5479	return (rval);
5480}
5481
5482/*
5483 * ql_els_prlo
5484 *	Issue a extended link service process logout request.
5485 *
5486 * Input:
5487 *	ha = adapter state pointer.
5488 *	pkt = pointer to fc_packet.
5489 *
5490 * Returns:
5491 *	FC_SUCCESS - the packet was accepted for transport.
5492 *	FC_TRANSPORT_ERROR - a transport error occurred.
5493 *
5494 * Context:
5495 *	Kernel context.
5496 */
5497/* ARGSUSED */
5498static int
5499ql_els_prlo(ql_adapter_state_t *ha, fc_packet_t *pkt)
5500{
5501	la_els_prli_t	acc;
5502	int		rval = FC_SUCCESS;
5503
5504	QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
5505	    pkt->pkt_cmd_fhdr.d_id);
5506
5507	/* Build ACC. */
5508	ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&acc,
5509	    (uint8_t *)pkt->pkt_cmd, sizeof (acc), DDI_DEV_AUTOINCR);
5510
5511	acc.ls_code = LA_ELS_ACC;
5512	acc.service_params[2] = 1;
5513
5514	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5515	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5516
5517	pkt->pkt_state = FC_PKT_SUCCESS;
5518
5519	if (rval != FC_SUCCESS) {
5520		EL(ha, "failed, rval = %xh\n", rval);
5521	} else {
5522		/*EMPTY*/
5523		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5524	}
5525	return (rval);
5526}
5527
5528/*
5529 * ql_els_adisc
5530 *	Issue a extended link service address discovery request.
5531 *
5532 * Input:
5533 *	ha = adapter state pointer.
5534 *	pkt = pointer to fc_packet.
5535 *
5536 * Returns:
5537 *	FC_SUCCESS - the packet was accepted for transport.
5538 *	FC_TRANSPORT_ERROR - a transport error occurred.
5539 *
5540 * Context:
5541 *	Kernel context.
5542 */
5543static int
5544ql_els_adisc(ql_adapter_state_t *ha, fc_packet_t *pkt)
5545{
5546	ql_dev_id_list_t	*list;
5547	uint32_t		list_size;
5548	ql_link_t		*link;
5549	ql_tgt_t		*tq;
5550	ql_lun_t		*lq;
5551	port_id_t		d_id;
5552	la_els_adisc_t		acc;
5553	uint16_t		index, loop_id;
5554	ql_mbx_data_t		mr;
5555	int			rval = FC_SUCCESS;
5556
5557	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
5558
5559	bzero(&acc, sizeof (acc));
5560	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5561
5562	/*
5563	 * MBC_GET_PORT_DATABASE causes ADISC to go out to
5564	 * the device from the firmware
5565	 */
5566	index = ql_alpa_to_index[d_id.b.al_pa];
5567	tq = NULL;
5568	for (link = ha->dev[index].first; link != NULL; link = link->next) {
5569		tq = link->base_address;
5570		if (tq->d_id.b24 == d_id.b24) {
5571			break;
5572		} else {
5573			tq = NULL;
5574		}
5575	}
5576
5577	if ((tq != NULL) && (!VALID_DEVICE_ID(ha, tq->loop_id))) {
5578		list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
5579		list = (ql_dev_id_list_t *)kmem_zalloc(list_size, KM_SLEEP);
5580
5581		if (list != NULL &&
5582		    ql_get_id_list(ha, (caddr_t)list, list_size, &mr) ==
5583		    QL_SUCCESS) {
5584
5585			for (index = 0; index < mr.mb[1]; index++) {
5586				ql_dev_list(ha, list, index, &d_id, &loop_id);
5587
5588				if (tq->d_id.b24 == d_id.b24) {
5589					tq->loop_id = loop_id;
5590					break;
5591				}
5592			}
5593		} else {
5594			cmn_err(CE_WARN, "!%s(%d) didn't get list for %xh",
5595			    QL_NAME, ha->instance, d_id.b24);
5596			tq = NULL;
5597		}
5598		if ((tq != NULL) && (!VALID_DEVICE_ID(ha, tq->loop_id))) {
5599			cmn_err(CE_WARN, "!%s(%d) no loop_id for adisc %xh",
5600			    QL_NAME, ha->instance, tq->d_id.b24);
5601			tq = NULL;
5602		}
5603
5604		if (list != NULL) {
5605			kmem_free(list, list_size);
5606		}
5607	}
5608
5609	if ((tq != NULL) && (VALID_DEVICE_ID(ha, tq->loop_id)) &&
5610	    ql_get_port_database(ha, tq, PDF_ADISC) == QL_SUCCESS) {
5611
5612		/* Build ACC. */
5613
5614		DEVICE_QUEUE_LOCK(tq);
5615		tq->flags &= ~TQF_NEED_AUTHENTICATION;
5616		if (tq->prli_svc_param_word_3 & PRLI_W3_RETRY) {
5617			for (link = tq->lun_queues.first; link != NULL;
5618			    link = link->next) {
5619				lq = link->base_address;
5620
5621				if (lq->cmd.first != NULL) {
5622					ql_next(ha, lq);
5623					DEVICE_QUEUE_LOCK(tq);
5624				}
5625			}
5626		}
5627		DEVICE_QUEUE_UNLOCK(tq);
5628
5629		acc.ls_code.ls_code = LA_ELS_ACC;
5630		acc.hard_addr.hard_addr = tq->hard_addr.b24;
5631
5632		bcopy((void *)&tq->port_name[0],
5633		    (void *)&acc.port_wwn.raw_wwn[0], 8);
5634		bcopy((void *)&tq->node_name[0],
5635		    (void *)&acc.node_wwn.raw_wwn[0], 8);
5636
5637		acc.nport_id.port_id = tq->d_id.b24;
5638
5639		pkt->pkt_state = FC_PKT_SUCCESS;
5640	} else {
5641		/* Build RJT. */
5642		acc.ls_code.ls_code = LA_ELS_RJT;
5643
5644		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5645		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5646		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5647	}
5648
5649	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5650	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5651
5652	if (rval != FC_SUCCESS) {
5653		EL(ha, "failed, rval = %xh\n", rval);
5654	} else {
5655		/*EMPTY*/
5656		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5657	}
5658	return (rval);
5659}
5660
5661/*
5662 * ql_els_linit
5663 *	Issue a extended link service loop initialize request.
5664 *
5665 * Input:
5666 *	ha = adapter state pointer.
5667 *	pkt = pointer to fc_packet.
5668 *
5669 * Returns:
5670 *	FC_SUCCESS - the packet was accepted for transport.
5671 *	FC_TRANSPORT_ERROR - a transport error occurred.
5672 *
5673 * Context:
5674 *	Kernel context.
5675 */
5676static int
5677ql_els_linit(ql_adapter_state_t *ha, fc_packet_t *pkt)
5678{
5679	ddi_dma_cookie_t	*cp;
5680	uint32_t		cnt;
5681	conv_num_t		n;
5682	port_id_t		d_id;
5683	int			rval = FC_SUCCESS;
5684
5685	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
5686
5687	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5688	if (ha->topology & QL_SNS_CONNECTION) {
5689		fc_linit_req_t els;
5690		lfa_cmd_t lfa;
5691
5692		ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
5693		    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
5694
5695		/* Setup LFA mailbox command data. */
5696		bzero((void *)&lfa, sizeof (lfa_cmd_t));
5697
5698		lfa.resp_buffer_length[0] = 4;
5699
5700		cp = pkt->pkt_resp_cookie;
5701		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
5702			n.size64 = (uint64_t)cp->dmac_laddress;
5703			LITTLE_ENDIAN_64(&n.size64);
5704		} else {
5705			n.size32[0] = LSD(cp->dmac_laddress);
5706			LITTLE_ENDIAN_32(&n.size32[0]);
5707			n.size32[1] = MSD(cp->dmac_laddress);
5708			LITTLE_ENDIAN_32(&n.size32[1]);
5709		}
5710
5711		/* Set buffer address. */
5712		for (cnt = 0; cnt < 8; cnt++) {
5713			lfa.resp_buffer_address[cnt] = n.size8[cnt];
5714		}
5715
5716		lfa.subcommand_length[0] = 4;
5717		n.size32[0] = d_id.b24;
5718		LITTLE_ENDIAN_32(&n.size32[0]);
5719		lfa.addr[0] = n.size8[0];
5720		lfa.addr[1] = n.size8[1];
5721		lfa.addr[2] = n.size8[2];
5722		lfa.subcommand[1] = 0x70;
5723		lfa.payload[2] = els.func;
5724		lfa.payload[4] = els.lip_b3;
5725		lfa.payload[5] = els.lip_b4;
5726
5727		if (ql_send_lfa(ha, &lfa) != QL_SUCCESS) {
5728			pkt->pkt_state = FC_PKT_TRAN_ERROR;
5729		} else {
5730			pkt->pkt_state = FC_PKT_SUCCESS;
5731		}
5732	} else {
5733		fc_linit_resp_t rjt;
5734
5735		/* Build RJT. */
5736		bzero(&rjt, sizeof (rjt));
5737		rjt.ls_code.ls_code = LA_ELS_RJT;
5738
5739		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
5740		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
5741
5742		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5743		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5744		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5745	}
5746
5747	if (rval != FC_SUCCESS) {
5748		EL(ha, "failed, rval = %xh\n", rval);
5749	} else {
5750		/*EMPTY*/
5751		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5752	}
5753	return (rval);
5754}
5755
5756/*
5757 * ql_els_lpc
5758 *	Issue a extended link service loop control request.
5759 *
5760 * Input:
5761 *	ha = adapter state pointer.
5762 *	pkt = pointer to fc_packet.
5763 *
5764 * Returns:
5765 *	FC_SUCCESS - the packet was accepted for transport.
5766 *	FC_TRANSPORT_ERROR - a transport error occurred.
5767 *
5768 * Context:
5769 *	Kernel context.
5770 */
5771static int
5772ql_els_lpc(ql_adapter_state_t *ha, fc_packet_t *pkt)
5773{
5774	ddi_dma_cookie_t	*cp;
5775	uint32_t		cnt;
5776	conv_num_t		n;
5777	port_id_t		d_id;
5778	int			rval = FC_SUCCESS;
5779
5780	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
5781
5782	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5783	if (ha->topology & QL_SNS_CONNECTION) {
5784		ql_lpc_t els;
5785		lfa_cmd_t lfa;
5786
5787		ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
5788		    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
5789
5790		/* Setup LFA mailbox command data. */
5791		bzero((void *)&lfa, sizeof (lfa_cmd_t));
5792
5793		lfa.resp_buffer_length[0] = 4;
5794
5795		cp = pkt->pkt_resp_cookie;
5796		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
5797			n.size64 = (uint64_t)(cp->dmac_laddress);
5798			LITTLE_ENDIAN_64(&n.size64);
5799		} else {
5800			n.size32[0] = cp->dmac_address;
5801			LITTLE_ENDIAN_32(&n.size32[0]);
5802			n.size32[1] = 0;
5803		}
5804
5805		/* Set buffer address. */
5806		for (cnt = 0; cnt < 8; cnt++) {
5807			lfa.resp_buffer_address[cnt] = n.size8[cnt];
5808		}
5809
5810		lfa.subcommand_length[0] = 20;
5811		n.size32[0] = d_id.b24;
5812		LITTLE_ENDIAN_32(&n.size32[0]);
5813		lfa.addr[0] = n.size8[0];
5814		lfa.addr[1] = n.size8[1];
5815		lfa.addr[2] = n.size8[2];
5816		lfa.subcommand[1] = 0x71;
5817		lfa.payload[4] = els.port_control;
5818		bcopy((void *)&els.lpb[0], (void *)&lfa.payload[6], 32);
5819
5820		if (ql_send_lfa(ha, &lfa) != QL_SUCCESS) {
5821			pkt->pkt_state = FC_PKT_TRAN_ERROR;
5822		} else {
5823			pkt->pkt_state = FC_PKT_SUCCESS;
5824		}
5825	} else {
5826		ql_lpc_resp_t rjt;
5827
5828		/* Build RJT. */
5829		bzero(&rjt, sizeof (rjt));
5830		rjt.ls_code.ls_code = LA_ELS_RJT;
5831
5832		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
5833		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
5834
5835		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5836		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5837		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5838	}
5839
5840	if (rval != FC_SUCCESS) {
5841		EL(ha, "failed, rval = %xh\n", rval);
5842	} else {
5843		/*EMPTY*/
5844		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5845	}
5846	return (rval);
5847}
5848
5849/*
5850 * ql_els_lsts
5851 *	Issue a extended link service loop status request.
5852 *
5853 * Input:
5854 *	ha = adapter state pointer.
5855 *	pkt = pointer to fc_packet.
5856 *
5857 * Returns:
5858 *	FC_SUCCESS - the packet was accepted for transport.
5859 *	FC_TRANSPORT_ERROR - a transport error occurred.
5860 *
5861 * Context:
5862 *	Kernel context.
5863 */
5864static int
5865ql_els_lsts(ql_adapter_state_t *ha, fc_packet_t *pkt)
5866{
5867	ddi_dma_cookie_t	*cp;
5868	uint32_t		cnt;
5869	conv_num_t		n;
5870	port_id_t		d_id;
5871	int			rval = FC_SUCCESS;
5872
5873	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
5874
5875	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
5876	if (ha->topology & QL_SNS_CONNECTION) {
5877		fc_lsts_req_t els;
5878		lfa_cmd_t lfa;
5879
5880		ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
5881		    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
5882
5883		/* Setup LFA mailbox command data. */
5884		bzero((void *)&lfa, sizeof (lfa_cmd_t));
5885
5886		lfa.resp_buffer_length[0] = 84;
5887
5888		cp = pkt->pkt_resp_cookie;
5889		if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
5890			n.size64 = cp->dmac_laddress;
5891			LITTLE_ENDIAN_64(&n.size64);
5892		} else {
5893			n.size32[0] = cp->dmac_address;
5894			LITTLE_ENDIAN_32(&n.size32[0]);
5895			n.size32[1] = 0;
5896		}
5897
5898		/* Set buffer address. */
5899		for (cnt = 0; cnt < 8; cnt++) {
5900			lfa.resp_buffer_address[cnt] = n.size8[cnt];
5901		}
5902
5903		lfa.subcommand_length[0] = 2;
5904		n.size32[0] = d_id.b24;
5905		LITTLE_ENDIAN_32(&n.size32[0]);
5906		lfa.addr[0] = n.size8[0];
5907		lfa.addr[1] = n.size8[1];
5908		lfa.addr[2] = n.size8[2];
5909		lfa.subcommand[1] = 0x72;
5910
5911		if (ql_send_lfa(ha, &lfa) != QL_SUCCESS) {
5912			pkt->pkt_state = FC_PKT_TRAN_ERROR;
5913		} else {
5914			pkt->pkt_state = FC_PKT_SUCCESS;
5915		}
5916	} else {
5917		fc_lsts_resp_t rjt;
5918
5919		/* Build RJT. */
5920		bzero(&rjt, sizeof (rjt));
5921		rjt.lsts_ls_code.ls_code = LA_ELS_RJT;
5922
5923		ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
5924		    (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
5925
5926		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5927		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5928		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5929	}
5930
5931	if (rval != FC_SUCCESS) {
5932		EL(ha, "failed=%xh\n", rval);
5933	} else {
5934		/*EMPTY*/
5935		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
5936	}
5937	return (rval);
5938}
5939
5940/*
5941 * ql_els_scr
5942 *	Issue a extended link service state change registration request.
5943 *
5944 * Input:
5945 *	ha = adapter state pointer.
5946 *	pkt = pointer to fc_packet.
5947 *
5948 * Returns:
5949 *	FC_SUCCESS - the packet was accepted for transport.
5950 *	FC_TRANSPORT_ERROR - a transport error occurred.
5951 *
5952 * Context:
5953 *	Kernel context.
5954 */
5955static int
5956ql_els_scr(ql_adapter_state_t *ha, fc_packet_t *pkt)
5957{
5958	fc_scr_resp_t	acc;
5959	int		rval = FC_SUCCESS;
5960
5961	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
5962
5963	bzero(&acc, sizeof (acc));
5964	if (ha->topology & QL_SNS_CONNECTION) {
5965		fc_scr_req_t els;
5966
5967		ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
5968		    (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
5969
5970		if (ql_send_change_request(ha, els.scr_func) ==
5971		    QL_SUCCESS) {
5972			/* Build ACC. */
5973			acc.scr_acc = LA_ELS_ACC;
5974
5975			pkt->pkt_state = FC_PKT_SUCCESS;
5976		} else {
5977			/* Build RJT. */
5978			acc.scr_acc = LA_ELS_RJT;
5979
5980			pkt->pkt_state = FC_PKT_TRAN_ERROR;
5981			pkt->pkt_reason = FC_REASON_HW_ERROR;
5982			EL(ha, "LA_ELS_RJT, FC_REASON_HW_ERROR\n");
5983		}
5984	} else {
5985		/* Build RJT. */
5986		acc.scr_acc = LA_ELS_RJT;
5987
5988		pkt->pkt_state = FC_PKT_TRAN_ERROR;
5989		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
5990		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
5991	}
5992
5993	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
5994	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
5995
5996	if (rval != FC_SUCCESS) {
5997		EL(ha, "failed, rval = %xh\n", rval);
5998	} else {
5999		/*EMPTY*/
6000		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6001	}
6002	return (rval);
6003}
6004
6005/*
6006 * ql_els_rscn
6007 *	Issue a extended link service register state
6008 *	change notification request.
6009 *
6010 * Input:
6011 *	ha = adapter state pointer.
6012 *	pkt = pointer to fc_packet.
6013 *
6014 * Returns:
6015 *	FC_SUCCESS - the packet was accepted for transport.
6016 *	FC_TRANSPORT_ERROR - a transport error occurred.
6017 *
6018 * Context:
6019 *	Kernel context.
6020 */
6021static int
6022ql_els_rscn(ql_adapter_state_t *ha, fc_packet_t *pkt)
6023{
6024	ql_rscn_resp_t	acc;
6025	int		rval = FC_SUCCESS;
6026
6027	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6028
6029	bzero(&acc, sizeof (acc));
6030	if (ha->topology & QL_SNS_CONNECTION) {
6031		/* Build ACC. */
6032		acc.scr_acc = LA_ELS_ACC;
6033
6034		pkt->pkt_state = FC_PKT_SUCCESS;
6035	} else {
6036		/* Build RJT. */
6037		acc.scr_acc = LA_ELS_RJT;
6038
6039		pkt->pkt_state = FC_PKT_TRAN_ERROR;
6040		pkt->pkt_reason = FC_REASON_NO_CONNECTION;
6041		EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
6042	}
6043
6044	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
6045	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
6046
6047	if (rval != FC_SUCCESS) {
6048		EL(ha, "failed, rval = %xh\n", rval);
6049	} else {
6050		/*EMPTY*/
6051		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6052	}
6053	return (rval);
6054}
6055
6056/*
6057 * ql_els_farp_req
6058 *	Issue FC Address Resolution Protocol (FARP)
6059 *	extended link service request.
6060 *
6061 *	Note: not supported.
6062 *
6063 * Input:
6064 *	ha = adapter state pointer.
6065 *	pkt = pointer to fc_packet.
6066 *
6067 * Returns:
6068 *	FC_SUCCESS - the packet was accepted for transport.
6069 *	FC_TRANSPORT_ERROR - a transport error occurred.
6070 *
6071 * Context:
6072 *	Kernel context.
6073 */
6074static int
6075ql_els_farp_req(ql_adapter_state_t *ha, fc_packet_t *pkt)
6076{
6077	ql_acc_rjt_t	acc;
6078	int		rval = FC_SUCCESS;
6079
6080	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6081
6082	bzero(&acc, sizeof (acc));
6083
6084	/* Build ACC. */
6085	acc.ls_code.ls_code = LA_ELS_ACC;
6086
6087	pkt->pkt_state = FC_PKT_SUCCESS;
6088
6089	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
6090	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
6091
6092	if (rval != FC_SUCCESS) {
6093		EL(ha, "failed, rval = %xh\n", rval);
6094	} else {
6095		/*EMPTY*/
6096		QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6097	}
6098	return (rval);
6099}
6100
6101/*
6102 * ql_els_farp_reply
6103 *	Issue FC Address Resolution Protocol (FARP)
6104 *	extended link service reply.
6105 *
6106 *	Note: not supported.
6107 *
6108 * Input:
6109 *	ha = adapter state pointer.
6110 *	pkt = pointer to fc_packet.
6111 *
6112 * Returns:
6113 *	FC_SUCCESS - the packet was accepted for transport.
6114 *	FC_TRANSPORT_ERROR - a transport error occurred.
6115 *
6116 * Context:
6117 *	Kernel context.
6118 */
6119/* ARGSUSED */
6120static int
6121ql_els_farp_reply(ql_adapter_state_t *ha, fc_packet_t *pkt)
6122{
6123	ql_acc_rjt_t	acc;
6124	int		rval = FC_SUCCESS;
6125
6126	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6127
6128	bzero(&acc, sizeof (acc));
6129
6130	/* Build ACC. */
6131	acc.ls_code.ls_code = LA_ELS_ACC;
6132
6133	pkt->pkt_state = FC_PKT_SUCCESS;
6134
6135	ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
6136	    (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
6137
6138	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
6139
6140	return (rval);
6141}
6142
6143static int
6144ql_els_rnid(ql_adapter_state_t *ha, fc_packet_t *pkt)
6145{
6146	uchar_t			*rnid_acc;
6147	port_id_t		d_id;
6148	ql_link_t		*link;
6149	ql_tgt_t		*tq;
6150	uint16_t		index;
6151	la_els_rnid_acc_t	acc;
6152	la_els_rnid_t		*req;
6153	size_t			req_len;
6154
6155	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
6156
6157	req_len =  FCIO_RNID_MAX_DATA_LEN + sizeof (fc_rnid_hdr_t);
6158	d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
6159	index = ql_alpa_to_index[d_id.b.al_pa];
6160
6161	tq = NULL;
6162	for (link = ha->dev[index].first; link != NULL; link = link->next) {
6163		tq = link->base_address;
6164		if (tq->d_id.b24 == d_id.b24) {
6165			break;