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 *
88f23e9faSHans Rosenfeld * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld * http://www.opensource.org/licenses/cddl1.txt.
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
22fcf3ce44SJohn Forte /*
238f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan * Use is subject to license terms.
25a3170057SPaul Winder * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26a3170057SPaul Winder * Copyright 2020 RackTop Systems, Inc.
27fcf3ce44SJohn Forte */
28fcf3ce44SJohn Forte
2982527734SSukumar Swaminathan #define EMLXS_FW_TABLE_DEF
3082527734SSukumar Swaminathan #define EMLXS_MODEL_DEF
31fcf3ce44SJohn Forte
3282527734SSukumar Swaminathan #include <emlxs.h>
33fcf3ce44SJohn Forte
3482527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3582527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_HBA_C);
36fcf3ce44SJohn Forte
37a9800bebSGarrett D'Amore
3882527734SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
3982527734SSukumar Swaminathan IOCBQ *iocbq);
40291a2b48SSukumar Swaminathan
41a9800bebSGarrett D'Amore static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
42a9800bebSGarrett D'Amore
43fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
4482527734SSukumar Swaminathan uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
4582527734SSukumar Swaminathan {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
4682527734SSukumar Swaminathan uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
4782527734SSukumar Swaminathan {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
4882527734SSukumar Swaminathan EMLXS_MSI0_MASK8};
49291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
50fcf3ce44SJohn Forte
5182527734SSukumar Swaminathan emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
5282527734SSukumar Swaminathan int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
53291a2b48SSukumar Swaminathan
54a9800bebSGarrett D'Amore emlxs_table_t emlxs_pci_cap[] = {
55a9800bebSGarrett D'Amore {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
56a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
57a9800bebSGarrett D'Amore {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
58a9800bebSGarrett D'Amore {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
59a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
60a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
61a9800bebSGarrett D'Amore {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
62a9800bebSGarrett D'Amore {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
63a9800bebSGarrett D'Amore {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
64a9800bebSGarrett D'Amore {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
65a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
66a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
67a9800bebSGarrett D'Amore {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
68a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
69a9800bebSGarrett D'Amore {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
70a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
71a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
72a9800bebSGarrett D'Amore {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
73a9800bebSGarrett D'Amore {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
74a9800bebSGarrett D'Amore
75a9800bebSGarrett D'Amore }; /* emlxs_pci_cap */
76a9800bebSGarrett D'Amore
778f23e9faSHans Rosenfeld emlxs_table_t emlxs_pci_ecap[] = {
788f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_AER, "PCIE_EXT_CAP_ID_AER"},
798f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC, "PCIE_EXT_CAP_ID_VC"},
808f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_SER, "PCIE_EXT_CAP_ID_SER"},
818f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_PWR_BUDGET, "PCIE_EXT_CAP_ID_PWR_BUDGET"},
828f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_LINK_DECL, "PCIE_EXT_CAP_ID_RC_LINK_DECL"},
838f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "PCIE_EXT_CAP_ID_RC_INT_LINKCTRL"},
848f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_EVNT_CEA, "PCIE_EXT_CAP_ID_RC_EVNT_CEA"},
858f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_MFVC, "PCIE_EXT_CAP_ID_MFVC"},
868f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC_WITH_MFVC, "PCIE_EXT_CAP_ID_VC_WITH_MFVC"},
878f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RCRB, "PCIE_EXT_CAP_ID_RCRB"},
888f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VS, "PCIE_EXT_CAP_ID_VS"},
898f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_CAC, "PCIE_EXT_CAP_ID_CAC"},
908f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ACS, "PCIE_EXT_CAP_ID_ACS"},
918f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ARI, "PCIE_EXT_CAP_ID_ARI"},
928f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ATS, "PCIE_EXT_CAP_ID_ATS"},
938f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SRIOV, "PCI_EXT_CAP_ID_SRIOV"},
948f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_TPH, "PCI_EXT_CAP_ID_TPH"},
958f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SEC_PCI, "PCI_EXT_CAP_ID_SEC_PCI"}
968f23e9faSHans Rosenfeld
978f23e9faSHans Rosenfeld }; /* emlxs_pci_ecap */
988f23e9faSHans Rosenfeld
998f23e9faSHans Rosenfeld
10082527734SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = {
10182527734SSukumar Swaminathan {FC_FCP_RING, "FCP Ring"},
10282527734SSukumar Swaminathan {FC_IP_RING, "IP Ring"},
10382527734SSukumar Swaminathan {FC_ELS_RING, "ELS Ring"},
10482527734SSukumar Swaminathan {FC_CT_RING, "CT Ring"}
105291a2b48SSukumar Swaminathan
10682527734SSukumar Swaminathan }; /* emlxs_ring_table */
107fcf3ce44SJohn Forte
10882527734SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = {
10982527734SSukumar Swaminathan {0, "NULL"},
11082527734SSukumar Swaminathan {FC_ERROR, "ERROR"},
11182527734SSukumar Swaminathan {FC_KILLED, "KILLED"},
11282527734SSukumar Swaminathan {FC_WARM_START, "WARM_START"},
11382527734SSukumar Swaminathan {FC_INIT_START, "INIT_START"},
11482527734SSukumar Swaminathan {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
11582527734SSukumar Swaminathan {FC_INIT_REV, "INIT_REV"},
11682527734SSukumar Swaminathan {FC_INIT_CFGPORT, "INIT_CFGPORT"},
11782527734SSukumar Swaminathan {FC_INIT_CFGRING, "INIT_CFGRING"},
11882527734SSukumar Swaminathan {FC_INIT_INITLINK, "INIT_INITLINK"},
11982527734SSukumar Swaminathan {FC_LINK_DOWN, "LINK_DOWN"},
12082527734SSukumar Swaminathan {FC_LINK_UP, "LINK_UP"},
12182527734SSukumar Swaminathan {FC_CLEAR_LA, "CLEAR_LA"},
12282527734SSukumar Swaminathan {FC_READY, "READY"}
123fcf3ce44SJohn Forte
12482527734SSukumar Swaminathan }; /* emlxs_ffstate_table */
125fcf3ce44SJohn Forte
126fcf3ce44SJohn Forte
127fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
128fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
129fcf3ce44SJohn Forte int32_t
emlxs_msi_init(emlxs_hba_t * hba,uint32_t max)130fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
131fcf3ce44SJohn Forte {
132fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
133fcf3ce44SJohn Forte int32_t pass = 0;
134fcf3ce44SJohn Forte int32_t type = 0;
135fcf3ce44SJohn Forte char s_type[16];
136fcf3ce44SJohn Forte int32_t types;
137fcf3ce44SJohn Forte int32_t count;
138fcf3ce44SJohn Forte int32_t nintrs;
139fcf3ce44SJohn Forte int32_t mode;
140fcf3ce44SJohn Forte int32_t actual;
141fcf3ce44SJohn Forte int32_t new_actual;
142fcf3ce44SJohn Forte int32_t i;
143fcf3ce44SJohn Forte int32_t ret;
144fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL;
145fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL;
146fcf3ce44SJohn Forte uint32_t *intr_pri = NULL;
147fcf3ce44SJohn Forte int32_t *intr_cap = NULL;
148fcf3ce44SJohn Forte int32_t hilevel_pri;
149fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG;
150fcf3ce44SJohn Forte
151fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
152fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max));
153fcf3ce44SJohn Forte }
154291a2b48SSukumar Swaminathan
155fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) {
156fcf3ce44SJohn Forte return (DDI_SUCCESS);
157fcf3ce44SJohn Forte }
158291a2b48SSukumar Swaminathan
159fcf3ce44SJohn Forte /* Set max interrupt count if not specified */
160fcf3ce44SJohn Forte if (max == 0) {
161fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) ||
162fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) {
163fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS;
164fcf3ce44SJohn Forte } else {
165fcf3ce44SJohn Forte max = 1;
166fcf3ce44SJohn Forte }
167fcf3ce44SJohn Forte }
168291a2b48SSukumar Swaminathan
169fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */
170fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
171fcf3ce44SJohn Forte max = hba->model_info.intr_limit;
172fcf3ce44SJohn Forte }
173291a2b48SSukumar Swaminathan
174fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */
175fcf3ce44SJohn Forte types = 0;
176fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types);
177fcf3ce44SJohn Forte
178fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) {
179fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
180fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
181fcf3ce44SJohn Forte
182fcf3ce44SJohn Forte /* Default to fixed type */
183fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED;
184fcf3ce44SJohn Forte }
185291a2b48SSukumar Swaminathan
186fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */
187fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) {
188fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED;
189fcf3ce44SJohn Forte }
190291a2b48SSukumar Swaminathan
191fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */
192fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) ||
193fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) {
194fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
195fcf3ce44SJohn Forte }
196291a2b48SSukumar Swaminathan
197fcf3ce44SJohn Forte begin:
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */
200fcf3ce44SJohn Forte type = 0;
201fcf3ce44SJohn Forte
202fcf3ce44SJohn Forte /* Check if MSIX is fully supported */
203fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) &&
204fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
205fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
206fcf3ce44SJohn Forte nintrs = 0;
207fcf3ce44SJohn Forte ret =
208291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
209291a2b48SSukumar Swaminathan &nintrs);
210fcf3ce44SJohn Forte
211fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) {
212fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX;
2138f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSIX", sizeof (s_type));
214fcf3ce44SJohn Forte goto initialize;
215fcf3ce44SJohn Forte }
216fcf3ce44SJohn Forte }
217291a2b48SSukumar Swaminathan
218fcf3ce44SJohn Forte /* Check if MSI is fully supported */
219fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) &&
220fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
221fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
222fcf3ce44SJohn Forte nintrs = 0;
223291a2b48SSukumar Swaminathan ret =
224291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
225fcf3ce44SJohn Forte
226fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) {
227fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI;
2288f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSI", sizeof (s_type));
229fcf3ce44SJohn Forte goto initialize;
230fcf3ce44SJohn Forte }
231fcf3ce44SJohn Forte }
232291a2b48SSukumar Swaminathan
233fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */
234fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) &&
235fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
236fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
237fcf3ce44SJohn Forte nintrs = 0;
238fcf3ce44SJohn Forte ret =
239291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
240291a2b48SSukumar Swaminathan &nintrs);
241fcf3ce44SJohn Forte
242fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) {
243fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED;
2448f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_FIXED", sizeof (s_type));
245fcf3ce44SJohn Forte goto initialize;
246fcf3ce44SJohn Forte }
247fcf3ce44SJohn Forte }
248291a2b48SSukumar Swaminathan
249fcf3ce44SJohn Forte goto init_failed;
250fcf3ce44SJohn Forte
251fcf3ce44SJohn Forte
252fcf3ce44SJohn Forte initialize:
253fcf3ce44SJohn Forte
254fcf3ce44SJohn Forte pass++;
255fcf3ce44SJohn Forte mode = 0;
256fcf3ce44SJohn Forte actual = 0;
257fcf3ce44SJohn Forte htable = NULL;
258fcf3ce44SJohn Forte intr_pri = NULL;
259fcf3ce44SJohn Forte intr_cap = NULL;
260fcf3ce44SJohn Forte hilevel_pri = 0;
261fcf3ce44SJohn Forte
262fcf3ce44SJohn Forte if (pass == 1) {
263fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
264291a2b48SSukumar Swaminathan "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
265291a2b48SSukumar Swaminathan cfg[CFG_MSI_MODE].current, types, nintrs);
266fcf3ce44SJohn Forte }
267291a2b48SSukumar Swaminathan
268fcf3ce44SJohn Forte /* Validate interrupt count */
269fcf3ce44SJohn Forte count = min(nintrs, max);
270fcf3ce44SJohn Forte
271fcf3ce44SJohn Forte if (count >= 8) {
272fcf3ce44SJohn Forte count = 8;
273fcf3ce44SJohn Forte } else if (count >= 4) {
274fcf3ce44SJohn Forte count = 4;
275fcf3ce44SJohn Forte } else if (count >= 2) {
276fcf3ce44SJohn Forte count = 2;
277fcf3ce44SJohn Forte } else {
278fcf3ce44SJohn Forte count = 1;
279fcf3ce44SJohn Forte }
280fcf3ce44SJohn Forte
281fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */
282fcf3ce44SJohn Forte htable =
283291a2b48SSukumar Swaminathan kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
284291a2b48SSukumar Swaminathan KM_SLEEP);
285fcf3ce44SJohn Forte
286fcf3ce44SJohn Forte /* Allocate 'count' interrupts */
287291a2b48SSukumar Swaminathan ret =
288291a2b48SSukumar Swaminathan ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
289fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL);
290fcf3ce44SJohn Forte
291fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
29282527734SSukumar Swaminathan "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
293fcf3ce44SJohn Forte
294fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) {
295fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
296fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret);
297fcf3ce44SJohn Forte
298a9800bebSGarrett D'Amore actual = 0;
299fcf3ce44SJohn Forte goto init_failed;
300fcf3ce44SJohn Forte }
301291a2b48SSukumar Swaminathan
302fcf3ce44SJohn Forte if (actual != count) {
303fcf3ce44SJohn Forte /* Validate actual count */
304fcf3ce44SJohn Forte if (actual >= 8) {
305fcf3ce44SJohn Forte new_actual = 8;
306fcf3ce44SJohn Forte } else if (actual >= 4) {
307fcf3ce44SJohn Forte new_actual = 4;
308fcf3ce44SJohn Forte } else if (actual >= 2) {
309fcf3ce44SJohn Forte new_actual = 2;
310fcf3ce44SJohn Forte } else {
311fcf3ce44SJohn Forte new_actual = 1;
312fcf3ce44SJohn Forte }
313fcf3ce44SJohn Forte
314fcf3ce44SJohn Forte if (new_actual < actual) {
315fcf3ce44SJohn Forte /* Free extra handles */
316fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) {
317fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]);
318fcf3ce44SJohn Forte }
319fcf3ce44SJohn Forte
320fcf3ce44SJohn Forte actual = new_actual;
321fcf3ce44SJohn Forte }
322291a2b48SSukumar Swaminathan
323fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */
324fcf3ce44SJohn Forte new_htable =
325fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
326fcf3ce44SJohn Forte KM_SLEEP);
327fcf3ce44SJohn Forte
328fcf3ce44SJohn Forte /* Copy old array to new array */
329fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable,
330fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t)));
331fcf3ce44SJohn Forte
332fcf3ce44SJohn Forte /* Free the old array */
333fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
334fcf3ce44SJohn Forte
335fcf3ce44SJohn Forte htable = new_htable;
336fcf3ce44SJohn Forte count = actual;
337fcf3ce44SJohn Forte }
338291a2b48SSukumar Swaminathan
339fcf3ce44SJohn Forte /* Allocate interrupt priority table */
340fcf3ce44SJohn Forte intr_pri =
341fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
342fcf3ce44SJohn Forte KM_SLEEP);
343fcf3ce44SJohn Forte
344fcf3ce44SJohn Forte /* Allocate interrupt capability table */
345fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
346fcf3ce44SJohn Forte
347fcf3ce44SJohn Forte /* Get minimum hilevel priority */
348fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri();
349fcf3ce44SJohn Forte
350fcf3ce44SJohn Forte /* Fill the priority and capability tables */
351fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
352fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
353fcf3ce44SJohn Forte
354fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
355fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
356fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. "
357291a2b48SSukumar Swaminathan "handle=%p ret=%d",
358291a2b48SSukumar Swaminathan i, &htable[i], ret);
359fcf3ce44SJohn Forte
360fcf3ce44SJohn Forte /* Clean up the interrupts */
361fcf3ce44SJohn Forte goto init_failed;
362fcf3ce44SJohn Forte }
363291a2b48SSukumar Swaminathan
364fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) {
365fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
366fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. "
367fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x",
368fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri);
369fcf3ce44SJohn Forte
370fcf3ce44SJohn Forte /* Clean up the interrupts */
371fcf3ce44SJohn Forte goto init_failed;
372fcf3ce44SJohn Forte }
373291a2b48SSukumar Swaminathan
374fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
375fcf3ce44SJohn Forte
376fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
377fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
378291a2b48SSukumar Swaminathan "MSI: ddi_intr_get_cap(%d) failed. "
379291a2b48SSukumar Swaminathan "handle=%p ret=%d",
380291a2b48SSukumar Swaminathan i, &htable[i], ret);
381fcf3ce44SJohn Forte
382fcf3ce44SJohn Forte /* Clean up the interrupts */
383fcf3ce44SJohn Forte goto init_failed;
384fcf3ce44SJohn Forte }
385291a2b48SSukumar Swaminathan
386fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
387291a2b48SSukumar Swaminathan "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
388291a2b48SSukumar Swaminathan intr_cap[i], intr_pri[i], hilevel_pri);
389fcf3ce44SJohn Forte
390fcf3ce44SJohn Forte }
391fcf3ce44SJohn Forte
392fcf3ce44SJohn Forte /* Set mode */
393fcf3ce44SJohn Forte switch (count) {
394fcf3ce44SJohn Forte case 8:
395fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8;
396fcf3ce44SJohn Forte break;
397fcf3ce44SJohn Forte
398fcf3ce44SJohn Forte case 4:
399fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4;
400fcf3ce44SJohn Forte break;
401fcf3ce44SJohn Forte
402fcf3ce44SJohn Forte case 2:
403fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2;
404fcf3ce44SJohn Forte break;
405fcf3ce44SJohn Forte
406fcf3ce44SJohn Forte default:
407fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1;
408fcf3ce44SJohn Forte }
409fcf3ce44SJohn Forte
410fcf3ce44SJohn Forte /* Save the info */
411fcf3ce44SJohn Forte hba->intr_htable = htable;
412fcf3ce44SJohn Forte hba->intr_count = count;
413fcf3ce44SJohn Forte hba->intr_pri = intr_pri;
414fcf3ce44SJohn Forte hba->intr_cap = intr_cap;
415fcf3ce44SJohn Forte hba->intr_type = type;
416291a2b48SSukumar Swaminathan hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
417fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode];
418fcf3ce44SJohn Forte
419fcf3ce44SJohn Forte hba->intr_cond = 0;
42082527734SSukumar Swaminathan
42182527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */
42282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
42382527734SSukumar Swaminathan hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
42482527734SSukumar Swaminathan }
42582527734SSukumar Swaminathan
426fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
427fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i];
428fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i];
429fcf3ce44SJohn Forte
4308f23e9faSHans Rosenfeld mutex_init(&hba->intr_lock[i], NULL, MUTEX_DRIVER,
431a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
432fcf3ce44SJohn Forte }
433fcf3ce44SJohn Forte
434fcf3ce44SJohn Forte /* Set flag to indicate support */
435fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED;
436fcf3ce44SJohn Forte
437fcf3ce44SJohn Forte /* Create the interrupt threads */
43882527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
4398f23e9faSHans Rosenfeld mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER,
440a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
441fcf3ce44SJohn Forte
44282527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread);
443fcf3ce44SJohn Forte }
444fcf3ce44SJohn Forte
445fcf3ce44SJohn Forte return (DDI_SUCCESS);
446fcf3ce44SJohn Forte
447fcf3ce44SJohn Forte init_failed:
448fcf3ce44SJohn Forte
449fcf3ce44SJohn Forte if (intr_cap) {
450fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t)));
451fcf3ce44SJohn Forte }
452291a2b48SSukumar Swaminathan
453fcf3ce44SJohn Forte if (intr_pri) {
454fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t)));
455fcf3ce44SJohn Forte }
456291a2b48SSukumar Swaminathan
457fcf3ce44SJohn Forte if (htable) {
458fcf3ce44SJohn Forte /* Process the interrupt handlers */
459fcf3ce44SJohn Forte for (i = 0; i < actual; i++) {
460fcf3ce44SJohn Forte /* Free the handle[i] */
461fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]);
462fcf3ce44SJohn Forte }
463fcf3ce44SJohn Forte
464fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
465fcf3ce44SJohn Forte }
466291a2b48SSukumar Swaminathan
467fcf3ce44SJohn Forte /* Initialize */
468fcf3ce44SJohn Forte hba->intr_htable = NULL;
469fcf3ce44SJohn Forte hba->intr_count = 0;
470fcf3ce44SJohn Forte hba->intr_pri = NULL;
471fcf3ce44SJohn Forte hba->intr_cap = NULL;
472fcf3ce44SJohn Forte hba->intr_type = 0;
473fcf3ce44SJohn Forte hba->intr_arg = NULL;
474fcf3ce44SJohn Forte hba->intr_cond = 0;
475fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map));
476fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock));
477fcf3ce44SJohn Forte
478fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) {
479fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
480fcf3ce44SJohn Forte goto begin;
481fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) {
482fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED;
483fcf3ce44SJohn Forte goto begin;
484fcf3ce44SJohn Forte }
485291a2b48SSukumar Swaminathan
486fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
487fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts");
488fcf3ce44SJohn Forte
489fcf3ce44SJohn Forte return (DDI_FAILURE);
490fcf3ce44SJohn Forte
491fcf3ce44SJohn Forte
49282527734SSukumar Swaminathan } /* emlxs_msi_init() */
493fcf3ce44SJohn Forte
494fcf3ce44SJohn Forte
495fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
496fcf3ce44SJohn Forte int32_t
emlxs_msi_uninit(emlxs_hba_t * hba)497fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba)
498fcf3ce44SJohn Forte {
499fcf3ce44SJohn Forte uint32_t count;
500fcf3ce44SJohn Forte int32_t i;
501fcf3ce44SJohn Forte ddi_intr_handle_t *htable;
502fcf3ce44SJohn Forte uint32_t *intr_pri;
503fcf3ce44SJohn Forte int32_t *intr_cap;
504fcf3ce44SJohn Forte int32_t ret;
505fcf3ce44SJohn Forte
506fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
507fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba));
508fcf3ce44SJohn Forte }
509291a2b48SSukumar Swaminathan
510fcf3ce44SJohn Forte /*
511291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5128f23e9faSHans Rosenfeld * "MSI: msi_uninit called. flags=%x",
513291a2b48SSukumar Swaminathan * hba->intr_flags);
514fcf3ce44SJohn Forte */
515fcf3ce44SJohn Forte
516fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */
517fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
518fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba);
519fcf3ce44SJohn Forte
520fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
521fcf3ce44SJohn Forte return (ret);
522fcf3ce44SJohn Forte }
523fcf3ce44SJohn Forte }
524291a2b48SSukumar Swaminathan
525fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */
526fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
527fcf3ce44SJohn Forte return (DDI_SUCCESS);
528fcf3ce44SJohn Forte }
529fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED;
530fcf3ce44SJohn Forte
531fcf3ce44SJohn Forte /* Get handle table parameters */
532fcf3ce44SJohn Forte htable = hba->intr_htable;
533fcf3ce44SJohn Forte count = hba->intr_count;
534fcf3ce44SJohn Forte intr_pri = hba->intr_pri;
535fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
536fcf3ce44SJohn Forte
537fcf3ce44SJohn Forte /* Clean up */
538fcf3ce44SJohn Forte hba->intr_count = 0;
539fcf3ce44SJohn Forte hba->intr_htable = NULL;
540fcf3ce44SJohn Forte hba->intr_pri = NULL;
541fcf3ce44SJohn Forte hba->intr_cap = NULL;
542fcf3ce44SJohn Forte hba->intr_type = 0;
543fcf3ce44SJohn Forte hba->intr_arg = NULL;
544fcf3ce44SJohn Forte hba->intr_cond = 0;
545fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map));
546fcf3ce44SJohn Forte
547fcf3ce44SJohn Forte if (intr_cap) {
548fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t)));
549fcf3ce44SJohn Forte }
550291a2b48SSukumar Swaminathan
551fcf3ce44SJohn Forte if (intr_pri) {
552fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t)));
553fcf3ce44SJohn Forte }
554291a2b48SSukumar Swaminathan
555fcf3ce44SJohn Forte if (htable) {
556fcf3ce44SJohn Forte /* Process the interrupt handlers */
557fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
558fcf3ce44SJohn Forte /* Free the handle[i] */
559291a2b48SSukumar Swaminathan ret = ddi_intr_free(htable[i]);
560fcf3ce44SJohn Forte }
561fcf3ce44SJohn Forte
562fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
563fcf3ce44SJohn Forte }
564291a2b48SSukumar Swaminathan
565fcf3ce44SJohn Forte /* Destroy the intr locks */
566fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
567fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]);
568fcf3ce44SJohn Forte }
569fcf3ce44SJohn Forte
570fcf3ce44SJohn Forte /* Destroy the interrupt threads */
57182527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
57282527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread);
57382527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock);
574fcf3ce44SJohn Forte }
575fcf3ce44SJohn Forte
576fcf3ce44SJohn Forte /*
577291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5788f23e9faSHans Rosenfeld * "MSI: msi_uninit done. flags=%x",
579291a2b48SSukumar Swaminathan * hba->intr_flags);
580fcf3ce44SJohn Forte */
581fcf3ce44SJohn Forte
582fcf3ce44SJohn Forte return (DDI_SUCCESS);
583fcf3ce44SJohn Forte
58482527734SSukumar Swaminathan } /* emlxs_msi_uninit() */
585fcf3ce44SJohn Forte
586fcf3ce44SJohn Forte
587fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */
588fcf3ce44SJohn Forte int32_t
emlxs_msi_add(emlxs_hba_t * hba)589fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba)
590fcf3ce44SJohn Forte {
591fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
592fcf3ce44SJohn Forte int32_t count;
593fcf3ce44SJohn Forte int32_t i;
594fcf3ce44SJohn Forte int32_t ret;
595fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL;
596fcf3ce44SJohn Forte int32_t *intr_cap = NULL;
597fcf3ce44SJohn Forte
598fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
599fcf3ce44SJohn Forte return (emlxs_intx_add(hba));
600fcf3ce44SJohn Forte }
601291a2b48SSukumar Swaminathan
602fcf3ce44SJohn Forte /* Check if interrupts have already been added */
603fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) {
604fcf3ce44SJohn Forte return (DDI_SUCCESS);
605fcf3ce44SJohn Forte }
606291a2b48SSukumar Swaminathan
607fcf3ce44SJohn Forte /* Check if interrupts have been initialized */
608fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
609fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0);
610fcf3ce44SJohn Forte
611fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
612fcf3ce44SJohn Forte return (ret);
613fcf3ce44SJohn Forte }
614fcf3ce44SJohn Forte }
615291a2b48SSukumar Swaminathan
616fcf3ce44SJohn Forte /* Get handle table parameters */
617fcf3ce44SJohn Forte htable = hba->intr_htable;
618fcf3ce44SJohn Forte count = hba->intr_count;
619fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
620fcf3ce44SJohn Forte
621fcf3ce44SJohn Forte /* Add the interrupt handlers */
622fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
623fcf3ce44SJohn Forte /* add handler for handle[i] */
624291a2b48SSukumar Swaminathan ret =
62582527734SSukumar Swaminathan ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
626291a2b48SSukumar Swaminathan (char *)hba, (char *)((unsigned long)i));
627fcf3ce44SJohn Forte
628fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
629fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
630291a2b48SSukumar Swaminathan "MSI: ddi_intr_add_handler(%d) failed. "
631291a2b48SSukumar Swaminathan "handle=%p ret=%d",
632291a2b48SSukumar Swaminathan i, &htable[i], ret);
633fcf3ce44SJohn Forte
634fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */
635fcf3ce44SJohn Forte while (i) {
636fcf3ce44SJohn Forte /* Decrement i */
637fcf3ce44SJohn Forte i--;
638fcf3ce44SJohn Forte
639fcf3ce44SJohn Forte /* Remove the handler */
640fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]);
641fcf3ce44SJohn Forte
642fcf3ce44SJohn Forte }
643fcf3ce44SJohn Forte
644fcf3ce44SJohn Forte return (DDI_FAILURE);
645fcf3ce44SJohn Forte }
646fcf3ce44SJohn Forte }
647fcf3ce44SJohn Forte
648fcf3ce44SJohn Forte /* Enable the interrupts */
649fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
650fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count);
651fcf3ce44SJohn Forte
652fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
653fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
654fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
655fcf3ce44SJohn Forte count, ret);
656fcf3ce44SJohn Forte
657fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
658fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]);
659fcf3ce44SJohn Forte
660fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
661fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
662fcf3ce44SJohn Forte &emlxs_init_debug_msg,
663fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. "
664291a2b48SSukumar Swaminathan "ret=%d",
665291a2b48SSukumar Swaminathan i, ret);
666fcf3ce44SJohn Forte }
667fcf3ce44SJohn Forte }
668fcf3ce44SJohn Forte }
669fcf3ce44SJohn Forte } else {
670fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
671fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]);
672fcf3ce44SJohn Forte
673fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
674291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT,
675291a2b48SSukumar Swaminathan &emlxs_init_debug_msg,
676fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d",
677fcf3ce44SJohn Forte i, ret);
678fcf3ce44SJohn Forte }
679fcf3ce44SJohn Forte }
680fcf3ce44SJohn Forte }
681fcf3ce44SJohn Forte
682fcf3ce44SJohn Forte
683fcf3ce44SJohn Forte /* Set flag to indicate support */
684fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED;
685fcf3ce44SJohn Forte
686fcf3ce44SJohn Forte return (DDI_SUCCESS);
687fcf3ce44SJohn Forte
68882527734SSukumar Swaminathan } /* emlxs_msi_add() */
689fcf3ce44SJohn Forte
690fcf3ce44SJohn Forte
691fcf3ce44SJohn Forte
692fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
693fcf3ce44SJohn Forte int32_t
emlxs_msi_remove(emlxs_hba_t * hba)694fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba)
695fcf3ce44SJohn Forte {
696fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
697fcf3ce44SJohn Forte uint32_t count;
698fcf3ce44SJohn Forte int32_t i;
699fcf3ce44SJohn Forte ddi_intr_handle_t *htable;
700fcf3ce44SJohn Forte int32_t *intr_cap;
701fcf3ce44SJohn Forte int32_t ret;
702fcf3ce44SJohn Forte
703fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
704fcf3ce44SJohn Forte return (emlxs_intx_remove(hba));
705fcf3ce44SJohn Forte }
706291a2b48SSukumar Swaminathan
707fcf3ce44SJohn Forte /*
708291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
7098f23e9faSHans Rosenfeld * "MSI: msi_remove called. flags=%x",
710291a2b48SSukumar Swaminathan * hba->intr_flags);
711fcf3ce44SJohn Forte */
712fcf3ce44SJohn Forte
713fcf3ce44SJohn Forte /* Check if interrupts have already been removed */
714fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
715fcf3ce44SJohn Forte return (DDI_SUCCESS);
716fcf3ce44SJohn Forte }
717fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED;
718fcf3ce44SJohn Forte
719fcf3ce44SJohn Forte /* Disable all adapter interrupts */
72082527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0);
721fcf3ce44SJohn Forte
722fcf3ce44SJohn Forte /* Get handle table parameters */
723fcf3ce44SJohn Forte htable = hba->intr_htable;
724fcf3ce44SJohn Forte count = hba->intr_count;
725fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
726fcf3ce44SJohn Forte
727fcf3ce44SJohn Forte /* Disable the interrupts */
728fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
729fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count);
730fcf3ce44SJohn Forte
731fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
732fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
733fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
734fcf3ce44SJohn Forte count, ret);
735fcf3ce44SJohn Forte
736fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
737fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]);
738fcf3ce44SJohn Forte
739fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
740fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
741fcf3ce44SJohn Forte &emlxs_init_debug_msg,
742fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. "
743291a2b48SSukumar Swaminathan "ret=%d",
744291a2b48SSukumar Swaminathan i, ret);
745fcf3ce44SJohn Forte }
746fcf3ce44SJohn Forte }
747fcf3ce44SJohn Forte }
748fcf3ce44SJohn Forte } else {
749fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
750fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]);
751fcf3ce44SJohn Forte
752fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
753291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT,
754291a2b48SSukumar Swaminathan &emlxs_init_debug_msg,
755fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d",
756fcf3ce44SJohn Forte i, ret);
757fcf3ce44SJohn Forte }
758fcf3ce44SJohn Forte }
759fcf3ce44SJohn Forte }
760fcf3ce44SJohn Forte
761fcf3ce44SJohn Forte /* Process the interrupt handlers */
762fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
763fcf3ce44SJohn Forte /* Remove the handler */
764fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]);
765fcf3ce44SJohn Forte
766fcf3ce44SJohn Forte
767fcf3ce44SJohn Forte }
768fcf3ce44SJohn Forte
769fcf3ce44SJohn Forte return (DDI_SUCCESS);
770fcf3ce44SJohn Forte
77182527734SSukumar Swaminathan } /* emlxs_msi_remove() */
772fcf3ce44SJohn Forte
773291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
774fcf3ce44SJohn Forte
775fcf3ce44SJohn Forte
776fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
777fcf3ce44SJohn Forte /* ARGSUSED */
778fcf3ce44SJohn Forte int32_t
emlxs_intx_init(emlxs_hba_t * hba,uint32_t max)779fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
780fcf3ce44SJohn Forte {
781fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
78282527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG;
783fcf3ce44SJohn Forte int32_t ret;
784fcf3ce44SJohn Forte uint32_t i;
785fcf3ce44SJohn Forte
786fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */
787fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) {
788fcf3ce44SJohn Forte return (DDI_SUCCESS);
789fcf3ce44SJohn Forte }
790291a2b48SSukumar Swaminathan
791fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */
792fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
793fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
794fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x",
795fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags);
796fcf3ce44SJohn Forte
797fcf3ce44SJohn Forte return (DDI_FAILURE);
798fcf3ce44SJohn Forte }
799291a2b48SSukumar Swaminathan
800fcf3ce44SJohn Forte /*
801291a2b48SSukumar Swaminathan * Interrupt number '0' is a high-level interrupt. This driver
802291a2b48SSukumar Swaminathan * does not support having its interrupts mapped above scheduler
803291a2b48SSukumar Swaminathan * priority; i.e., we always expect to be able to call general
804291a2b48SSukumar Swaminathan * kernel routines that may invoke the scheduler.
805fcf3ce44SJohn Forte */
806fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
807fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
808fcf3ce44SJohn Forte "INTX: High-level interrupt not supported.");
809fcf3ce44SJohn Forte
810fcf3ce44SJohn Forte return (DDI_FAILURE);
811fcf3ce44SJohn Forte }
812291a2b48SSukumar Swaminathan
813fcf3ce44SJohn Forte /* Get an iblock cookie */
814291a2b48SSukumar Swaminathan ret =
815291a2b48SSukumar Swaminathan ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER,
816fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg);
817fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
818fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
819fcf3ce44SJohn Forte "INTX: ddi_get_iblock_cookie failed. ret=%d", ret);
820fcf3ce44SJohn Forte
821fcf3ce44SJohn Forte return (ret);
822fcf3ce44SJohn Forte }
823291a2b48SSukumar Swaminathan
824fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_INITED;
825fcf3ce44SJohn Forte
82682527734SSukumar Swaminathan hba->intr_count = 1;
82782527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */
82882527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
82982527734SSukumar Swaminathan hba->chan_count = cfg[CFG_NUM_WQ].current;
83082527734SSukumar Swaminathan }
83182527734SSukumar Swaminathan
832fcf3ce44SJohn Forte /* Create the interrupt threads */
83382527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
8348f23e9faSHans Rosenfeld mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER,
835a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
836fcf3ce44SJohn Forte
83782527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread);
838fcf3ce44SJohn Forte }
839fcf3ce44SJohn Forte
840fcf3ce44SJohn Forte return (DDI_SUCCESS);
841fcf3ce44SJohn Forte
84282527734SSukumar Swaminathan } /* emlxs_intx_init() */
843fcf3ce44SJohn Forte
844fcf3ce44SJohn Forte
845fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
846fcf3ce44SJohn Forte int32_t
emlxs_intx_uninit(emlxs_hba_t * hba)847fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba)
848fcf3ce44SJohn Forte {
849fcf3ce44SJohn Forte int32_t ret;
850fcf3ce44SJohn Forte uint32_t i;
851fcf3ce44SJohn Forte
852fcf3ce44SJohn Forte /* Make sure interrupts have been removed */
853fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_INTX_ADDED)) {
854fcf3ce44SJohn Forte ret = emlxs_intx_remove(hba);
855fcf3ce44SJohn Forte
856fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
857fcf3ce44SJohn Forte return (ret);
858fcf3ce44SJohn Forte }
859fcf3ce44SJohn Forte }
860291a2b48SSukumar Swaminathan
861fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */
862fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
863fcf3ce44SJohn Forte return (DDI_SUCCESS);
864fcf3ce44SJohn Forte }
865fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_INITED;
866fcf3ce44SJohn Forte
867fcf3ce44SJohn Forte hba->intr_arg = NULL;
868fcf3ce44SJohn Forte
869fcf3ce44SJohn Forte /* Create the interrupt threads */
87082527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
87182527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread);
87282527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock);
873fcf3ce44SJohn Forte }
874fcf3ce44SJohn Forte
875fcf3ce44SJohn Forte return (DDI_SUCCESS);
876fcf3ce44SJohn Forte
87782527734SSukumar Swaminathan } /* emlxs_intx_uninit() */
878fcf3ce44SJohn Forte
879fcf3ce44SJohn Forte
880291a2b48SSukumar Swaminathan /*
881291a2b48SSukumar Swaminathan * This is the legacy method for adding interrupts in Solaris
882291a2b48SSukumar Swaminathan * EMLXS_INTR_ADD
883291a2b48SSukumar Swaminathan */
884fcf3ce44SJohn Forte int32_t
emlxs_intx_add(emlxs_hba_t * hba)885fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba)
886fcf3ce44SJohn Forte {
887fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
888fcf3ce44SJohn Forte int32_t ret;
889fcf3ce44SJohn Forte
890fcf3ce44SJohn Forte /* Check if interrupts have already been added */
891fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_ADDED) {
892fcf3ce44SJohn Forte return (DDI_SUCCESS);
893fcf3ce44SJohn Forte }
894291a2b48SSukumar Swaminathan
895fcf3ce44SJohn Forte /* Check if interrupts have been initialized */
896fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) {
897fcf3ce44SJohn Forte ret = emlxs_intx_init(hba, 0);
898fcf3ce44SJohn Forte
899fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
900fcf3ce44SJohn Forte return (ret);
901fcf3ce44SJohn Forte }
902fcf3ce44SJohn Forte }
903291a2b48SSukumar Swaminathan
904fcf3ce44SJohn Forte /* add intrrupt handler routine */
905291a2b48SSukumar Swaminathan ret = ddi_add_intr((void *)hba->dip,
906291a2b48SSukumar Swaminathan (uint_t)EMLXS_INUMBER,
907291a2b48SSukumar Swaminathan (ddi_iblock_cookie_t *)&hba->intr_arg,
908291a2b48SSukumar Swaminathan (ddi_idevice_cookie_t *)0,
90982527734SSukumar Swaminathan (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba);
910fcf3ce44SJohn Forte
911fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
912fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg,
913fcf3ce44SJohn Forte "INTX: ddi_add_intr failed. ret=%d", ret);
914fcf3ce44SJohn Forte
915fcf3ce44SJohn Forte return (ret);
916fcf3ce44SJohn Forte }
917291a2b48SSukumar Swaminathan
918fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_ADDED;
919fcf3ce44SJohn Forte
920fcf3ce44SJohn Forte return (DDI_SUCCESS);
921fcf3ce44SJohn Forte
92282527734SSukumar Swaminathan } /* emlxs_intx_add() */
923fcf3ce44SJohn Forte
924fcf3ce44SJohn Forte
925fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
926fcf3ce44SJohn Forte int32_t
emlxs_intx_remove(emlxs_hba_t * hba)927fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba)
928fcf3ce44SJohn Forte {
929fcf3ce44SJohn Forte /* Check if interrupts have already been removed */
930fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_ADDED)) {
931fcf3ce44SJohn Forte return (DDI_SUCCESS);
932fcf3ce44SJohn Forte }
933fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_ADDED;
934fcf3ce44SJohn Forte
935fcf3ce44SJohn Forte /* Diable all adapter interrupts */
93682527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0);
937fcf3ce44SJohn Forte
938fcf3ce44SJohn Forte /* Remove the interrupt */
939fcf3ce44SJohn Forte (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER,
940fcf3ce44SJohn Forte hba->intr_arg);
941fcf3ce44SJohn Forte
942fcf3ce44SJohn Forte return (DDI_SUCCESS);
943fcf3ce44SJohn Forte
94482527734SSukumar Swaminathan } /* emlxs_intx_remove() */
945fcf3ce44SJohn Forte
946fcf3ce44SJohn Forte
94782527734SSukumar Swaminathan extern void
emlxs_process_link_speed(emlxs_hba_t * hba)948fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba)
949fcf3ce44SJohn Forte {
950fcf3ce44SJohn Forte emlxs_vpd_t *vpd;
951fcf3ce44SJohn Forte emlxs_config_t *cfg;
952fcf3ce44SJohn Forte uint32_t hi;
953fcf3ce44SJohn Forte
954fcf3ce44SJohn Forte /*
955291a2b48SSukumar Swaminathan * This routine modifies the link-speed config parameter entry
956291a2b48SSukumar Swaminathan * based on adapter capabilities
957fcf3ce44SJohn Forte */
958fcf3ce44SJohn Forte vpd = &VPD;
959fcf3ce44SJohn Forte cfg = &hba->config[CFG_LINK_SPEED];
960fcf3ce44SJohn Forte
9618f23e9faSHans Rosenfeld (void) strlcpy(cfg->help, "Select link speed. [0=Auto",
9628f23e9faSHans Rosenfeld EMLXS_CFG_HELP_SIZE);
963fcf3ce44SJohn Forte hi = 0;
964fcf3ce44SJohn Forte
965fcf3ce44SJohn Forte if (vpd->link_speed & LMT_1GB_CAPABLE) {
9668f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 1=1Gb", EMLXS_CFG_HELP_SIZE);
967fcf3ce44SJohn Forte hi = 1;
968fcf3ce44SJohn Forte }
969291a2b48SSukumar Swaminathan
970fcf3ce44SJohn Forte if (vpd->link_speed & LMT_2GB_CAPABLE) {
9718f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 2=2Gb", EMLXS_CFG_HELP_SIZE);
972fcf3ce44SJohn Forte hi = 2;
973fcf3ce44SJohn Forte }
974291a2b48SSukumar Swaminathan
975fcf3ce44SJohn Forte if (vpd->link_speed & LMT_4GB_CAPABLE) {
9768f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 4=4Gb", EMLXS_CFG_HELP_SIZE);
977fcf3ce44SJohn Forte hi = 4;
978fcf3ce44SJohn Forte }
979291a2b48SSukumar Swaminathan
980fcf3ce44SJohn Forte if (vpd->link_speed & LMT_8GB_CAPABLE) {
9818f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 8=8Gb", EMLXS_CFG_HELP_SIZE);
982fcf3ce44SJohn Forte hi = 8;
983fcf3ce44SJohn Forte }
984291a2b48SSukumar Swaminathan
985fcf3ce44SJohn Forte if (vpd->link_speed & LMT_10GB_CAPABLE) {
9868f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 10=10Gb", EMLXS_CFG_HELP_SIZE);
987fcf3ce44SJohn Forte hi = 10;
988fcf3ce44SJohn Forte }
989291a2b48SSukumar Swaminathan
9908f23e9faSHans Rosenfeld if (vpd->link_speed & LMT_16GB_CAPABLE) {
9918f23e9faSHans Rosenfeld (void) strlcat(cfg->help, ", 16=16Gb", EMLXS_CFG_HELP_SIZE);
9928f23e9faSHans Rosenfeld hi = 16;
9938f23e9faSHans Rosenfeld }
9948f23e9faSHans Rosenfeld
995a3170057SPaul Winder if (vpd->link_speed & LMT_32GB_CAPABLE) {
996a3170057SPaul Winder (void) strlcat(cfg->help, ", 32=32Gb", EMLXS_CFG_HELP_SIZE);
997a3170057SPaul Winder hi = 32;
998a3170057SPaul Winder }
999a3170057SPaul Winder
10008f23e9faSHans Rosenfeld (void) strlcat(cfg->help, "]", EMLXS_CFG_HELP_SIZE);
1001fcf3ce44SJohn Forte cfg->hi = hi;
1002fcf3ce44SJohn Forte
1003fcf3ce44SJohn Forte /* Now revalidate the current parameter setting */
1004fcf3ce44SJohn Forte cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current);
1005fcf3ce44SJohn Forte
1006fcf3ce44SJohn Forte return;
1007fcf3ce44SJohn Forte
100882527734SSukumar Swaminathan } /* emlxs_process_link_speed() */
1009fcf3ce44SJohn Forte
1010fcf3ce44SJohn Forte
1011fcf3ce44SJohn Forte /*
1012291a2b48SSukumar Swaminathan * emlxs_parse_vpd()
1013fcf3ce44SJohn Forte *
1014fcf3ce44SJohn Forte * This routine will parse the VPD data
1015fcf3ce44SJohn Forte */
1016fcf3ce44SJohn Forte extern int
emlxs_parse_vpd(emlxs_hba_t * hba,uint8_t * vpd_buf,uint32_t size)1017fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size)
1018fcf3ce44SJohn Forte {
1019fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
1020fcf3ce44SJohn Forte char tag[3];
1021fcf3ce44SJohn Forte uint8_t lenlo, lenhi;
1022fcf3ce44SJohn Forte uint32_t n;
1023fcf3ce44SJohn Forte uint16_t block_size;
1024fcf3ce44SJohn Forte uint32_t block_index = 0;
1025fcf3ce44SJohn Forte uint8_t sub_size;
1026fcf3ce44SJohn Forte uint32_t sub_index;
1027fcf3ce44SJohn Forte int32_t finished = 0;
1028fcf3ce44SJohn Forte int32_t index = 0;
1029fcf3ce44SJohn Forte char buffer[128];
1030fcf3ce44SJohn Forte emlxs_vpd_t *vpd;
1031fcf3ce44SJohn Forte
1032fcf3ce44SJohn Forte vpd = &VPD;
1033fcf3ce44SJohn Forte
1034fcf3ce44SJohn Forte
1035fcf3ce44SJohn Forte while (!finished && (block_index < size)) {
1036fcf3ce44SJohn Forte /*
1037291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1038291a2b48SSukumar Swaminathan * "block_index = %x", block_index);
1039fcf3ce44SJohn Forte */
1040fcf3ce44SJohn Forte
1041fcf3ce44SJohn Forte switch (vpd_buf[block_index]) {
1042fcf3ce44SJohn Forte case 0x82:
1043fcf3ce44SJohn Forte index = block_index;
1044fcf3ce44SJohn Forte index += 1;
1045fcf3ce44SJohn Forte lenlo = vpd_buf[index];
1046fcf3ce44SJohn Forte index += 1;
1047fcf3ce44SJohn Forte lenhi = vpd_buf[index];
1048fcf3ce44SJohn Forte index += 1;
1049fcf3ce44SJohn Forte block_index = index;
1050fcf3ce44SJohn Forte
1051fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1052fcf3ce44SJohn Forte block_index += block_size;
1053fcf3ce44SJohn Forte
1054fcf3ce44SJohn Forte /*
1055fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1056291a2b48SSukumar Swaminathan * "block_size = %x", block_size);
1057fcf3ce44SJohn Forte */
1058fcf3ce44SJohn Forte
1059fcf3ce44SJohn Forte n = sizeof (buffer);
1060fcf3ce44SJohn Forte bzero(buffer, n);
1061fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer,
1062fcf3ce44SJohn Forte (block_size < (n - 1)) ? block_size : (n - 1));
1063fcf3ce44SJohn Forte
10648f23e9faSHans Rosenfeld (void) strncpy(vpd->id, buffer, (sizeof (vpd->id)-1));
1065291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s",
1066291a2b48SSukumar Swaminathan vpd->id);
1067fcf3ce44SJohn Forte
1068fcf3ce44SJohn Forte break;
1069fcf3ce44SJohn Forte
1070fcf3ce44SJohn Forte case 0x90:
1071fcf3ce44SJohn Forte index = block_index;
1072fcf3ce44SJohn Forte index += 1;
1073fcf3ce44SJohn Forte lenlo = vpd_buf[index];
1074fcf3ce44SJohn Forte index += 1;
1075fcf3ce44SJohn Forte lenhi = vpd_buf[index];
1076fcf3ce44SJohn Forte index += 1;
1077fcf3ce44SJohn Forte block_index = index;
1078fcf3ce44SJohn Forte sub_index = index;
1079fcf3ce44SJohn Forte
1080fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo);
1081fcf3ce44SJohn Forte block_index += block_size;
1082fcf3ce44SJohn Forte
1083fcf3ce44SJohn Forte /*
1084fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1085291a2b48SSukumar Swaminathan * "block_size = %x", block_size);
1086fcf3ce44SJohn Forte */
1087fcf3ce44SJohn Forte
1088fcf3ce44SJohn Forte /* Scan for sub-blocks */
1089fcf3ce44SJohn Forte while ((sub_index < block_index) &&
1090fcf3ce44SJohn Forte (sub_index < size)) {
1091fcf3ce44SJohn Forte /*
1092fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1093291a2b48SSukumar Swaminathan * "sub_index = %x", sub_index);
1094fcf3ce44SJohn Forte */
1095fcf3ce44SJohn Forte
1096fcf3ce44SJohn Forte index = sub_index;
1097fcf3ce44SJohn Forte tag[0] = vpd_buf[index++];
1098fcf3ce44SJohn Forte tag[1] = vpd_buf[index++];
1099fcf3ce44SJohn Forte tag[2] = 0;
1100fcf3ce44SJohn Forte sub_size = vpd_buf[index++];
1101fcf3ce44SJohn Forte
1102fcf3ce44SJohn Forte /*
1103fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1104291a2b48SSukumar Swaminathan * "sub_size = %x", sub_size);
1105fcf3ce44SJohn Forte */
1106fcf3ce44SJohn Forte
1107fcf3ce44SJohn Forte sub_index = (index + sub_size);
1108fcf3ce44SJohn Forte
1109fcf3ce44SJohn Forte n = sizeof (buffer);
1110fcf3ce44SJohn Forte bzero(buffer, n);
1111fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer,
1112fcf3ce44SJohn Forte (sub_size < (n - 1)) ? sub_size : (n - 1));
1113fcf3ce44SJohn Forte
1114fcf3ce44SJohn Forte /*
1115fcf3ce44SJohn Forte * Look for Engineering Change (EC)
1116fcf3ce44SJohn Forte */
1117fcf3ce44SJohn Forte if (strcmp(tag, "EC") == 0) {
11188f23e9faSHans Rosenfeld (void) strncpy(vpd->eng_change, buffer,
11198f23e9faSHans Rosenfeld (sizeof (vpd->eng_change)-1));
1120fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1121291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "EC: %s",
1122291a2b48SSukumar Swaminathan vpd->eng_change);
1123fcf3ce44SJohn Forte }
1124fcf3ce44SJohn Forte /*
1125fcf3ce44SJohn Forte * Look for Manufacturer (MN)
1126fcf3ce44SJohn Forte */
1127fcf3ce44SJohn Forte else if (strcmp(tag, "MN") == 0) {
11288f23e9faSHans Rosenfeld (void) strncpy(vpd->manufacturer,
11298f23e9faSHans Rosenfeld buffer,
11308f23e9faSHans Rosenfeld (sizeof (vpd->manufacturer)-1));
1131fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1132291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "MN: %s",
1133291a2b48SSukumar Swaminathan vpd->manufacturer);
1134fcf3ce44SJohn Forte }
1135fcf3ce44SJohn Forte /*
1136fcf3ce44SJohn Forte * Look for Serial Number (SN)
1137fcf3ce44SJohn Forte */
1138fcf3ce44SJohn Forte else if (strcmp(tag, "SN") == 0) {
11398f23e9faSHans Rosenfeld (void) strncpy(vpd->serial_num, buffer,
11408f23e9faSHans Rosenfeld (sizeof (vpd->serial_num)-1));
1141fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1142291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "SN: %s",
1143291a2b48SSukumar Swaminathan vpd->serial_num);
1144fcf3ce44SJohn Forte
1145fcf3ce44SJohn Forte /* Validate the serial number */
1146291a2b48SSukumar Swaminathan if (strncmp(buffer, "FFFFFFFFFF", 10) ==
1147291a2b48SSukumar Swaminathan 0 ||
1148291a2b48SSukumar Swaminathan strncmp(buffer, "0000000000", 10) ==
1149291a2b48SSukumar Swaminathan 0) {
1150fcf3ce44SJohn Forte vpd->serial_num[0] = 0;
1151fcf3ce44SJohn Forte }
1152fcf3ce44SJohn Forte }
1153fcf3ce44SJohn Forte /*
1154fcf3ce44SJohn Forte * Look for Part Number (PN)
1155fcf3ce44SJohn Forte */
1156fcf3ce44SJohn Forte else if (strcmp(tag, "PN") == 0) {
11578f23e9faSHans Rosenfeld (void) strncpy(vpd->part_num, buffer,
11588f23e9faSHans Rosenfeld (sizeof (vpd->part_num)-1));
1159fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1160291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "PN: %s",
1161291a2b48SSukumar Swaminathan vpd->part_num);
1162fcf3ce44SJohn Forte }
1163fcf3ce44SJohn Forte /*
1164fcf3ce44SJohn Forte * Look for (V0)
1165fcf3ce44SJohn Forte */
1166fcf3ce44SJohn Forte else if (strcmp(tag, "V0") == 0) {
1167fcf3ce44SJohn Forte /* Not used */
1168fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1169291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "V0: %s", buffer);
1170fcf3ce44SJohn Forte }
1171fcf3ce44SJohn Forte /*
1172fcf3ce44SJohn Forte * Look for model description (V1)
1173fcf3ce44SJohn Forte */
1174fcf3ce44SJohn Forte else if (strcmp(tag, "V1") == 0) {
11758f23e9faSHans Rosenfeld (void) strncpy(vpd->model_desc, buffer,
11768f23e9faSHans Rosenfeld (sizeof (vpd->model_desc)-1));
1177fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1178291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Desc: %s",
1179291a2b48SSukumar Swaminathan vpd->model_desc);
1180fcf3ce44SJohn Forte }
1181fcf3ce44SJohn Forte /*
1182fcf3ce44SJohn Forte * Look for model (V2)
1183fcf3ce44SJohn Forte */
1184fcf3ce44SJohn Forte else if (strcmp(tag, "V2") == 0) {
11858f23e9faSHans Rosenfeld (void) strncpy(vpd->model, buffer,
11868f23e9faSHans Rosenfeld (sizeof (vpd->model)-1));
1187fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1188291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Model: %s",
1189291a2b48SSukumar Swaminathan vpd->model);
1190fcf3ce44SJohn Forte }
1191fcf3ce44SJohn Forte /*
1192fcf3ce44SJohn Forte * Look for program type (V3)
1193fcf3ce44SJohn Forte */
1194fcf3ce44SJohn Forte
1195fcf3ce44SJohn Forte else if (strcmp(tag, "V3") == 0) {
11968f23e9faSHans Rosenfeld (void) strncpy(vpd->prog_types,
11978f23e9faSHans Rosenfeld buffer,
11988f23e9faSHans Rosenfeld (sizeof (vpd->prog_types)-1));
1199fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1200291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Prog Types: %s",
1201291a2b48SSukumar Swaminathan vpd->prog_types);
1202fcf3ce44SJohn Forte }
1203fcf3ce44SJohn Forte /*
1204fcf3ce44SJohn Forte * Look for port number (V4)
1205fcf3ce44SJohn Forte */
1206fcf3ce44SJohn Forte else if (strcmp(tag, "V4") == 0) {
12078f23e9faSHans Rosenfeld (void) strncpy(vpd->port_num, buffer,
12088f23e9faSHans Rosenfeld (sizeof (vpd->port_num)-1));
1209fcf3ce44SJohn Forte vpd->port_index =
1210fcf3ce44SJohn Forte emlxs_strtol(vpd->port_num, 10);
1211fcf3ce44SJohn Forte
1212fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1213291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Port: %s",
1214291a2b48SSukumar Swaminathan (vpd->port_num[0]) ? vpd->
1215291a2b48SSukumar Swaminathan port_num : "not applicable");
1216fcf3ce44SJohn Forte }
1217fcf3ce44SJohn Forte /*
1218fcf3ce44SJohn Forte * Look for checksum (RV)
1219fcf3ce44SJohn Forte */
1220fcf3ce44SJohn Forte else if (strcmp(tag, "RV") == 0) {
1221fcf3ce44SJohn Forte /* Not used */
1222fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1223291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Checksum: 0x%x",
1224291a2b48SSukumar Swaminathan buffer[0]);
1225291a2b48SSukumar Swaminathan }
1226291a2b48SSukumar Swaminathan
1227291a2b48SSukumar Swaminathan else {
1228fcf3ce44SJohn Forte /* Generic */
1229fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
1230291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Tag: %s: %s",
1231291a2b48SSukumar Swaminathan tag, buffer);
1232fcf3ce44SJohn Forte }
1233fcf3ce44SJohn Forte }
1234fcf3ce44SJohn Forte
1235fcf3ce44SJohn Forte break;
1236fcf3ce44SJohn Forte
1237fcf3ce44SJohn Forte case 0x78:
1238fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag.");
1239fcf3ce44SJohn Forte finished = 1;
1240fcf3ce44SJohn Forte break;
1241fcf3ce44SJohn Forte
1242fcf3ce44SJohn Forte default:
1243fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1244fcf3ce44SJohn Forte "Unknown block: %x %x %x %x %x %x %x %x",
1245fcf3ce44SJohn Forte vpd_buf[index], vpd_buf[index + 1],
1246fcf3ce44SJohn Forte vpd_buf[index + 2], vpd_buf[index + 3],
1247fcf3ce44SJohn Forte vpd_buf[index + 4], vpd_buf[index + 5],
1248fcf3ce44SJohn Forte vpd_buf[index + 6], vpd_buf[index + 7]);
1249fcf3ce44SJohn Forte return (0);
1250fcf3ce44SJohn Forte }
1251fcf3ce44SJohn Forte }
1252fcf3ce44SJohn Forte
1253fcf3ce44SJohn Forte return (1);
1254fcf3ce44SJohn Forte
125582527734SSukumar Swaminathan } /* emlxs_parse_vpd */
125682527734SSukumar Swaminathan
125782527734SSukumar Swaminathan
125882527734SSukumar Swaminathan /*
125982527734SSukumar Swaminathan * emlxs_parse_fcoe()
126082527734SSukumar Swaminathan *
126182527734SSukumar Swaminathan * This routine will parse the VPD data
126282527734SSukumar Swaminathan */
126382527734SSukumar Swaminathan extern int
emlxs_parse_fcoe(emlxs_hba_t * hba,uint8_t * fcoep,uint32_t size)126482527734SSukumar Swaminathan emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size)
126582527734SSukumar Swaminathan {
126682527734SSukumar Swaminathan emlxs_port_t *port = &PPORT;
126782527734SSukumar Swaminathan tlv_fcoe_t *fcoelist;
126882527734SSukumar Swaminathan tlv_fcfconnectlist_t *fcflist;
126982527734SSukumar Swaminathan int i;
12708f23e9faSHans Rosenfeld uint32_t flags;
12718f23e9faSHans Rosenfeld uint32_t entry_count;
12728f23e9faSHans Rosenfeld char FabricName[32];
12738f23e9faSHans Rosenfeld char SwitchName[32];
127482527734SSukumar Swaminathan
127582527734SSukumar Swaminathan /* Validate the config region 23 signature */
127682527734SSukumar Swaminathan if ((*fcoep != 'R') || (*(fcoep+1) != 'G') ||
127782527734SSukumar Swaminathan (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) {
127882527734SSukumar Swaminathan return (0);
127982527734SSukumar Swaminathan }
128082527734SSukumar Swaminathan
128182527734SSukumar Swaminathan /* Search the config region 23, for FCOE Parameters record */
128282527734SSukumar Swaminathan i = 4;
128382527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) {
128482527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2;
128582527734SSukumar Swaminathan }
128682527734SSukumar Swaminathan
128782527734SSukumar Swaminathan if (*(fcoep+i) == 0xA0) {
128882527734SSukumar Swaminathan fcoelist = (tlv_fcoe_t *)(fcoep+i);
128982527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
129082527734SSukumar Swaminathan "Found FCOE Params (A0):%d x%x",
129182527734SSukumar Swaminathan fcoelist->length, fcoelist->fip_flags);
129282527734SSukumar Swaminathan bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE,
129382527734SSukumar Swaminathan sizeof (tlv_fcoe_t));
129482527734SSukumar Swaminathan }
129582527734SSukumar Swaminathan
129682527734SSukumar Swaminathan
129782527734SSukumar Swaminathan /* Search the config region 23, for FCF record */
129882527734SSukumar Swaminathan i = 4;
129982527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) {
130082527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2;
130182527734SSukumar Swaminathan }
130282527734SSukumar Swaminathan
130382527734SSukumar Swaminathan if (*(fcoep+i) == 0xA1) {
130482527734SSukumar Swaminathan fcflist = (tlv_fcfconnectlist_t *)(fcoep+i);
130582527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
130682527734SSukumar Swaminathan "Found FCF ConnectList (A1):%d", fcflist->length);
13078f23e9faSHans Rosenfeld
130882527734SSukumar Swaminathan bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF,
130982527734SSukumar Swaminathan sizeof (tlv_fcfconnectlist_t));
13108f23e9faSHans Rosenfeld
13118f23e9faSHans Rosenfeld /* Display the list */
13128f23e9faSHans Rosenfeld entry_count = (hba->sli.sli4.cfgFCF.length *
13138f23e9faSHans Rosenfeld sizeof (uint32_t)) / sizeof (tlv_fcfconnectentry_t);
13148f23e9faSHans Rosenfeld
13158f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
13168f23e9faSHans Rosenfeld "FCF List: %d entries", entry_count);
13178f23e9faSHans Rosenfeld
13188f23e9faSHans Rosenfeld for (i = 0; i < entry_count; i++) {
13198f23e9faSHans Rosenfeld flags = *(uint32_t *)&hba->sli.sli4.cfgFCF.entry[i];
13208f23e9faSHans Rosenfeld (void) emlxs_wwn_xlate(FabricName, sizeof (FabricName),
13218f23e9faSHans Rosenfeld hba->sli.sli4.cfgFCF.entry[i].FabricName);
13228f23e9faSHans Rosenfeld (void) emlxs_wwn_xlate(SwitchName, sizeof (SwitchName),
13238f23e9faSHans Rosenfeld hba->sli.sli4.cfgFCF.entry[i].SwitchName);
13248f23e9faSHans Rosenfeld
13258f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
13268f23e9faSHans Rosenfeld "FCF List:%02d %08x %s %s",
13278f23e9faSHans Rosenfeld i, flags, FabricName, SwitchName);
13288f23e9faSHans Rosenfeld }
132982527734SSukumar Swaminathan }
133082527734SSukumar Swaminathan
133182527734SSukumar Swaminathan return (1);
133282527734SSukumar Swaminathan
133382527734SSukumar Swaminathan } /* emlxs_parse_fcoe */
1334fcf3ce44SJohn Forte
1335fcf3ce44SJohn Forte
1336fcf3ce44SJohn Forte extern void
emlxs_decode_firmware_rev(emlxs_hba_t * hba,emlxs_vpd_t * vpd)1337fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1338fcf3ce44SJohn Forte {
1339fcf3ce44SJohn Forte if (vpd->rBit) {
1340fcf3ce44SJohn Forte switch (hba->sli_mode) {
1341291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI4_MODE:
13428f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli4FwName,
13438f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1));
13448f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli4FwLabel,
13458f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1346fcf3ce44SJohn Forte break;
1347291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI3_MODE:
13488f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli3FwName,
13498f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1));
13508f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli3FwLabel,
13518f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1352fcf3ce44SJohn Forte break;
1353291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI2_MODE:
13548f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli2FwName,
13558f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1));
13568f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli2FwLabel,
13578f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1358fcf3ce44SJohn Forte break;
1359291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI1_MODE:
13608f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, vpd->sli1FwName,
13618f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1));
13628f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->sli1FwLabel,
13638f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1364fcf3ce44SJohn Forte break;
1365fcf3ce44SJohn Forte default:
13668f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_version, "unknown",
13678f23e9faSHans Rosenfeld (sizeof (vpd->fw_version)-1));
13688f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->fw_version,
13698f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1370fcf3ce44SJohn Forte }
1371fcf3ce44SJohn Forte } else {
13728f23e9faSHans Rosenfeld emlxs_decode_version(vpd->smFwRev, vpd->fw_version,
13738f23e9faSHans Rosenfeld sizeof (vpd->fw_version));
13748f23e9faSHans Rosenfeld (void) strncpy(vpd->fw_label, vpd->fw_version,
13758f23e9faSHans Rosenfeld (sizeof (vpd->fw_label)-1));
1376fcf3ce44SJohn Forte }
1377fcf3ce44SJohn Forte
1378fcf3ce44SJohn Forte return;
1379fcf3ce44SJohn Forte
138082527734SSukumar Swaminathan } /* emlxs_decode_firmware_rev() */
1381fcf3ce44SJohn Forte
1382fcf3ce44SJohn Forte
1383fcf3ce44SJohn Forte
1384fcf3ce44SJohn Forte extern void
emlxs_decode_version(uint32_t version,char * buffer,size_t len)13858f23e9faSHans Rosenfeld emlxs_decode_version(uint32_t version, char *buffer, size_t len)
1386fcf3ce44SJohn Forte {
1387fcf3ce44SJohn Forte uint32_t b1, b2, b3, b4;
1388fcf3ce44SJohn Forte char c;
1389fcf3ce44SJohn Forte
1390fcf3ce44SJohn Forte b1 = (version & 0x0000f000) >> 12;
1391fcf3ce44SJohn Forte b2 = (version & 0x00000f00) >> 8;
1392fcf3ce44SJohn Forte b3 = (version & 0x000000c0) >> 6;
1393fcf3ce44SJohn Forte b4 = (version & 0x00000030) >> 4;
1394fcf3ce44SJohn Forte
1395fcf3ce44SJohn Forte if (b1 == 0 && b2 == 0) {
13968f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "none");
1397fcf3ce44SJohn Forte return;
1398fcf3ce44SJohn Forte }
1399291a2b48SSukumar Swaminathan
1400fcf3ce44SJohn Forte c = 0;
1401fcf3ce44SJohn Forte switch (b4) {
1402fcf3ce44SJohn Forte case 0:
1403fcf3ce44SJohn Forte c = 'n';
1404fcf3ce44SJohn Forte break;
1405fcf3ce44SJohn Forte case 1:
1406fcf3ce44SJohn Forte c = 'a';
1407fcf3ce44SJohn Forte break;
1408fcf3ce44SJohn Forte case 2:
1409fcf3ce44SJohn Forte c = 'b';
1410fcf3ce44SJohn Forte break;
1411fcf3ce44SJohn Forte case 3:
1412fcf3ce44SJohn Forte if ((version & 0x0000000f)) {
1413fcf3ce44SJohn Forte c = 'x';
1414fcf3ce44SJohn Forte }
1415fcf3ce44SJohn Forte break;
1416fcf3ce44SJohn Forte
1417fcf3ce44SJohn Forte }
1418fcf3ce44SJohn Forte b4 = (version & 0x0000000f);
1419fcf3ce44SJohn Forte
1420fcf3ce44SJohn Forte if (c == 0) {
14218f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "%d.%d%d", b1, b2, b3);
1422fcf3ce44SJohn Forte } else {
14238f23e9faSHans Rosenfeld (void) snprintf(buffer, len, "%d.%d%d%c%d", b1, b2, b3, c, b4);
1424fcf3ce44SJohn Forte }
1425fcf3ce44SJohn Forte
1426fcf3ce44SJohn Forte return;
1427fcf3ce44SJohn Forte
142882527734SSukumar Swaminathan } /* emlxs_decode_version() */
1429fcf3ce44SJohn Forte
1430fcf3ce44SJohn Forte
143182527734SSukumar Swaminathan extern void
emlxs_decode_label(char * label,char * buffer,int bige,size_t len)14328f23e9faSHans Rosenfeld emlxs_decode_label(char *label, char *buffer, int bige, size_t len)
1433fcf3ce44SJohn Forte {
1434fcf3ce44SJohn Forte uint32_t i;
1435fcf3ce44SJohn Forte char name[16];
1436fcf3ce44SJohn Forte
14378f23e9faSHans Rosenfeld bzero(name, sizeof (name));
14388f23e9faSHans Rosenfeld bcopy(label, name, MIN(sizeof (name), len));
143982527734SSukumar Swaminathan /* bige is TRUE if the data format is big endian */
1440fcf3ce44SJohn Forte
144182527734SSukumar Swaminathan if (bige) {
144282527734SSukumar Swaminathan /* Data format big Endian */
144382527734SSukumar Swaminathan LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
144482527734SSukumar Swaminathan
144582527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) {
144682527734SSukumar Swaminathan if (name[i] == 0x20) {
144782527734SSukumar Swaminathan name[i] = 0;
144882527734SSukumar Swaminathan }
144982527734SSukumar Swaminathan }
145082527734SSukumar Swaminathan } else {
145182527734SSukumar Swaminathan /* Data format little Endian */
145282527734SSukumar Swaminathan BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name));
1453fcf3ce44SJohn Forte
145482527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) {
145582527734SSukumar Swaminathan if (name[i] == 0x20) {
145682527734SSukumar Swaminathan name[i] = 0;
145782527734SSukumar Swaminathan }
1458fcf3ce44SJohn Forte }
1459fcf3ce44SJohn Forte }
1460fcf3ce44SJohn Forte
14618f23e9faSHans Rosenfeld (void) strlcpy(buffer, name, len);
1462fcf3ce44SJohn Forte
1463fcf3ce44SJohn Forte return;
1464fcf3ce44SJohn Forte
146582527734SSukumar Swaminathan } /* emlxs_decode_label() */
1466fcf3ce44SJohn Forte
1467fcf3ce44SJohn Forte
1468fcf3ce44SJohn Forte extern uint32_t
emlxs_strtol(char * str,uint32_t base)1469fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base)
1470fcf3ce44SJohn Forte {
1471fcf3ce44SJohn Forte uint32_t value = 0;
1472fcf3ce44SJohn Forte char *ptr;
1473fcf3ce44SJohn Forte uint32_t factor = 1;
1474fcf3ce44SJohn Forte uint32_t digits;
1475fcf3ce44SJohn Forte
1476fcf3ce44SJohn Forte if (*str == 0) {
1477fcf3ce44SJohn Forte return (0);
1478fcf3ce44SJohn Forte }
1479291a2b48SSukumar Swaminathan
1480fcf3ce44SJohn Forte if (base != 10 && base != 16) {
1481fcf3ce44SJohn Forte return (0);
1482fcf3ce44SJohn Forte }
1483291a2b48SSukumar Swaminathan
1484fcf3ce44SJohn Forte /* Get max digits of value */
1485fcf3ce44SJohn Forte digits = (base == 10) ? 9 : 8;
1486fcf3ce44SJohn Forte
1487fcf3ce44SJohn Forte /* Position pointer to end of string */
1488fcf3ce44SJohn Forte ptr = str + strlen(str);
1489fcf3ce44SJohn Forte
1490fcf3ce44SJohn Forte /* Process string backwards */
1491fcf3ce44SJohn Forte while ((ptr-- > str) && digits) {
1492fcf3ce44SJohn Forte /* check for base 10 numbers */
1493fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') {
1494fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor;
1495fcf3ce44SJohn Forte factor *= base;
1496fcf3ce44SJohn Forte digits--;
1497fcf3ce44SJohn Forte } else if (base == 16) {
1498fcf3ce44SJohn Forte /* Check for base 16 numbers */
1499fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') {
1500291a2b48SSukumar Swaminathan value +=
1501291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor;
1502fcf3ce44SJohn Forte factor *= base;
1503fcf3ce44SJohn Forte digits--;
1504fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') {
1505291a2b48SSukumar Swaminathan value +=
1506291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor;
1507fcf3ce44SJohn Forte factor *= base;
1508fcf3ce44SJohn Forte digits--;
1509fcf3ce44SJohn Forte } else if (factor > 1) {
1510fcf3ce44SJohn Forte break;
1511fcf3ce44SJohn Forte }
1512fcf3ce44SJohn Forte } else if (factor > 1) {
1513fcf3ce44SJohn Forte break;
1514fcf3ce44SJohn Forte }
1515fcf3ce44SJohn Forte }
1516fcf3ce44SJohn Forte
1517fcf3ce44SJohn Forte return (value);
1518fcf3ce44SJohn Forte
151982527734SSukumar Swaminathan } /* emlxs_strtol() */
1520fcf3ce44SJohn Forte
1521fcf3ce44SJohn Forte
1522fcf3ce44SJohn Forte extern uint64_t
emlxs_strtoll(char * str,uint32_t base)1523fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base)
1524fcf3ce44SJohn Forte {
1525fcf3ce44SJohn Forte uint64_t value = 0;
1526fcf3ce44SJohn Forte char *ptr;
1527fcf3ce44SJohn Forte uint32_t factor = 1;
1528fcf3ce44SJohn Forte uint32_t digits;
1529fcf3ce44SJohn Forte
1530fcf3ce44SJohn Forte if (*str == 0) {
1531fcf3ce44SJohn Forte return (0);
1532fcf3ce44SJohn Forte }
1533291a2b48SSukumar Swaminathan
1534fcf3ce44SJohn Forte if (base != 10 && base != 16) {
1535fcf3ce44SJohn Forte return (0);
1536fcf3ce44SJohn Forte }
1537291a2b48SSukumar Swaminathan
1538fcf3ce44SJohn Forte /* Get max digits of value */
1539fcf3ce44SJohn Forte digits = (base == 10) ? 19 : 16;
1540fcf3ce44SJohn Forte
1541fcf3ce44SJohn Forte /* Position pointer to end of string */
1542fcf3ce44SJohn Forte ptr = str + strlen(str);
1543fcf3ce44SJohn Forte
1544fcf3ce44SJohn Forte /* Process string backwards */
1545fcf3ce44SJohn Forte while ((ptr-- > str) && digits) {
1546fcf3ce44SJohn Forte /* check for base 10 numbers */
1547fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') {
1548fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor;
1549fcf3ce44SJohn Forte factor *= base;
1550fcf3ce44SJohn Forte digits--;
1551fcf3ce44SJohn Forte } else if (base == 16) {
1552fcf3ce44SJohn Forte /* Check for base 16 numbers */
1553fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') {
1554291a2b48SSukumar Swaminathan value +=
1555291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor;
1556fcf3ce44SJohn Forte factor *= base;
1557fcf3ce44SJohn Forte digits--;
1558fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') {
1559291a2b48SSukumar Swaminathan value +=
1560291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor;
1561fcf3ce44SJohn Forte factor *= base;
1562fcf3ce44SJohn Forte digits--;
1563fcf3ce44SJohn Forte } else if (factor > 1) {
1564fcf3ce44SJohn Forte break;
1565fcf3ce44SJohn Forte }
1566fcf3ce44SJohn Forte } else if (factor > 1) {
1567fcf3ce44SJohn Forte break;
1568fcf3ce44SJohn Forte }
1569fcf3ce44SJohn Forte }
1570fcf3ce44SJohn Forte
1571fcf3ce44SJohn Forte return (value);
1572fcf3ce44SJohn Forte
157382527734SSukumar Swaminathan } /* emlxs_strtoll() */
1574fcf3ce44SJohn Forte
157582527734SSukumar Swaminathan extern void
emlxs_parse_prog_types(emlxs_hba_t * hba,char * prog_types)1576fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types)
1577fcf3ce44SJohn Forte {
1578fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
1579fcf3ce44SJohn Forte uint32_t i;
1580fcf3ce44SJohn Forte char *ptr;
1581fcf3ce44SJohn Forte emlxs_model_t *model;
1582fcf3ce44SJohn Forte char types_buffer[256];
1583fcf3ce44SJohn Forte char *types;
1584fcf3ce44SJohn Forte
1585fcf3ce44SJohn Forte bcopy(prog_types, types_buffer, 256);
1586fcf3ce44SJohn Forte types = types_buffer;
1587fcf3ce44SJohn Forte
1588fcf3ce44SJohn Forte model = &hba->model_info;
1589fcf3ce44SJohn Forte
1590fcf3ce44SJohn Forte while (*types) {
1591fcf3ce44SJohn Forte if (strncmp(types, "T2:", 3) == 0) {
1592fcf3ce44SJohn Forte bzero(model->pt_2, sizeof (model->pt_2));
1593fcf3ce44SJohn Forte types += 3;
1594fcf3ce44SJohn Forte
1595fcf3ce44SJohn Forte i = 0;
1596fcf3ce44SJohn Forte while (*types && *types != 'T') {
1597fcf3ce44SJohn Forte /* Null terminate the next value */
1598fcf3ce44SJohn Forte ptr = types;
1599fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1600fcf3ce44SJohn Forte ptr++;
1601fcf3ce44SJohn Forte *ptr = 0;
1602fcf3ce44SJohn Forte
1603fcf3ce44SJohn Forte /* Save the value */
1604fcf3ce44SJohn Forte model->pt_2[i++] =
1605fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1606fcf3ce44SJohn Forte
1607fcf3ce44SJohn Forte /*
1608fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1609fcf3ce44SJohn Forte * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]);
1610fcf3ce44SJohn Forte */
1611fcf3ce44SJohn Forte
1612fcf3ce44SJohn Forte /* Move the str pointer */
1613fcf3ce44SJohn Forte types = ptr + 1;
1614fcf3ce44SJohn Forte }
1615fcf3ce44SJohn Forte
1616fcf3ce44SJohn Forte } else if (strncmp(types, "T3:", 3) == 0) {
1617fcf3ce44SJohn Forte bzero(model->pt_3, sizeof (model->pt_3));
1618fcf3ce44SJohn Forte types += 3;
1619fcf3ce44SJohn Forte
1620fcf3ce44SJohn Forte i = 0;
1621fcf3ce44SJohn Forte while (*types && *types != 'T') {
1622fcf3ce44SJohn Forte /* Null terminate the next value */
1623fcf3ce44SJohn Forte ptr = types;
1624fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1625fcf3ce44SJohn Forte ptr++;
1626fcf3ce44SJohn Forte *ptr = 0;
1627fcf3ce44SJohn Forte
1628fcf3ce44SJohn Forte /* Save the value */
1629fcf3ce44SJohn Forte model->pt_3[i++] =
1630fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1631fcf3ce44SJohn Forte
1632fcf3ce44SJohn Forte /*
1633fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1634fcf3ce44SJohn Forte * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]);
1635fcf3ce44SJohn Forte */
1636fcf3ce44SJohn Forte
1637fcf3ce44SJohn Forte /* Move the str pointer */
1638fcf3ce44SJohn Forte types = ptr + 1;
1639fcf3ce44SJohn Forte }
1640fcf3ce44SJohn Forte } else if (strncmp(types, "T6:", 3) == 0) {
1641fcf3ce44SJohn Forte bzero(model->pt_6, sizeof (model->pt_6));
1642fcf3ce44SJohn Forte types += 3;
1643fcf3ce44SJohn Forte
1644fcf3ce44SJohn Forte i = 0;
1645fcf3ce44SJohn Forte while (*types && *types != 'T') {
1646fcf3ce44SJohn Forte /* Null terminate the next value */
1647fcf3ce44SJohn Forte ptr = types;
1648fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1649fcf3ce44SJohn Forte ptr++;
1650fcf3ce44SJohn Forte *ptr = 0;
1651fcf3ce44SJohn Forte
1652fcf3ce44SJohn Forte /* Save the value */
1653fcf3ce44SJohn Forte model->pt_6[i++] =
1654fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1655fcf3ce44SJohn Forte model->pt_6[i] = 0;
1656fcf3ce44SJohn Forte
1657fcf3ce44SJohn Forte /*
1658fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1659fcf3ce44SJohn Forte * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]);
1660fcf3ce44SJohn Forte */
1661fcf3ce44SJohn Forte
1662fcf3ce44SJohn Forte /* Move the str pointer */
1663fcf3ce44SJohn Forte types = ptr + 1;
1664fcf3ce44SJohn Forte }
1665fcf3ce44SJohn Forte } else if (strncmp(types, "T7:", 3) == 0) {
1666fcf3ce44SJohn Forte bzero(model->pt_7, sizeof (model->pt_7));
1667fcf3ce44SJohn Forte types += 3;
1668fcf3ce44SJohn Forte
1669fcf3ce44SJohn Forte i = 0;
1670fcf3ce44SJohn Forte while (*types && *types != 'T') {
1671fcf3ce44SJohn Forte /* Null terminate the next value */
1672fcf3ce44SJohn Forte ptr = types;
1673fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1674fcf3ce44SJohn Forte ptr++;
1675fcf3ce44SJohn Forte *ptr = 0;
1676fcf3ce44SJohn Forte
1677fcf3ce44SJohn Forte /* Save the value */
1678fcf3ce44SJohn Forte model->pt_7[i++] =
1679fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1680fcf3ce44SJohn Forte model->pt_7[i] = 0;
1681fcf3ce44SJohn Forte
1682fcf3ce44SJohn Forte /*
1683fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1684fcf3ce44SJohn Forte * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]);
1685fcf3ce44SJohn Forte */
1686fcf3ce44SJohn Forte
1687fcf3ce44SJohn Forte /* Move the str pointer */
1688fcf3ce44SJohn Forte types = ptr + 1;
1689fcf3ce44SJohn Forte }
1690fcf3ce44SJohn Forte } else if (strncmp(types, "TA:", 3) == 0) {
1691fcf3ce44SJohn Forte bzero(model->pt_A, sizeof (model->pt_A));
1692fcf3ce44SJohn Forte types += 3;
1693fcf3ce44SJohn Forte
1694fcf3ce44SJohn Forte i = 0;
1695fcf3ce44SJohn Forte while (*types && *types != 'T') {
1696fcf3ce44SJohn Forte /* Null terminate the next value */
1697fcf3ce44SJohn Forte ptr = types;
1698fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1699fcf3ce44SJohn Forte ptr++;
1700fcf3ce44SJohn Forte *ptr = 0;
1701fcf3ce44SJohn Forte
1702fcf3ce44SJohn Forte /* Save the value */
1703fcf3ce44SJohn Forte model->pt_A[i++] =
1704fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1705fcf3ce44SJohn Forte
1706fcf3ce44SJohn Forte /*
1707fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1708fcf3ce44SJohn Forte * "TA[%d]: 0x%x", i-1, model->pt_A[i-1]);
1709fcf3ce44SJohn Forte */
1710fcf3ce44SJohn Forte
1711fcf3ce44SJohn Forte /* Move the str pointer */
1712fcf3ce44SJohn Forte types = ptr + 1;
1713fcf3ce44SJohn Forte }
1714fcf3ce44SJohn Forte } else if (strncmp(types, "TB:", 3) == 0) {
1715fcf3ce44SJohn Forte bzero(model->pt_B, sizeof (model->pt_B));
1716fcf3ce44SJohn Forte types += 3;
1717fcf3ce44SJohn Forte
1718fcf3ce44SJohn Forte i = 0;
1719fcf3ce44SJohn Forte while (*types && *types != 'T') {
1720fcf3ce44SJohn Forte /* Null terminate the next value */
1721fcf3ce44SJohn Forte ptr = types;
1722fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1723fcf3ce44SJohn Forte ptr++;
1724fcf3ce44SJohn Forte *ptr = 0;
1725fcf3ce44SJohn Forte
1726fcf3ce44SJohn Forte /* Save the value */
1727fcf3ce44SJohn Forte model->pt_B[i++] =
1728fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1729fcf3ce44SJohn Forte
1730fcf3ce44SJohn Forte /*
1731fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1732fcf3ce44SJohn Forte * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]);
1733fcf3ce44SJohn Forte */
1734fcf3ce44SJohn Forte
1735fcf3ce44SJohn Forte /* Move the str pointer */
1736fcf3ce44SJohn Forte types = ptr + 1;
1737fcf3ce44SJohn Forte }
1738fcf3ce44SJohn Forte } else if (strncmp(types, "TFF:", 4) == 0) {
1739fcf3ce44SJohn Forte bzero(model->pt_FF, sizeof (model->pt_FF));
1740fcf3ce44SJohn Forte types += 4;
1741fcf3ce44SJohn Forte
1742fcf3ce44SJohn Forte i = 0;
1743fcf3ce44SJohn Forte while (*types && *types != 'T') {
1744fcf3ce44SJohn Forte /* Null terminate the next value */
1745fcf3ce44SJohn Forte ptr = types;
1746fcf3ce44SJohn Forte while (*ptr && (*ptr != ','))
1747fcf3ce44SJohn Forte ptr++;
1748fcf3ce44SJohn Forte *ptr = 0;
1749fcf3ce44SJohn Forte
1750fcf3ce44SJohn Forte /* Save the value */
1751fcf3ce44SJohn Forte model->pt_FF[i++] =
1752fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16);
1753fcf3ce44SJohn Forte
1754fcf3ce44SJohn Forte /*
1755fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1756fcf3ce44SJohn Forte * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]);
1757fcf3ce44SJohn Forte */
1758fcf3ce44SJohn Forte
1759291a2b48SSukumar Swaminathan /* Move the str pointer */
1760291a2b48SSukumar Swaminathan types = ptr + 1;
1761291a2b48SSukumar Swaminathan }
1762291a2b48SSukumar Swaminathan } else if (strncmp(types, "T20:", 4) == 0) {
1763291a2b48SSukumar Swaminathan bzero(model->pt_20, sizeof (model->pt_20));
1764291a2b48SSukumar Swaminathan types += 4;
1765291a2b48SSukumar Swaminathan
1766291a2b48SSukumar Swaminathan i = 0;
1767291a2b48SSukumar Swaminathan while (*types && *types != 'T') {
1768291a2b48SSukumar Swaminathan /* Null terminate the next value */
1769291a2b48SSukumar Swaminathan ptr = types;
1770291a2b48SSukumar Swaminathan while (*ptr && (*ptr != ','))
1771291a2b48SSukumar Swaminathan ptr++;
1772291a2b48SSukumar Swaminathan *ptr = 0;
1773291a2b48SSukumar Swaminathan
1774291a2b48SSukumar Swaminathan /* Save the value */
1775291a2b48SSukumar Swaminathan model->pt_20[i++] =
1776291a2b48SSukumar Swaminathan (uint8_t)emlxs_strtol(types, 16);
1777291a2b48SSukumar Swaminathan model->pt_20[i] = 0;
1778291a2b48SSukumar Swaminathan
1779291a2b48SSukumar Swaminathan /*
1780291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1781291a2b48SSukumar Swaminathan * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]);
1782291a2b48SSukumar Swaminathan */
1783291a2b48SSukumar Swaminathan
1784fcf3ce44SJohn Forte /* Move the str pointer */
1785fcf3ce44SJohn Forte types = ptr + 1;
1786fcf3ce44SJohn Forte }
1787fcf3ce44SJohn Forte } else {
1788fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg,
1789fcf3ce44SJohn Forte "Unknown prog type string = %s", types);
1790fcf3ce44SJohn Forte break;
1791fcf3ce44SJohn Forte }
1792fcf3ce44SJohn Forte }
1793fcf3ce44SJohn Forte
1794fcf3ce44SJohn Forte return;
1795fcf3ce44SJohn Forte
179682527734SSukumar Swaminathan } /* emlxs_parse_prog_types() */
1797fcf3ce44SJohn Forte
1798fcf3ce44SJohn Forte
179982527734SSukumar Swaminathan extern void
emlxs_build_prog_types(emlxs_hba_t * hba,emlxs_vpd_t * vpd)18008f23e9faSHans Rosenfeld emlxs_build_prog_types(emlxs_hba_t *hba, emlxs_vpd_t *vpd)
1801fcf3ce44SJohn Forte {
1802fcf3ce44SJohn Forte uint32_t i;
1803fcf3ce44SJohn Forte uint32_t found = 0;
1804fcf3ce44SJohn Forte char buffer[256];
1805fcf3ce44SJohn Forte
18068f23e9faSHans Rosenfeld bzero(vpd->prog_types, sizeof (vpd->prog_types));
1807fcf3ce44SJohn Forte
1808fcf3ce44SJohn Forte /* Rebuild the prog type string */
1809fcf3ce44SJohn Forte if (hba->model_info.pt_2[0]) {
18108f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T2:",
18118f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1812fcf3ce44SJohn Forte found = 1;
1813fcf3ce44SJohn Forte
1814fcf3ce44SJohn Forte i = 0;
18158f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_2[i])) {
18168f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18178f23e9faSHans Rosenfeld hba->model_info.pt_2[i]);
18188f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18198f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1820fcf3ce44SJohn Forte i++;
1821fcf3ce44SJohn Forte }
1822fcf3ce44SJohn Forte }
1823291a2b48SSukumar Swaminathan
1824fcf3ce44SJohn Forte if (hba->model_info.pt_3[0]) {
18258f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T3:",
18268f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1827fcf3ce44SJohn Forte found = 1;
1828fcf3ce44SJohn Forte
1829fcf3ce44SJohn Forte i = 0;
18308f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_3[i])) {
18318f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18328f23e9faSHans Rosenfeld hba->model_info.pt_3[i]);
18338f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18348f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1835fcf3ce44SJohn Forte i++;
1836fcf3ce44SJohn Forte
1837fcf3ce44SJohn Forte }
1838fcf3ce44SJohn Forte }
1839291a2b48SSukumar Swaminathan
1840fcf3ce44SJohn Forte if (hba->model_info.pt_6[0]) {
18418f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T6:",
18428f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1843fcf3ce44SJohn Forte found = 1;
1844fcf3ce44SJohn Forte
1845fcf3ce44SJohn Forte i = 0;
18468f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_6[i])) {
18478f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18488f23e9faSHans Rosenfeld hba->model_info.pt_6[i]);
18498f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18508f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1851fcf3ce44SJohn Forte i++;
1852fcf3ce44SJohn Forte }
1853fcf3ce44SJohn Forte }
1854291a2b48SSukumar Swaminathan
1855fcf3ce44SJohn Forte if (hba->model_info.pt_7[0]) {
18568f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T7:",
18578f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1858fcf3ce44SJohn Forte found = 1;
1859fcf3ce44SJohn Forte
1860fcf3ce44SJohn Forte i = 0;
18618f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_7[i])) {
18628f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18638f23e9faSHans Rosenfeld hba->model_info.pt_7[i]);
18648f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18658f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1866fcf3ce44SJohn Forte i++;
1867fcf3ce44SJohn Forte }
1868fcf3ce44SJohn Forte }
1869291a2b48SSukumar Swaminathan
1870fcf3ce44SJohn Forte if (hba->model_info.pt_A[0]) {
18718f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TA:",
18728f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1873fcf3ce44SJohn Forte found = 1;
1874fcf3ce44SJohn Forte
1875fcf3ce44SJohn Forte i = 0;
18768f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_A[i])) {
18778f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18788f23e9faSHans Rosenfeld hba->model_info.pt_A[i]);
18798f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18808f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1881fcf3ce44SJohn Forte i++;
1882fcf3ce44SJohn Forte }
1883fcf3ce44SJohn Forte }
1884291a2b48SSukumar Swaminathan
1885291a2b48SSukumar Swaminathan
1886fcf3ce44SJohn Forte if (hba->model_info.pt_B[0]) {
18878f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TB:",
18888f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1889fcf3ce44SJohn Forte found = 1;
1890fcf3ce44SJohn Forte
1891fcf3ce44SJohn Forte i = 0;
18928f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_B[i])) {
18938f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
18948f23e9faSHans Rosenfeld hba->model_info.pt_B[i]);
18958f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
18968f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1897fcf3ce44SJohn Forte i++;
1898fcf3ce44SJohn Forte }
1899fcf3ce44SJohn Forte }
1900291a2b48SSukumar Swaminathan
1901291a2b48SSukumar Swaminathan if (hba->model_info.pt_20[0]) {
19028f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "T20:",
19038f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1904291a2b48SSukumar Swaminathan found = 1;
1905291a2b48SSukumar Swaminathan
1906291a2b48SSukumar Swaminathan i = 0;
19078f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_20[i])) {
19088f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
19098f23e9faSHans Rosenfeld hba->model_info.pt_20[i]);
19108f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
19118f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1912291a2b48SSukumar Swaminathan i++;
1913291a2b48SSukumar Swaminathan }
1914291a2b48SSukumar Swaminathan }
1915291a2b48SSukumar Swaminathan
1916fcf3ce44SJohn Forte if (hba->model_info.pt_FF[0]) {
19178f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, "TFF:",
19188f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1919fcf3ce44SJohn Forte found = 1;
1920fcf3ce44SJohn Forte
1921fcf3ce44SJohn Forte i = 0;
19228f23e9faSHans Rosenfeld while ((i < 8) && (hba->model_info.pt_FF[i])) {
19238f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "%X,",
19248f23e9faSHans Rosenfeld hba->model_info.pt_FF[i]);
19258f23e9faSHans Rosenfeld (void) strlcat(vpd->prog_types, buffer,
19268f23e9faSHans Rosenfeld sizeof (vpd->prog_types));
1927fcf3ce44SJohn Forte i++;
1928fcf3ce44SJohn Forte }
1929fcf3ce44SJohn Forte }
1930291a2b48SSukumar Swaminathan
1931fcf3ce44SJohn Forte if (found) {
1932fcf3ce44SJohn Forte /* Terminate at the last comma in string */
19338f23e9faSHans Rosenfeld vpd->prog_types[(strlen(vpd->prog_types) - 1)] = 0;
1934fcf3ce44SJohn Forte }
1935291a2b48SSukumar Swaminathan
1936fcf3ce44SJohn Forte return;
1937fcf3ce44SJohn Forte
193882527734SSukumar Swaminathan } /* emlxs_build_prog_types() */
1939fcf3ce44SJohn Forte
1940fcf3ce44SJohn Forte
1941fcf3ce44SJohn Forte extern uint32_t
emlxs_init_adapter_info(emlxs_hba_t * hba)1942fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba)
1943fcf3ce44SJohn Forte {
1944fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
1945fcf3ce44SJohn Forte uint32_t pci_id;
1946fcf3ce44SJohn Forte uint32_t cache_line;
1947fcf3ce44SJohn Forte uint32_t channels;
1948a3170057SPaul Winder uint16_t vendor_id;
1949fcf3ce44SJohn Forte uint16_t device_id;
1950fcf3ce44SJohn Forte uint16_t ssdid;
1951fcf3ce44SJohn Forte uint32_t i;
1952fcf3ce44SJohn Forte uint32_t found = 0;
1953*e2d1a434SCarsten Grzemba pci_regspec_t *prop;
195482527734SSukumar Swaminathan uint32_t num_prop;
1955fcf3ce44SJohn Forte
1956fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) {
1957fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) {
1958fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info,
1959fcf3ce44SJohn Forte sizeof (emlxs_model_t));
1960fcf3ce44SJohn Forte
1961a3170057SPaul Winder hba->model_info.vendor_id = 0;
1962fcf3ce44SJohn Forte hba->model_info.device_id = 0;
1963fcf3ce44SJohn Forte
1964fcf3ce44SJohn Forte return (0);
1965fcf3ce44SJohn Forte }
1966291a2b48SSukumar Swaminathan
1967fcf3ce44SJohn Forte /* Read the PCI device id */
1968291a2b48SSukumar Swaminathan pci_id =
1969291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle,
1970fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
1971a3170057SPaul Winder vendor_id = (uint16_t)pci_id;
1972fcf3ce44SJohn Forte device_id = (uint16_t)(pci_id >> 16);
1973fcf3ce44SJohn Forte
1974fcf3ce44SJohn Forte /* Find matching adapter model */
1975fcf3ce44SJohn Forte for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) {
1976a3170057SPaul Winder if (emlxs_sbus_model[i].vendor_id == vendor_id &&
1977a3170057SPaul Winder emlxs_sbus_model[i].device_id == device_id) {
1978fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[i], &hba->model_info,
1979fcf3ce44SJohn Forte sizeof (emlxs_model_t));
1980fcf3ce44SJohn Forte found = 1;
1981fcf3ce44SJohn Forte break;
1982fcf3ce44SJohn Forte }
1983fcf3ce44SJohn Forte }
1984fcf3ce44SJohn Forte
1985fcf3ce44SJohn Forte /* If not found then use the unknown model */
1986fcf3ce44SJohn Forte if (!found) {
1987fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info,
1988fcf3ce44SJohn Forte sizeof (emlxs_model_t));
1989fcf3ce44SJohn Forte
1990a3170057SPaul Winder hba->model_info.vendor_id = vendor_id;
1991fcf3ce44SJohn Forte hba->model_info.device_id = device_id;
1992fcf3ce44SJohn Forte
1993fcf3ce44SJohn Forte return (0);
1994fcf3ce44SJohn Forte }
1995fcf3ce44SJohn Forte } else { /* PCI model */
1996291a2b48SSukumar Swaminathan
1997fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) {
1998fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info,
1999fcf3ce44SJohn Forte sizeof (emlxs_model_t));
2000fcf3ce44SJohn Forte
2001a3170057SPaul Winder hba->model_info.vendor_id = 0;
2002fcf3ce44SJohn Forte hba->model_info.device_id = 0;
2003fcf3ce44SJohn Forte
2004fcf3ce44SJohn Forte return (0);
2005fcf3ce44SJohn Forte }
2006291a2b48SSukumar Swaminathan
2007a3170057SPaul Winder /* Read the PCI vendor and device id */
2008a3170057SPaul Winder vendor_id =
2009a3170057SPaul Winder ddi_get16(hba->pci_acc_handle,
2010a3170057SPaul Winder (uint16_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER));
2011a3170057SPaul Winder
2012291a2b48SSukumar Swaminathan device_id =
2013291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle,
2014fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER));
2015fcf3ce44SJohn Forte
2016fcf3ce44SJohn Forte /* Read the PCI Subsystem id */
2017291a2b48SSukumar Swaminathan ssdid =
2018291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle,
2019fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER));
2020fcf3ce44SJohn Forte
2021fcf3ce44SJohn Forte if (ssdid == 0 || ssdid == 0xffff) {
2022fcf3ce44SJohn Forte ssdid = device_id;
2023fcf3ce44SJohn Forte }
2024291a2b48SSukumar Swaminathan
2025fcf3ce44SJohn Forte /* Read the Cache Line reg */
2026291a2b48SSukumar Swaminathan cache_line =
2027291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle,
2028fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER));
2029fcf3ce44SJohn Forte
2030a3170057SPaul Winder EMLXS_MSGF(EMLXS_CONTEXT,
2031a3170057SPaul Winder &emlxs_init_debug_msg, "Device IDs: %x/%x/%x/%x",
2032a3170057SPaul Winder vendor_id, device_id, ssdid, cache_line);
2033a3170057SPaul Winder
2034fcf3ce44SJohn Forte /* Check for the multifunction bit being set */
2035fcf3ce44SJohn Forte if ((cache_line & 0x00ff0000) == 0x00800000) {
20368f23e9faSHans Rosenfeld channels = EMLXS_MULTI_CHANNEL;
2037fcf3ce44SJohn Forte } else {
20388f23e9faSHans Rosenfeld channels = EMLXS_SINGLE_CHANNEL;
2039fcf3ce44SJohn Forte }
2040fcf3ce44SJohn Forte
2041fcf3ce44SJohn Forte /* If device ids are unique, then use them for search */
2042fcf3ce44SJohn Forte if (device_id != ssdid) {
20438f23e9faSHans Rosenfeld /*
20448f23e9faSHans Rosenfeld * Find matching adapter model using
2045a3170057SPaul Winder * vendor_id, device_id, ssdid, and channels
20468f23e9faSHans Rosenfeld */
20478f23e9faSHans Rosenfeld for (i = 1; i < emlxs_pci_model_count; i++) {
2048a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id &&
2049a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id &&
20508f23e9faSHans Rosenfeld emlxs_pci_model[i].ssdid == ssdid &&
20518f23e9faSHans Rosenfeld emlxs_pci_model[i].channels ==
20528f23e9faSHans Rosenfeld channels) {
20538f23e9faSHans Rosenfeld bcopy(&emlxs_pci_model[i],
20548f23e9faSHans Rosenfeld &hba->model_info,
20558f23e9faSHans Rosenfeld sizeof (emlxs_model_t));
20568f23e9faSHans Rosenfeld found = 1;
20578f23e9faSHans Rosenfeld break;
2058fcf3ce44SJohn Forte }
2059fcf3ce44SJohn Forte }
2060fcf3ce44SJohn Forte }
2061291a2b48SSukumar Swaminathan
2062fcf3ce44SJohn Forte /* If adapter not found, try again */
2063fcf3ce44SJohn Forte if (!found) {
20648f23e9faSHans Rosenfeld /*
20658f23e9faSHans Rosenfeld * Find matching adapter model using
2066a3170057SPaul Winder * vendor_id, device_id and channels
20678f23e9faSHans Rosenfeld */
206882527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) {
2069a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id &&
2070a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id &&
2071fcf3ce44SJohn Forte emlxs_pci_model[i].channels == channels) {
2072fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i],
2073fcf3ce44SJohn Forte &hba->model_info,
2074fcf3ce44SJohn Forte sizeof (emlxs_model_t));
2075fcf3ce44SJohn Forte found = 1;
2076fcf3ce44SJohn Forte break;
2077fcf3ce44SJohn Forte }
2078fcf3ce44SJohn Forte }
2079fcf3ce44SJohn Forte }
2080291a2b48SSukumar Swaminathan
2081fcf3ce44SJohn Forte /* If adapter not found, try one last time */
2082fcf3ce44SJohn Forte if (!found) {
20838f23e9faSHans Rosenfeld /*
20848f23e9faSHans Rosenfeld * Find matching adapter model using
2085a3170057SPaul Winder * vendor_id and device_id only
20868f23e9faSHans Rosenfeld */
208782527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) {
2088a3170057SPaul Winder if (emlxs_pci_model[i].vendor_id == vendor_id &&
2089a3170057SPaul Winder emlxs_pci_model[i].device_id == device_id) {
2090fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i],
2091fcf3ce44SJohn Forte &hba->model_info,
2092fcf3ce44SJohn Forte sizeof (emlxs_model_t));
2093fcf3ce44SJohn Forte found = 1;
2094fcf3ce44SJohn Forte break;
2095fcf3ce44SJohn Forte }
2096fcf3ce44SJohn Forte }
2097fcf3ce44SJohn Forte }
2098291a2b48SSukumar Swaminathan
2099fcf3ce44SJohn Forte /* If not found, set adapter to unknown */
2100fcf3ce44SJohn Forte if (!found) {
2101fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info,
2102fcf3ce44SJohn Forte sizeof (emlxs_model_t));
2103fcf3ce44SJohn Forte
2104a3170057SPaul Winder hba->model_info.vendor_id = vendor_id;
2105fcf3ce44SJohn Forte hba->model_info.device_id = device_id;
2106fcf3ce44SJohn Forte hba->model_info.ssdid = ssdid;
2107fcf3ce44SJohn Forte
2108fcf3ce44SJohn Forte return (0);
2109fcf3ce44SJohn Forte }
2110fcf3ce44SJohn Forte
2111fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT
2112fcf3ce44SJohn Forte /*
2113291a2b48SSukumar Swaminathan * This will disable MSI support for Saturn adapter's
2114291a2b48SSukumar Swaminathan * due to a PCI bus issue
2115fcf3ce44SJohn Forte */
2116fcf3ce44SJohn Forte if (hba->model_info.chip == EMLXS_SATURN_CHIP) {
2117fcf3ce44SJohn Forte hba->model_info.flags &=
2118fcf3ce44SJohn Forte ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED);
2119fcf3ce44SJohn Forte }
2120291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */
2121fcf3ce44SJohn Forte
2122a9800bebSGarrett D'Amore /* Scan the PCI capabilities */
2123a9800bebSGarrett D'Amore emlxs_pci_cap_offsets(hba);
2124fcf3ce44SJohn Forte
2125fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
2126fcf3ce44SJohn Forte /* Verify MSI support */
2127a9800bebSGarrett D'Amore if ((hba->model_info.flags & EMLXS_MSI_SUPPORTED) &&
2128a9800bebSGarrett D'Amore !hba->pci_cap_offset[PCI_CAP_ID_MSI]) {
2129a9800bebSGarrett D'Amore hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED;
2130fcf3ce44SJohn Forte }
2131291a2b48SSukumar Swaminathan
2132fcf3ce44SJohn Forte /* Verify MSI-X support */
2133a9800bebSGarrett D'Amore if ((hba->model_info.flags & EMLXS_MSIX_SUPPORTED) &&
2134a9800bebSGarrett D'Amore !hba->pci_cap_offset[PCI_CAP_ID_MSI_X]) {
2135a9800bebSGarrett D'Amore hba->model_info.flags &= ~EMLXS_MSIX_SUPPORTED;
2136fcf3ce44SJohn Forte }
2137291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
21388f23e9faSHans Rosenfeld
21398f23e9faSHans Rosenfeld /* Set the sli_intf value */
21408f23e9faSHans Rosenfeld if (hba->pci_cap_offset[PCI_CAP_ID_VS]) {
21418f23e9faSHans Rosenfeld /* Save the SLI_INTF register, this contains */
21428f23e9faSHans Rosenfeld /* information about the BAR register layout */
21438f23e9faSHans Rosenfeld /* and other HBA information. */
21448f23e9faSHans Rosenfeld hba->sli_intf =
21458f23e9faSHans Rosenfeld ddi_get32(hba->pci_acc_handle,
21468f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr +
21478f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS] +
21488f23e9faSHans Rosenfeld PCI_VS_SLI_INTF_OFFSET));
21498f23e9faSHans Rosenfeld
21508f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT,
21518f23e9faSHans Rosenfeld &emlxs_init_debug_msg, "PCI_CAP_ID_VS: "
21528f23e9faSHans Rosenfeld "SLI_INTF:%08x",
21538f23e9faSHans Rosenfeld hba->sli_intf);
21548f23e9faSHans Rosenfeld
21558f23e9faSHans Rosenfeld /* Check validity */
21568f23e9faSHans Rosenfeld if ((hba->sli_intf & SLI_INTF_VALID_MASK) !=
21578f23e9faSHans Rosenfeld SLI_INTF_VALID) {
21588f23e9faSHans Rosenfeld hba->sli_intf = 0;
21598f23e9faSHans Rosenfeld }
21608f23e9faSHans Rosenfeld }
2161291a2b48SSukumar Swaminathan }
2162fcf3ce44SJohn Forte
216382527734SSukumar Swaminathan if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0,
2164*e2d1a434SCarsten Grzemba "reg", (int **)&prop, &num_prop) == DDI_PROP_SUCCESS) {
216582527734SSukumar Swaminathan /* Parse the property for PCI function, device and bus no. */
216682527734SSukumar Swaminathan hba->pci_function_number =
2167*e2d1a434SCarsten Grzemba (uint8_t)PCI_REG_FUNC_G(prop[0].pci_phys_hi);
21688f23e9faSHans Rosenfeld hba->pci_device_number =
2169*e2d1a434SCarsten Grzemba (uint8_t)PCI_REG_DEV_G(prop[0].pci_phys_hi);
2170*e2d1a434SCarsten Grzemba hba->pci_bus_number =
2171*e2d1a434SCarsten Grzemba (uint8_t)PCI_REG_BUS_G(prop[0].pci_phys_hi);
217282527734SSukumar Swaminathan ddi_prop_free((void *)prop);
217382527734SSukumar Swaminathan }
217482527734SSukumar Swaminathan
21758f23e9faSHans Rosenfeld switch (hba->sli_intf & SLI_INTF_SLI_REV_MASK) {
21768f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_NONE: /* Legacy support */
21778f23e9faSHans Rosenfeld if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) {
21788f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli4_api;
21798f23e9faSHans Rosenfeld } else {
21808f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli3_api;
21818f23e9faSHans Rosenfeld }
21828f23e9faSHans Rosenfeld break;
21838f23e9faSHans Rosenfeld
21848f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_3:
21858f23e9faSHans Rosenfeld if (!(hba->model_info.sli_mask & EMLXS_SLI3_MASK)) {
21868f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT,
21878f23e9faSHans Rosenfeld &emlxs_init_failed_msg,
21888f23e9faSHans Rosenfeld "Adapter does not support SLI3 interface. "
21898f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x",
21908f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask);
21918f23e9faSHans Rosenfeld return (0);
21928f23e9faSHans Rosenfeld }
219382527734SSukumar Swaminathan hba->sli_api = emlxs_sli3_api;
21948f23e9faSHans Rosenfeld break;
21958f23e9faSHans Rosenfeld
21968f23e9faSHans Rosenfeld case SLI_INTF_SLI_REV_4:
21978f23e9faSHans Rosenfeld if (!(hba->model_info.sli_mask & EMLXS_SLI4_MASK)) {
21988f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT,
21998f23e9faSHans Rosenfeld &emlxs_init_failed_msg,
22008f23e9faSHans Rosenfeld "Adapter does not support SLI4 interface. "
22018f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x",
22028f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask);
22038f23e9faSHans Rosenfeld return (0);
22048f23e9faSHans Rosenfeld }
22058f23e9faSHans Rosenfeld hba->sli_api = emlxs_sli4_api;
22068f23e9faSHans Rosenfeld break;
22078f23e9faSHans Rosenfeld
22088f23e9faSHans Rosenfeld default:
22098f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT,
22108f23e9faSHans Rosenfeld &emlxs_init_failed_msg,
22118f23e9faSHans Rosenfeld "Invalid SLI interface specified. "
22128f23e9faSHans Rosenfeld "sli_intf=%08x sli_mask=%08x",
22138f23e9faSHans Rosenfeld hba->sli_intf, hba->model_info.sli_mask);
22148f23e9faSHans Rosenfeld return (0);
221582527734SSukumar Swaminathan }
221682527734SSukumar Swaminathan
22174baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT
22184baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
22194baa2c25SSukumar Swaminathan != DDI_FM_OK) {
22204baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT,
22214baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL);
22224baa2c25SSukumar Swaminathan return (0);
22234baa2c25SSukumar Swaminathan }
22244baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */
22254baa2c25SSukumar Swaminathan
2226fcf3ce44SJohn Forte return (1);
2227fcf3ce44SJohn Forte
222882527734SSukumar Swaminathan } /* emlxs_init_adapter_info() */
2229fcf3ce44SJohn Forte
2230fcf3ce44SJohn Forte
2231291a2b48SSukumar Swaminathan /* ARGSUSED */
2232291a2b48SSukumar Swaminathan static void
emlxs_handle_async_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)223382527734SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2234fcf3ce44SJohn Forte {
2235291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT;
2236291a2b48SSukumar Swaminathan IOCB *iocb;
2237291a2b48SSukumar Swaminathan uint32_t *w;
2238291a2b48SSukumar Swaminathan int i, j;
2239fcf3ce44SJohn Forte
2240291a2b48SSukumar Swaminathan iocb = &iocbq->iocb;
2241fcf3ce44SJohn Forte
224282527734SSukumar Swaminathan if (iocb->ULPSTATUS != 0) {
2243291a2b48SSukumar Swaminathan return;
2244fcf3ce44SJohn Forte }
2245fcf3ce44SJohn Forte
2246291a2b48SSukumar Swaminathan switch (iocb->un.astat.EventCode) {
2247291a2b48SSukumar Swaminathan case 0x0100: /* Temp Warning */
2248291a2b48SSukumar Swaminathan
2249291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg,
2250291a2b48SSukumar Swaminathan "Adapter is very hot (%d �C). Take corrective action.",
225182527734SSukumar Swaminathan iocb->ULPCONTEXT);
225282527734SSukumar Swaminathan
225382527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT;
225482527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT);
2255fcf3ce44SJohn Forte
2256fcf3ce44SJohn Forte
2257291a2b48SSukumar Swaminathan break;
2258fcf3ce44SJohn Forte
2259fcf3ce44SJohn Forte
2260291a2b48SSukumar Swaminathan case 0x0101: /* Temp Safe */
2261fcf3ce44SJohn Forte
2262291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg,
2263291a2b48SSukumar Swaminathan "Adapter temperature now safe (%d �C).",
226482527734SSukumar Swaminathan iocb->ULPCONTEXT);
2265fcf3ce44SJohn Forte
226682527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT;
226782527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT);
2268fcf3ce44SJohn Forte
2269291a2b48SSukumar Swaminathan break;
2270fcf3ce44SJohn Forte
2271291a2b48SSukumar Swaminathan default:
2272fcf3ce44SJohn Forte
2273291a2b48SSukumar Swaminathan w = (uint32_t *)iocb;
2274291a2b48SSukumar Swaminathan for (i = 0, j = 0; i < 8; i++, j += 2) {
2275291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg,
2276291a2b48SSukumar Swaminathan "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1,
2277291a2b48SSukumar Swaminathan w[j + 1]);
2278291a2b48SSukumar Swaminathan }
2279fcf3ce44SJohn Forte
2280291a2b48SSukumar Swaminathan emlxs_log_async_event(port, iocb);
2281fcf3ce44SJohn Forte }
2282fcf3ce44SJohn Forte
2283fcf3ce44SJohn Forte return;
2284fcf3ce44SJohn Forte
228582527734SSukumar Swaminathan } /* emlxs_handle_async_event() */
2286fcf3ce44SJohn Forte
2287fcf3ce44SJohn Forte
2288bb63f56eSSukumar Swaminathan /* ARGSUSED */
2289291a2b48SSukumar Swaminathan extern void
emlxs_reset_link_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2290bb63f56eSSukumar Swaminathan emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2291fcf3ce44SJohn Forte {
2292291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT;
2293fcf3ce44SJohn Forte
2294291a2b48SSukumar Swaminathan /* Attempt a link reset to recover */
2295291a2b48SSukumar Swaminathan (void) emlxs_reset(port, FC_FCA_LINK_RESET);
2296fcf3ce44SJohn Forte
2297bb63f56eSSukumar Swaminathan return;
2298fcf3ce44SJohn Forte
229982527734SSukumar Swaminathan } /* emlxs_reset_link_thread() */
2300fcf3ce44SJohn Forte
2301fcf3ce44SJohn Forte
2302bb63f56eSSukumar Swaminathan /* ARGSUSED */
2303fcf3ce44SJohn Forte extern void
emlxs_restart_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2304bb63f56eSSukumar Swaminathan emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2305fcf3ce44SJohn Forte {
2306fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
2307fcf3ce44SJohn Forte
2308fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting...");
2309fcf3ce44SJohn Forte
2310fcf3ce44SJohn Forte /* Attempt a full hardware reset to recover */
2311fcf3ce44SJohn Forte if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) {
231282527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR);
2313fcf3ce44SJohn Forte
231482527734SSukumar Swaminathan emlxs_shutdown_thread(hba, arg1, arg2);
2315fcf3ce44SJohn Forte }
2316fcf3ce44SJohn Forte
2317bb63f56eSSukumar Swaminathan return;
2318291a2b48SSukumar Swaminathan
231982527734SSukumar Swaminathan } /* emlxs_restart_thread() */
2320fcf3ce44SJohn Forte
2321fcf3ce44SJohn Forte
2322bb63f56eSSukumar Swaminathan /* ARGSUSED */
2323fcf3ce44SJohn Forte extern void
emlxs_shutdown_thread(emlxs_hba_t * hba,void * arg1,void * arg2)2324bb63f56eSSukumar Swaminathan emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2)
2325fcf3ce44SJohn Forte {
2326fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
2327fcf3ce44SJohn Forte
2328fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK);
2329fcf3ce44SJohn Forte if (hba->flag & FC_SHUTDOWN) {
2330fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK);
2331bb63f56eSSukumar Swaminathan return;
2332fcf3ce44SJohn Forte }
2333fcf3ce44SJohn Forte hba->flag |= FC_SHUTDOWN;
2334fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK);
2335fcf3ce44SJohn Forte
2336291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg,
2337291a2b48SSukumar Swaminathan "Shutting down...");
2338fcf3ce44SJohn Forte
2339fcf3ce44SJohn Forte /* Take adapter offline and leave it there */
23408f23e9faSHans Rosenfeld (void) emlxs_offline(hba, 0);
2341fcf3ce44SJohn Forte
234282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
234382527734SSukumar Swaminathan /*
234482527734SSukumar Swaminathan * Dump is not defined for SLI4, so just
234582527734SSukumar Swaminathan * reset the HBA for now.
234682527734SSukumar Swaminathan */
234782527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
234882527734SSukumar Swaminathan
234982527734SSukumar Swaminathan } else {
235082527734SSukumar Swaminathan if (hba->flag & FC_OVERTEMP_EVENT) {
235182527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x01,
235282527734SSukumar Swaminathan hba->temperature);
235382527734SSukumar Swaminathan } else {
235482527734SSukumar Swaminathan emlxs_log_dump_event(port, NULL, 0);
235582527734SSukumar Swaminathan }
235682527734SSukumar Swaminathan }
2357fcf3ce44SJohn Forte
2358fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required.");
2359fcf3ce44SJohn Forte
2360bb63f56eSSukumar Swaminathan return;
2361fcf3ce44SJohn Forte
236282527734SSukumar Swaminathan } /* emlxs_shutdown_thread() */
2363fcf3ce44SJohn Forte
2364fcf3ce44SJohn Forte
2365fcf3ce44SJohn Forte /* ARGSUSED */
2366fcf3ce44SJohn Forte extern void
emlxs_proc_channel(emlxs_hba_t * hba,CHANNEL * cp,void * arg2)236782527734SSukumar Swaminathan emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2)
2368fcf3ce44SJohn Forte {
2369fcf3ce44SJohn Forte IOCBQ *iocbq;
2370fcf3ce44SJohn Forte IOCBQ *rsp_head;
2371fcf3ce44SJohn Forte
2372fcf3ce44SJohn Forte /*
2373291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
23748f23e9faSHans Rosenfeld * "proc_channel: channel=%d", cp->channelno);
2375fcf3ce44SJohn Forte */
2376fcf3ce44SJohn Forte
237782527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock);
2378fcf3ce44SJohn Forte
237982527734SSukumar Swaminathan while ((rsp_head = cp->rsp_head) != NULL) {
238082527734SSukumar Swaminathan cp->rsp_head = NULL;
238182527734SSukumar Swaminathan cp->rsp_tail = NULL;
2382fcf3ce44SJohn Forte
238382527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock);
2384fcf3ce44SJohn Forte
2385fcf3ce44SJohn Forte while ((iocbq = rsp_head) != NULL) {
2386fcf3ce44SJohn Forte rsp_head = (IOCBQ *) iocbq->next;
2387fcf3ce44SJohn Forte
238882527734SSukumar Swaminathan emlxs_proc_channel_event(hba, cp, iocbq);
2389fcf3ce44SJohn Forte }
2390fcf3ce44SJohn Forte
239182527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock);
2392fcf3ce44SJohn Forte }
2393fcf3ce44SJohn Forte
239482527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock);
2395fcf3ce44SJohn Forte
239682527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0);
2397fcf3ce44SJohn Forte
2398fcf3ce44SJohn Forte return;
2399fcf3ce44SJohn Forte
240082527734SSukumar Swaminathan } /* emlxs_proc_channel() */
2401fcf3ce44SJohn Forte
2402fcf3ce44SJohn Forte
2403fcf3ce44SJohn Forte /*
2404291a2b48SSukumar Swaminathan * Called from SLI ring event routines to process a rsp ring IOCB.
2405fcf3ce44SJohn Forte */
2406291a2b48SSukumar Swaminathan void
emlxs_proc_channel_event(emlxs_hba_t * hba,CHANNEL * cp,IOCBQ * iocbq)240782527734SSukumar Swaminathan emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
2408fcf3ce44SJohn Forte {
2409fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
2410fcf3ce44SJohn Forte char buffer[MAX_MSG_DATA + 1];
2411fcf3ce44SJohn Forte IOCB *iocb;
241282527734SSukumar Swaminathan emlxs_buf_t *sbp;
24138f23e9faSHans Rosenfeld fc_packet_t *pkt;
2414fcf3ce44SJohn Forte
2415fcf3ce44SJohn Forte iocb = &iocbq->iocb;
2416fcf3ce44SJohn Forte
241782527734SSukumar Swaminathan #ifdef DEBUG_CMPL_IOCB
2418a9800bebSGarrett D'Amore emlxs_data_dump(port, "CMPL_IOCB", (uint32_t *)iocb, 8, 0);
241982527734SSukumar Swaminathan #endif
242082527734SSukumar Swaminathan
242182527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp;
242282527734SSukumar Swaminathan if (sbp) {
242382527734SSukumar Swaminathan if (!(sbp->pkt_flags & PACKET_VALID) ||
242482527734SSukumar Swaminathan (sbp->pkt_flags & (PACKET_ULP_OWNED |
242582527734SSukumar Swaminathan PACKET_IN_COMPLETION))) {
242682527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg,
242782527734SSukumar Swaminathan "Duplicate: iocb=%p cmd=%x status=%x "
24288f23e9faSHans Rosenfeld "error=%x iotag=%d context=%x info=%x",
242982527734SSukumar Swaminathan iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND,
243082527734SSukumar Swaminathan iocbq->iocb.ULPSTATUS,
243182527734SSukumar Swaminathan (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError,
243282527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPIOTAG,
243382527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPCONTEXT,
243482527734SSukumar Swaminathan (uint8_t)iocbq->iocb.ULPRSVDBYTE);
243582527734SSukumar Swaminathan
243682527734SSukumar Swaminathan /* Drop this IO immediately */
243782527734SSukumar Swaminathan return;
243882527734SSukumar Swaminathan }
243982527734SSukumar Swaminathan
244082527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TIMEOUT) {
244182527734SSukumar Swaminathan /*
244282527734SSukumar Swaminathan * If the packet is tagged for timeout then set the
244382527734SSukumar Swaminathan * return codes appropriately
244482527734SSukumar Swaminathan */
244582527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
244682527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT;
244782527734SSukumar Swaminathan } else if (sbp->pkt_flags &
244882527734SSukumar Swaminathan (PACKET_IN_FLUSH | PACKET_IN_ABORT)) {
244982527734SSukumar Swaminathan /*
245082527734SSukumar Swaminathan * If the packet is tagged for abort then set the
245182527734SSukumar Swaminathan * return codes appropriately
245282527734SSukumar Swaminathan */
245382527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT;
245482527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError =
245582527734SSukumar Swaminathan IOERR_ABORT_REQUESTED;
245682527734SSukumar Swaminathan }
245782527734SSukumar Swaminathan }
245882527734SSukumar Swaminathan
2459fcf3ce44SJohn Forte /* Check for IOCB local error */
246082527734SSukumar Swaminathan if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) {
2461fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg,
2462291a2b48SSukumar Swaminathan "Local reject. ringno=%d iocb=%p cmd=%x "
24638f23e9faSHans Rosenfeld "iotag=%d context=%x info=%x error=%x",
246482527734SSukumar Swaminathan cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND,
246582527734SSukumar Swaminathan (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT,
246682527734SSukumar Swaminathan (uint8_t)iocb->ULPRSVDBYTE,
2467fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError);
2468fcf3ce44SJohn Forte }
2469291a2b48SSukumar Swaminathan
247082527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) {
2471fcf3ce44SJohn Forte /* RING 0 FCP commands */
2472fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR:
2473fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX:
2474fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR:
2475fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX:
2476fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR:
2477fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX:
2478fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR:
2479fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX:
2480fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR:
2481fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX:
2482fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR:
2483fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX:
248482527734SSukumar Swaminathan emlxs_handle_fcp_event(hba, cp, iocbq);
2485fcf3ce44SJohn Forte break;
2486fcf3ce44SJohn Forte
2487fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT
2488291a2b48SSukumar Swaminathan case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */
2489fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */
2490fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */
2491fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */
2492291a2b48SSukumar Swaminathan case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */
2493291a2b48SSukumar Swaminathan case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */
24948f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
24958f23e9faSHans Rosenfeld (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq);
24968f23e9faSHans Rosenfeld }
2497fcf3ce44SJohn Forte break;
2498291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2499fcf3ce44SJohn Forte
2500fcf3ce44SJohn Forte /* RING 1 IP commands */
2501fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN:
2502fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX:
2503fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN:
2504fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX:
250582527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq);
2506fcf3ce44SJohn Forte break;
2507fcf3ce44SJohn Forte
2508fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX:
2509fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR:
2510fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX:
2511fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR:
2512fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2513fcf3ce44SJohn Forte case FC_TYPE_IS8802_SNAP:
251482527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq);
2515fcf3ce44SJohn Forte break;
2516fcf3ce44SJohn Forte
2517fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES:
251882527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq);
2519fcf3ce44SJohn Forte break;
2520fcf3ce44SJohn Forte
2521fcf3ce44SJohn Forte default:
2522fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
25238f23e9faSHans Rosenfeld "cmd=%x type=%x status=%x iotag=%d context=%x ",
252482527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
252582527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG,
252682527734SSukumar Swaminathan iocb->ULPCONTEXT);
2527fcf3ce44SJohn Forte }
2528fcf3ce44SJohn Forte break;
2529fcf3ce44SJohn Forte
2530fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE_CX:
2531fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE64_CX:
2532fcf3ce44SJohn Forte case CMD_RCV_SEQ64_CX:
2533fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */
2534fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */
2535291a2b48SSukumar Swaminathan case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */
253682527734SSukumar Swaminathan if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) {
253782527734SSukumar Swaminathan (void) emlxs_handle_rcv_seq(hba, cp, iocbq);
253882527734SSukumar Swaminathan }
2539fcf3ce44SJohn Forte break;
2540fcf3ce44SJohn Forte
2541fcf3ce44SJohn Forte case CMD_RCV_SEQ_LIST64_CX:
254282527734SSukumar Swaminathan (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq);
2543fcf3ce44SJohn Forte break;
2544fcf3ce44SJohn Forte
2545fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR:
2546fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX:
254782527734SSukumar Swaminathan (void) emlxs_handle_create_xri(hba, cp, iocbq);
2548fcf3ce44SJohn Forte break;
2549fcf3ce44SJohn Forte
2550fcf3ce44SJohn Forte /* RING 2 ELS commands */
2551fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR:
2552fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX:
2553fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX:
2554fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR:
2555fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX:
2556fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX:
255782527734SSukumar Swaminathan (void) emlxs_els_handle_event(hba, cp, iocbq);
2558fcf3ce44SJohn Forte break;
2559fcf3ce44SJohn Forte
2560fcf3ce44SJohn Forte /* RING 3 CT commands */
2561fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR:
2562fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX:
2563fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) {
2564fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT
2565fcf3ce44SJohn Forte case EMLXS_MENLO_TYPE:
256682527734SSukumar Swaminathan (void) emlxs_menlo_handle_event(hba, cp, iocbq);
2567fcf3ce44SJohn Forte break;
2568291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */
2569fcf3ce44SJohn Forte
2570fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES:
257182527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq);
2572fcf3ce44SJohn Forte break;
2573fcf3ce44SJohn Forte
2574fcf3ce44SJohn Forte default:
2575fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
25768f23e9faSHans Rosenfeld "cmd=%x type=%x status=%x iotag=%d context=%x ",
257782527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type,
257882527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG,
257982527734SSukumar Swaminathan iocb->ULPCONTEXT);
2580fcf3ce44SJohn Forte }
2581fcf3ce44SJohn Forte break;
2582fcf3ce44SJohn Forte
2583fcf3ce44SJohn Forte case CMD_ABORT_XRI_CN: /* Abort fcp command */
2584fcf3ce44SJohn Forte
2585fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
25868f23e9faSHans Rosenfeld "ABORT_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2587fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag,
258882527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2589291a2b48SSukumar Swaminathan iocb->un.acxri.parm);
2590fcf3ce44SJohn Forte
2591291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
25928f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
259382527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2594291a2b48SSukumar Swaminathan }
2595291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2596fcf3ce44SJohn Forte break;
2597fcf3ce44SJohn Forte
2598fcf3ce44SJohn Forte case CMD_ABORT_XRI_CX: /* Abort command */
2599fcf3ce44SJohn Forte
2600fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
26018f23e9faSHans Rosenfeld "ABORT_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2602fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag,
260382527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2604291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp);
2605fcf3ce44SJohn Forte
2606291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
26078f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
260882527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2609291a2b48SSukumar Swaminathan }
2610291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2611fcf3ce44SJohn Forte break;
2612fcf3ce44SJohn Forte
2613fcf3ce44SJohn Forte case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */
2614fcf3ce44SJohn Forte
2615fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
26168f23e9faSHans Rosenfeld "XRI_ABORTED_CX: rpi=%d iotag=%d status=%x parm=%x",
2617fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag,
261882527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2619291a2b48SSukumar Swaminathan iocb->un.acxri.parm);
2620fcf3ce44SJohn Forte
2621291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
26228f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
262382527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2624291a2b48SSukumar Swaminathan }
2625291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2626fcf3ce44SJohn Forte break;
2627fcf3ce44SJohn Forte
2628fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */
2629fcf3ce44SJohn Forte
2630fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
26318f23e9faSHans Rosenfeld "CLOSE_XRI_CN: rpi=%d iotag=%d status=%x parm=%x",
2632fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag,
263382527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2634291a2b48SSukumar Swaminathan iocb->un.acxri.parm);
2635fcf3ce44SJohn Forte
2636291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
26378f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
263882527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2639291a2b48SSukumar Swaminathan }
2640291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2641fcf3ce44SJohn Forte break;
2642fcf3ce44SJohn Forte
2643fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */
2644fcf3ce44SJohn Forte
2645fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
26468f23e9faSHans Rosenfeld "CLOSE_XRI_CX: rpi=%d iotag=%d status=%x parm=%x sbp=%p",
2647fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag,
264882527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS,
2649291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp);
2650fcf3ce44SJohn Forte
2651291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT
26528f23e9faSHans Rosenfeld if (port->mode == MODE_TARGET) {
265382527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq);
2654291a2b48SSukumar Swaminathan }
2655291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */
2656fcf3ce44SJohn Forte break;
2657fcf3ce44SJohn Forte
2658fcf3ce44SJohn Forte case CMD_ADAPTER_MSG:
2659fcf3ce44SJohn Forte /* Allows debug adapter firmware messages to print on host */
2660fcf3ce44SJohn Forte bzero(buffer, sizeof (buffer));
2661fcf3ce44SJohn Forte bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA);
2662fcf3ce44SJohn Forte
2663fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer);
2664fcf3ce44SJohn Forte
2665fcf3ce44SJohn Forte break;
2666fcf3ce44SJohn Forte
2667fcf3ce44SJohn Forte case CMD_QUE_RING_LIST64_CN:
2668fcf3ce44SJohn Forte case CMD_QUE_RING_BUF64_CN:
2669fcf3ce44SJohn Forte break;
2670fcf3ce44SJohn Forte
2671fcf3ce44SJohn Forte case CMD_ASYNC_STATUS:
267282527734SSukumar Swaminathan emlxs_handle_async_event(hba, cp, iocbq);
2673fcf3ce44SJohn Forte break;
2674fcf3ce44SJohn Forte
26758f23e9faSHans Rosenfeld case CMD_XMIT_BLS_RSP64_CX:
26768f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg,
26778f23e9faSHans Rosenfeld "CMD_XMIT_BLS_RSP64_CX: sbp = %p", sbp);
26788f23e9faSHans Rosenfeld
26798f23e9faSHans Rosenfeld /*
26808f23e9faSHans Rosenfeld * The exchange should have been already freed in the wqe_cmpl
26818f23e9faSHans Rosenfeld * so just free up the pkt here.
26828f23e9faSHans Rosenfeld */
26838f23e9faSHans Rosenfeld pkt = PRIV2PKT(sbp);
26848f23e9faSHans Rosenfeld emlxs_pkt_free(pkt);
26858f23e9faSHans Rosenfeld break;
26868f23e9faSHans Rosenfeld
2687fcf3ce44SJohn Forte default:
26888f23e9faSHans Rosenfeld if (iocb->ULPCOMMAND == 0) {
26898f23e9faSHans Rosenfeld break;
26908f23e9faSHans Rosenfeld }
26918f23e9faSHans Rosenfeld
2692fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg,
26938f23e9faSHans Rosenfeld "cmd=%x status=%x iotag=%d context=%x", iocb->ULPCOMMAND,
269482527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT);
2695fcf3ce44SJohn Forte
2696fcf3ce44SJohn Forte break;
269782527734SSukumar Swaminathan } /* switch(entry->ULPCOMMAND) */
2698fcf3ce44SJohn Forte
2699fcf3ce44SJohn Forte return;
2700fcf3ce44SJohn Forte
270182527734SSukumar Swaminathan } /* emlxs_proc_channel_event() */
2702fcf3ce44SJohn Forte
2703fcf3ce44SJohn Forte
2704291a2b48SSukumar Swaminathan extern char *
emlxs_ffstate_xlate(uint32_t state)2705291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state)
2706fcf3ce44SJohn Forte {
2707291a2b48SSukumar Swaminathan static char buffer[32];
2708291a2b48SSukumar Swaminathan uint32_t i;
2709291a2b48SSukumar Swaminathan uint32_t count;
2710fcf3ce44SJohn Forte
2711291a2b48SSukumar Swaminathan count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t);
2712291a2b48SSukumar Swaminathan for (i = 0; i < count; i++) {
2713291a2b48SSukumar Swaminathan if (state == emlxs_ffstate_table[i].code) {
2714291a2b48SSukumar Swaminathan return (emlxs_ffstate_table[i].string);
2715fcf3ce44SJohn Forte }
2716fcf3ce44SJohn Forte }
2717fcf3ce44SJohn Forte
27188f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "state=0x%x", state);
2719291a2b48SSukumar Swaminathan return (buffer);
2720fcf3ce44SJohn Forte
272182527734SSukumar Swaminathan } /* emlxs_ffstate_xlate() */
2722fcf3ce44SJohn Forte
2723fcf3ce44SJohn Forte
2724fcf3ce44SJohn Forte extern char *
emlxs_ring_xlate(uint32_t ringno)2725fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno)
2726fcf3ce44SJohn Forte {
2727fcf3ce44SJohn Forte static char buffer[32];
2728fcf3ce44SJohn Forte uint32_t i;
2729fcf3ce44SJohn Forte uint32_t count;
2730fcf3ce44SJohn Forte
2731fcf3ce44SJohn Forte count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t);
2732fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
2733fcf3ce44SJohn Forte if (ringno == emlxs_ring_table[i].code) {
2734fcf3ce44SJohn Forte return (emlxs_ring_table[i].string);
2735fcf3ce44SJohn Forte }
2736fcf3ce44SJohn Forte }
2737fcf3ce44SJohn Forte
27388f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "ring=0x%x", ringno);
2739fcf3ce44SJohn Forte return (buffer);
2740fcf3ce44SJohn Forte
274182527734SSukumar Swaminathan } /* emlxs_ring_xlate() */
2742fcf3ce44SJohn Forte
2743fcf3ce44SJohn Forte
2744a9800bebSGarrett D'Amore extern char *
emlxs_pci_cap_xlate(uint32_t id)2745a9800bebSGarrett D'Amore emlxs_pci_cap_xlate(uint32_t id)
2746a9800bebSGarrett D'Amore {
2747a9800bebSGarrett D'Amore static char buffer[32];
2748a9800bebSGarrett D'Amore uint32_t i;
2749a9800bebSGarrett D'Amore uint32_t count;
2750a9800bebSGarrett D'Amore
2751a9800bebSGarrett D'Amore count = sizeof (emlxs_pci_cap) / sizeof (emlxs_table_t);
2752a9800bebSGarrett D'Amore for (i = 0; i < count; i++) {
2753a9800bebSGarrett D'Amore if (id == emlxs_pci_cap[i].code) {
2754a9800bebSGarrett D'Amore return (emlxs_pci_cap[i].string);
2755a9800bebSGarrett D'Amore }
2756a9800bebSGarrett D'Amore }
2757a9800bebSGarrett D'Amore
27588f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "PCI_CAP_ID_%02X", id);
2759a9800bebSGarrett D'Amore return (buffer);
2760a9800bebSGarrett D'Amore
2761a9800bebSGarrett D'Amore } /* emlxs_pci_cap_xlate() */
2762a9800bebSGarrett D'Amore
2763fcf3ce44SJohn Forte
27648f23e9faSHans Rosenfeld extern char *
emlxs_pci_ecap_xlate(uint32_t id)27658f23e9faSHans Rosenfeld emlxs_pci_ecap_xlate(uint32_t id)
27668f23e9faSHans Rosenfeld {
27678f23e9faSHans Rosenfeld static char buffer[32];
27688f23e9faSHans Rosenfeld uint32_t i;
27698f23e9faSHans Rosenfeld uint32_t count;
27708f23e9faSHans Rosenfeld
27718f23e9faSHans Rosenfeld count = sizeof (emlxs_pci_ecap) / sizeof (emlxs_table_t);
27728f23e9faSHans Rosenfeld for (i = 0; i < count; i++) {
27738f23e9faSHans Rosenfeld if (id == emlxs_pci_ecap[i].code) {
27748f23e9faSHans Rosenfeld return (emlxs_pci_ecap[i].string);
27758f23e9faSHans Rosenfeld }
27768f23e9faSHans Rosenfeld }
27778f23e9faSHans Rosenfeld
27788f23e9faSHans Rosenfeld (void) snprintf(buffer, sizeof (buffer), "PCI_EXT_CAP_ID_%02X", id);
27798f23e9faSHans Rosenfeld return (buffer);
27808f23e9faSHans Rosenfeld
27818f23e9faSHans Rosenfeld } /* emlxs_pci_ecap_xlate() */
27828f23e9faSHans Rosenfeld
27838f23e9faSHans Rosenfeld
2784fcf3ce44SJohn Forte extern void
emlxs_pcix_mxr_update(emlxs_hba_t * hba,uint32_t verbose)2785fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose)
2786fcf3ce44SJohn Forte {
2787fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
278882527734SSukumar Swaminathan MAILBOXQ *mbq;
2789fcf3ce44SJohn Forte MAILBOX *mb;
2790fcf3ce44SJohn Forte emlxs_config_t *cfg;
2791fcf3ce44SJohn Forte uint32_t value;
2792fcf3ce44SJohn Forte
2793fcf3ce44SJohn Forte cfg = &CFG;
2794fcf3ce44SJohn Forte
2795fcf3ce44SJohn Forte xlate:
2796fcf3ce44SJohn Forte
2797fcf3ce44SJohn Forte switch (cfg[CFG_PCI_MAX_READ].current) {
2798fcf3ce44SJohn Forte case 512:
2799fcf3ce44SJohn Forte value = 0;
2800fcf3ce44SJohn Forte break;
2801fcf3ce44SJohn Forte
2802fcf3ce44SJohn Forte case 1024:
2803fcf3ce44SJohn Forte value = 1;
2804fcf3ce44SJohn Forte break;
2805fcf3ce44SJohn Forte
2806fcf3ce44SJohn Forte case 2048:
2807fcf3ce44SJohn Forte value = 2;
2808fcf3ce44SJohn Forte break;
2809fcf3ce44SJohn Forte
2810fcf3ce44SJohn Forte case 4096:
2811fcf3ce44SJohn Forte value = 3;
2812fcf3ce44SJohn Forte break;
2813fcf3ce44SJohn Forte
2814fcf3ce44SJohn Forte default:
2815fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2816fcf3ce44SJohn Forte "PCI_MAX_READ: Invalid parameter value. old=%d new=%d",
2817fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def);
2818fcf3ce44SJohn Forte
2819fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def;
2820fcf3ce44SJohn Forte goto xlate;
2821fcf3ce44SJohn Forte }
2822fcf3ce44SJohn Forte
28238f23e9faSHans Rosenfeld if ((mbq = (MAILBOXQ *) kmem_zalloc((sizeof (MAILBOXQ)),
28248f23e9faSHans Rosenfeld KM_SLEEP)) == 0) {
2825fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2826fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to allocate mailbox buffer.");
2827fcf3ce44SJohn Forte return;
2828fcf3ce44SJohn Forte }
282982527734SSukumar Swaminathan mb = (MAILBOX *)mbq;
2830fcf3ce44SJohn Forte
283182527734SSukumar Swaminathan emlxs_mb_set_var(hba, mbq, 0x00100506, value);
2832291a2b48SSukumar Swaminathan
283382527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2834fcf3ce44SJohn Forte if (verbose || (mb->mbxStatus != 0x12)) {
2835fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2836291a2b48SSukumar Swaminathan "PCI_MAX_READ: Unable to update. "
2837291a2b48SSukumar Swaminathan "status=%x value=%d (%d bytes)",
2838291a2b48SSukumar Swaminathan mb->mbxStatus, value,
2839fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current);
2840fcf3ce44SJohn Forte }
2841fcf3ce44SJohn Forte } else {
2842291a2b48SSukumar Swaminathan if (verbose &&
2843291a2b48SSukumar Swaminathan (cfg[CFG_PCI_MAX_READ].current !=
2844fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].def)) {
2845fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2846fcf3ce44SJohn Forte "PCI_MAX_READ: Updated. %d bytes",
2847fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current);
2848fcf3ce44SJohn Forte }
2849fcf3ce44SJohn Forte }
2850fcf3ce44SJohn Forte
28518f23e9faSHans Rosenfeld (void) kmem_free((uint8_t *)mbq, sizeof (MAILBOXQ));
2852fcf3ce44SJohn Forte
2853fcf3ce44SJohn Forte return;
2854fcf3ce44SJohn Forte
285582527734SSukumar Swaminathan } /* emlxs_pcix_mxr_update */
2856fcf3ce44SJohn Forte
2857fcf3ce44SJohn Forte
2858fcf3ce44SJohn Forte
2859fcf3ce44SJohn Forte extern uint32_t
emlxs_get_key(emlxs_hba_t * hba,MAILBOXQ * mbq)286082527734SSukumar Swaminathan emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq)
2861fcf3ce44SJohn Forte {
2862fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
286382527734SSukumar Swaminathan MAILBOX *mb = (MAILBOX *)mbq;
2864fcf3ce44SJohn Forte uint32_t npname0, npname1;
2865fcf3ce44SJohn Forte uint32_t tmpkey, theKey;
2866fcf3ce44SJohn Forte uint16_t key850;
2867fcf3ce44SJohn Forte uint32_t t1, t2, t3, t4;
2868fcf3ce44SJohn Forte uint32_t ts;
2869fcf3ce44SJohn Forte
2870fcf3ce44SJohn Forte #define SEED 0x876EDC21
2871fcf3ce44SJohn Forte
2872fcf3ce44SJohn Forte /* This key is only used currently for SBUS adapters */
2873fcf3ce44SJohn Forte if (hba->bus_type != SBUS_FC) {
2874fcf3ce44SJohn Forte return (0);
2875fcf3ce44SJohn Forte }
2876291a2b48SSukumar Swaminathan
2877fcf3ce44SJohn Forte tmpkey = mb->un.varWords[30];
287882527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS);
2879fcf3ce44SJohn Forte
288082527734SSukumar Swaminathan emlxs_mb_read_nv(hba, mbq);
288182527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
2882fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
2883291a2b48SSukumar Swaminathan "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand,
2884291a2b48SSukumar Swaminathan mb->mbxStatus);
2885fcf3ce44SJohn Forte
2886fcf3ce44SJohn Forte return (0);
2887fcf3ce44SJohn Forte }
2888fcf3ce44SJohn Forte npname0 = mb->un.varRDnvp.portname[0];
2889fcf3ce44SJohn Forte npname1 = mb->un.varRDnvp.portname[1];
2890fcf3ce44SJohn Forte
2891fcf3ce44SJohn Forte key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8);
2892fcf3ce44SJohn Forte ts = (uint16_t)(npname1 + 1);
2893fcf3ce44SJohn Forte t1 = ts * key850;
2894fcf3ce44SJohn Forte ts = (uint16_t)((npname1 >> 16) + 1);
2895fcf3ce44SJohn Forte t2 = ts * key850;
2896fcf3ce44SJohn Forte ts = (uint16_t)(npname0 + 1);
2897fcf3ce44SJohn Forte t3 = ts * key850;
2898fcf3ce44SJohn Forte ts = (uint16_t)((npname0 >> 16) + 1);
2899fcf3ce44SJohn Forte t4 = ts * key850;
2900fcf3ce44SJohn Forte theKey = SEED + t1 + t2 + t3 + t4;
2901fcf3ce44SJohn Forte
2902fcf3ce44SJohn Forte return (theKey);
2903fcf3ce44SJohn Forte
290482527734SSukumar Swaminathan } /* emlxs_get_key() */
2905291a2b48SSukumar Swaminathan
2906291a2b48SSukumar Swaminathan
2907291a2b48SSukumar Swaminathan extern void
emlxs_fw_show(emlxs_hba_t * hba)2908291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba)
2909291a2b48SSukumar Swaminathan {
2910291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT;
2911291a2b48SSukumar Swaminathan uint32_t i;
2912291a2b48SSukumar Swaminathan
2913291a2b48SSukumar Swaminathan /* Display firmware library one time */
291482527734SSukumar Swaminathan for (i = 0; i < emlxs_fw_count; i++) {
2915291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s",
2916291a2b48SSukumar Swaminathan emlxs_fw_table[i].label);
2917291a2b48SSukumar Swaminathan }
2918291a2b48SSukumar Swaminathan
2919291a2b48SSukumar Swaminathan return;
2920291a2b48SSukumar Swaminathan
292182527734SSukumar Swaminathan } /* emlxs_fw_show() */
2922291a2b48SSukumar Swaminathan
2923291a2b48SSukumar Swaminathan
2924291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT
292582527734SSukumar Swaminathan extern void
emlxs_fw_load(emlxs_hba_t * hba,emlxs_firmware_t * fw)2926291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2927291a2b48SSukumar Swaminathan {
2928291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT;
2929291a2b48SSukumar Swaminathan int (*emlxs_fw_get)(emlxs_firmware_t *);
2930291a2b48SSukumar Swaminathan int err;
29318f23e9faSHans Rosenfeld char name[64];
2932291a2b48SSukumar Swaminathan
2933291a2b48SSukumar Swaminathan /* Make sure image is unloaded and image buffer pointer is clear */
2934291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw);
2935291a2b48SSukumar Swaminathan
2936291a2b48SSukumar Swaminathan err = 0;
2937291a2b48SSukumar Swaminathan hba->fw_modhandle =
2938291a2b48SSukumar Swaminathan ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err);
2939291a2b48SSukumar Swaminathan if (!hba->fw_modhandle) {
2940291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2941291a2b48SSukumar Swaminathan "Unable to load firmware module. error=%d", err);
2942291a2b48SSukumar Swaminathan
2943291a2b48SSukumar Swaminathan return;
2944291a2b48SSukumar Swaminathan } else {
2945291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2946291a2b48SSukumar Swaminathan "Firmware module loaded.");
2947291a2b48SSukumar Swaminathan }
2948291a2b48SSukumar Swaminathan
29498f23e9faSHans Rosenfeld (void) snprintf(name, sizeof (name), "%s_fw_get", DRIVER_NAME);
2950291a2b48SSukumar Swaminathan err = 0;
2951291a2b48SSukumar Swaminathan emlxs_fw_get =
29528f23e9faSHans Rosenfeld (int (*)())ddi_modsym(hba->fw_modhandle, name, &err);
2953291a2b48SSukumar Swaminathan if ((void *)emlxs_fw_get == NULL) {
2954291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
29558f23e9faSHans Rosenfeld "%s not present. error=%d", name, err);
2956291a2b48SSukumar Swaminathan
2957291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw);
2958291a2b48SSukumar Swaminathan return;
2959291a2b48SSukumar Swaminathan }
2960291a2b48SSukumar Swaminathan
2961291a2b48SSukumar Swaminathan if (emlxs_fw_get(fw)) {
2962291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
2963291a2b48SSukumar Swaminathan "Invalid firmware image module found. %s", fw->label);
2964291a2b48SSukumar Swaminathan
2965291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw);
2966291a2b48SSukumar Swaminathan return;
2967291a2b48SSukumar Swaminathan }
2968291a2b48SSukumar Swaminathan
2969291a2b48SSukumar Swaminathan return;
2970291a2b48SSukumar Swaminathan
297182527734SSukumar Swaminathan } /* emlxs_fw_load() */
2972291a2b48SSukumar Swaminathan
2973291a2b48SSukumar Swaminathan
297482527734SSukumar Swaminathan extern void
emlxs_fw_unload(emlxs_hba_t * hba,emlxs_firmware_t * fw)2975291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw)
2976291a2b48SSukumar Swaminathan {
2977291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT;
2978291a2b48SSukumar Swaminathan
2979291a2b48SSukumar Swaminathan /* Clear the firmware image */
2980291a2b48SSukumar Swaminathan fw->image = NULL;
2981291a2b48SSukumar Swaminathan fw->size = 0;
2982291a2b48SSukumar Swaminathan
2983291a2b48SSukumar Swaminathan if (hba->fw_modhandle) {
2984291a2b48SSukumar Swaminathan /* Close the module */
2985291a2b48SSukumar Swaminathan (void) ddi_modclose(hba->fw_modhandle);
2986291a2b48SSukumar Swaminathan hba->fw_modhandle = NULL;
2987291a2b48SSukumar Swaminathan
2988291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg,
2989291a2b48SSukumar Swaminathan "Firmware module unloaded.");
2990291a2b48SSukumar Swaminathan }
2991291a2b48SSukumar Swaminathan
2992291a2b48SSukumar Swaminathan return;
2993291a2b48SSukumar Swaminathan
299482527734SSukumar Swaminathan } /* emlxs_fw_unload() */
2995291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */
2996a9800bebSGarrett D'Amore
2997a9800bebSGarrett D'Amore
2998a9800bebSGarrett D'Amore static void
emlxs_pci_cap_offsets(emlxs_hba_t * hba)2999a9800bebSGarrett D'Amore emlxs_pci_cap_offsets(emlxs_hba_t *hba)
3000a9800bebSGarrett D'Amore {
3001a9800bebSGarrett D'Amore emlxs_port_t *port = &PPORT;
30028f23e9faSHans Rosenfeld uint32_t reg;
3003a9800bebSGarrett D'Amore uint8_t offset;
30048f23e9faSHans Rosenfeld uint8_t next;
3005a9800bebSGarrett D'Amore uint8_t id;
30068f23e9faSHans Rosenfeld uint16_t eoffset;
30078f23e9faSHans Rosenfeld uint16_t enext;
30088f23e9faSHans Rosenfeld uint8_t eversion;
30098f23e9faSHans Rosenfeld uint16_t eid;
30108f23e9faSHans Rosenfeld
30118f23e9faSHans Rosenfeld /* Read PCI capbabilities */
3012a9800bebSGarrett D'Amore
3013a9800bebSGarrett D'Amore bzero(hba->pci_cap_offset, sizeof (hba->pci_cap_offset));
3014a9800bebSGarrett D'Amore
3015a9800bebSGarrett D'Amore /* Read first offset */
30168f23e9faSHans Rosenfeld offset = PCI_CAP_POINTER;
3017a9800bebSGarrett D'Amore offset = ddi_get8(hba->pci_acc_handle,
30188f23e9faSHans Rosenfeld (uint8_t *)(hba->pci_addr + offset));
3019a9800bebSGarrett D'Amore
3020a9800bebSGarrett D'Amore while (offset >= PCI_CAP_PTR_OFF) {
30218f23e9faSHans Rosenfeld /* Read the cap */
30228f23e9faSHans Rosenfeld reg = ddi_get32(hba->pci_acc_handle,
30238f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr + offset));
30248f23e9faSHans Rosenfeld
30258f23e9faSHans Rosenfeld id = ((reg >> PCI_CAP_ID_SHIFT) & PCI_CAP_ID_MASK);
30268f23e9faSHans Rosenfeld next = ((reg >> PCI_CAP_NEXT_PTR_SHIFT) &
30278f23e9faSHans Rosenfeld PCI_CAP_NEXT_PTR_MASK);
3028a9800bebSGarrett D'Amore
30298f23e9faSHans Rosenfeld if ((id < PCI_CAP_MAX_PTR) &&
30308f23e9faSHans Rosenfeld (hba->pci_cap_offset[id] == 0)) {
3031a9800bebSGarrett D'Amore hba->pci_cap_offset[id] = offset;
3032a9800bebSGarrett D'Amore }
3033a9800bebSGarrett D'Amore
3034a9800bebSGarrett D'Amore EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
30358f23e9faSHans Rosenfeld "%s: offset=0x%x next=0x%x",
30368f23e9faSHans Rosenfeld emlxs_pci_cap_xlate(id), offset, next);
30378f23e9faSHans Rosenfeld
30388f23e9faSHans Rosenfeld offset = next;
30398f23e9faSHans Rosenfeld }
30408f23e9faSHans Rosenfeld
30418f23e9faSHans Rosenfeld /* Workaround for BE adapters */
30428f23e9faSHans Rosenfeld if ((hba->pci_cap_offset[PCI_CAP_ID_VS] == 0) &&
30438f23e9faSHans Rosenfeld (hba->model_info.chip & EMLXS_BE_CHIPS)) {
30448f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS] = 0x54;
30458f23e9faSHans Rosenfeld
30468f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
30478f23e9faSHans Rosenfeld "%s: offset=0x%x Added.",
30488f23e9faSHans Rosenfeld emlxs_pci_cap_xlate(PCI_CAP_ID_VS),
30498f23e9faSHans Rosenfeld hba->pci_cap_offset[PCI_CAP_ID_VS]);
30508f23e9faSHans Rosenfeld }
30518f23e9faSHans Rosenfeld
30528f23e9faSHans Rosenfeld if (! hba->pci_cap_offset[PCI_CAP_ID_PCI_E]) {
30538f23e9faSHans Rosenfeld /* It's not a PCIE adapter. */
30548f23e9faSHans Rosenfeld return;
30558f23e9faSHans Rosenfeld }
30568f23e9faSHans Rosenfeld
30578f23e9faSHans Rosenfeld /* Read PCI Extended capbabilities */
30588f23e9faSHans Rosenfeld
30598f23e9faSHans Rosenfeld bzero(hba->pci_ecap_offset, sizeof (hba->pci_ecap_offset));
30608f23e9faSHans Rosenfeld
30618f23e9faSHans Rosenfeld /* Set first offset */
30628f23e9faSHans Rosenfeld eoffset = PCIE_EXT_CAP;
30638f23e9faSHans Rosenfeld
30648f23e9faSHans Rosenfeld while (eoffset >= PCIE_EXT_CAP) {
30658f23e9faSHans Rosenfeld /* Read the cap */
30668f23e9faSHans Rosenfeld reg = ddi_get32(hba->pci_acc_handle,
30678f23e9faSHans Rosenfeld (uint32_t *)(hba->pci_addr + eoffset));
30688f23e9faSHans Rosenfeld
30698f23e9faSHans Rosenfeld eid = ((reg >> PCIE_EXT_CAP_ID_SHIFT) & PCIE_EXT_CAP_ID_MASK);
30708f23e9faSHans Rosenfeld eversion = ((reg >> PCIE_EXT_CAP_VER_SHIFT) &
30718f23e9faSHans Rosenfeld PCIE_EXT_CAP_VER_MASK);
30728f23e9faSHans Rosenfeld enext = ((reg >> PCIE_EXT_CAP_NEXT_PTR_SHIFT) &
30738f23e9faSHans Rosenfeld PCIE_EXT_CAP_NEXT_PTR_MASK);
30748f23e9faSHans Rosenfeld
30758f23e9faSHans Rosenfeld if ((eid < PCI_EXT_CAP_MAX_PTR) &&
30768f23e9faSHans Rosenfeld (hba->pci_ecap_offset[eid] == 0)) {
30778f23e9faSHans Rosenfeld hba->pci_ecap_offset[eid] = eoffset;
30788f23e9faSHans Rosenfeld }
30798f23e9faSHans Rosenfeld
30808f23e9faSHans Rosenfeld EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
30818f23e9faSHans Rosenfeld "%s: offset=0x%x version=0x%x next=0x%x",
30828f23e9faSHans Rosenfeld emlxs_pci_ecap_xlate(eid),
30838f23e9faSHans Rosenfeld eoffset, eversion, enext);
3084a9800bebSGarrett D'Amore
30858f23e9faSHans Rosenfeld eoffset = enext;
3086a9800bebSGarrett D'Amore }
3087a9800bebSGarrett D'Amore
3088a9800bebSGarrett D'Amore return;
3089a9800bebSGarrett D'Amore
3090a9800bebSGarrett D'Amore } /* emlxs_pci_cap_offsets() */
3091