1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22c1fad183SDaniel Beauregard /* Copyright 2010 QLogic Corporation */
23fcf3ce44SJohn Forte 
24fcf3ce44SJohn Forte /*
25f885d00fSDaniel Beauregard  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26fcf3ce44SJohn Forte  */
27db5b5f1eSGarrett D'Amore /*
28db5b5f1eSGarrett D'Amore  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2948bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
30db5b5f1eSGarrett D'Amore  */
31fcf3ce44SJohn Forte 
32c1fad183SDaniel Beauregard #pragma ident	"Copyright 2010 QLogic Corporation; ql_api.c"
33fcf3ce44SJohn Forte 
34fcf3ce44SJohn Forte /*
35fcf3ce44SJohn Forte  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
36fcf3ce44SJohn Forte  *
37fcf3ce44SJohn Forte  * ***********************************************************************
38fcf3ce44SJohn Forte  * *									**
39fcf3ce44SJohn Forte  * *				NOTICE					**
40c1fad183SDaniel Beauregard  * *		COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION		**
41fcf3ce44SJohn Forte  * *			ALL RIGHTS RESERVED				**
42fcf3ce44SJohn Forte  * *									**
43fcf3ce44SJohn Forte  * ***********************************************************************
44fcf3ce44SJohn Forte  *
45fcf3ce44SJohn Forte  */
46fcf3ce44SJohn Forte 
47fcf3ce44SJohn Forte #include <ql_apps.h>
48fcf3ce44SJohn Forte #include <ql_api.h>
49fcf3ce44SJohn Forte #include <ql_debug.h>
50fcf3ce44SJohn Forte #include <ql_init.h>
51fcf3ce44SJohn Forte #include <ql_iocb.h>
52fcf3ce44SJohn Forte #include <ql_ioctl.h>
53fcf3ce44SJohn Forte #include <ql_isr.h>
54fcf3ce44SJohn Forte #include <ql_mbx.h>
55eb82ff87SDaniel Beauregard #include <ql_nx.h>
56fcf3ce44SJohn Forte #include <ql_xioctl.h>
57fcf3ce44SJohn Forte 
58fcf3ce44SJohn Forte /*
59fcf3ce44SJohn Forte  * Solaris external defines.
60fcf3ce44SJohn Forte  */
61fcf3ce44SJohn Forte extern pri_t minclsyspri;
62fcf3ce44SJohn Forte extern pri_t maxclsyspri;
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte /*
65fcf3ce44SJohn Forte  * dev_ops functions prototypes
66fcf3ce44SJohn Forte  */
67fcf3ce44SJohn Forte static int ql_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
68fcf3ce44SJohn Forte static int ql_attach(dev_info_t *, ddi_attach_cmd_t);
69fcf3ce44SJohn Forte static int ql_detach(dev_info_t *, ddi_detach_cmd_t);
70fcf3ce44SJohn Forte static int ql_power(dev_info_t *, int, int);
7116dd44c2SDaniel Beauregard static int ql_quiesce(dev_info_t *);
72fcf3ce44SJohn Forte 
73fcf3ce44SJohn Forte /*
74fcf3ce44SJohn Forte  * FCA functions prototypes exported by means of the transport table
75fcf3ce44SJohn Forte  */
76fcf3ce44SJohn Forte static opaque_t ql_bind_port(dev_info_t *, fc_fca_port_info_t *,
77fcf3ce44SJohn Forte     fc_fca_bind_info_t *);
78fcf3ce44SJohn Forte static void ql_unbind_port(opaque_t);
79fcf3ce44SJohn Forte static int ql_init_pkt(opaque_t, fc_packet_t *, int);
80fcf3ce44SJohn Forte static int ql_un_init_pkt(opaque_t, fc_packet_t *);
81fcf3ce44SJohn Forte static int ql_els_send(opaque_t, fc_packet_t *);
82fcf3ce44SJohn Forte static int ql_get_cap(opaque_t, char *, void *);
83fcf3ce44SJohn Forte static int ql_set_cap(opaque_t, char *, void *);
84fcf3ce44SJohn Forte static int ql_getmap(opaque_t, fc_lilpmap_t *);
85fcf3ce44SJohn Forte static int ql_transport(opaque_t, fc_packet_t *);
86fcf3ce44SJohn Forte static int ql_ub_alloc(opaque_t, uint64_t *, uint32_t, uint32_t *, uint32_t);
87fcf3ce44SJohn Forte static int ql_ub_free(opaque_t, uint32_t, uint64_t *);
88fcf3ce44SJohn Forte static int ql_ub_release(opaque_t, uint32_t, uint64_t *);
89fcf3ce44SJohn Forte static int ql_abort(opaque_t, fc_packet_t *, int);
90fcf3ce44SJohn Forte static int ql_reset(opaque_t, uint32_t);
91fcf3ce44SJohn Forte static int ql_port_manage(opaque_t, fc_fca_pm_t *);
92fcf3ce44SJohn Forte static opaque_t ql_get_device(opaque_t, fc_portid_t);
93fcf3ce44SJohn Forte 
94fcf3ce44SJohn Forte /*
95fcf3ce44SJohn Forte  * FCA Driver Support Function Prototypes.
96fcf3ce44SJohn Forte  */
97fcf3ce44SJohn Forte static uint16_t	ql_wait_outstanding(ql_adapter_state_t *);
98fcf3ce44SJohn Forte static void ql_task_mgmt(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
99fcf3ce44SJohn Forte     ql_srb_t *);
100fcf3ce44SJohn Forte static void ql_task_daemon(void *);
101fcf3ce44SJohn Forte static void ql_task_thread(ql_adapter_state_t *);
102fcf3ce44SJohn Forte static void ql_unsol_callback(ql_srb_t *);
103fcf3ce44SJohn Forte static void ql_free_unsolicited_buffer(ql_adapter_state_t *,
104fcf3ce44SJohn Forte     fc_unsol_buf_t *);
105fcf3ce44SJohn Forte static void ql_timer(void *);
106fcf3ce44SJohn Forte static void ql_watchdog(ql_adapter_state_t *, uint32_t *, uint32_t *);
107fcf3ce44SJohn Forte static void ql_cmd_timeout(ql_adapter_state_t *, ql_tgt_t *q, ql_srb_t *,
108fcf3ce44SJohn Forte     uint32_t *, uint32_t *);
109fcf3ce44SJohn Forte static void ql_halt(ql_adapter_state_t *, int);
110fcf3ce44SJohn Forte static int ql_els_plogi(ql_adapter_state_t *, fc_packet_t *);
111fcf3ce44SJohn Forte static int ql_els_flogi(ql_adapter_state_t *, fc_packet_t *);
112fcf3ce44SJohn Forte static int ql_els_logo(ql_adapter_state_t *, fc_packet_t *);
113fcf3ce44SJohn Forte static int ql_els_prli(ql_adapter_state_t *, fc_packet_t *);
114fcf3ce44SJohn Forte static int ql_els_prlo(ql_adapter_state_t *, fc_packet_t *);
115fcf3ce44SJohn Forte static int ql_els_adisc(ql_adapter_state_t *, fc_packet_t *);
116fcf3ce44SJohn Forte static int ql_els_linit(ql_adapter_state_t *, fc_packet_t *);
117fcf3ce44SJohn Forte static int ql_els_lpc(ql_adapter_state_t *, fc_packet_t *);
118fcf3ce44SJohn Forte static int ql_els_lsts(ql_adapter_state_t *, fc_packet_t *);
119fcf3ce44SJohn Forte static int ql_els_scr(ql_adapter_state_t *, fc_packet_t *);
120fcf3ce44SJohn Forte static int ql_els_rscn(ql_adapter_state_t *, fc_packet_t *);
121fcf3ce44SJohn Forte static int ql_els_farp_req(ql_adapter_state_t *, fc_packet_t *);
122fcf3ce44SJohn Forte static int ql_els_farp_reply(ql_adapter_state_t *, fc_packet_t *);
123fcf3ce44SJohn Forte static int ql_els_rls(ql_adapter_state_t *, fc_packet_t *);
124fcf3ce44SJohn Forte static int ql_els_rnid(ql_adapter_state_t *, fc_packet_t *);
125fcf3ce44SJohn Forte static int ql_login_port(ql_adapter_state_t *, port_id_t);
126fcf3ce44SJohn Forte static int ql_login_fabric_port(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
127fcf3ce44SJohn Forte static int ql_logout_port(ql_adapter_state_t *, port_id_t);
128fcf3ce44SJohn Forte static ql_lun_t *ql_lun_queue(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
129fcf3ce44SJohn Forte static int ql_fcp_scsi_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
130fcf3ce44SJohn Forte static int ql_fcp_ip_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
131fcf3ce44SJohn Forte static int ql_fc_services(ql_adapter_state_t *, fc_packet_t *);
132fcf3ce44SJohn Forte static int ql_poll_cmd(ql_adapter_state_t *, ql_srb_t *, time_t);
133fcf3ce44SJohn Forte static int ql_start_cmd(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
134fcf3ce44SJohn Forte     ql_srb_t *);
135fcf3ce44SJohn Forte static int ql_kstat_update(kstat_t *, int);
136fcf3ce44SJohn Forte static ql_adapter_state_t *ql_fca_handle_to_state(opaque_t);
137fcf3ce44SJohn Forte static ql_adapter_state_t *ql_cmd_setup(opaque_t, fc_packet_t *, int *);
138fcf3ce44SJohn Forte static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, uint8_t);
139fcf3ce44SJohn Forte static void ql_rst_aen(ql_adapter_state_t *);
140fcf3ce44SJohn Forte static void ql_restart_queues(ql_adapter_state_t *);
141fcf3ce44SJohn Forte static void ql_abort_queues(ql_adapter_state_t *);
1424f8b8adcSDaniel Beauregard static void ql_abort_device_queues(ql_adapter_state_t *ha, ql_tgt_t *tq);
143fcf3ce44SJohn Forte static void ql_idle_check(ql_adapter_state_t *);
144fcf3ce44SJohn Forte static int ql_loop_resync(ql_adapter_state_t *);
145fcf3ce44SJohn Forte static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
146f33c1cdbSDaniel Beauregard static size_t ql_2581_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
147fcf3ce44SJohn Forte static int ql_save_config_regs(dev_info_t *);
148fcf3ce44SJohn Forte static int ql_restore_config_regs(dev_info_t *);
149fcf3ce44SJohn Forte static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
150fcf3ce44SJohn Forte static int ql_handle_rscn_update(ql_adapter_state_t *);
151fcf3ce44SJohn Forte static int ql_send_plogi(ql_adapter_state_t *, ql_tgt_t *, ql_head_t *);
152fcf3ce44SJohn Forte static int ql_process_rscn_for_device(ql_adapter_state_t *, ql_tgt_t *);
153fcf3ce44SJohn Forte static int ql_dump_firmware(ql_adapter_state_t *);
154fcf3ce44SJohn Forte static int ql_process_logo_for_device(ql_adapter_state_t *, ql_tgt_t *);
155fcf3ce44SJohn Forte static int ql_2200_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
156fcf3ce44SJohn Forte static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
157fcf3ce44SJohn Forte static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
158fcf3ce44SJohn Forte static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
159f33c1cdbSDaniel Beauregard static int ql_81xx_binary_fw_dump(ql_adapter_state_t *, ql_81xx_fw_dump_t *);
160fcf3ce44SJohn Forte static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
161fcf3ce44SJohn Forte     void *);
162fcf3ce44SJohn Forte static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
163fcf3ce44SJohn Forte     uint8_t);
164fcf3ce44SJohn Forte static int ql_busy_plogi(ql_adapter_state_t *, fc_packet_t *, ql_tgt_t *);
165fcf3ce44SJohn Forte static int ql_suspend_adapter(ql_adapter_state_t *);
166fcf3ce44SJohn Forte static int ql_bstr_to_dec(char *, uint32_t *, uint32_t);
167fcf3ce44SJohn Forte static void ql_update_rscn(ql_adapter_state_t *, fc_affected_id_t *);
168fcf3ce44SJohn Forte int ql_alloc_dma_resouce(ql_adapter_state_t *, dma_mem_t *, int);
169fcf3ce44SJohn Forte static int ql_bind_dma_buffer(ql_adapter_state_t *, dma_mem_t *, int);
170fcf3ce44SJohn Forte static void ql_unbind_dma_buffer(ql_adapter_state_t *, dma_mem_t *);
171fcf3ce44SJohn Forte static void ql_timeout_insert(ql_adapter_state_t *, ql_tgt_t *, ql_srb_t *);
172fcf3ce44SJohn Forte static int ql_setup_interrupts(ql_adapter_state_t *);
173fcf3ce44SJohn Forte static int ql_setup_msi(ql_adapter_state_t *);
174fcf3ce44SJohn Forte static int ql_setup_msix(ql_adapter_state_t *);
175fcf3ce44SJohn Forte static int ql_setup_fixed(ql_adapter_state_t *);
176fcf3ce44SJohn Forte static void ql_release_intr(ql_adapter_state_t *);
177fcf3ce44SJohn Forte static void ql_disable_intr(ql_adapter_state_t *);
178fcf3ce44SJohn Forte static int ql_legacy_intr(ql_adapter_state_t *);
179fcf3ce44SJohn Forte static int ql_init_mutex(ql_adapter_state_t *);
180fcf3ce44SJohn Forte static void ql_destroy_mutex(ql_adapter_state_t *);
181fcf3ce44SJohn Forte static void ql_iidma(ql_adapter_state_t *);
182fcf3ce44SJohn Forte 
1835dfd244aSDaniel Beauregard static int ql_n_port_plogi(ql_adapter_state_t *);
1845dfd244aSDaniel Beauregard static void ql_fca_isp_els_request(ql_adapter_state_t *, fc_packet_t *,
1855dfd244aSDaniel Beauregard     els_descriptor_t *);
1865dfd244aSDaniel Beauregard static void ql_isp_els_request_ctor(els_descriptor_t *,
1875dfd244aSDaniel Beauregard     els_passthru_entry_t *);
1885dfd244aSDaniel Beauregard static int ql_p2p_plogi(ql_adapter_state_t *, fc_packet_t *);
189f885d00fSDaniel Beauregard static int ql_wait_for_td_stop(ql_adapter_state_t *);
190f885d00fSDaniel Beauregard static void ql_process_idc_event(ql_adapter_state_t *);
191a2b3ff35SDaniel Beauregard 
192fcf3ce44SJohn Forte /*
193fcf3ce44SJohn Forte  * Global data
194fcf3ce44SJohn Forte  */
195fcf3ce44SJohn Forte static uint8_t	ql_enable_pm = 1;
196fcf3ce44SJohn Forte static int	ql_flash_sbus_fpga = 0;
197fcf3ce44SJohn Forte uint32_t	ql_os_release_level;
198fcf3ce44SJohn Forte uint32_t	ql_disable_aif = 0;
199fcf3ce44SJohn Forte uint32_t	ql_disable_msi = 0;
200fcf3ce44SJohn Forte uint32_t	ql_disable_msix = 0;
201f885d00fSDaniel Beauregard uint32_t	ql_enable_ets = 0;
202f885d00fSDaniel Beauregard uint16_t	ql_osc_wait_count = 1000;
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte /* Timer routine variables. */
205fcf3ce44SJohn Forte static timeout_id_t	ql_timer_timeout_id = NULL;
206fcf3ce44SJohn Forte static clock_t		ql_timer_ticks;
207fcf3ce44SJohn Forte 
208fcf3ce44SJohn Forte /* Soft state head pointer. */
209fcf3ce44SJohn Forte void *ql_state = NULL;
210fcf3ce44SJohn Forte 
211fcf3ce44SJohn Forte /* Head adapter link. */
212fcf3ce44SJohn Forte ql_head_t ql_hba = {
213fcf3ce44SJohn Forte 	NULL,
214fcf3ce44SJohn Forte 	NULL
215fcf3ce44SJohn Forte };
216fcf3ce44SJohn Forte 
217fcf3ce44SJohn Forte /* Global hba index */
218fcf3ce44SJohn Forte uint32_t ql_gfru_hba_index = 1;
219fcf3ce44SJohn Forte 
220fcf3ce44SJohn Forte /*
221fcf3ce44SJohn Forte  * Some IP defines and globals
222fcf3ce44SJohn Forte  */
223fcf3ce44SJohn Forte uint32_t	ql_ip_buffer_count = 128;
224fcf3ce44SJohn Forte uint32_t	ql_ip_low_water = 10;
225fcf3ce44SJohn Forte uint8_t		ql_ip_fast_post_count = 5;
226fcf3ce44SJohn Forte static int	ql_ip_mtu = 65280;		/* equivalent to FCIPMTU */
227fcf3ce44SJohn Forte 
228fcf3ce44SJohn Forte /* Device AL_PA to Device Head Queue index array. */
229fcf3ce44SJohn Forte uint8_t ql_alpa_to_index[] = {
230fcf3ce44SJohn Forte 	0x7e, 0x7d, 0x7c, 0x00, 0x7b, 0x01, 0x02, 0x03, 0x7a, 0x04,
231fcf3ce44SJohn Forte 	0x05, 0x06, 0x07, 0x08, 0x09, 0x79, 0x78, 0x0a, 0x0b, 0x0c,
232fcf3ce44SJohn Forte 	0x0d, 0x0e, 0x0f, 0x77, 0x76, 0x10, 0x11, 0x75, 0x12, 0x74,
233fcf3ce44SJohn Forte 	0x73, 0x72, 0x13, 0x14, 0x15, 0x71, 0x16, 0x70, 0x6f, 0x6e,
234fcf3ce44SJohn Forte 	0x17, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x18, 0x19, 0x67,
235fcf3ce44SJohn Forte 	0x66, 0x65, 0x64, 0x63, 0x62, 0x20, 0x21, 0x61, 0x60, 0x23,
236fcf3ce44SJohn Forte 	0x5f, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x5e, 0x2a, 0x5d,
237fcf3ce44SJohn Forte 	0x5c, 0x5b, 0x2b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x2c,
238fcf3ce44SJohn Forte 	0x2d, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x2e, 0x2f, 0x4e,
239fcf3ce44SJohn Forte 	0x4d, 0x30, 0x4c, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x4b,
240fcf3ce44SJohn Forte 	0x37, 0x4a, 0x49, 0x48, 0x38, 0x47, 0x46, 0x45, 0x44, 0x43,
241fcf3ce44SJohn Forte 	0x42, 0x39, 0x3a, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b,
242fcf3ce44SJohn Forte 	0x3c, 0x3b, 0x3a, 0x3d, 0x39, 0x3e, 0x3f, 0x40, 0x38, 0x37,
243fcf3ce44SJohn Forte 	0x36, 0x41, 0x35, 0x42, 0x43, 0x44, 0x34, 0x45, 0x46, 0x47,
244fcf3ce44SJohn Forte 	0x48, 0x49, 0x4a, 0x33, 0x32, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
245fcf3ce44SJohn Forte 	0x50, 0x31, 0x30, 0x51, 0x52, 0x2f, 0x53, 0x2e, 0x2d, 0x2c,
246fcf3ce44SJohn Forte 	0x54, 0x55, 0x56, 0x2b, 0x57, 0x2a, 0x29, 0x28, 0x58, 0x27,
247fcf3ce44SJohn Forte 	0x26, 0x25, 0x24, 0x23, 0x22, 0x59, 0x5a, 0x21, 0x20, 0x1f,
248fcf3ce44SJohn Forte 	0x1e, 0x1d, 0x1c, 0x5b, 0x5c, 0x1b, 0x1a, 0x5d, 0x19, 0x5e,
249fcf3ce44SJohn Forte 	0x5f, 0x60, 0x61, 0x62, 0x63, 0x18, 0x64, 0x17, 0x16, 0x15,
250fcf3ce44SJohn Forte 	0x65, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x66, 0x67, 0x0e,
251fcf3ce44SJohn Forte 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x68, 0x69, 0x08, 0x07, 0x6a,
252fcf3ce44SJohn Forte 	0x06, 0x6b, 0x6c, 0x6d, 0x05, 0x04, 0x03, 0x6e, 0x02, 0x6f,
253fcf3ce44SJohn Forte 	0x70, 0x71, 0x01, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x00,
254fcf3ce44SJohn Forte 	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7f, 0x80, 0x00, 0x01,
255fcf3ce44SJohn Forte 	0x02, 0x03, 0x80, 0x7f, 0x7e, 0x04
256fcf3ce44SJohn Forte };
257fcf3ce44SJohn Forte 
258fcf3ce44SJohn Forte /* Device loop_id to ALPA array. */
259fcf3ce44SJohn Forte static uint8_t ql_index_to_alpa[] = {
260fcf3ce44SJohn Forte 	0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
261fcf3ce44SJohn Forte 	0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
262fcf3ce44SJohn Forte 	0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
263fcf3ce44SJohn Forte 	0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
264fcf3ce44SJohn Forte 	0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
265fcf3ce44SJohn Forte 	0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
266fcf3ce44SJohn Forte 	0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
267fcf3ce44SJohn Forte 	0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
268fcf3ce44SJohn Forte 	0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
269fcf3ce44SJohn Forte 	0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
270fcf3ce44SJohn Forte 	0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
271fcf3ce44SJohn Forte 	0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
272fcf3ce44SJohn Forte 	0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
273fcf3ce44SJohn Forte };
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte /* 2200 register offsets */
276fcf3ce44SJohn Forte static reg_off_t reg_off_2200 = {
277eb82ff87SDaniel Beauregard 	0x00,	/* flash_address */
278eb82ff87SDaniel Beauregard 	0x02,	/* flash_data */
279eb82ff87SDaniel Beauregard 	0x06,	/* ctrl_status */
280eb82ff87SDaniel Beauregard 	0x08,	/* ictrl */
281eb82ff87SDaniel Beauregard 	0x0a,	/* istatus */
282eb82ff87SDaniel Beauregard 	0x0c,	/* semaphore */
283eb82ff87SDaniel Beauregard 	0x0e,	/* nvram */
284eb82ff87SDaniel Beauregard 	0x18,	/* req_in */
285eb82ff87SDaniel Beauregard 	0x18,	/* req_out */
286eb82ff87SDaniel Beauregard 	0x1a,	/* resp_in */
287eb82ff87SDaniel Beauregard 	0x1a,	/* resp_out */
288eb82ff87SDaniel Beauregard 	0xff,	/* risc2host - n/a */
289eb82ff87SDaniel Beauregard 	24,	/* Number of mailboxes */
290eb82ff87SDaniel Beauregard 
291eb82ff87SDaniel Beauregard 	/* Mailbox in register offsets 0 - 23 */
292fcf3ce44SJohn Forte 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
293fcf3ce44SJohn Forte 	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
294fcf3ce44SJohn Forte 	0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
295eb82ff87SDaniel Beauregard 	/* 2200 does not have mailbox 24-31 - n/a */
296eb82ff87SDaniel Beauregard 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
297eb82ff87SDaniel Beauregard 
298eb82ff87SDaniel Beauregard 	/* Mailbox out register offsets 0 - 23 */
299eb82ff87SDaniel Beauregard 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
300eb82ff87SDaniel Beauregard 	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
301eb82ff87SDaniel Beauregard 	0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
302eb82ff87SDaniel Beauregard 	/* 2200 does not have mailbox 24-31 - n/a */
303eb82ff87SDaniel Beauregard 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
304eb82ff87SDaniel Beauregard 
305eb82ff87SDaniel Beauregard 	0x96,	/* fpm_diag_config */
306eb82ff87SDaniel Beauregard 	0xa4,	/* pcr */
307eb82ff87SDaniel Beauregard 	0xb0,	/* mctr */
308eb82ff87SDaniel Beauregard 	0xb8,	/* fb_cmd */
309eb82ff87SDaniel Beauregard 	0xc0,	/* hccr */
310eb82ff87SDaniel Beauregard 	0xcc,	/* gpiod */
311eb82ff87SDaniel Beauregard 	0xce,	/* gpioe */
312eb82ff87SDaniel Beauregard 	0xff,	/* host_to_host_sema - n/a */
313eb82ff87SDaniel Beauregard 	0xff,	/* pri_req_in - n/a */
314eb82ff87SDaniel Beauregard 	0xff,	/* pri_req_out - n/a */
315eb82ff87SDaniel Beauregard 	0xff,	/* atio_req_in - n/a */
316eb82ff87SDaniel Beauregard 	0xff,	/* atio_req_out - n/a */
317eb82ff87SDaniel Beauregard 	0xff,	/* io_base_addr - n/a */
318eb82ff87SDaniel Beauregard 	0xff,	/* nx_host_int - n/a */
319eb82ff87SDaniel Beauregard 	0xff	/* nx_risc_int - n/a */
320fcf3ce44SJohn Forte };
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte /* 2300 register offsets */
323fcf3ce44SJohn Forte static reg_off_t reg_off_2300 = {
324eb82ff87SDaniel Beauregard 	0x00,	/* flash_address */
325eb82ff87SDaniel Beauregard 	0x02,	/* flash_data */
326eb82ff87SDaniel Beauregard 	0x06,	/* ctrl_status */
327eb82ff87SDaniel Beauregard 	0x08,	/* ictrl */
328eb82ff87SDaniel Beauregard 	0x0a,	/* istatus */
329eb82ff87SDaniel Beauregard 	0x0c,	/* semaphore */
330eb82ff87SDaniel Beauregard 	0x0e,	/* nvram */
331eb82ff87SDaniel Beauregard 	0x10,	/* req_in */
332eb82ff87SDaniel Beauregard 	0x12,	/* req_out */
333eb82ff87SDaniel Beauregard 	0x14,	/* resp_in */
334eb82ff87SDaniel Beauregard 	0x16,	/* resp_out */
335eb82ff87SDaniel Beauregard 	0x18,	/* risc2host */
336eb82ff87SDaniel Beauregard 	32,	/* Number of mailboxes */
337eb82ff87SDaniel Beauregard 
338eb82ff87SDaniel Beauregard 	/* Mailbox in register offsets 0 - 31 */
339eb82ff87SDaniel Beauregard 	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
340eb82ff87SDaniel Beauregard 	0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
341eb82ff87SDaniel Beauregard 	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
342eb82ff87SDaniel Beauregard 	0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
343eb82ff87SDaniel Beauregard 
344eb82ff87SDaniel Beauregard 	/* Mailbox out register offsets 0 - 31 */
345fcf3ce44SJohn Forte 	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e,
346fcf3ce44SJohn Forte 	0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
347fcf3ce44SJohn Forte 	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e,
348fcf3ce44SJohn Forte 	0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
349eb82ff87SDaniel Beauregard 
350eb82ff87SDaniel Beauregard 	0x96,	/* fpm_diag_config */
351eb82ff87SDaniel Beauregard 	0xa4,	/* pcr */
352eb82ff87SDaniel Beauregard 	0xb0,	/* mctr */
353eb82ff87SDaniel Beauregard 	0x80,	/* fb_cmd */
354eb82ff87SDaniel Beauregard 	0xc0,	/* hccr */
355eb82ff87SDaniel Beauregard 	0xcc,	/* gpiod */
356eb82ff87SDaniel Beauregard 	0xce,	/* gpioe */
357eb82ff87SDaniel Beauregard 	0x1c,	/* host_to_host_sema */
358eb82ff87SDaniel Beauregard 	0xff,	/* pri_req_in - n/a */
359eb82ff87SDaniel Beauregard 	0xff,	/* pri_req_out - n/a */
360eb82ff87SDaniel Beauregard 	0xff,	/* atio_req_in - n/a */
361eb82ff87SDaniel Beauregard 	0xff,	/* atio_req_out - n/a */
362eb82ff87SDaniel Beauregard 	0xff,	/* io_base_addr - n/a */
363eb82ff87SDaniel Beauregard 	0xff,	/* nx_host_int - n/a */
364eb82ff87SDaniel Beauregard 	0xff	/* nx_risc_int - n/a */
365fcf3ce44SJohn Forte };
366fcf3ce44SJohn Forte 
367fcf3ce44SJohn Forte /* 2400/2500 register offsets */
368fcf3ce44SJohn Forte reg_off_t reg_off_2400_2500 = {
369eb82ff87SDaniel Beauregard 	0x00,	/* flash_address */
370eb82ff87SDaniel Beauregard 	0x04,	/* flash_data */
371eb82ff87SDaniel Beauregard 	0x08,	/* ctrl_status */
372eb82ff87SDaniel Beauregard 	0x0c,	/* ictrl */
373eb82ff87SDaniel Beauregard 	0x10,	/* istatus */
374eb82ff87SDaniel Beauregard 	0xff,	/* semaphore - n/a */
375eb82ff87SDaniel Beauregard 	0xff,	/* nvram - n/a */
376eb82ff87SDaniel Beauregard 	0x1c,	/* req_in */
377eb82ff87SDaniel Beauregard 	0x20,	/* req_out */
378eb82ff87SDaniel Beauregard 	0x24,	/* resp_in */
379eb82ff87SDaniel Beauregard 	0x28,	/* resp_out */
380eb82ff87SDaniel Beauregard 	0x44,	/* risc2host */
381eb82ff87SDaniel Beauregard 	32,	/* Number of mailboxes */
382eb82ff87SDaniel Beauregard 
383eb82ff87SDaniel Beauregard 	/* Mailbox in register offsets 0 - 31 */
384fcf3ce44SJohn Forte 	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
385fcf3ce44SJohn Forte 	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
386fcf3ce44SJohn Forte 	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
387fcf3ce44SJohn Forte 	0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
388eb82ff87SDaniel Beauregard 
389eb82ff87SDaniel Beauregard 	/* Mailbox out register offsets 0 - 31 */
390eb82ff87SDaniel Beauregard 	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
391eb82ff87SDaniel Beauregard 	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
392eb82ff87SDaniel Beauregard 	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
393eb82ff87SDaniel Beauregard 	0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
394eb82ff87SDaniel Beauregard 
395eb82ff87SDaniel Beauregard 	0xff,	/* fpm_diag_config  - n/a */
396eb82ff87SDaniel Beauregard 	0xff,	/* pcr - n/a */
397eb82ff87SDaniel Beauregard 	0xff,	/* mctr - n/a */
398eb82ff87SDaniel Beauregard 	0xff,	/* fb_cmd - n/a */
399eb82ff87SDaniel Beauregard 	0x48,	/* hccr */
400eb82ff87SDaniel Beauregard 	0x4c,	/* gpiod */
401eb82ff87SDaniel Beauregard 	0x50,	/* gpioe */
402eb82ff87SDaniel Beauregard 	0xff,	/* host_to_host_sema - n/a */
403eb82ff87SDaniel Beauregard 	0x2c,	/* pri_req_in */
404eb82ff87SDaniel Beauregard 	0x30,	/* pri_req_out */
405eb82ff87SDaniel Beauregard 	0x3c,	/* atio_req_in */
406eb82ff87SDaniel Beauregard 	0x40,	/* atio_req_out */
407eb82ff87SDaniel Beauregard 	0x54,	/* io_base_addr */
408eb82ff87SDaniel Beauregard 	0xff,	/* nx_host_int - n/a */
409eb82ff87SDaniel Beauregard 	0xff	/* nx_risc_int - n/a */
410eb82ff87SDaniel Beauregard };
411eb82ff87SDaniel Beauregard 
412eb82ff87SDaniel Beauregard /* P3 register offsets */
413eb82ff87SDaniel Beauregard static reg_off_t reg_off_8021 = {
414eb82ff87SDaniel Beauregard 	0x00,	/* flash_address */
415eb82ff87SDaniel Beauregard 	0x04,	/* flash_data */
416eb82ff87SDaniel Beauregard 	0x08,	/* ctrl_status */
417eb82ff87SDaniel Beauregard 	0x0c,	/* ictrl */
418eb82ff87SDaniel Beauregard 	0x10,	/* istatus */
419eb82ff87SDaniel Beauregard 	0xff,	/* semaphore - n/a */
420eb82ff87SDaniel Beauregard 	0xff,	/* nvram - n/a */
421eb82ff87SDaniel Beauregard 	0xff,	/* req_in - n/a */
422eb82ff87SDaniel Beauregard 	0x0,	/* req_out */
423eb82ff87SDaniel Beauregard 	0x100,	/* resp_in */
424eb82ff87SDaniel Beauregard 	0x200,	/* resp_out */
425eb82ff87SDaniel Beauregard 	0x500,	/* risc2host */
426eb82ff87SDaniel Beauregard 	32,	/* Number of mailboxes */
427eb82ff87SDaniel Beauregard 
428eb82ff87SDaniel Beauregard 	/* Mailbox in register offsets 0 - 31 */
429eb82ff87SDaniel Beauregard 	0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e,
430eb82ff87SDaniel Beauregard 	0x310, 0x312, 0x314, 0x316, 0x318, 0x31a, 0x31c, 0x31e,
431eb82ff87SDaniel Beauregard 	0x320, 0x322, 0x324, 0x326, 0x328, 0x32a, 0x32c, 0x32e,
432eb82ff87SDaniel Beauregard 	0x330, 0x332, 0x334, 0x336, 0x338, 0x33a, 0x33c, 0x33e,
433eb82ff87SDaniel Beauregard 
434eb82ff87SDaniel Beauregard 	/* Mailbox out register offsets 0 - 31 */
435eb82ff87SDaniel Beauregard 	0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e,
436eb82ff87SDaniel Beauregard 	0x410, 0x412, 0x414, 0x416, 0x418, 0x41a, 0x41c, 0x41e,
437eb82ff87SDaniel Beauregard 	0x420, 0x422, 0x424, 0x426, 0x428, 0x42a, 0x42c, 0x42e,
438eb82ff87SDaniel Beauregard 	0x430, 0x432, 0x434, 0x436, 0x438, 0x43a, 0x43c, 0x43e,
439eb82ff87SDaniel Beauregard 
440eb82ff87SDaniel Beauregard 	0xff,	/* fpm_diag_config  - n/a */
441eb82ff87SDaniel Beauregard 	0xff,	/* pcr - n/a */
442eb82ff87SDaniel Beauregard 	0xff,	/* mctr - n/a */
443eb82ff87SDaniel Beauregard 	0xff,	/* fb_cmd - n/a */
444eb82ff87SDaniel Beauregard 	0x48,	/* hccr */
445eb82ff87SDaniel Beauregard 	0x4c,	/* gpiod */
446eb82ff87SDaniel Beauregard 	0x50,	/* gpioe */
447eb82ff87SDaniel Beauregard 	0xff,	/* host_to_host_sema - n/a */
448eb82ff87SDaniel Beauregard 	0x2c,	/* pri_req_in */
449eb82ff87SDaniel Beauregard 	0x30,	/* pri_req_out */
450eb82ff87SDaniel Beauregard 	0x3c,	/* atio_req_in */
451eb82ff87SDaniel Beauregard 	0x40,	/* atio_req_out */
452eb82ff87SDaniel Beauregard 	0x54,	/* io_base_addr */
453eb82ff87SDaniel Beauregard 	0x380,	/* nx_host_int */
454eb82ff87SDaniel Beauregard 	0x504	/* nx_risc_int */
455fcf3ce44SJohn Forte };
456fcf3ce44SJohn Forte 
457fcf3ce44SJohn Forte /* mutex for protecting variables shared by all instances of the driver */
458fcf3ce44SJohn Forte kmutex_t ql_global_mutex;
459fcf3ce44SJohn Forte kmutex_t ql_global_hw_mutex;
460fcf3ce44SJohn Forte kmutex_t ql_global_el_mutex;
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte /* DMA access attribute structure. */
463fcf3ce44SJohn Forte static ddi_device_acc_attr_t ql_dev_acc_attr = {
464fcf3ce44SJohn Forte 	DDI_DEVICE_ATTR_V0,
465fcf3ce44SJohn Forte 	DDI_STRUCTURE_LE_ACC,
466fcf3ce44SJohn Forte 	DDI_STRICTORDER_ACC
467fcf3ce44SJohn Forte };
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte /* I/O DMA attributes structures. */
470fcf3ce44SJohn Forte static ddi_dma_attr_t ql_64bit_io_dma_attr = {
471fcf3ce44SJohn Forte 	DMA_ATTR_V0,			/* dma_attr_version */
472fcf3ce44SJohn Forte 	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
473fcf3ce44SJohn Forte 	QL_DMA_HIGH_64BIT_ADDRESS,	/* high DMA address range */
474fcf3ce44SJohn Forte 	QL_DMA_XFER_COUNTER,		/* DMA counter register */
475fcf3ce44SJohn Forte 	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
476fcf3ce44SJohn Forte 	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
477fcf3ce44SJohn Forte 	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
478fcf3ce44SJohn Forte 	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
479fcf3ce44SJohn Forte 	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
480fcf3ce44SJohn Forte 	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
481fcf3ce44SJohn Forte 	QL_DMA_GRANULARITY,		/* granularity of device */
482fcf3ce44SJohn Forte 	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
483fcf3ce44SJohn Forte };
484fcf3ce44SJohn Forte 
485fcf3ce44SJohn Forte static ddi_dma_attr_t ql_32bit_io_dma_attr = {
486fcf3ce44SJohn Forte 	DMA_ATTR_V0,			/* dma_attr_version */
487fcf3ce44SJohn Forte 	QL_DMA_LOW_ADDRESS,		/* low DMA address range */
488fcf3ce44SJohn Forte 	QL_DMA_HIGH_32BIT_ADDRESS,	/* high DMA address range */
489fcf3ce44SJohn Forte 	QL_DMA_XFER_COUNTER,		/* DMA counter register */
490fcf3ce44SJohn Forte 	QL_DMA_ADDRESS_ALIGNMENT,	/* DMA address alignment */
491fcf3ce44SJohn Forte 	QL_DMA_BURSTSIZES,		/* DMA burstsizes */
492fcf3ce44SJohn Forte 	QL_DMA_MIN_XFER_SIZE,		/* min effective DMA size */
493fcf3ce44SJohn Forte 	QL_DMA_MAX_XFER_SIZE,		/* max DMA xfer size */
494fcf3ce44SJohn Forte 	QL_DMA_SEGMENT_BOUNDARY,	/* segment boundary */
495fcf3ce44SJohn Forte 	QL_DMA_SG_LIST_LENGTH,		/* s/g list length */
496fcf3ce44SJohn Forte 	QL_DMA_GRANULARITY,		/* granularity of device */
497fcf3ce44SJohn Forte 	QL_DMA_XFER_FLAGS		/* DMA transfer flags */
498fcf3ce44SJohn Forte };
499fcf3ce44SJohn Forte 
500fcf3ce44SJohn Forte /* Load the default dma attributes */
501fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcsm_cmd_dma_attr;
502fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcsm_cmd_dma_attr;
503fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcsm_rsp_dma_attr;
504fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcsm_rsp_dma_attr;
505fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcip_cmd_dma_attr;
506fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcip_cmd_dma_attr;
507fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcip_rsp_dma_attr;
508fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcip_rsp_dma_attr;
509fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcp_cmd_dma_attr;
510fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcp_cmd_dma_attr;
511fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcp_rsp_dma_attr;
512fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcp_rsp_dma_attr;
513fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_32fcp_data_dma_attr;
514fcf3ce44SJohn Forte static	ddi_dma_attr_t	ql_64fcp_data_dma_attr;
515fcf3ce44SJohn Forte 
516fcf3ce44SJohn Forte /* Static declarations of cb_ops entry point functions... */
517fcf3ce44SJohn Forte static struct cb_ops ql_cb_ops = {
518fcf3ce44SJohn Forte 	ql_open,			/* b/c open */
519fcf3ce44SJohn Forte 	ql_close,			/* b/c close */
520fcf3ce44SJohn Forte 	nodev,				/* b strategy */
521fcf3ce44SJohn Forte 	nodev,				/* b print */
522fcf3ce44SJohn Forte 	nodev,				/* b dump */
523fcf3ce44SJohn Forte 	nodev,				/* c read */
524fcf3ce44SJohn Forte 	nodev,				/* c write */
525fcf3ce44SJohn Forte 	ql_ioctl,			/* c ioctl */
526fcf3ce44SJohn Forte 	nodev,				/* c devmap */
527fcf3ce44SJohn Forte 	nodev,				/* c mmap */
528fcf3ce44SJohn Forte 	nodev,				/* c segmap */
529fcf3ce44SJohn Forte 	nochpoll,			/* c poll */
530fcf3ce44SJohn Forte 	nodev,				/* cb_prop_op */
531fcf3ce44SJohn Forte 	NULL,				/* streamtab  */
532fcf3ce44SJohn Forte 	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
533fcf3ce44SJohn Forte 	CB_REV,				/* cb_ops revision */
534fcf3ce44SJohn Forte 	nodev,				/* c aread */
535fcf3ce44SJohn Forte 	nodev				/* c awrite */
536fcf3ce44SJohn Forte };
537fcf3ce44SJohn Forte 
538fcf3ce44SJohn Forte /* Static declarations of dev_ops entry point functions... */
539fcf3ce44SJohn Forte static struct dev_ops ql_devops = {
540fcf3ce44SJohn Forte 	DEVO_REV,			/* devo_rev */
541fcf3ce44SJohn Forte 	0,				/* refcnt */
542fcf3ce44SJohn Forte 	ql_getinfo,			/* getinfo */
543fcf3ce44SJohn Forte 	nulldev,			/* identify */
544fcf3ce44SJohn Forte 	nulldev,			/* probe */
545fcf3ce44SJohn Forte 	ql_attach,			/* attach */
546fcf3ce44SJohn Forte 	ql_detach,			/* detach */
547fcf3ce44SJohn Forte 	nodev,				/* reset */
548fcf3ce44SJohn Forte 	&ql_cb_ops,			/* char/block ops */
549fcf3ce44SJohn Forte 	NULL,				/* bus operations */
55016dd44c2SDaniel Beauregard 	ql_power,			/* power management */
55116dd44c2SDaniel Beauregard 	ql_quiesce			/* quiesce device */
552fcf3ce44SJohn Forte };
553fcf3ce44SJohn Forte 
55416dd44c2SDaniel Beauregard /* ELS command code to text converter */
55516dd44c2SDaniel Beauregard cmd_table_t els_cmd_tbl[] = ELS_CMD_TABLE();
55616dd44c2SDaniel Beauregard /* Mailbox command code to text converter */
55716dd44c2SDaniel Beauregard cmd_table_t mbox_cmd_tbl[] = MBOX_CMD_TABLE();
558fcf3ce44SJohn Forte 
559fcf3ce44SJohn Forte char qlc_driver_version[] = QL_VERSION;
560fcf3ce44SJohn Forte 
561fcf3ce44SJohn Forte /*
562fcf3ce44SJohn Forte  * Loadable Driver Interface Structures.
563fcf3ce44SJohn Forte  * Declare and initialize the module configuration section...
564fcf3ce44SJohn Forte  */
565fcf3ce44SJohn Forte static struct modldrv modldrv = {
566fcf3ce44SJohn Forte 	&mod_driverops,				/* type of module: driver */
567fcf3ce44SJohn Forte 	"SunFC Qlogic FCA v" QL_VERSION,	/* name of module */
568fcf3ce44SJohn Forte 	&ql_devops				/* driver dev_ops */
569fcf3ce44SJohn Forte };
570fcf3ce44SJohn Forte 
571fcf3ce44SJohn Forte static struct modlinkage modlinkage = {
572fcf3ce44SJohn Forte 	MODREV_1,
573fcf3ce44SJohn Forte 	&modldrv,
574fcf3ce44SJohn Forte 	NULL
575fcf3ce44SJohn Forte };
576fcf3ce44SJohn Forte 
577fcf3ce44SJohn Forte /* ************************************************************************ */
578fcf3ce44SJohn Forte /*				Loadable Module Routines.		    */
579fcf3ce44SJohn Forte /* ************************************************************************ */
580fcf3ce44SJohn Forte 
581fcf3ce44SJohn Forte /*
582fcf3ce44SJohn Forte  * _init
583fcf3ce44SJohn Forte  *	Initializes a loadable module. It is called before any other
584fcf3ce44SJohn Forte  *	routine in a loadable module.
585fcf3ce44SJohn Forte  *
586fcf3ce44SJohn Forte  * Returns:
587fcf3ce44SJohn Forte  *	0 = success
588fcf3ce44SJohn Forte  *
589fcf3ce44SJohn Forte  * Context:
590fcf3ce44SJohn Forte  *	Kernel context.
591fcf3ce44SJohn Forte  */
592fcf3ce44SJohn Forte int
_init(void)593fcf3ce44SJohn Forte _init(void)
594fcf3ce44SJohn Forte {
595fcf3ce44SJohn Forte 	uint16_t	w16;
596fcf3ce44SJohn Forte 	int		rval = 0;
597fcf3ce44SJohn Forte 
598fcf3ce44SJohn Forte 	/* Get OS major release level. */
599fcf3ce44SJohn Forte 	for (w16 = 0; w16 < sizeof (utsname.release); w16++) {
600fcf3ce44SJohn Forte 		if (utsname.release[w16] == '.') {
601fcf3ce44SJohn Forte 			w16++;
602fcf3ce44SJohn Forte 			break;
603fcf3ce44SJohn Forte 		}
604fcf3ce44SJohn Forte 	}
605fcf3ce44SJohn Forte 	if (w16 < sizeof (utsname.release)) {
606fcf3ce44SJohn Forte 		(void) ql_bstr_to_dec(&utsname.release[w16],
607fcf3ce44SJohn Forte 		    &ql_os_release_level, 0);
608fcf3ce44SJohn Forte 	} else {
609fcf3ce44SJohn Forte 		ql_os_release_level = 0;
610fcf3ce44SJohn Forte 	}
611fcf3ce44SJohn Forte 	if (ql_os_release_level < 6) {
612fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "%s Unsupported OS release level = %d",
613fcf3ce44SJohn Forte 		    QL_NAME, ql_os_release_level);
614fcf3ce44SJohn Forte 		rval = EINVAL;
615fcf3ce44SJohn Forte 	}
616fcf3ce44SJohn Forte 	if (ql_os_release_level == 6) {
617fcf3ce44SJohn Forte 		ql_32bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
618fcf3ce44SJohn Forte 		ql_64bit_io_dma_attr.dma_attr_count_max = 0x00ffffff;
619fcf3ce44SJohn Forte 	}
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte 	if (rval == 0) {
622fcf3ce44SJohn Forte 		rval = ddi_soft_state_init(&ql_state,
623fcf3ce44SJohn Forte 		    sizeof (ql_adapter_state_t), 0);
624fcf3ce44SJohn Forte 	}
625fcf3ce44SJohn Forte 	if (rval == 0) {
626fcf3ce44SJohn Forte 		/* allow the FC Transport to tweak the dev_ops */
627fcf3ce44SJohn Forte 		fc_fca_init(&ql_devops);
628fcf3ce44SJohn Forte 
629fcf3ce44SJohn Forte 		mutex_init(&ql_global_mutex, NULL, MUTEX_DRIVER, NULL);
630fcf3ce44SJohn Forte 		mutex_init(&ql_global_hw_mutex, NULL, MUTEX_DRIVER, NULL);
631fcf3ce44SJohn Forte 		mutex_init(&ql_global_el_mutex, NULL, MUTEX_DRIVER, NULL);
632fcf3ce44SJohn Forte 		rval = mod_install(&modlinkage);
633fcf3ce44SJohn Forte 		if (rval != 0) {
634fcf3ce44SJohn Forte 			mutex_destroy(&ql_global_hw_mutex);
635fcf3ce44SJohn Forte 			mutex_destroy(&ql_global_mutex);
636fcf3ce44SJohn Forte 			mutex_destroy(&ql_global_el_mutex);
637fcf3ce44SJohn Forte 			ddi_soft_state_fini(&ql_state);
638fcf3ce44SJohn Forte 		} else {
639fcf3ce44SJohn Forte 			/*EMPTY*/
640fcf3ce44SJohn Forte 			ql_32fcsm_cmd_dma_attr = ql_32bit_io_dma_attr;
641fcf3ce44SJohn Forte 			ql_64fcsm_cmd_dma_attr = ql_64bit_io_dma_attr;
642fcf3ce44SJohn Forte 			ql_32fcsm_rsp_dma_attr = ql_32bit_io_dma_attr;
643fcf3ce44SJohn Forte 			ql_64fcsm_rsp_dma_attr = ql_64bit_io_dma_attr;
644fcf3ce44SJohn Forte 			ql_32fcip_cmd_dma_attr = ql_32bit_io_dma_attr;
645fcf3ce44SJohn Forte 			ql_64fcip_cmd_dma_attr = ql_64bit_io_dma_attr;
646fcf3ce44SJohn Forte 			ql_32fcip_rsp_dma_attr = ql_32bit_io_dma_attr;
647fcf3ce44SJohn Forte 			ql_64fcip_rsp_dma_attr = ql_64bit_io_dma_attr;
648fcf3ce44SJohn Forte 			ql_32fcp_cmd_dma_attr = ql_32bit_io_dma_attr;
649fcf3ce44SJohn Forte 			ql_64fcp_cmd_dma_attr = ql_64bit_io_dma_attr;
650fcf3ce44SJohn Forte 			ql_32fcp_rsp_dma_attr = ql_32bit_io_dma_attr;
651fcf3ce44SJohn Forte 			ql_64fcp_rsp_dma_attr = ql_64bit_io_dma_attr;
652fcf3ce44SJohn Forte 			ql_32fcp_data_dma_attr = ql_32bit_io_dma_attr;
653fcf3ce44SJohn Forte 			ql_64fcp_data_dma_attr = ql_64bit_io_dma_attr;
654fcf3ce44SJohn Forte 			ql_32fcsm_cmd_dma_attr.dma_attr_sgllen =
655fcf3ce44SJohn Forte 			    ql_64fcsm_cmd_dma_attr.dma_attr_sgllen =
656fcf3ce44SJohn Forte 			    QL_FCSM_CMD_SGLLEN;
657fcf3ce44SJohn Forte 			ql_32fcsm_rsp_dma_attr.dma_attr_sgllen =
658fcf3ce44SJohn Forte 			    ql_64fcsm_rsp_dma_attr.dma_attr_sgllen =
659fcf3ce44SJohn Forte 			    QL_FCSM_RSP_SGLLEN;
660fcf3ce44SJohn Forte 			ql_32fcip_cmd_dma_attr.dma_attr_sgllen =
661fcf3ce44SJohn Forte 			    ql_64fcip_cmd_dma_attr.dma_attr_sgllen =
662fcf3ce44SJohn Forte 			    QL_FCIP_CMD_SGLLEN;
663fcf3ce44SJohn Forte 			ql_32fcip_rsp_dma_attr.dma_attr_sgllen =
664fcf3ce44SJohn Forte 			    ql_64fcip_rsp_dma_attr.dma_attr_sgllen =
665fcf3ce44SJohn Forte 			    QL_FCIP_RSP_SGLLEN;
666fcf3ce44SJohn Forte 			ql_32fcp_cmd_dma_attr.dma_attr_sgllen =
667fcf3ce44SJohn Forte 			    ql_64fcp_cmd_dma_attr.dma_attr_sgllen =
668fcf3ce44SJohn Forte 			    QL_FCP_CMD_SGLLEN;
669fcf3ce44SJohn Forte 			ql_32fcp_rsp_dma_attr.dma_attr_sgllen =
670fcf3ce44SJohn Forte 			    ql_64fcp_rsp_dma_attr.dma_attr_sgllen =
671fcf3ce44SJohn Forte 			    QL_FCP_RSP_SGLLEN;
672fcf3ce44SJohn Forte 		}
673fcf3ce44SJohn Forte 	}
674fcf3ce44SJohn Forte 
675fcf3ce44SJohn Forte 	if (rval != 0) {
676fcf3ce44SJohn Forte 		cmn_err(CE_CONT, "?Unable to install/attach driver '%s'",
677fcf3ce44SJohn Forte 		    QL_NAME);
678fcf3ce44SJohn Forte 	}
679fcf3ce44SJohn Forte 
680fcf3ce44SJohn Forte 	return (rval);
681fcf3ce44SJohn Forte }
682fcf3ce44SJohn Forte 
683fcf3ce44SJohn Forte /*
684fcf3ce44SJohn Forte  * _fini
685fcf3ce44SJohn Forte  *	Prepares a module for unloading. It is called when the system
686fcf3ce44SJohn Forte  *	wants to unload a module. If the module determines that it can
687fcf3ce44SJohn Forte  *	be unloaded, then _fini() returns the value returned by
688fcf3ce44SJohn Forte  *	mod_remove(). Upon successful return from _fini() no other
689fcf3ce44SJohn Forte  *	routine in the module will be called before _init() is called.
690fcf3ce44SJohn Forte  *
691fcf3ce44SJohn Forte  * Returns:
692fcf3ce44SJohn Forte  *	0 = success
693fcf3ce44SJohn Forte  *
694fcf3ce44SJohn Forte  * Context:
695fcf3ce44SJohn Forte  *	Kernel context.
696fcf3ce44SJohn Forte  */
697fcf3ce44SJohn Forte int
_fini(void)698fcf3ce44SJohn Forte _fini(void)
699fcf3ce44SJohn Forte {
700fcf3ce44SJohn Forte 	int	rval;
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 	rval = mod_remove(&modlinkage);
703fcf3ce44SJohn Forte 	if (rval == 0) {
704fcf3ce44SJohn Forte 		mutex_destroy(&ql_global_hw_mutex);
705fcf3ce44SJohn Forte 		mutex_destroy(&ql_global_mutex);
706fcf3ce44SJohn Forte 		mutex_destroy(&ql_global_el_mutex);
707fcf3ce44SJohn Forte 		ddi_soft_state_fini(&ql_state);
708fcf3ce44SJohn Forte 	}
709fcf3ce44SJohn Forte 
710fcf3ce44SJohn Forte 	return (rval);
711fcf3ce44SJohn Forte }
712fcf3ce44SJohn Forte 
713fcf3ce44SJohn Forte /*
714fcf3ce44SJohn Forte  * _info
715fcf3ce44SJohn Forte  *	Returns information about loadable module.
716fcf3ce44SJohn Forte  *
717fcf3ce44SJohn Forte  * Input:
718fcf3ce44SJohn Forte  *	modinfo = pointer to module information structure.
719fcf3ce44SJohn Forte  *
720fcf3ce44SJohn Forte  * Returns:
721fcf3ce44SJohn Forte  *	Value returned by mod_info().
722fcf3ce44SJohn Forte  *
723fcf3ce44SJohn Forte  * Context:
724fcf3ce44SJohn Forte  *	Kernel context.
725fcf3ce44SJohn Forte  */
726fcf3ce44SJohn Forte int
_info(struct modinfo * modinfop)727fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
728fcf3ce44SJohn Forte {
729fcf3ce44SJohn Forte 	return (mod_info(&modlinkage, modinfop));
730fcf3ce44SJohn Forte }
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte /* ************************************************************************ */
733fcf3ce44SJohn Forte /*			dev_ops functions				    */
734fcf3ce44SJohn Forte /* ************************************************************************ */
735fcf3ce44SJohn Forte 
736fcf3ce44SJohn Forte /*
737fcf3ce44SJohn Forte  * ql_getinfo
738fcf3ce44SJohn Forte  *	Returns the pointer associated with arg when cmd is
739fcf3ce44SJohn Forte  *	set to DDI_INFO_DEVT2DEVINFO, or it should return the
740fcf3ce44SJohn Forte  *	instance number associated with arg when cmd is set
741fcf3ce44SJohn Forte  *	to DDI_INFO_DEV2INSTANCE.
742fcf3ce44SJohn Forte  *
743fcf3ce44SJohn Forte  * Input:
744fcf3ce44SJohn Forte  *	dip = Do not use.
745fcf3ce44SJohn Forte  *	cmd = command argument.
746fcf3ce44SJohn Forte  *	arg = command specific argument.
747fcf3ce44SJohn Forte  *	resultp = pointer to where request information is stored.
748fcf3ce44SJohn Forte  *
749fcf3ce44SJohn Forte  * Returns:
750fcf3ce44SJohn Forte  *	DDI_SUCCESS or DDI_FAILURE.
751fcf3ce44SJohn Forte  *
752fcf3ce44SJohn Forte  * Context:
753fcf3ce44SJohn Forte  *	Kernel context.
754fcf3ce44SJohn Forte  */
755fcf3ce44SJohn Forte /* ARGSUSED */
756fcf3ce44SJohn Forte static int
ql_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)757fcf3ce44SJohn Forte ql_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
758fcf3ce44SJohn Forte {
759fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha;
760fcf3ce44SJohn Forte 	int			minor;
761fcf3ce44SJohn Forte 	int			rval = DDI_FAILURE;
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte 	minor = (int)(getminor((dev_t)arg));
764fcf3ce44SJohn Forte 	ha = ddi_get_soft_state(ql_state, minor);
765fcf3ce44SJohn Forte 	if (ha == NULL) {
766fcf3ce44SJohn Forte 		QL_PRINT_2(CE_CONT, "failed, unknown minor=%d\n",
767fcf3ce44SJohn Forte 		    getminor((dev_t)arg));
768fcf3ce44SJohn Forte 		*resultp = NULL;
769fcf3ce44SJohn Forte 		return (rval);
770fcf3ce44SJohn Forte 	}
771fcf3ce44SJohn Forte 
7725dfd244aSDaniel Beauregard 	QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
773fcf3ce44SJohn Forte 
774fcf3ce44SJohn Forte 	switch (cmd) {
775fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2DEVINFO:
776fcf3ce44SJohn Forte 		*resultp = ha->dip;
777fcf3ce44SJohn Forte 		rval = DDI_SUCCESS;
778fcf3ce44SJohn Forte 		break;
779fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2INSTANCE:
78016dd44c2SDaniel Beauregard 		*resultp = (void *)(uintptr_t)(ha->instance);
781fcf3ce44SJohn Forte 		rval = DDI_SUCCESS;
782fcf3ce44SJohn Forte 		break;
783fcf3ce44SJohn Forte 	default:
784fcf3ce44SJohn Forte 		EL(ha, "failed, unsupported cmd=%d\n", cmd);
785fcf3ce44SJohn Forte 		rval = DDI_FAILURE;
786fcf3ce44SJohn Forte 		break;
787fcf3ce44SJohn Forte 	}
788fcf3ce44SJohn Forte 
7895dfd244aSDaniel Beauregard 	QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
790fcf3ce44SJohn Forte 
791fcf3ce44SJohn Forte 	return (rval);
792fcf3ce44SJohn Forte }
793fcf3ce44SJohn Forte 
794fcf3ce44SJohn Forte /*
795fcf3ce44SJohn Forte  * ql_attach
796fcf3ce44SJohn Forte  *	Configure and attach an instance of the driver
797fcf3ce44SJohn Forte  *	for a port.
798fcf3ce44SJohn Forte  *
799fcf3ce44SJohn Forte  * Input:
800fcf3ce44SJohn Forte  *	dip = pointer to device information structure.
801fcf3ce44SJohn Forte  *	cmd = attach type.
802fcf3ce44SJohn Forte  *
803fcf3ce44SJohn Forte  * Returns:
804fcf3ce44SJohn Forte  *	DDI_SUCCESS or DDI_FAILURE.
805fcf3ce44SJohn Forte  *
806fcf3ce44SJohn Forte  * Context:
807fcf3ce44SJohn Forte  *	Kernel context.
808fcf3ce44SJohn Forte  */
809fcf3ce44SJohn Forte static int
ql_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)810fcf3ce44SJohn Forte ql_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
811fcf3ce44SJohn Forte {
812eb82ff87SDaniel Beauregard 	off_t			regsize;
813fcf3ce44SJohn Forte 	uint32_t		size;
814eb82ff87SDaniel Beauregard 	int			rval, *ptr;
815fcf3ce44SJohn Forte 	int			instance;
816fcf3ce44SJohn Forte 	uint_t			progress = 0;
817fcf3ce44SJohn Forte 	char			*buf;
818fcf3ce44SJohn Forte 	ushort_t		caps_ptr, cap;
819fcf3ce44SJohn Forte 	fc_fca_tran_t		*tran;
820fcf3ce44SJohn Forte 	ql_adapter_state_t	*ha = NULL;
82116dd44c2SDaniel Beauregard 
822fcf3ce44SJohn Forte 	static char *pmcomps[] = {
823fcf3ce44SJohn Forte 		NULL,
824fcf3ce44SJohn Forte 		PM_LEVEL_D3_STR,		/* Device OFF */
825fcf3ce44SJohn Forte 		PM_LEVEL_D0_STR,		/* Device ON */
826fcf3ce44SJohn Forte 	};
827fcf3ce44SJohn Forte 
828fcf3ce44SJohn Forte 	QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n",
829fcf3ce44SJohn Forte 	    ddi_get_instance(dip), cmd);
830fcf3ce44SJohn Forte 
831fcf3ce44SJohn Forte 	buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
832fcf3ce44SJohn Forte 
833fcf3ce44SJohn Forte 	switch (cmd) {
834fcf3ce44SJohn Forte 	case DDI_ATTACH:
835fcf3ce44SJohn Forte 		/* first get the instance */
836fcf3ce44SJohn Forte 		instance = ddi_get_instance(dip);
837fcf3ce44SJohn Forte 
838fcf3ce44SJohn Forte 		cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
839fcf3ce44SJohn Forte 		    QL_NAME, instance, QL_VERSION);
840fcf3ce44SJohn Forte 
841fcf3ce44SJohn Forte 		/* Correct OS version? */
842fcf3ce44SJohn Forte 		if (ql_os_release_level != 11) {
843fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): This driver is for Solaris "
844fcf3ce44SJohn Forte 			    "11", QL_NAME, instance);
845fcf3ce44SJohn Forte 			goto attach_failed;
846fcf3ce44SJohn Forte 		}
847fcf3ce44SJohn Forte 
848fcf3ce44SJohn Forte 		/* Hardware is installed in a DMA-capable slot? */
849fcf3ce44SJohn Forte 		if (ddi_slaveonly(dip) == DDI_SUCCESS) {
850fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): slave only", QL_NAME,
851fcf3ce44SJohn Forte 			    instance);
852fcf3ce44SJohn Forte 			goto attach_failed;
853fcf3ce44SJohn Forte 		}
854fcf3ce44SJohn Forte 
855fcf3ce44SJohn Forte 		/* No support for high-level interrupts */
856fcf3ce44SJohn Forte 		if (ddi_intr_hilevel(dip, 0) != 0) {
857fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): High level interrupt"
858fcf3ce44SJohn Forte 			    " not supported", QL_NAME, instance);
859fcf3ce44SJohn Forte 			goto attach_failed;
860fcf3ce44SJohn Forte 		}
861fcf3ce44SJohn Forte 
862fcf3ce44SJohn Forte 		/* Allocate our per-device-instance structure */
863fcf3ce44SJohn Forte 		if (ddi_soft_state_zalloc(ql_state,
864fcf3ce44SJohn Forte 		    instance) != DDI_SUCCESS) {
865fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): soft state alloc failed",
866fcf3ce44SJohn Forte 			    QL_NAME, instance);
867fcf3ce44SJohn Forte 			goto attach_failed;
868fcf3ce44SJohn Forte 		}
869fcf3ce44SJohn Forte 		progress |= QL_SOFT_STATE_ALLOCED;
870fcf3ce44SJohn Forte 
871fcf3ce44SJohn Forte 		ha = ddi_get_soft_state(ql_state, instance);
872fcf3ce44SJohn Forte 		if (ha == NULL) {
873fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "%s(%d): can't get soft state",
874fcf3ce44SJohn Forte 			    QL_NAME, instance);
875fcf3ce44SJohn Forte 			goto attach_failed;
876fcf3ce44SJohn Forte 		}
877fcf3ce44SJohn Forte 		ha->dip = dip;
878fcf3ce44SJohn Forte 		ha->instance = instance;
879fcf3ce44SJohn Forte 		ha->hba.base_address = ha;
880fcf3ce44SJohn Forte 		ha->pha = ha;
881fcf3ce44SJohn Forte 
88216dd44c2SDaniel Beauregard 		if (ql_el_trace_desc_ctor(ha) != DDI_SUCCESS) {
88316dd44c2SDaniel Beauregard 			cmn_err(CE_WARN, "%s(%d): can't setup el tracing",
88416dd44c2SDaniel Beauregard 			    QL_NAME, instance);
88516dd44c2SDaniel Beauregard 			goto attach_failed;
88616dd44c2SDaniel Beauregard 		}
88716dd44c2SDaniel Beauregard 
888fcf3ce44SJohn Forte 		/* Get extended logging and dump flags. */
889fcf3ce44SJohn Forte 		ql_common_properties(ha);
890fcf3ce44SJohn Forte 
89116dd44c2SDaniel Beauregard 		if (strcmp(ddi_driver_name(ddi_get_parent(dip)),
89216dd44c2SDaniel Beauregard 		    "sbus") == 0) {
893fcf3ce44SJohn Forte 			EL(ha, "%s SBUS card detected", QL_NAME);
894fcf3ce44SJohn Forte 			ha->cfg_flags |= CFG_SBUS_CARD;
895fcf3ce44SJohn Forte 		}
896fcf3ce44SJohn Forte 
897fcf3ce44SJohn Forte 		ha->dev = kmem_zalloc(sizeof (*ha->dev) *
898fcf3ce44SJohn Forte 		    DEVICE_HEAD_LIST_SIZE, KM_SLEEP);
899fcf3ce44SJohn Forte 
900fcf3ce44SJohn Forte 		ha->outstanding_cmds = kmem_zalloc(
901fcf3ce44SJohn Forte 		    sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS,
902fcf3ce44SJohn Forte 		    KM_SLEEP);
903fcf3ce44SJohn Forte 
904fcf3ce44SJohn Forte 		ha->ub_array = kmem_zalloc(sizeof (*ha->ub_array) *
905fcf3ce44SJohn Forte 		    QL_UB_LIMIT, KM_SLEEP);
906fcf3ce44SJohn Forte 
907fcf3ce44SJohn Forte 		ha->adapter_stats = kmem_zalloc(sizeof (*ha->adapter_stats),
908fcf3ce44SJohn Forte 		    KM_SLEEP);
909fcf3ce44SJohn Forte 
910fcf3ce44SJohn Forte 		(void) ddi_pathname(dip, buf);
911fcf3ce44SJohn Forte 		ha->devpath = kmem_zalloc(strlen(buf)+1, KM_SLEEP);
912fcf3ce44SJohn Forte 		if (ha->devpath == NULL) {
913fcf3ce44SJohn Forte 			EL(ha, "devpath mem alloc failed\n");
914fcf3ce44SJohn Forte 		} else {
915fcf3ce44SJohn Forte 			(void) strcpy(ha->devpath, buf);
916fcf3ce44SJohn Forte 			EL(ha, "devpath is: %s\n", ha->devpath);
917fcf3ce44SJohn Forte 		}
918fcf3ce44SJohn Forte 
919fcf3ce44SJohn Forte 		if (CFG_IST(ha, CFG_SBUS_CARD)) {
920fcf3ce44SJohn Forte 			/*
921fcf3ce44SJohn Forte 			 * For cards where PCI is mapped to sbus e.g. Ivory.
922fcf3ce44SJohn Forte 			 *
923fcf3ce44SJohn Forte 			 * 0x00	: 0x000 - 0x0FF PCI Config Space for 2200
924fcf3ce44SJohn Forte 			 *	: 0x100 - 0x3FF PCI IO space for 2200
925fcf3ce44SJohn Forte 			 * 0x01	: 0x000 - 0x0FF PCI Config Space for fpga
926fcf3ce44SJohn Forte 			 *	: 0x100 - 0x3FF PCI IO Space for fpga
927fcf3ce44SJohn Forte 			 */
928fcf3ce44SJohn Forte 			if (ddi_regs_map_setup(dip, 0, (caddr_t *)&ha->iobase,
929eb82ff87SDaniel Beauregard 			    0x100, 0x300, &ql_dev_acc_attr, &ha->dev_handle) !=
930eb82ff87SDaniel Beauregard 			    DDI_SUCCESS) {
931fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "%s(%d): Unable to map device"
932fcf3ce44SJohn Forte 				    " registers", QL_NAME, instance);
933fcf3ce44SJohn Forte 				goto attach_failed;
934fcf3ce44SJohn Forte 			}
935fcf3ce44SJohn Forte 			if (ddi_regs_map_setup(dip, 1,
936fcf3ce44SJohn Forte 			    (caddr_t *)&ha->sbus_fpga_iobase, 0, 0x400,
937eb82ff87SDaniel Beauregard 			    &ql_dev_acc_attr, &ha->sbus_fpga_dev_handle) !=
938eb82ff87SDaniel Beauregard 			    DDI_SUCCESS) {
939fcf3ce44SJohn Forte 				/* We should not fail attach here */
940fcf3ce44SJohn Forte 				cmn_err(CE_WARN, "%s(%d): Unable to map FPGA",
941fcf3ce44SJohn Forte 				    QL_NAME, instance);
942fcf3ce44SJohn Forte 				ha->sbus_fpga_iobase = NULL;
943fcf3ce44SJohn Forte 			}
944fcf3ce44SJohn Forte 			progress |= QL_REGS_MAPPED;
945eb82ff87SDaniel Beauregard 
946eb82ff87SDaniel Beauregard 			/*
947eb82ff87SDaniel Beauregard 			 * We should map config space before adding interrupt
948eb82ff87SDaniel Beauregard 			 * So that the chip type (2200 or 2300) can be
949eb82ff87SDaniel Beauregard 			 * determined before the interrupt routine gets a
950eb82ff87SDaniel Beauregard 			 * chance to execute.
951eb82ff87SDaniel Beauregard 			 */
952eb82ff87SDaniel Beauregard 			if (ddi_regs_map_setup(dip, 0,
953eb82ff87SDaniel Beauregard 			    (caddr_t *)&ha->sbus_config_base, 0, 0x100,
954eb82ff87SDaniel Beauregard 			    &ql_dev_acc_attr, &ha->sbus_config_handle) !=
955eb82ff87SDaniel Beauregard 			    DDI_SUCCESS) {
956eb82ff87SDaniel Beauregard 				cmn_err(CE_WARN, "%s(%d): Unable to map sbus "
957eb82ff87SDaniel Beauregard 				    "config registers", QL_NAME, instance);
958eb82ff87SDaniel Beauregard 				goto attach_failed;
959eb82ff87SDaniel Beauregard 			}
960eb82ff87SDaniel Beauregard 			progress |= QL_CONFIG_SPACE_SETUP;
961fcf3ce44SJohn Forte 		} else {
962eb82ff87SDaniel Beauregard 			/*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/
963eb82ff87SDaniel Beauregard 			rval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
964eb82ff87SDaniel Beauregard 			    DDI_PROP_DONTPASS, "reg", &ptr, &size);
965eb82ff87SDaniel Beauregard 			if (rval != DDI_PROP_SUCCESS) {
966eb82ff87SDaniel Beauregard 				cmn_err(CE_WARN, "%s(%d): Unable to get PCI "
967eb82ff87SDaniel Beauregard 				    "address registers", QL_NAME, instance);
968eb82ff87SDaniel Beauregard 				goto attach_failed;
969eb82ff87SDaniel Beauregard 			} else {
970eb82ff87SDaniel Beauregard 				ha->pci_bus_addr = ptr[0];
971eb82ff87SDaniel Beauregard 				ha->function_number = (uint8_t)