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