1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22fcf3ce44SJohn Forte /* 23291a2b48SSukumar Swaminathan * Copyright 2009 Emulex. All rights reserved. 24*82527734SSukumar Swaminathan * Use is subject to license terms. 25fcf3ce44SJohn Forte */ 26fcf3ce44SJohn Forte 27291a2b48SSukumar Swaminathan 28*82527734SSukumar Swaminathan #define EMLXS_FW_TABLE_DEF 29*82527734SSukumar Swaminathan #define EMLXS_MODEL_DEF 30fcf3ce44SJohn Forte 31*82527734SSukumar Swaminathan #include <emlxs.h> 32fcf3ce44SJohn Forte 33*82527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 34*82527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_HBA_C); 35fcf3ce44SJohn Forte 36*82527734SSukumar Swaminathan static uint32_t emlxs_decode_biu_rev(uint32_t rev); 37*82527734SSukumar Swaminathan static uint32_t emlxs_decode_endec_rev(uint32_t rev); 38*82527734SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, 39*82527734SSukumar Swaminathan IOCBQ *iocbq); 40291a2b48SSukumar Swaminathan 41fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 42*82527734SSukumar Swaminathan uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] = 43*82527734SSukumar Swaminathan {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8}; 44*82527734SSukumar Swaminathan uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] = 45*82527734SSukumar Swaminathan {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4, 46*82527734SSukumar Swaminathan EMLXS_MSI0_MASK8}; 47291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 48fcf3ce44SJohn Forte 49*82527734SSukumar Swaminathan emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE; 50*82527734SSukumar Swaminathan int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t); 51291a2b48SSukumar Swaminathan 52*82527734SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = { 53*82527734SSukumar Swaminathan {FC_FCP_RING, "FCP Ring"}, 54*82527734SSukumar Swaminathan {FC_IP_RING, "IP Ring"}, 55*82527734SSukumar Swaminathan {FC_ELS_RING, "ELS Ring"}, 56*82527734SSukumar Swaminathan {FC_CT_RING, "CT Ring"} 57291a2b48SSukumar Swaminathan 58*82527734SSukumar Swaminathan }; /* emlxs_ring_table */ 59fcf3ce44SJohn Forte 60fcf3ce44SJohn Forte 61*82527734SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = { 62*82527734SSukumar Swaminathan {0, "NULL"}, 63*82527734SSukumar Swaminathan {FC_ERROR, "ERROR"}, 64*82527734SSukumar Swaminathan {FC_KILLED, "KILLED"}, 65*82527734SSukumar Swaminathan {FC_WARM_START, "WARM_START"}, 66*82527734SSukumar Swaminathan {FC_INIT_START, "INIT_START"}, 67*82527734SSukumar Swaminathan {FC_INIT_NVPARAMS, "INIT_NVPARAMS"}, 68*82527734SSukumar Swaminathan {FC_INIT_REV, "INIT_REV"}, 69*82527734SSukumar Swaminathan {FC_INIT_CFGPORT, "INIT_CFGPORT"}, 70*82527734SSukumar Swaminathan {FC_INIT_CFGRING, "INIT_CFGRING"}, 71*82527734SSukumar Swaminathan {FC_INIT_INITLINK, "INIT_INITLINK"}, 72*82527734SSukumar Swaminathan {FC_LINK_DOWN, "LINK_DOWN"}, 73*82527734SSukumar Swaminathan {FC_LINK_UP, "LINK_UP"}, 74*82527734SSukumar Swaminathan {FC_CLEAR_LA, "CLEAR_LA"}, 75*82527734SSukumar Swaminathan {FC_READY, "READY"} 76fcf3ce44SJohn Forte 77*82527734SSukumar Swaminathan }; /* emlxs_ffstate_table */ 78fcf3ce44SJohn Forte 79fcf3ce44SJohn Forte 80fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 81fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 82fcf3ce44SJohn Forte int32_t 83fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max) 84fcf3ce44SJohn Forte { 85fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 86fcf3ce44SJohn Forte int32_t pass = 0; 87fcf3ce44SJohn Forte int32_t type = 0; 88fcf3ce44SJohn Forte char s_type[16]; 89fcf3ce44SJohn Forte int32_t types; 90fcf3ce44SJohn Forte int32_t count; 91fcf3ce44SJohn Forte int32_t nintrs; 92fcf3ce44SJohn Forte int32_t mode; 93fcf3ce44SJohn Forte int32_t actual; 94fcf3ce44SJohn Forte int32_t new_actual; 95fcf3ce44SJohn Forte int32_t i; 96fcf3ce44SJohn Forte int32_t ret; 97fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 98fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL; 99fcf3ce44SJohn Forte uint32_t *intr_pri = NULL; 100fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 101fcf3ce44SJohn Forte int32_t hilevel_pri; 102fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG; 103fcf3ce44SJohn Forte char buf[64]; 104fcf3ce44SJohn Forte 105fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 106fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max)); 107fcf3ce44SJohn Forte } 108291a2b48SSukumar Swaminathan 109fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) { 110fcf3ce44SJohn Forte return (DDI_SUCCESS); 111fcf3ce44SJohn Forte } 112291a2b48SSukumar Swaminathan 113fcf3ce44SJohn Forte /* Set max interrupt count if not specified */ 114fcf3ce44SJohn Forte if (max == 0) { 115fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) || 116fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) { 117fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS; 118fcf3ce44SJohn Forte } else { 119fcf3ce44SJohn Forte max = 1; 120fcf3ce44SJohn Forte } 121fcf3ce44SJohn Forte } 122291a2b48SSukumar Swaminathan 123fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */ 124fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) { 125fcf3ce44SJohn Forte max = hba->model_info.intr_limit; 126fcf3ce44SJohn Forte } 127291a2b48SSukumar Swaminathan 128fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */ 129fcf3ce44SJohn Forte types = 0; 130fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types); 131fcf3ce44SJohn Forte 132fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) { 133fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 134fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret); 135fcf3ce44SJohn Forte 136fcf3ce44SJohn Forte /* Default to fixed type */ 137fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED; 138fcf3ce44SJohn Forte } 139291a2b48SSukumar Swaminathan 140fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */ 141fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) { 142fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 143fcf3ce44SJohn Forte } 144291a2b48SSukumar Swaminathan 145fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */ 146fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) || 147fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) { 148fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 149fcf3ce44SJohn Forte } 150291a2b48SSukumar Swaminathan 151fcf3ce44SJohn Forte begin: 152fcf3ce44SJohn Forte 153fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */ 154fcf3ce44SJohn Forte type = 0; 155fcf3ce44SJohn Forte 156fcf3ce44SJohn Forte /* Check if MSIX is fully supported */ 157fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) && 158fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) { 159fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 160fcf3ce44SJohn Forte nintrs = 0; 161fcf3ce44SJohn Forte ret = 162291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX, 163291a2b48SSukumar Swaminathan &nintrs); 164fcf3ce44SJohn Forte 165fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 166fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX; 167fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSIX"); 168fcf3ce44SJohn Forte goto initialize; 169fcf3ce44SJohn Forte } 170fcf3ce44SJohn Forte } 171291a2b48SSukumar Swaminathan 172fcf3ce44SJohn Forte /* Check if MSI is fully supported */ 173fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) && 174fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) { 175fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 176fcf3ce44SJohn Forte nintrs = 0; 177291a2b48SSukumar Swaminathan ret = 178291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs); 179fcf3ce44SJohn Forte 180fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) { 181fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI; 182fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_MSI"); 183fcf3ce44SJohn Forte goto initialize; 184fcf3ce44SJohn Forte } 185fcf3ce44SJohn Forte } 186291a2b48SSukumar Swaminathan 187fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */ 188fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) && 189fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 190fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */ 191fcf3ce44SJohn Forte nintrs = 0; 192fcf3ce44SJohn Forte ret = 193291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED, 194291a2b48SSukumar Swaminathan &nintrs); 195fcf3ce44SJohn Forte 196fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) { 197fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED; 198fcf3ce44SJohn Forte (void) strcpy(s_type, "TYPE_FIXED"); 199fcf3ce44SJohn Forte goto initialize; 200fcf3ce44SJohn Forte } 201fcf3ce44SJohn Forte } 202291a2b48SSukumar Swaminathan 203fcf3ce44SJohn Forte goto init_failed; 204fcf3ce44SJohn Forte 205fcf3ce44SJohn Forte 206fcf3ce44SJohn Forte initialize: 207fcf3ce44SJohn Forte 208fcf3ce44SJohn Forte pass++; 209fcf3ce44SJohn Forte mode = 0; 210fcf3ce44SJohn Forte actual = 0; 211fcf3ce44SJohn Forte htable = NULL; 212fcf3ce44SJohn Forte intr_pri = NULL; 213fcf3ce44SJohn Forte intr_cap = NULL; 214fcf3ce44SJohn Forte hilevel_pri = 0; 215fcf3ce44SJohn Forte 216fcf3ce44SJohn Forte if (pass == 1) { 217fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 218291a2b48SSukumar Swaminathan "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type, 219291a2b48SSukumar Swaminathan cfg[CFG_MSI_MODE].current, types, nintrs); 220fcf3ce44SJohn Forte } 221291a2b48SSukumar Swaminathan 222fcf3ce44SJohn Forte /* Validate interrupt count */ 223fcf3ce44SJohn Forte count = min(nintrs, max); 224fcf3ce44SJohn Forte 225fcf3ce44SJohn Forte if (count >= 8) { 226fcf3ce44SJohn Forte count = 8; 227fcf3ce44SJohn Forte } else if (count >= 4) { 228fcf3ce44SJohn Forte count = 4; 229fcf3ce44SJohn Forte } else if (count >= 2) { 230fcf3ce44SJohn Forte count = 2; 231fcf3ce44SJohn Forte } else { 232fcf3ce44SJohn Forte count = 1; 233fcf3ce44SJohn Forte } 234fcf3ce44SJohn Forte 235fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */ 236fcf3ce44SJohn Forte htable = 237291a2b48SSukumar Swaminathan kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)), 238291a2b48SSukumar Swaminathan KM_SLEEP); 239fcf3ce44SJohn Forte 240fcf3ce44SJohn Forte /* Allocate 'count' interrupts */ 241291a2b48SSukumar Swaminathan ret = 242291a2b48SSukumar Swaminathan ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count, 243fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL); 244fcf3ce44SJohn Forte 245fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 246*82527734SSukumar Swaminathan "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret); 247fcf3ce44SJohn Forte 248fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) { 249fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 250fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret); 251fcf3ce44SJohn Forte 252fcf3ce44SJohn Forte goto init_failed; 253fcf3ce44SJohn Forte } 254291a2b48SSukumar Swaminathan 255fcf3ce44SJohn Forte if (actual != count) { 256fcf3ce44SJohn Forte /* Validate actual count */ 257fcf3ce44SJohn Forte if (actual >= 8) { 258fcf3ce44SJohn Forte new_actual = 8; 259fcf3ce44SJohn Forte } else if (actual >= 4) { 260fcf3ce44SJohn Forte new_actual = 4; 261fcf3ce44SJohn Forte } else if (actual >= 2) { 262fcf3ce44SJohn Forte new_actual = 2; 263fcf3ce44SJohn Forte } else { 264fcf3ce44SJohn Forte new_actual = 1; 265fcf3ce44SJohn Forte } 266fcf3ce44SJohn Forte 267fcf3ce44SJohn Forte if (new_actual < actual) { 268fcf3ce44SJohn Forte /* Free extra handles */ 269fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) { 270fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 271fcf3ce44SJohn Forte } 272fcf3ce44SJohn Forte 273fcf3ce44SJohn Forte actual = new_actual; 274fcf3ce44SJohn Forte } 275291a2b48SSukumar Swaminathan 276fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */ 277fcf3ce44SJohn Forte new_htable = 278fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)), 279fcf3ce44SJohn Forte KM_SLEEP); 280fcf3ce44SJohn Forte 281fcf3ce44SJohn Forte /* Copy old array to new array */ 282fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable, 283fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t))); 284fcf3ce44SJohn Forte 285fcf3ce44SJohn Forte /* Free the old array */ 286fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 287fcf3ce44SJohn Forte 288fcf3ce44SJohn Forte htable = new_htable; 289fcf3ce44SJohn Forte count = actual; 290fcf3ce44SJohn Forte } 291291a2b48SSukumar Swaminathan 292fcf3ce44SJohn Forte /* Allocate interrupt priority table */ 293fcf3ce44SJohn Forte intr_pri = 294fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)), 295fcf3ce44SJohn Forte KM_SLEEP); 296fcf3ce44SJohn Forte 297fcf3ce44SJohn Forte /* Allocate interrupt capability table */ 298fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP); 299fcf3ce44SJohn Forte 300fcf3ce44SJohn Forte /* Get minimum hilevel priority */ 301fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri(); 302fcf3ce44SJohn Forte 303fcf3ce44SJohn Forte /* Fill the priority and capability tables */ 304fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 305fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]); 306fcf3ce44SJohn Forte 307fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 308fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 309fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. " 310291a2b48SSukumar Swaminathan "handle=%p ret=%d", 311291a2b48SSukumar Swaminathan i, &htable[i], ret); 312fcf3ce44SJohn Forte 313fcf3ce44SJohn Forte /* Clean up the interrupts */ 314fcf3ce44SJohn Forte goto init_failed; 315fcf3ce44SJohn Forte } 316291a2b48SSukumar Swaminathan 317fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) { 318fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 319fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. " 320fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x", 321fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri); 322fcf3ce44SJohn Forte 323fcf3ce44SJohn Forte /* Clean up the interrupts */ 324fcf3ce44SJohn Forte goto init_failed; 325fcf3ce44SJohn Forte } 326291a2b48SSukumar Swaminathan 327fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]); 328fcf3ce44SJohn Forte 329fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 330fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 331291a2b48SSukumar Swaminathan "MSI: ddi_intr_get_cap(%d) failed. " 332291a2b48SSukumar Swaminathan "handle=%p ret=%d", 333291a2b48SSukumar Swaminathan i, &htable[i], ret); 334fcf3ce44SJohn Forte 335fcf3ce44SJohn Forte /* Clean up the interrupts */ 336fcf3ce44SJohn Forte goto init_failed; 337fcf3ce44SJohn Forte } 338291a2b48SSukumar Swaminathan 339fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 340291a2b48SSukumar Swaminathan "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i, 341291a2b48SSukumar Swaminathan intr_cap[i], intr_pri[i], hilevel_pri); 342fcf3ce44SJohn Forte 343fcf3ce44SJohn Forte } 344fcf3ce44SJohn Forte 345fcf3ce44SJohn Forte /* Set mode */ 346fcf3ce44SJohn Forte switch (count) { 347fcf3ce44SJohn Forte case 8: 348fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8; 349fcf3ce44SJohn Forte break; 350fcf3ce44SJohn Forte 351fcf3ce44SJohn Forte case 4: 352fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4; 353fcf3ce44SJohn Forte break; 354fcf3ce44SJohn Forte 355fcf3ce44SJohn Forte case 2: 356fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2; 357fcf3ce44SJohn Forte break; 358fcf3ce44SJohn Forte 359fcf3ce44SJohn Forte default: 360fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1; 361fcf3ce44SJohn Forte } 362fcf3ce44SJohn Forte 363fcf3ce44SJohn Forte /* Save the info */ 364fcf3ce44SJohn Forte hba->intr_htable = htable; 365fcf3ce44SJohn Forte hba->intr_count = count; 366fcf3ce44SJohn Forte hba->intr_pri = intr_pri; 367fcf3ce44SJohn Forte hba->intr_cap = intr_cap; 368fcf3ce44SJohn Forte hba->intr_type = type; 369291a2b48SSukumar Swaminathan hba->intr_arg = (void *)((unsigned long)intr_pri[0]); 370fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode]; 371fcf3ce44SJohn Forte 372fcf3ce44SJohn Forte hba->intr_cond = 0; 373*82527734SSukumar Swaminathan 374*82527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */ 375*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 376*82527734SSukumar Swaminathan hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current; 377*82527734SSukumar Swaminathan } 378*82527734SSukumar Swaminathan 379fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 380fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i]; 381fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i]; 382fcf3ce44SJohn Forte 383fcf3ce44SJohn Forte (void) sprintf(buf, "%s%d_msi%d mutex", DRIVER_NAME, 384fcf3ce44SJohn Forte hba->ddiinst, i); 385fcf3ce44SJohn Forte mutex_init(&hba->intr_lock[i], buf, MUTEX_DRIVER, 386291a2b48SSukumar Swaminathan (void *)hba->intr_arg); 387fcf3ce44SJohn Forte } 388fcf3ce44SJohn Forte 389fcf3ce44SJohn Forte /* Set flag to indicate support */ 390fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED; 391fcf3ce44SJohn Forte 392fcf3ce44SJohn Forte /* Create the interrupt threads */ 393*82527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 394*82527734SSukumar Swaminathan (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, 395fcf3ce44SJohn Forte hba->ddiinst, i); 396*82527734SSukumar Swaminathan mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, 397291a2b48SSukumar Swaminathan (void *)hba->intr_arg); 398fcf3ce44SJohn Forte 399*82527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread); 400fcf3ce44SJohn Forte } 401fcf3ce44SJohn Forte 402fcf3ce44SJohn Forte return (DDI_SUCCESS); 403fcf3ce44SJohn Forte 404fcf3ce44SJohn Forte init_failed: 405fcf3ce44SJohn Forte 406fcf3ce44SJohn Forte if (intr_cap) { 407fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 408fcf3ce44SJohn Forte } 409291a2b48SSukumar Swaminathan 410fcf3ce44SJohn Forte if (intr_pri) { 411fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 412fcf3ce44SJohn Forte } 413291a2b48SSukumar Swaminathan 414fcf3ce44SJohn Forte if (htable) { 415fcf3ce44SJohn Forte /* Process the interrupt handlers */ 416fcf3ce44SJohn Forte for (i = 0; i < actual; i++) { 417fcf3ce44SJohn Forte /* Free the handle[i] */ 418fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]); 419fcf3ce44SJohn Forte } 420fcf3ce44SJohn Forte 421fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 422fcf3ce44SJohn Forte } 423291a2b48SSukumar Swaminathan 424fcf3ce44SJohn Forte /* Initialize */ 425fcf3ce44SJohn Forte hba->intr_htable = NULL; 426fcf3ce44SJohn Forte hba->intr_count = 0; 427fcf3ce44SJohn Forte hba->intr_pri = NULL; 428fcf3ce44SJohn Forte hba->intr_cap = NULL; 429fcf3ce44SJohn Forte hba->intr_type = 0; 430fcf3ce44SJohn Forte hba->intr_arg = NULL; 431fcf3ce44SJohn Forte hba->intr_cond = 0; 432fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 433fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock)); 434fcf3ce44SJohn Forte 435fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) { 436fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED); 437fcf3ce44SJohn Forte goto begin; 438fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) { 439fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED; 440fcf3ce44SJohn Forte goto begin; 441fcf3ce44SJohn Forte } 442291a2b48SSukumar Swaminathan 443fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 444fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts"); 445fcf3ce44SJohn Forte 446fcf3ce44SJohn Forte return (DDI_FAILURE); 447fcf3ce44SJohn Forte 448fcf3ce44SJohn Forte 449*82527734SSukumar Swaminathan } /* emlxs_msi_init() */ 450fcf3ce44SJohn Forte 451fcf3ce44SJohn Forte 452fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 453fcf3ce44SJohn Forte int32_t 454fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba) 455fcf3ce44SJohn Forte { 456fcf3ce44SJohn Forte uint32_t count; 457fcf3ce44SJohn Forte int32_t i; 458fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 459fcf3ce44SJohn Forte uint32_t *intr_pri; 460fcf3ce44SJohn Forte int32_t *intr_cap; 461fcf3ce44SJohn Forte int32_t ret; 462fcf3ce44SJohn Forte 463fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 464fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba)); 465fcf3ce44SJohn Forte } 466291a2b48SSukumar Swaminathan 467fcf3ce44SJohn Forte /* 468291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 469291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_uninit called. flags=%x", 470291a2b48SSukumar Swaminathan * hba->intr_flags); 471fcf3ce44SJohn Forte */ 472fcf3ce44SJohn Forte 473fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */ 474fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) { 475fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba); 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 478fcf3ce44SJohn Forte return (ret); 479fcf3ce44SJohn Forte } 480fcf3ce44SJohn Forte } 481291a2b48SSukumar Swaminathan 482fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 483fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 484fcf3ce44SJohn Forte return (DDI_SUCCESS); 485fcf3ce44SJohn Forte } 486fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED; 487fcf3ce44SJohn Forte 488fcf3ce44SJohn Forte /* Get handle table parameters */ 489fcf3ce44SJohn Forte htable = hba->intr_htable; 490fcf3ce44SJohn Forte count = hba->intr_count; 491fcf3ce44SJohn Forte intr_pri = hba->intr_pri; 492fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 493fcf3ce44SJohn Forte 494fcf3ce44SJohn Forte /* Clean up */ 495fcf3ce44SJohn Forte hba->intr_count = 0; 496fcf3ce44SJohn Forte hba->intr_htable = NULL; 497fcf3ce44SJohn Forte hba->intr_pri = NULL; 498fcf3ce44SJohn Forte hba->intr_cap = NULL; 499fcf3ce44SJohn Forte hba->intr_type = 0; 500fcf3ce44SJohn Forte hba->intr_arg = NULL; 501fcf3ce44SJohn Forte hba->intr_cond = 0; 502fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map)); 503fcf3ce44SJohn Forte 504fcf3ce44SJohn Forte if (intr_cap) { 505fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t))); 506fcf3ce44SJohn Forte } 507291a2b48SSukumar Swaminathan 508fcf3ce44SJohn Forte if (intr_pri) { 509fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t))); 510fcf3ce44SJohn Forte } 511291a2b48SSukumar Swaminathan 512fcf3ce44SJohn Forte if (htable) { 513fcf3ce44SJohn Forte /* Process the interrupt handlers */ 514fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 515fcf3ce44SJohn Forte /* Free the handle[i] */ 516291a2b48SSukumar Swaminathan ret = ddi_intr_free(htable[i]); 517fcf3ce44SJohn Forte } 518fcf3ce44SJohn Forte 519fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t))); 520fcf3ce44SJohn Forte } 521291a2b48SSukumar Swaminathan 522fcf3ce44SJohn Forte /* Destroy the intr locks */ 523fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) { 524fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]); 525fcf3ce44SJohn Forte } 526fcf3ce44SJohn Forte 527fcf3ce44SJohn Forte /* Destroy the interrupt threads */ 528*82527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 529*82527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread); 530*82527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock); 531fcf3ce44SJohn Forte } 532fcf3ce44SJohn Forte 533fcf3ce44SJohn Forte /* 534291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 535291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_uninit done. flags=%x", 536291a2b48SSukumar Swaminathan * hba->intr_flags); 537fcf3ce44SJohn Forte */ 538fcf3ce44SJohn Forte 539fcf3ce44SJohn Forte return (DDI_SUCCESS); 540fcf3ce44SJohn Forte 541*82527734SSukumar Swaminathan } /* emlxs_msi_uninit() */ 542fcf3ce44SJohn Forte 543fcf3ce44SJohn Forte 544fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */ 545fcf3ce44SJohn Forte int32_t 546fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba) 547fcf3ce44SJohn Forte { 548fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 549fcf3ce44SJohn Forte int32_t count; 550fcf3ce44SJohn Forte int32_t i; 551fcf3ce44SJohn Forte int32_t ret; 552fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL; 553fcf3ce44SJohn Forte int32_t *intr_cap = NULL; 554fcf3ce44SJohn Forte 555fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 556fcf3ce44SJohn Forte return (emlxs_intx_add(hba)); 557fcf3ce44SJohn Forte } 558291a2b48SSukumar Swaminathan 559fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 560fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) { 561fcf3ce44SJohn Forte return (DDI_SUCCESS); 562fcf3ce44SJohn Forte } 563291a2b48SSukumar Swaminathan 564fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 565fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) { 566fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0); 567fcf3ce44SJohn Forte 568fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 569fcf3ce44SJohn Forte return (ret); 570fcf3ce44SJohn Forte } 571fcf3ce44SJohn Forte } 572291a2b48SSukumar Swaminathan 573fcf3ce44SJohn Forte /* Get handle table parameters */ 574fcf3ce44SJohn Forte htable = hba->intr_htable; 575fcf3ce44SJohn Forte count = hba->intr_count; 576fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 577fcf3ce44SJohn Forte 578fcf3ce44SJohn Forte /* Add the interrupt handlers */ 579fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 580fcf3ce44SJohn Forte /* add handler for handle[i] */ 581291a2b48SSukumar Swaminathan ret = 582*82527734SSukumar Swaminathan ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR, 583291a2b48SSukumar Swaminathan (char *)hba, (char *)((unsigned long)i)); 584fcf3ce44SJohn Forte 585fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 586fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 587291a2b48SSukumar Swaminathan "MSI: ddi_intr_add_handler(%d) failed. " 588291a2b48SSukumar Swaminathan "handle=%p ret=%d", 589291a2b48SSukumar Swaminathan i, &htable[i], ret); 590fcf3ce44SJohn Forte 591fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */ 592fcf3ce44SJohn Forte while (i) { 593fcf3ce44SJohn Forte /* Decrement i */ 594fcf3ce44SJohn Forte i--; 595fcf3ce44SJohn Forte 596fcf3ce44SJohn Forte /* Remove the handler */ 597fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 598fcf3ce44SJohn Forte 599fcf3ce44SJohn Forte } 600fcf3ce44SJohn Forte 601fcf3ce44SJohn Forte return (DDI_FAILURE); 602fcf3ce44SJohn Forte } 603fcf3ce44SJohn Forte } 604fcf3ce44SJohn Forte 605fcf3ce44SJohn Forte /* Enable the interrupts */ 606fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 607fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count); 608fcf3ce44SJohn Forte 609fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 610fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 611fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d", 612fcf3ce44SJohn Forte count, ret); 613fcf3ce44SJohn Forte 614fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 615fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 616fcf3ce44SJohn Forte 617fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 618fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 619fcf3ce44SJohn Forte &emlxs_init_debug_msg, 620fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. " 621291a2b48SSukumar Swaminathan "ret=%d", 622291a2b48SSukumar Swaminathan i, ret); 623fcf3ce44SJohn Forte } 624fcf3ce44SJohn Forte } 625fcf3ce44SJohn Forte } 626fcf3ce44SJohn Forte } else { 627fcf3ce44SJohn Forte for (i = 0; i < count; ++i) { 628fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]); 629fcf3ce44SJohn Forte 630fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 631291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 632291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 633fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d", 634fcf3ce44SJohn Forte i, ret); 635fcf3ce44SJohn Forte } 636fcf3ce44SJohn Forte } 637fcf3ce44SJohn Forte } 638fcf3ce44SJohn Forte 639fcf3ce44SJohn Forte 640fcf3ce44SJohn Forte /* Set flag to indicate support */ 641fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED; 642fcf3ce44SJohn Forte 643fcf3ce44SJohn Forte return (DDI_SUCCESS); 644fcf3ce44SJohn Forte 645*82527734SSukumar Swaminathan } /* emlxs_msi_add() */ 646fcf3ce44SJohn Forte 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte 649fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 650fcf3ce44SJohn Forte int32_t 651fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba) 652fcf3ce44SJohn Forte { 653fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 654fcf3ce44SJohn Forte uint32_t count; 655fcf3ce44SJohn Forte int32_t i; 656fcf3ce44SJohn Forte ddi_intr_handle_t *htable; 657fcf3ce44SJohn Forte int32_t *intr_cap; 658fcf3ce44SJohn Forte int32_t ret; 659fcf3ce44SJohn Forte 660fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) { 661fcf3ce44SJohn Forte return (emlxs_intx_remove(hba)); 662fcf3ce44SJohn Forte } 663291a2b48SSukumar Swaminathan 664fcf3ce44SJohn Forte /* 665291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 666291a2b48SSukumar Swaminathan * "MSI: emlxs_msi_remove called. flags=%x", 667291a2b48SSukumar Swaminathan * hba->intr_flags); 668fcf3ce44SJohn Forte */ 669fcf3ce44SJohn Forte 670fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 671fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) { 672fcf3ce44SJohn Forte return (DDI_SUCCESS); 673fcf3ce44SJohn Forte } 674fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED; 675fcf3ce44SJohn Forte 676fcf3ce44SJohn Forte /* Disable all adapter interrupts */ 677*82527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 678fcf3ce44SJohn Forte 679fcf3ce44SJohn Forte /* Get handle table parameters */ 680fcf3ce44SJohn Forte htable = hba->intr_htable; 681fcf3ce44SJohn Forte count = hba->intr_count; 682fcf3ce44SJohn Forte intr_cap = hba->intr_cap; 683fcf3ce44SJohn Forte 684fcf3ce44SJohn Forte /* Disable the interrupts */ 685fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) { 686fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count); 687fcf3ce44SJohn Forte 688fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 689fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 690fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d", 691fcf3ce44SJohn Forte count, ret); 692fcf3ce44SJohn Forte 693fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 694fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 695fcf3ce44SJohn Forte 696fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 697fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 698fcf3ce44SJohn Forte &emlxs_init_debug_msg, 699fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. " 700291a2b48SSukumar Swaminathan "ret=%d", 701291a2b48SSukumar Swaminathan i, ret); 702fcf3ce44SJohn Forte } 703fcf3ce44SJohn Forte } 704fcf3ce44SJohn Forte } 705fcf3ce44SJohn Forte } else { 706fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 707fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]); 708fcf3ce44SJohn Forte 709fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 710291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 711291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 712fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d", 713fcf3ce44SJohn Forte i, ret); 714fcf3ce44SJohn Forte } 715fcf3ce44SJohn Forte } 716fcf3ce44SJohn Forte } 717fcf3ce44SJohn Forte 718fcf3ce44SJohn Forte /* Process the interrupt handlers */ 719fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 720fcf3ce44SJohn Forte /* Remove the handler */ 721fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]); 722fcf3ce44SJohn Forte 723fcf3ce44SJohn Forte 724fcf3ce44SJohn Forte } 725fcf3ce44SJohn Forte 726fcf3ce44SJohn Forte return (DDI_SUCCESS); 727fcf3ce44SJohn Forte 728*82527734SSukumar Swaminathan } /* emlxs_msi_remove() */ 729fcf3ce44SJohn Forte 730291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 731fcf3ce44SJohn Forte 732fcf3ce44SJohn Forte 733fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */ 734fcf3ce44SJohn Forte /* ARGSUSED */ 735fcf3ce44SJohn Forte int32_t 736fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max) 737fcf3ce44SJohn Forte { 738fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 739*82527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG; 740fcf3ce44SJohn Forte int32_t ret; 741fcf3ce44SJohn Forte uint32_t i; 742fcf3ce44SJohn Forte char buf[64]; 743fcf3ce44SJohn Forte 744fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */ 745fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) { 746fcf3ce44SJohn Forte return (DDI_SUCCESS); 747fcf3ce44SJohn Forte } 748291a2b48SSukumar Swaminathan 749fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */ 750fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) { 751fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 752fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x", 753fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags); 754fcf3ce44SJohn Forte 755fcf3ce44SJohn Forte return (DDI_FAILURE); 756fcf3ce44SJohn Forte } 757291a2b48SSukumar Swaminathan 758fcf3ce44SJohn Forte /* 759291a2b48SSukumar Swaminathan * Interrupt number '0' is a high-level interrupt. This driver 760291a2b48SSukumar Swaminathan * does not support having its interrupts mapped above scheduler 761291a2b48SSukumar Swaminathan * priority; i.e., we always expect to be able to call general 762291a2b48SSukumar Swaminathan * kernel routines that may invoke the scheduler. 763fcf3ce44SJohn Forte */ 764fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) { 765fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 766fcf3ce44SJohn Forte "INTX: High-level interrupt not supported."); 767fcf3ce44SJohn Forte 768fcf3ce44SJohn Forte return (DDI_FAILURE); 769fcf3ce44SJohn Forte } 770291a2b48SSukumar Swaminathan 771fcf3ce44SJohn Forte /* Get an iblock cookie */ 772291a2b48SSukumar Swaminathan ret = 773291a2b48SSukumar Swaminathan ddi_get_iblock_cookie(hba->dip, (uint32_t)EMLXS_INUMBER, 774fcf3ce44SJohn Forte (ddi_iblock_cookie_t *)&hba->intr_arg); 775fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 776fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 777fcf3ce44SJohn Forte "INTX: ddi_get_iblock_cookie failed. ret=%d", ret); 778fcf3ce44SJohn Forte 779fcf3ce44SJohn Forte return (ret); 780fcf3ce44SJohn Forte } 781291a2b48SSukumar Swaminathan 782fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_INITED; 783fcf3ce44SJohn Forte 784*82527734SSukumar Swaminathan hba->intr_count = 1; 785*82527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */ 786*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 787*82527734SSukumar Swaminathan hba->chan_count = cfg[CFG_NUM_WQ].current; 788*82527734SSukumar Swaminathan } 789*82527734SSukumar Swaminathan 790fcf3ce44SJohn Forte /* Create the interrupt threads */ 791*82527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 792*82527734SSukumar Swaminathan (void) sprintf(buf, "%s%d_channel%d mutex", DRIVER_NAME, 793fcf3ce44SJohn Forte hba->ddiinst, i); 794*82527734SSukumar Swaminathan mutex_init(&hba->chan[i].rsp_lock, buf, MUTEX_DRIVER, 795fcf3ce44SJohn Forte (void *)hba->intr_arg); 796fcf3ce44SJohn Forte 797*82527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread); 798fcf3ce44SJohn Forte } 799fcf3ce44SJohn Forte 800fcf3ce44SJohn Forte return (DDI_SUCCESS); 801fcf3ce44SJohn Forte 802*82527734SSukumar Swaminathan } /* emlxs_intx_init() */ 803fcf3ce44SJohn Forte 804fcf3ce44SJohn Forte 805fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */ 806fcf3ce44SJohn Forte int32_t 807fcf3ce44SJohn Forte emlxs_intx_uninit(emlxs_hba_t *hba) 808fcf3ce44SJohn Forte { 809fcf3ce44SJohn Forte int32_t ret; 810fcf3ce44SJohn Forte uint32_t i; 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte /* Make sure interrupts have been removed */ 813fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_INTX_ADDED)) { 814fcf3ce44SJohn Forte ret = emlxs_intx_remove(hba); 815fcf3ce44SJohn Forte 816fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 817fcf3ce44SJohn Forte return (ret); 818fcf3ce44SJohn Forte } 819fcf3ce44SJohn Forte } 820291a2b48SSukumar Swaminathan 821fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */ 822fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 823fcf3ce44SJohn Forte return (DDI_SUCCESS); 824fcf3ce44SJohn Forte } 825fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_INITED; 826fcf3ce44SJohn Forte 827fcf3ce44SJohn Forte hba->intr_arg = NULL; 828fcf3ce44SJohn Forte 829fcf3ce44SJohn Forte /* Create the interrupt threads */ 830*82527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) { 831*82527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread); 832*82527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock); 833fcf3ce44SJohn Forte } 834fcf3ce44SJohn Forte 835fcf3ce44SJohn Forte return (DDI_SUCCESS); 836fcf3ce44SJohn Forte 837*82527734SSukumar Swaminathan } /* emlxs_intx_uninit() */ 838fcf3ce44SJohn Forte 839fcf3ce44SJohn Forte 840291a2b48SSukumar Swaminathan /* 841291a2b48SSukumar Swaminathan * This is the legacy method for adding interrupts in Solaris 842291a2b48SSukumar Swaminathan * EMLXS_INTR_ADD 843291a2b48SSukumar Swaminathan */ 844fcf3ce44SJohn Forte int32_t 845fcf3ce44SJohn Forte emlxs_intx_add(emlxs_hba_t *hba) 846fcf3ce44SJohn Forte { 847fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 848fcf3ce44SJohn Forte int32_t ret; 849fcf3ce44SJohn Forte 850fcf3ce44SJohn Forte /* Check if interrupts have already been added */ 851fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_ADDED) { 852fcf3ce44SJohn Forte return (DDI_SUCCESS); 853fcf3ce44SJohn Forte } 854291a2b48SSukumar Swaminathan 855fcf3ce44SJohn Forte /* Check if interrupts have been initialized */ 856fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_INITED)) { 857fcf3ce44SJohn Forte ret = emlxs_intx_init(hba, 0); 858fcf3ce44SJohn Forte 859fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 860fcf3ce44SJohn Forte return (ret); 861fcf3ce44SJohn Forte } 862fcf3ce44SJohn Forte } 863291a2b48SSukumar Swaminathan 864fcf3ce44SJohn Forte /* add intrrupt handler routine */ 865291a2b48SSukumar Swaminathan ret = ddi_add_intr((void *)hba->dip, 866291a2b48SSukumar Swaminathan (uint_t)EMLXS_INUMBER, 867291a2b48SSukumar Swaminathan (ddi_iblock_cookie_t *)&hba->intr_arg, 868291a2b48SSukumar Swaminathan (ddi_idevice_cookie_t *)0, 869*82527734SSukumar Swaminathan (uint_t(*)())EMLXS_SLI_INTX_INTR, (caddr_t)hba); 870fcf3ce44SJohn Forte 871fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) { 872fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_attach_failed_msg, 873fcf3ce44SJohn Forte "INTX: ddi_add_intr failed. ret=%d", ret); 874fcf3ce44SJohn Forte 875fcf3ce44SJohn Forte return (ret); 876fcf3ce44SJohn Forte } 877291a2b48SSukumar Swaminathan 878fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_INTX_ADDED; 879fcf3ce44SJohn Forte 880fcf3ce44SJohn Forte return (DDI_SUCCESS); 881fcf3ce44SJohn Forte 882*82527734SSukumar Swaminathan } /* emlxs_intx_add() */ 883fcf3ce44SJohn Forte 884fcf3ce44SJohn Forte 885fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */ 886fcf3ce44SJohn Forte int32_t 887fcf3ce44SJohn Forte emlxs_intx_remove(emlxs_hba_t *hba) 888fcf3ce44SJohn Forte { 889fcf3ce44SJohn Forte /* Check if interrupts have already been removed */ 890fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_INTX_ADDED)) { 891fcf3ce44SJohn Forte return (DDI_SUCCESS); 892fcf3ce44SJohn Forte } 893fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_INTX_ADDED; 894fcf3ce44SJohn Forte 895fcf3ce44SJohn Forte /* Diable all adapter interrupts */ 896*82527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0); 897fcf3ce44SJohn Forte 898fcf3ce44SJohn Forte /* Remove the interrupt */ 899fcf3ce44SJohn Forte (void) ddi_remove_intr((void *)hba->dip, (uint_t)EMLXS_INUMBER, 900fcf3ce44SJohn Forte hba->intr_arg); 901fcf3ce44SJohn Forte 902fcf3ce44SJohn Forte return (DDI_SUCCESS); 903fcf3ce44SJohn Forte 904*82527734SSukumar Swaminathan } /* emlxs_intx_remove() */ 905fcf3ce44SJohn Forte 906fcf3ce44SJohn Forte 907*82527734SSukumar Swaminathan extern void 908fcf3ce44SJohn Forte emlxs_process_link_speed(emlxs_hba_t *hba) 909fcf3ce44SJohn Forte { 910fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 911fcf3ce44SJohn Forte emlxs_config_t *cfg; 912fcf3ce44SJohn Forte char *cptr; 913fcf3ce44SJohn Forte uint32_t hi; 914fcf3ce44SJohn Forte 915fcf3ce44SJohn Forte /* 916291a2b48SSukumar Swaminathan * This routine modifies the link-speed config parameter entry 917291a2b48SSukumar Swaminathan * based on adapter capabilities 918fcf3ce44SJohn Forte */ 919fcf3ce44SJohn Forte vpd = &VPD; 920fcf3ce44SJohn Forte cfg = &hba->config[CFG_LINK_SPEED]; 921fcf3ce44SJohn Forte 922fcf3ce44SJohn Forte cptr = cfg->help; 923fcf3ce44SJohn Forte (void) strcpy(cptr, "Select link speed. [0=Auto"); 924fcf3ce44SJohn Forte cptr += 26; 925fcf3ce44SJohn Forte hi = 0; 926fcf3ce44SJohn Forte 927fcf3ce44SJohn Forte if (vpd->link_speed & LMT_1GB_CAPABLE) { 928fcf3ce44SJohn Forte (void) strcpy(cptr, ", 1=1Gb"); 929fcf3ce44SJohn Forte cptr += 7; 930fcf3ce44SJohn Forte hi = 1; 931fcf3ce44SJohn Forte } 932291a2b48SSukumar Swaminathan 933fcf3ce44SJohn Forte if (vpd->link_speed & LMT_2GB_CAPABLE) { 934fcf3ce44SJohn Forte (void) strcpy(cptr, ", 2=2Gb"); 935fcf3ce44SJohn Forte cptr += 7; 936fcf3ce44SJohn Forte hi = 2; 937fcf3ce44SJohn Forte } 938291a2b48SSukumar Swaminathan 939fcf3ce44SJohn Forte if (vpd->link_speed & LMT_4GB_CAPABLE) { 940fcf3ce44SJohn Forte (void) strcpy(cptr, ", 4=4Gb"); 941fcf3ce44SJohn Forte cptr += 7; 942fcf3ce44SJohn Forte hi = 4; 943fcf3ce44SJohn Forte } 944291a2b48SSukumar Swaminathan 945fcf3ce44SJohn Forte if (vpd->link_speed & LMT_8GB_CAPABLE) { 946fcf3ce44SJohn Forte (void) strcpy(cptr, ", 8=8Gb"); 947fcf3ce44SJohn Forte cptr += 7; 948fcf3ce44SJohn Forte hi = 8; 949fcf3ce44SJohn Forte } 950291a2b48SSukumar Swaminathan 951fcf3ce44SJohn Forte if (vpd->link_speed & LMT_10GB_CAPABLE) { 952fcf3ce44SJohn Forte (void) strcpy(cptr, ", 10=10Gb"); 953fcf3ce44SJohn Forte cptr += 9; 954fcf3ce44SJohn Forte hi = 10; 955fcf3ce44SJohn Forte } 956291a2b48SSukumar Swaminathan 957fcf3ce44SJohn Forte (void) strcpy(cptr, "]"); 958fcf3ce44SJohn Forte cfg->hi = hi; 959fcf3ce44SJohn Forte 960fcf3ce44SJohn Forte /* Now revalidate the current parameter setting */ 961fcf3ce44SJohn Forte cfg->current = emlxs_check_parm(hba, CFG_LINK_SPEED, cfg->current); 962fcf3ce44SJohn Forte 963fcf3ce44SJohn Forte return; 964fcf3ce44SJohn Forte 965*82527734SSukumar Swaminathan } /* emlxs_process_link_speed() */ 966fcf3ce44SJohn Forte 967fcf3ce44SJohn Forte 968fcf3ce44SJohn Forte /* 969291a2b48SSukumar Swaminathan * emlxs_parse_vpd() 970fcf3ce44SJohn Forte * 971fcf3ce44SJohn Forte * This routine will parse the VPD data 972fcf3ce44SJohn Forte */ 973fcf3ce44SJohn Forte extern int 974fcf3ce44SJohn Forte emlxs_parse_vpd(emlxs_hba_t *hba, uint8_t *vpd_buf, uint32_t size) 975fcf3ce44SJohn Forte { 976fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 977fcf3ce44SJohn Forte char tag[3]; 978fcf3ce44SJohn Forte uint8_t lenlo, lenhi; 979fcf3ce44SJohn Forte uint32_t n; 980fcf3ce44SJohn Forte uint16_t block_size; 981fcf3ce44SJohn Forte uint32_t block_index = 0; 982fcf3ce44SJohn Forte uint8_t sub_size; 983fcf3ce44SJohn Forte uint32_t sub_index; 984fcf3ce44SJohn Forte int32_t finished = 0; 985fcf3ce44SJohn Forte int32_t index = 0; 986fcf3ce44SJohn Forte char buffer[128]; 987fcf3ce44SJohn Forte emlxs_vpd_t *vpd; 988fcf3ce44SJohn Forte 989fcf3ce44SJohn Forte vpd = &VPD; 990fcf3ce44SJohn Forte 991fcf3ce44SJohn Forte 992fcf3ce44SJohn Forte while (!finished && (block_index < size)) { 993fcf3ce44SJohn Forte /* 994291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 995291a2b48SSukumar Swaminathan * "block_index = %x", block_index); 996fcf3ce44SJohn Forte */ 997fcf3ce44SJohn Forte 998fcf3ce44SJohn Forte switch (vpd_buf[block_index]) { 999fcf3ce44SJohn Forte case 0x82: 1000fcf3ce44SJohn Forte index = block_index; 1001fcf3ce44SJohn Forte index += 1; 1002fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 1003fcf3ce44SJohn Forte index += 1; 1004fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 1005fcf3ce44SJohn Forte index += 1; 1006fcf3ce44SJohn Forte block_index = index; 1007fcf3ce44SJohn Forte 1008fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1009fcf3ce44SJohn Forte block_index += block_size; 1010fcf3ce44SJohn Forte 1011fcf3ce44SJohn Forte /* 1012fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1013291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 1014fcf3ce44SJohn Forte */ 1015fcf3ce44SJohn Forte 1016fcf3ce44SJohn Forte n = sizeof (buffer); 1017fcf3ce44SJohn Forte bzero(buffer, n); 1018fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 1019fcf3ce44SJohn Forte (block_size < (n - 1)) ? block_size : (n - 1)); 1020fcf3ce44SJohn Forte 1021fcf3ce44SJohn Forte (void) strcpy(vpd->id, buffer); 1022291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "ID: %s", 1023291a2b48SSukumar Swaminathan vpd->id); 1024fcf3ce44SJohn Forte 1025fcf3ce44SJohn Forte break; 1026fcf3ce44SJohn Forte 1027fcf3ce44SJohn Forte case 0x90: 1028fcf3ce44SJohn Forte index = block_index; 1029fcf3ce44SJohn Forte index += 1; 1030fcf3ce44SJohn Forte lenlo = vpd_buf[index]; 1031fcf3ce44SJohn Forte index += 1; 1032fcf3ce44SJohn Forte lenhi = vpd_buf[index]; 1033fcf3ce44SJohn Forte index += 1; 1034fcf3ce44SJohn Forte block_index = index; 1035fcf3ce44SJohn Forte sub_index = index; 1036fcf3ce44SJohn Forte 1037fcf3ce44SJohn Forte block_size = ((((uint16_t)lenhi) << 8) + lenlo); 1038fcf3ce44SJohn Forte block_index += block_size; 1039fcf3ce44SJohn Forte 1040fcf3ce44SJohn Forte /* 1041fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1042291a2b48SSukumar Swaminathan * "block_size = %x", block_size); 1043fcf3ce44SJohn Forte */ 1044fcf3ce44SJohn Forte 1045fcf3ce44SJohn Forte /* Scan for sub-blocks */ 1046fcf3ce44SJohn Forte while ((sub_index < block_index) && 1047fcf3ce44SJohn Forte (sub_index < size)) { 1048fcf3ce44SJohn Forte /* 1049fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1050291a2b48SSukumar Swaminathan * "sub_index = %x", sub_index); 1051fcf3ce44SJohn Forte */ 1052fcf3ce44SJohn Forte 1053fcf3ce44SJohn Forte index = sub_index; 1054fcf3ce44SJohn Forte tag[0] = vpd_buf[index++]; 1055fcf3ce44SJohn Forte tag[1] = vpd_buf[index++]; 1056fcf3ce44SJohn Forte tag[2] = 0; 1057fcf3ce44SJohn Forte sub_size = vpd_buf[index++]; 1058fcf3ce44SJohn Forte 1059fcf3ce44SJohn Forte /* 1060fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1061291a2b48SSukumar Swaminathan * "sub_size = %x", sub_size); 1062fcf3ce44SJohn Forte */ 1063fcf3ce44SJohn Forte 1064fcf3ce44SJohn Forte sub_index = (index + sub_size); 1065fcf3ce44SJohn Forte 1066fcf3ce44SJohn Forte n = sizeof (buffer); 1067fcf3ce44SJohn Forte bzero(buffer, n); 1068fcf3ce44SJohn Forte bcopy(&vpd_buf[index], buffer, 1069fcf3ce44SJohn Forte (sub_size < (n - 1)) ? sub_size : (n - 1)); 1070fcf3ce44SJohn Forte 1071fcf3ce44SJohn Forte /* 1072fcf3ce44SJohn Forte * Look for Engineering Change (EC) 1073fcf3ce44SJohn Forte */ 1074fcf3ce44SJohn Forte if (strcmp(tag, "EC") == 0) { 1075fcf3ce44SJohn Forte (void) strcpy(vpd->eng_change, buffer); 1076fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1077291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "EC: %s", 1078291a2b48SSukumar Swaminathan vpd->eng_change); 1079fcf3ce44SJohn Forte } 1080fcf3ce44SJohn Forte /* 1081fcf3ce44SJohn Forte * Look for Manufacturer (MN) 1082fcf3ce44SJohn Forte */ 1083fcf3ce44SJohn Forte else if (strcmp(tag, "MN") == 0) { 1084fcf3ce44SJohn Forte (void) strcpy(vpd->manufacturer, 1085fcf3ce44SJohn Forte buffer); 1086fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1087291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "MN: %s", 1088291a2b48SSukumar Swaminathan vpd->manufacturer); 1089fcf3ce44SJohn Forte } 1090fcf3ce44SJohn Forte /* 1091fcf3ce44SJohn Forte * Look for Serial Number (SN) 1092fcf3ce44SJohn Forte */ 1093fcf3ce44SJohn Forte else if (strcmp(tag, "SN") == 0) { 1094fcf3ce44SJohn Forte (void) strcpy(vpd->serial_num, buffer); 1095fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1096291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "SN: %s", 1097291a2b48SSukumar Swaminathan vpd->serial_num); 1098fcf3ce44SJohn Forte 1099fcf3ce44SJohn Forte /* Validate the serial number */ 1100291a2b48SSukumar Swaminathan if (strncmp(buffer, "FFFFFFFFFF", 10) == 1101291a2b48SSukumar Swaminathan 0 || 1102291a2b48SSukumar Swaminathan strncmp(buffer, "0000000000", 10) == 1103291a2b48SSukumar Swaminathan 0) { 1104fcf3ce44SJohn Forte vpd->serial_num[0] = 0; 1105fcf3ce44SJohn Forte } 1106fcf3ce44SJohn Forte } 1107fcf3ce44SJohn Forte /* 1108fcf3ce44SJohn Forte * Look for Part Number (PN) 1109fcf3ce44SJohn Forte */ 1110fcf3ce44SJohn Forte else if (strcmp(tag, "PN") == 0) { 1111fcf3ce44SJohn Forte (void) strcpy(vpd->part_num, buffer); 1112fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1113291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "PN: %s", 1114291a2b48SSukumar Swaminathan vpd->part_num); 1115fcf3ce44SJohn Forte } 1116fcf3ce44SJohn Forte /* 1117fcf3ce44SJohn Forte * Look for (V0) 1118fcf3ce44SJohn Forte */ 1119fcf3ce44SJohn Forte else if (strcmp(tag, "V0") == 0) { 1120fcf3ce44SJohn Forte /* Not used */ 1121fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1122291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "V0: %s", buffer); 1123fcf3ce44SJohn Forte } 1124fcf3ce44SJohn Forte /* 1125fcf3ce44SJohn Forte * Look for model description (V1) 1126fcf3ce44SJohn Forte */ 1127fcf3ce44SJohn Forte else if (strcmp(tag, "V1") == 0) { 1128fcf3ce44SJohn Forte (void) strcpy(vpd->model_desc, buffer); 1129fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1130291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Desc: %s", 1131291a2b48SSukumar Swaminathan vpd->model_desc); 1132fcf3ce44SJohn Forte } 1133fcf3ce44SJohn Forte /* 1134fcf3ce44SJohn Forte * Look for model (V2) 1135fcf3ce44SJohn Forte */ 1136fcf3ce44SJohn Forte else if (strcmp(tag, "V2") == 0) { 1137fcf3ce44SJohn Forte (void) strcpy(vpd->model, buffer); 1138fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1139291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Model: %s", 1140291a2b48SSukumar Swaminathan vpd->model); 1141fcf3ce44SJohn Forte } 1142fcf3ce44SJohn Forte /* 1143fcf3ce44SJohn Forte * Look for program type (V3) 1144fcf3ce44SJohn Forte */ 1145fcf3ce44SJohn Forte 1146fcf3ce44SJohn Forte else if (strcmp(tag, "V3") == 0) { 1147fcf3ce44SJohn Forte (void) strcpy(vpd->prog_types, buffer); 1148fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1149291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Prog Types: %s", 1150291a2b48SSukumar Swaminathan vpd->prog_types); 1151fcf3ce44SJohn Forte } 1152fcf3ce44SJohn Forte /* 1153fcf3ce44SJohn Forte * Look for port number (V4) 1154fcf3ce44SJohn Forte */ 1155fcf3ce44SJohn Forte else if (strcmp(tag, "V4") == 0) { 1156fcf3ce44SJohn Forte (void) strcpy(vpd->port_num, buffer); 1157fcf3ce44SJohn Forte vpd->port_index = 1158fcf3ce44SJohn Forte emlxs_strtol(vpd->port_num, 10); 1159fcf3ce44SJohn Forte 1160fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1161291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Port: %s", 1162291a2b48SSukumar Swaminathan (vpd->port_num[0]) ? vpd-> 1163291a2b48SSukumar Swaminathan port_num : "not applicable"); 1164fcf3ce44SJohn Forte } 1165fcf3ce44SJohn Forte /* 1166fcf3ce44SJohn Forte * Look for checksum (RV) 1167fcf3ce44SJohn Forte */ 1168fcf3ce44SJohn Forte else if (strcmp(tag, "RV") == 0) { 1169fcf3ce44SJohn Forte /* Not used */ 1170fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1171291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Checksum: 0x%x", 1172291a2b48SSukumar Swaminathan buffer[0]); 1173291a2b48SSukumar Swaminathan } 1174291a2b48SSukumar Swaminathan 1175291a2b48SSukumar Swaminathan else { 1176fcf3ce44SJohn Forte /* Generic */ 1177fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, 1178291a2b48SSukumar Swaminathan &emlxs_vpd_msg, "Tag: %s: %s", 1179291a2b48SSukumar Swaminathan tag, buffer); 1180fcf3ce44SJohn Forte } 1181fcf3ce44SJohn Forte } 1182fcf3ce44SJohn Forte 1183fcf3ce44SJohn Forte break; 1184fcf3ce44SJohn Forte 1185fcf3ce44SJohn Forte case 0x78: 1186fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, "End Tag."); 1187fcf3ce44SJohn Forte finished = 1; 1188fcf3ce44SJohn Forte break; 1189fcf3ce44SJohn Forte 1190fcf3ce44SJohn Forte default: 1191fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1192fcf3ce44SJohn Forte "Unknown block: %x %x %x %x %x %x %x %x", 1193fcf3ce44SJohn Forte vpd_buf[index], vpd_buf[index + 1], 1194fcf3ce44SJohn Forte vpd_buf[index + 2], vpd_buf[index + 3], 1195fcf3ce44SJohn Forte vpd_buf[index + 4], vpd_buf[index + 5], 1196fcf3ce44SJohn Forte vpd_buf[index + 6], vpd_buf[index + 7]); 1197fcf3ce44SJohn Forte return (0); 1198fcf3ce44SJohn Forte } 1199fcf3ce44SJohn Forte } 1200fcf3ce44SJohn Forte 1201fcf3ce44SJohn Forte return (1); 1202fcf3ce44SJohn Forte 1203*82527734SSukumar Swaminathan } /* emlxs_parse_vpd */ 1204*82527734SSukumar Swaminathan 1205*82527734SSukumar Swaminathan 1206*82527734SSukumar Swaminathan /* 1207*82527734SSukumar Swaminathan * emlxs_parse_fcoe() 1208*82527734SSukumar Swaminathan * 1209*82527734SSukumar Swaminathan * This routine will parse the VPD data 1210*82527734SSukumar Swaminathan */ 1211*82527734SSukumar Swaminathan extern int 1212*82527734SSukumar Swaminathan emlxs_parse_fcoe(emlxs_hba_t *hba, uint8_t *fcoep, uint32_t size) 1213*82527734SSukumar Swaminathan { 1214*82527734SSukumar Swaminathan emlxs_port_t *port = &PPORT; 1215*82527734SSukumar Swaminathan tlv_fcoe_t *fcoelist; 1216*82527734SSukumar Swaminathan tlv_fcfconnectlist_t *fcflist; 1217*82527734SSukumar Swaminathan int i; 1218*82527734SSukumar Swaminathan 1219*82527734SSukumar Swaminathan /* Validate the config region 23 signature */ 1220*82527734SSukumar Swaminathan if ((*fcoep != 'R') || (*(fcoep+1) != 'G') || 1221*82527734SSukumar Swaminathan (*(fcoep+2) != '2') || (*(fcoep+3) != '3')) { 1222*82527734SSukumar Swaminathan return (0); 1223*82527734SSukumar Swaminathan } 1224*82527734SSukumar Swaminathan 1225*82527734SSukumar Swaminathan /* Search the config region 23, for FCOE Parameters record */ 1226*82527734SSukumar Swaminathan i = 4; 1227*82527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA0) && (*(fcoep+i) != 0xff)) { 1228*82527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2; 1229*82527734SSukumar Swaminathan } 1230*82527734SSukumar Swaminathan 1231*82527734SSukumar Swaminathan if (*(fcoep+i) == 0xA0) { 1232*82527734SSukumar Swaminathan fcoelist = (tlv_fcoe_t *)(fcoep+i); 1233*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1234*82527734SSukumar Swaminathan "Found FCOE Params (A0):%d x%x", 1235*82527734SSukumar Swaminathan fcoelist->length, fcoelist->fip_flags); 1236*82527734SSukumar Swaminathan bcopy((uint8_t *)fcoelist, (uint8_t *)&hba->sli.sli4.cfgFCOE, 1237*82527734SSukumar Swaminathan sizeof (tlv_fcoe_t)); 1238*82527734SSukumar Swaminathan } 1239*82527734SSukumar Swaminathan 1240*82527734SSukumar Swaminathan 1241*82527734SSukumar Swaminathan /* Search the config region 23, for FCF record */ 1242*82527734SSukumar Swaminathan i = 4; 1243*82527734SSukumar Swaminathan while ((i < size) && (*(fcoep+i) != 0xA1) && (*(fcoep+i) != 0xff)) { 1244*82527734SSukumar Swaminathan i += fcoep[i+1] * sizeof (uint32_t) + 2; 1245*82527734SSukumar Swaminathan } 1246*82527734SSukumar Swaminathan 1247*82527734SSukumar Swaminathan if (*(fcoep+i) == 0xA1) { 1248*82527734SSukumar Swaminathan fcflist = (tlv_fcfconnectlist_t *)(fcoep+i); 1249*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1250*82527734SSukumar Swaminathan "Found FCF ConnectList (A1):%d", fcflist->length); 1251*82527734SSukumar Swaminathan bcopy((uint8_t *)fcflist, (uint8_t *)&hba->sli.sli4.cfgFCF, 1252*82527734SSukumar Swaminathan sizeof (tlv_fcfconnectlist_t)); 1253*82527734SSukumar Swaminathan } 1254*82527734SSukumar Swaminathan 1255*82527734SSukumar Swaminathan return (1); 1256*82527734SSukumar Swaminathan 1257*82527734SSukumar Swaminathan } /* emlxs_parse_fcoe */ 1258fcf3ce44SJohn Forte 1259fcf3ce44SJohn Forte 1260fcf3ce44SJohn Forte 1261fcf3ce44SJohn Forte static uint32_t 1262fcf3ce44SJohn Forte emlxs_decode_biu_rev(uint32_t rev) 1263fcf3ce44SJohn Forte { 1264fcf3ce44SJohn Forte return (rev & 0xf); 1265*82527734SSukumar Swaminathan } /* End emlxs_decode_biu_rev */ 1266fcf3ce44SJohn Forte 1267fcf3ce44SJohn Forte 1268fcf3ce44SJohn Forte static uint32_t 1269fcf3ce44SJohn Forte emlxs_decode_endec_rev(uint32_t rev) 1270fcf3ce44SJohn Forte { 1271fcf3ce44SJohn Forte return ((rev >> 28) & 0xf); 1272*82527734SSukumar Swaminathan } /* End emlxs_decode_endec_rev */ 1273fcf3ce44SJohn Forte 1274fcf3ce44SJohn Forte 1275fcf3ce44SJohn Forte extern void 1276fcf3ce44SJohn Forte emlxs_decode_firmware_rev(emlxs_hba_t *hba, emlxs_vpd_t *vpd) 1277fcf3ce44SJohn Forte { 1278fcf3ce44SJohn Forte if (vpd->rBit) { 1279fcf3ce44SJohn Forte switch (hba->sli_mode) { 1280291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI4_MODE: 1281fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli4FwName); 1282fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli4FwLabel); 1283fcf3ce44SJohn Forte break; 1284291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI3_MODE: 1285fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli3FwName); 1286fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli3FwLabel); 1287fcf3ce44SJohn Forte break; 1288291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI2_MODE: 1289fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli2FwName); 1290fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli2FwLabel); 1291fcf3ce44SJohn Forte break; 1292291a2b48SSukumar Swaminathan case EMLXS_HBA_SLI1_MODE: 1293fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, vpd->sli1FwName); 1294fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->sli1FwLabel); 1295fcf3ce44SJohn Forte break; 1296fcf3ce44SJohn Forte default: 1297fcf3ce44SJohn Forte (void) strcpy(vpd->fw_version, "unknown"); 1298fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 1299fcf3ce44SJohn Forte } 1300fcf3ce44SJohn Forte } else { 1301fcf3ce44SJohn Forte emlxs_decode_version(vpd->smFwRev, vpd->fw_version); 1302fcf3ce44SJohn Forte (void) strcpy(vpd->fw_label, vpd->fw_version); 1303fcf3ce44SJohn Forte } 1304fcf3ce44SJohn Forte 1305fcf3ce44SJohn Forte return; 1306fcf3ce44SJohn Forte 1307*82527734SSukumar Swaminathan } /* emlxs_decode_firmware_rev() */ 1308fcf3ce44SJohn Forte 1309fcf3ce44SJohn Forte 1310fcf3ce44SJohn Forte 1311fcf3ce44SJohn Forte extern void 1312fcf3ce44SJohn Forte emlxs_decode_version(uint32_t version, char *buffer) 1313fcf3ce44SJohn Forte { 1314fcf3ce44SJohn Forte uint32_t b1, b2, b3, b4; 1315fcf3ce44SJohn Forte char c; 1316fcf3ce44SJohn Forte 1317fcf3ce44SJohn Forte b1 = (version & 0x0000f000) >> 12; 1318fcf3ce44SJohn Forte b2 = (version & 0x00000f00) >> 8; 1319fcf3ce44SJohn Forte b3 = (version & 0x000000c0) >> 6; 1320fcf3ce44SJohn Forte b4 = (version & 0x00000030) >> 4; 1321fcf3ce44SJohn Forte 1322fcf3ce44SJohn Forte if (b1 == 0 && b2 == 0) { 1323fcf3ce44SJohn Forte (void) sprintf(buffer, "none"); 1324fcf3ce44SJohn Forte return; 1325fcf3ce44SJohn Forte } 1326291a2b48SSukumar Swaminathan 1327fcf3ce44SJohn Forte c = 0; 1328fcf3ce44SJohn Forte switch (b4) { 1329fcf3ce44SJohn Forte case 0: 1330fcf3ce44SJohn Forte c = 'n'; 1331fcf3ce44SJohn Forte break; 1332fcf3ce44SJohn Forte case 1: 1333fcf3ce44SJohn Forte c = 'a'; 1334fcf3ce44SJohn Forte break; 1335fcf3ce44SJohn Forte case 2: 1336fcf3ce44SJohn Forte c = 'b'; 1337fcf3ce44SJohn Forte break; 1338fcf3ce44SJohn Forte case 3: 1339fcf3ce44SJohn Forte if ((version & 0x0000000f)) { 1340fcf3ce44SJohn Forte c = 'x'; 1341fcf3ce44SJohn Forte } 1342fcf3ce44SJohn Forte break; 1343fcf3ce44SJohn Forte 1344fcf3ce44SJohn Forte } 1345fcf3ce44SJohn Forte b4 = (version & 0x0000000f); 1346fcf3ce44SJohn Forte 1347fcf3ce44SJohn Forte if (c == 0) { 1348fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d", b1, b2, b3); 1349fcf3ce44SJohn Forte } else { 1350fcf3ce44SJohn Forte (void) sprintf(buffer, "%d.%d%d%c%d", b1, b2, b3, c, b4); 1351fcf3ce44SJohn Forte } 1352fcf3ce44SJohn Forte 1353fcf3ce44SJohn Forte return; 1354fcf3ce44SJohn Forte 1355*82527734SSukumar Swaminathan } /* emlxs_decode_version() */ 1356fcf3ce44SJohn Forte 1357fcf3ce44SJohn Forte 1358*82527734SSukumar Swaminathan extern void 1359*82527734SSukumar Swaminathan emlxs_decode_label(char *label, char *buffer, int bige) 1360fcf3ce44SJohn Forte { 1361fcf3ce44SJohn Forte uint32_t i; 1362fcf3ce44SJohn Forte char name[16]; 1363fcf3ce44SJohn Forte 1364*82527734SSukumar Swaminathan bcopy(label, name, sizeof (name)); 1365*82527734SSukumar Swaminathan /* bige is TRUE if the data format is big endian */ 1366fcf3ce44SJohn Forte 1367*82527734SSukumar Swaminathan if (bige) { 1368*82527734SSukumar Swaminathan /* Data format big Endian */ 1369*82527734SSukumar Swaminathan LE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 1370*82527734SSukumar Swaminathan 1371*82527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) { 1372*82527734SSukumar Swaminathan if (name[i] == 0x20) { 1373*82527734SSukumar Swaminathan name[i] = 0; 1374*82527734SSukumar Swaminathan } 1375*82527734SSukumar Swaminathan } 1376*82527734SSukumar Swaminathan } else { 1377*82527734SSukumar Swaminathan /* Data format little Endian */ 1378*82527734SSukumar Swaminathan BE_SWAP32_BUFFER((uint8_t *)name, sizeof (name)); 1379fcf3ce44SJohn Forte 1380*82527734SSukumar Swaminathan for (i = 0; i < sizeof (name); i++) { 1381*82527734SSukumar Swaminathan if (name[i] == 0x20) { 1382*82527734SSukumar Swaminathan name[i] = 0; 1383*82527734SSukumar Swaminathan } 1384fcf3ce44SJohn Forte } 1385fcf3ce44SJohn Forte } 1386fcf3ce44SJohn Forte 1387fcf3ce44SJohn Forte (void) strcpy(buffer, name); 1388fcf3ce44SJohn Forte 1389fcf3ce44SJohn Forte return; 1390fcf3ce44SJohn Forte 1391*82527734SSukumar Swaminathan } /* emlxs_decode_label() */ 1392fcf3ce44SJohn Forte 1393fcf3ce44SJohn Forte 1394fcf3ce44SJohn Forte extern uint32_t 1395fcf3ce44SJohn Forte emlxs_strtol(char *str, uint32_t base) 1396fcf3ce44SJohn Forte { 1397fcf3ce44SJohn Forte uint32_t value = 0; 1398fcf3ce44SJohn Forte char *ptr; 1399fcf3ce44SJohn Forte uint32_t factor = 1; 1400fcf3ce44SJohn Forte uint32_t digits; 1401fcf3ce44SJohn Forte 1402fcf3ce44SJohn Forte if (*str == 0) { 1403fcf3ce44SJohn Forte return (0); 1404fcf3ce44SJohn Forte } 1405291a2b48SSukumar Swaminathan 1406fcf3ce44SJohn Forte if (base != 10 && base != 16) { 1407fcf3ce44SJohn Forte return (0); 1408fcf3ce44SJohn Forte } 1409291a2b48SSukumar Swaminathan 1410fcf3ce44SJohn Forte /* Get max digits of value */ 1411fcf3ce44SJohn Forte digits = (base == 10) ? 9 : 8; 1412fcf3ce44SJohn Forte 1413fcf3ce44SJohn Forte /* Position pointer to end of string */ 1414fcf3ce44SJohn Forte ptr = str + strlen(str); 1415fcf3ce44SJohn Forte 1416fcf3ce44SJohn Forte /* Process string backwards */ 1417fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 1418fcf3ce44SJohn Forte /* check for base 10 numbers */ 1419fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 1420fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 1421fcf3ce44SJohn Forte factor *= base; 1422fcf3ce44SJohn Forte digits--; 1423fcf3ce44SJohn Forte } else if (base == 16) { 1424fcf3ce44SJohn Forte /* Check for base 16 numbers */ 1425fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 1426291a2b48SSukumar Swaminathan value += 1427291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 1428fcf3ce44SJohn Forte factor *= base; 1429fcf3ce44SJohn Forte digits--; 1430fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 1431291a2b48SSukumar Swaminathan value += 1432291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 1433fcf3ce44SJohn Forte factor *= base; 1434fcf3ce44SJohn Forte digits--; 1435fcf3ce44SJohn Forte } else if (factor > 1) { 1436fcf3ce44SJohn Forte break; 1437fcf3ce44SJohn Forte } 1438fcf3ce44SJohn Forte } else if (factor > 1) { 1439fcf3ce44SJohn Forte break; 1440fcf3ce44SJohn Forte } 1441fcf3ce44SJohn Forte } 1442fcf3ce44SJohn Forte 1443fcf3ce44SJohn Forte return (value); 1444fcf3ce44SJohn Forte 1445*82527734SSukumar Swaminathan } /* emlxs_strtol() */ 1446fcf3ce44SJohn Forte 1447fcf3ce44SJohn Forte 1448fcf3ce44SJohn Forte extern uint64_t 1449fcf3ce44SJohn Forte emlxs_strtoll(char *str, uint32_t base) 1450fcf3ce44SJohn Forte { 1451fcf3ce44SJohn Forte uint64_t value = 0; 1452fcf3ce44SJohn Forte char *ptr; 1453fcf3ce44SJohn Forte uint32_t factor = 1; 1454fcf3ce44SJohn Forte uint32_t digits; 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte if (*str == 0) { 1457fcf3ce44SJohn Forte return (0); 1458fcf3ce44SJohn Forte } 1459291a2b48SSukumar Swaminathan 1460fcf3ce44SJohn Forte if (base != 10 && base != 16) { 1461fcf3ce44SJohn Forte return (0); 1462fcf3ce44SJohn Forte } 1463291a2b48SSukumar Swaminathan 1464fcf3ce44SJohn Forte /* Get max digits of value */ 1465fcf3ce44SJohn Forte digits = (base == 10) ? 19 : 16; 1466fcf3ce44SJohn Forte 1467fcf3ce44SJohn Forte /* Position pointer to end of string */ 1468fcf3ce44SJohn Forte ptr = str + strlen(str); 1469fcf3ce44SJohn Forte 1470fcf3ce44SJohn Forte /* Process string backwards */ 1471fcf3ce44SJohn Forte while ((ptr-- > str) && digits) { 1472fcf3ce44SJohn Forte /* check for base 10 numbers */ 1473fcf3ce44SJohn Forte if (*ptr >= '0' && *ptr <= '9') { 1474fcf3ce44SJohn Forte value += ((uint32_t)(*ptr - '0')) * factor; 1475fcf3ce44SJohn Forte factor *= base; 1476fcf3ce44SJohn Forte digits--; 1477fcf3ce44SJohn Forte } else if (base == 16) { 1478fcf3ce44SJohn Forte /* Check for base 16 numbers */ 1479fcf3ce44SJohn Forte if (*ptr >= 'a' && *ptr <= 'f') { 1480291a2b48SSukumar Swaminathan value += 1481291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'a') + 10) * factor; 1482fcf3ce44SJohn Forte factor *= base; 1483fcf3ce44SJohn Forte digits--; 1484fcf3ce44SJohn Forte } else if (*ptr >= 'A' && *ptr <= 'F') { 1485291a2b48SSukumar Swaminathan value += 1486291a2b48SSukumar Swaminathan ((uint32_t)(*ptr - 'A') + 10) * factor; 1487fcf3ce44SJohn Forte factor *= base; 1488fcf3ce44SJohn Forte digits--; 1489fcf3ce44SJohn Forte } else if (factor > 1) { 1490fcf3ce44SJohn Forte break; 1491fcf3ce44SJohn Forte } 1492fcf3ce44SJohn Forte } else if (factor > 1) { 1493fcf3ce44SJohn Forte break; 1494fcf3ce44SJohn Forte } 1495fcf3ce44SJohn Forte } 1496fcf3ce44SJohn Forte 1497fcf3ce44SJohn Forte return (value); 1498fcf3ce44SJohn Forte 1499*82527734SSukumar Swaminathan } /* emlxs_strtoll() */ 1500fcf3ce44SJohn Forte 1501*82527734SSukumar Swaminathan extern void 1502fcf3ce44SJohn Forte emlxs_parse_prog_types(emlxs_hba_t *hba, char *prog_types) 1503fcf3ce44SJohn Forte { 1504fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1505fcf3ce44SJohn Forte uint32_t i; 1506fcf3ce44SJohn Forte char *ptr; 1507fcf3ce44SJohn Forte emlxs_model_t *model; 1508fcf3ce44SJohn Forte char types_buffer[256]; 1509fcf3ce44SJohn Forte char *types; 1510fcf3ce44SJohn Forte 1511fcf3ce44SJohn Forte bcopy(prog_types, types_buffer, 256); 1512fcf3ce44SJohn Forte types = types_buffer; 1513fcf3ce44SJohn Forte 1514fcf3ce44SJohn Forte model = &hba->model_info; 1515fcf3ce44SJohn Forte 1516fcf3ce44SJohn Forte while (*types) { 1517fcf3ce44SJohn Forte if (strncmp(types, "T2:", 3) == 0) { 1518fcf3ce44SJohn Forte bzero(model->pt_2, sizeof (model->pt_2)); 1519fcf3ce44SJohn Forte types += 3; 1520fcf3ce44SJohn Forte 1521fcf3ce44SJohn Forte i = 0; 1522fcf3ce44SJohn Forte while (*types && *types != 'T') { 1523fcf3ce44SJohn Forte /* Null terminate the next value */ 1524fcf3ce44SJohn Forte ptr = types; 1525fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1526fcf3ce44SJohn Forte ptr++; 1527fcf3ce44SJohn Forte *ptr = 0; 1528fcf3ce44SJohn Forte 1529fcf3ce44SJohn Forte /* Save the value */ 1530fcf3ce44SJohn Forte model->pt_2[i++] = 1531fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1532fcf3ce44SJohn Forte 1533fcf3ce44SJohn Forte /* 1534fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1535fcf3ce44SJohn Forte * "T2[%d]: 0x%x", i-1, model->pt_2[i-1]); 1536fcf3ce44SJohn Forte */ 1537fcf3ce44SJohn Forte 1538fcf3ce44SJohn Forte /* Move the str pointer */ 1539fcf3ce44SJohn Forte types = ptr + 1; 1540fcf3ce44SJohn Forte } 1541fcf3ce44SJohn Forte 1542fcf3ce44SJohn Forte } else if (strncmp(types, "T3:", 3) == 0) { 1543fcf3ce44SJohn Forte bzero(model->pt_3, sizeof (model->pt_3)); 1544fcf3ce44SJohn Forte types += 3; 1545fcf3ce44SJohn Forte 1546fcf3ce44SJohn Forte i = 0; 1547fcf3ce44SJohn Forte while (*types && *types != 'T') { 1548fcf3ce44SJohn Forte /* Null terminate the next value */ 1549fcf3ce44SJohn Forte ptr = types; 1550fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1551fcf3ce44SJohn Forte ptr++; 1552fcf3ce44SJohn Forte *ptr = 0; 1553fcf3ce44SJohn Forte 1554fcf3ce44SJohn Forte /* Save the value */ 1555fcf3ce44SJohn Forte model->pt_3[i++] = 1556fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1557fcf3ce44SJohn Forte 1558fcf3ce44SJohn Forte /* 1559fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1560fcf3ce44SJohn Forte * "T3[%d]: 0x%x", i-1, model->pt_3[i-1]); 1561fcf3ce44SJohn Forte */ 1562fcf3ce44SJohn Forte 1563fcf3ce44SJohn Forte /* Move the str pointer */ 1564fcf3ce44SJohn Forte types = ptr + 1; 1565fcf3ce44SJohn Forte } 1566fcf3ce44SJohn Forte } else if (strncmp(types, "T6:", 3) == 0) { 1567fcf3ce44SJohn Forte bzero(model->pt_6, sizeof (model->pt_6)); 1568fcf3ce44SJohn Forte types += 3; 1569fcf3ce44SJohn Forte 1570fcf3ce44SJohn Forte i = 0; 1571fcf3ce44SJohn Forte while (*types && *types != 'T') { 1572fcf3ce44SJohn Forte /* Null terminate the next value */ 1573fcf3ce44SJohn Forte ptr = types; 1574fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1575fcf3ce44SJohn Forte ptr++; 1576fcf3ce44SJohn Forte *ptr = 0; 1577fcf3ce44SJohn Forte 1578fcf3ce44SJohn Forte /* Save the value */ 1579fcf3ce44SJohn Forte model->pt_6[i++] = 1580fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1581fcf3ce44SJohn Forte model->pt_6[i] = 0; 1582fcf3ce44SJohn Forte 1583fcf3ce44SJohn Forte /* 1584fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1585fcf3ce44SJohn Forte * "T6[%d]: 0x%x", i-1, model->pt_6[i-1]); 1586fcf3ce44SJohn Forte */ 1587fcf3ce44SJohn Forte 1588fcf3ce44SJohn Forte /* Move the str pointer */ 1589fcf3ce44SJohn Forte types = ptr + 1; 1590fcf3ce44SJohn Forte } 1591fcf3ce44SJohn Forte } else if (strncmp(types, "T7:", 3) == 0) { 1592fcf3ce44SJohn Forte bzero(model->pt_7, sizeof (model->pt_7)); 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_7[i++] = 1605fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1606fcf3ce44SJohn Forte model->pt_7[i] = 0; 1607fcf3ce44SJohn Forte 1608fcf3ce44SJohn Forte /* 1609fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1610fcf3ce44SJohn Forte * "T7[%d]: 0x%x", i-1, model->pt_7[i-1]); 1611fcf3ce44SJohn Forte */ 1612fcf3ce44SJohn Forte 1613fcf3ce44SJohn Forte /* Move the str pointer */ 1614fcf3ce44SJohn Forte types = ptr + 1; 1615fcf3ce44SJohn Forte } 1616fcf3ce44SJohn Forte } else if (strncmp(types, "TA:", 3) == 0) { 1617fcf3ce44SJohn Forte bzero(model->pt_A, sizeof (model->pt_A)); 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_A[i++] = 1630fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1631fcf3ce44SJohn Forte 1632fcf3ce44SJohn Forte /* 1633fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1634fcf3ce44SJohn Forte * "TA[%d]: 0x%x", i-1, model->pt_A[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, "TB:", 3) == 0) { 1641fcf3ce44SJohn Forte bzero(model->pt_B, sizeof (model->pt_B)); 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_B[i++] = 1654fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1655fcf3ce44SJohn Forte 1656fcf3ce44SJohn Forte /* 1657fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1658fcf3ce44SJohn Forte * "TB[%d]: 0x%x", i-1, model->pt_B[i-1]); 1659fcf3ce44SJohn Forte */ 1660fcf3ce44SJohn Forte 1661fcf3ce44SJohn Forte /* Move the str pointer */ 1662fcf3ce44SJohn Forte types = ptr + 1; 1663fcf3ce44SJohn Forte } 1664fcf3ce44SJohn Forte } else if (strncmp(types, "TFF:", 4) == 0) { 1665fcf3ce44SJohn Forte bzero(model->pt_FF, sizeof (model->pt_FF)); 1666fcf3ce44SJohn Forte types += 4; 1667fcf3ce44SJohn Forte 1668fcf3ce44SJohn Forte i = 0; 1669fcf3ce44SJohn Forte while (*types && *types != 'T') { 1670fcf3ce44SJohn Forte /* Null terminate the next value */ 1671fcf3ce44SJohn Forte ptr = types; 1672fcf3ce44SJohn Forte while (*ptr && (*ptr != ',')) 1673fcf3ce44SJohn Forte ptr++; 1674fcf3ce44SJohn Forte *ptr = 0; 1675fcf3ce44SJohn Forte 1676fcf3ce44SJohn Forte /* Save the value */ 1677fcf3ce44SJohn Forte model->pt_FF[i++] = 1678fcf3ce44SJohn Forte (uint8_t)emlxs_strtol(types, 16); 1679fcf3ce44SJohn Forte 1680fcf3ce44SJohn Forte /* 1681fcf3ce44SJohn Forte * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1682fcf3ce44SJohn Forte * "TF[%d]: 0x%x", i-1, model->pt_FF[i-1]); 1683fcf3ce44SJohn Forte */ 1684fcf3ce44SJohn Forte 1685291a2b48SSukumar Swaminathan /* Move the str pointer */ 1686291a2b48SSukumar Swaminathan types = ptr + 1; 1687291a2b48SSukumar Swaminathan } 1688291a2b48SSukumar Swaminathan } else if (strncmp(types, "T20:", 4) == 0) { 1689291a2b48SSukumar Swaminathan bzero(model->pt_20, sizeof (model->pt_20)); 1690291a2b48SSukumar Swaminathan types += 4; 1691291a2b48SSukumar Swaminathan 1692291a2b48SSukumar Swaminathan i = 0; 1693291a2b48SSukumar Swaminathan while (*types && *types != 'T') { 1694291a2b48SSukumar Swaminathan /* Null terminate the next value */ 1695291a2b48SSukumar Swaminathan ptr = types; 1696291a2b48SSukumar Swaminathan while (*ptr && (*ptr != ',')) 1697291a2b48SSukumar Swaminathan ptr++; 1698291a2b48SSukumar Swaminathan *ptr = 0; 1699291a2b48SSukumar Swaminathan 1700291a2b48SSukumar Swaminathan /* Save the value */ 1701291a2b48SSukumar Swaminathan model->pt_20[i++] = 1702291a2b48SSukumar Swaminathan (uint8_t)emlxs_strtol(types, 16); 1703291a2b48SSukumar Swaminathan model->pt_20[i] = 0; 1704291a2b48SSukumar Swaminathan 1705291a2b48SSukumar Swaminathan /* 1706291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1707291a2b48SSukumar Swaminathan * "T20[%d]: 0x%x", i-1, model->pt_20[i-1]); 1708291a2b48SSukumar Swaminathan */ 1709291a2b48SSukumar Swaminathan 1710fcf3ce44SJohn Forte /* Move the str pointer */ 1711fcf3ce44SJohn Forte types = ptr + 1; 1712fcf3ce44SJohn Forte } 1713fcf3ce44SJohn Forte } else { 1714fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_vpd_msg, 1715fcf3ce44SJohn Forte "Unknown prog type string = %s", types); 1716fcf3ce44SJohn Forte break; 1717fcf3ce44SJohn Forte } 1718fcf3ce44SJohn Forte } 1719fcf3ce44SJohn Forte 1720fcf3ce44SJohn Forte return; 1721fcf3ce44SJohn Forte 1722*82527734SSukumar Swaminathan } /* emlxs_parse_prog_types() */ 1723fcf3ce44SJohn Forte 1724fcf3ce44SJohn Forte 1725*82527734SSukumar Swaminathan extern void 1726fcf3ce44SJohn Forte emlxs_build_prog_types(emlxs_hba_t *hba, char *prog_types) 1727fcf3ce44SJohn Forte { 1728fcf3ce44SJohn Forte uint32_t i; 1729fcf3ce44SJohn Forte uint32_t found = 0; 1730fcf3ce44SJohn Forte char buffer[256]; 1731fcf3ce44SJohn Forte 1732fcf3ce44SJohn Forte bzero(prog_types, 256); 1733fcf3ce44SJohn Forte 1734fcf3ce44SJohn Forte /* Rebuild the prog type string */ 1735fcf3ce44SJohn Forte if (hba->model_info.pt_2[0]) { 1736fcf3ce44SJohn Forte (void) strcat(prog_types, "T2:"); 1737fcf3ce44SJohn Forte found = 1; 1738fcf3ce44SJohn Forte 1739fcf3ce44SJohn Forte i = 0; 1740fcf3ce44SJohn Forte while (hba->model_info.pt_2[i] && i < 8) { 1741fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_2[i]); 1742fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1743fcf3ce44SJohn Forte i++; 1744fcf3ce44SJohn Forte } 1745fcf3ce44SJohn Forte } 1746291a2b48SSukumar Swaminathan 1747fcf3ce44SJohn Forte if (hba->model_info.pt_3[0]) { 1748fcf3ce44SJohn Forte (void) strcat(prog_types, "T3:"); 1749fcf3ce44SJohn Forte found = 1; 1750fcf3ce44SJohn Forte 1751fcf3ce44SJohn Forte i = 0; 1752fcf3ce44SJohn Forte while (hba->model_info.pt_3[i] && i < 8) { 1753fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_3[i]); 1754fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1755fcf3ce44SJohn Forte i++; 1756fcf3ce44SJohn Forte 1757fcf3ce44SJohn Forte } 1758fcf3ce44SJohn Forte } 1759291a2b48SSukumar Swaminathan 1760fcf3ce44SJohn Forte if (hba->model_info.pt_6[0]) { 1761fcf3ce44SJohn Forte (void) strcat(prog_types, "T6:"); 1762fcf3ce44SJohn Forte found = 1; 1763fcf3ce44SJohn Forte 1764fcf3ce44SJohn Forte i = 0; 1765fcf3ce44SJohn Forte while (hba->model_info.pt_6[i] && i < 8) { 1766fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_6[i]); 1767fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1768fcf3ce44SJohn Forte i++; 1769fcf3ce44SJohn Forte } 1770fcf3ce44SJohn Forte } 1771291a2b48SSukumar Swaminathan 1772fcf3ce44SJohn Forte if (hba->model_info.pt_7[0]) { 1773fcf3ce44SJohn Forte (void) strcat(prog_types, "T7:"); 1774fcf3ce44SJohn Forte found = 1; 1775fcf3ce44SJohn Forte 1776fcf3ce44SJohn Forte i = 0; 1777fcf3ce44SJohn Forte while (hba->model_info.pt_7[i] && i < 8) { 1778fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_7[i]); 1779fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1780fcf3ce44SJohn Forte i++; 1781fcf3ce44SJohn Forte } 1782fcf3ce44SJohn Forte } 1783291a2b48SSukumar Swaminathan 1784fcf3ce44SJohn Forte if (hba->model_info.pt_A[0]) { 1785fcf3ce44SJohn Forte (void) strcat(prog_types, "TA:"); 1786fcf3ce44SJohn Forte found = 1; 1787fcf3ce44SJohn Forte 1788fcf3ce44SJohn Forte i = 0; 1789fcf3ce44SJohn Forte while (hba->model_info.pt_A[i] && i < 8) { 1790fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_A[i]); 1791fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1792fcf3ce44SJohn Forte i++; 1793fcf3ce44SJohn Forte } 1794fcf3ce44SJohn Forte } 1795291a2b48SSukumar Swaminathan 1796291a2b48SSukumar Swaminathan 1797fcf3ce44SJohn Forte if (hba->model_info.pt_B[0]) { 1798fcf3ce44SJohn Forte (void) strcat(prog_types, "TB:"); 1799fcf3ce44SJohn Forte found = 1; 1800fcf3ce44SJohn Forte 1801fcf3ce44SJohn Forte i = 0; 1802fcf3ce44SJohn Forte while (hba->model_info.pt_B[i] && i < 8) { 1803fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_B[i]); 1804fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1805fcf3ce44SJohn Forte i++; 1806fcf3ce44SJohn Forte } 1807fcf3ce44SJohn Forte } 1808291a2b48SSukumar Swaminathan 1809291a2b48SSukumar Swaminathan if (hba->model_info.pt_20[0]) { 1810291a2b48SSukumar Swaminathan (void) strcat(prog_types, "T20:"); 1811291a2b48SSukumar Swaminathan found = 1; 1812291a2b48SSukumar Swaminathan 1813291a2b48SSukumar Swaminathan i = 0; 1814291a2b48SSukumar Swaminathan while (hba->model_info.pt_20[i] && i < 8) { 1815291a2b48SSukumar Swaminathan (void) sprintf(buffer, "%X,", hba->model_info.pt_20[i]); 1816291a2b48SSukumar Swaminathan (void) strcat(prog_types, buffer); 1817291a2b48SSukumar Swaminathan i++; 1818291a2b48SSukumar Swaminathan } 1819291a2b48SSukumar Swaminathan } 1820291a2b48SSukumar Swaminathan 1821fcf3ce44SJohn Forte if (hba->model_info.pt_FF[0]) { 1822fcf3ce44SJohn Forte (void) strcat(prog_types, "TFF:"); 1823fcf3ce44SJohn Forte found = 1; 1824fcf3ce44SJohn Forte 1825fcf3ce44SJohn Forte i = 0; 1826fcf3ce44SJohn Forte while (hba->model_info.pt_FF[i] && i < 8) { 1827fcf3ce44SJohn Forte (void) sprintf(buffer, "%X,", hba->model_info.pt_FF[i]); 1828fcf3ce44SJohn Forte (void) strcat(prog_types, buffer); 1829fcf3ce44SJohn Forte i++; 1830fcf3ce44SJohn Forte } 1831fcf3ce44SJohn Forte } 1832291a2b48SSukumar Swaminathan 1833fcf3ce44SJohn Forte if (found) { 1834fcf3ce44SJohn Forte /* Terminate at the last comma in string */ 1835fcf3ce44SJohn Forte prog_types[(strlen(prog_types) - 1)] = 0; 1836fcf3ce44SJohn Forte } 1837291a2b48SSukumar Swaminathan 1838fcf3ce44SJohn Forte return; 1839fcf3ce44SJohn Forte 1840*82527734SSukumar Swaminathan } /* emlxs_build_prog_types() */ 1841fcf3ce44SJohn Forte 1842fcf3ce44SJohn Forte 1843fcf3ce44SJohn Forte 1844fcf3ce44SJohn Forte 1845fcf3ce44SJohn Forte extern uint32_t 1846fcf3ce44SJohn Forte emlxs_init_adapter_info(emlxs_hba_t *hba) 1847fcf3ce44SJohn Forte { 1848fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 1849fcf3ce44SJohn Forte uint32_t pci_id; 1850fcf3ce44SJohn Forte uint32_t cache_line; 1851fcf3ce44SJohn Forte uint32_t channels; 1852fcf3ce44SJohn Forte uint16_t device_id; 1853fcf3ce44SJohn Forte uint16_t ssdid; 1854fcf3ce44SJohn Forte uint32_t i; 1855fcf3ce44SJohn Forte uint32_t found = 0; 1856*82527734SSukumar Swaminathan int32_t *prop; 1857*82527734SSukumar Swaminathan uint32_t num_prop; 1858fcf3ce44SJohn Forte 1859fcf3ce44SJohn Forte if (hba->bus_type == SBUS_FC) { 1860fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 1861fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 1862fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1863fcf3ce44SJohn Forte 1864fcf3ce44SJohn Forte hba->model_info.device_id = 0; 1865fcf3ce44SJohn Forte 1866fcf3ce44SJohn Forte return (0); 1867fcf3ce44SJohn Forte } 1868291a2b48SSukumar Swaminathan 1869fcf3ce44SJohn Forte /* Read the PCI device id */ 1870291a2b48SSukumar Swaminathan pci_id = 1871291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 1872fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)); 1873fcf3ce44SJohn Forte device_id = (uint16_t)(pci_id >> 16); 1874fcf3ce44SJohn Forte 1875fcf3ce44SJohn Forte /* Find matching adapter model */ 1876fcf3ce44SJohn Forte for (i = 1; i < EMLXS_SBUS_MODEL_COUNT; i++) { 1877fcf3ce44SJohn Forte if (emlxs_sbus_model[i].device_id == device_id) { 1878fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[i], &hba->model_info, 1879fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1880fcf3ce44SJohn Forte found = 1; 1881fcf3ce44SJohn Forte break; 1882fcf3ce44SJohn Forte } 1883fcf3ce44SJohn Forte } 1884fcf3ce44SJohn Forte 1885fcf3ce44SJohn Forte /* If not found then use the unknown model */ 1886fcf3ce44SJohn Forte if (!found) { 1887fcf3ce44SJohn Forte bcopy(&emlxs_sbus_model[0], &hba->model_info, 1888fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1889fcf3ce44SJohn Forte 1890fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 1891fcf3ce44SJohn Forte 1892fcf3ce44SJohn Forte return (0); 1893fcf3ce44SJohn Forte } 1894fcf3ce44SJohn Forte } else { /* PCI model */ 1895291a2b48SSukumar Swaminathan 1896fcf3ce44SJohn Forte if (hba->pci_acc_handle == NULL) { 1897fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 1898fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1899fcf3ce44SJohn Forte 1900fcf3ce44SJohn Forte hba->model_info.device_id = 0; 1901fcf3ce44SJohn Forte 1902fcf3ce44SJohn Forte return (0); 1903fcf3ce44SJohn Forte } 1904291a2b48SSukumar Swaminathan 1905fcf3ce44SJohn Forte /* Read the PCI device id */ 1906291a2b48SSukumar Swaminathan device_id = 1907291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 1908fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_DEVICE_ID_REGISTER)); 1909fcf3ce44SJohn Forte 1910fcf3ce44SJohn Forte /* Read the PCI Subsystem id */ 1911291a2b48SSukumar Swaminathan ssdid = 1912291a2b48SSukumar Swaminathan ddi_get16(hba->pci_acc_handle, 1913fcf3ce44SJohn Forte (uint16_t *)(hba->pci_addr + PCI_SSDID_REGISTER)); 1914fcf3ce44SJohn Forte 1915fcf3ce44SJohn Forte if (ssdid == 0 || ssdid == 0xffff) { 1916fcf3ce44SJohn Forte ssdid = device_id; 1917fcf3ce44SJohn Forte } 1918291a2b48SSukumar Swaminathan 1919fcf3ce44SJohn Forte /* Read the Cache Line reg */ 1920291a2b48SSukumar Swaminathan cache_line = 1921291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 1922fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CACHE_LINE_REGISTER)); 1923fcf3ce44SJohn Forte 1924fcf3ce44SJohn Forte /* Check for the multifunction bit being set */ 1925fcf3ce44SJohn Forte if ((cache_line & 0x00ff0000) == 0x00800000) { 1926fcf3ce44SJohn Forte channels = 2; 1927fcf3ce44SJohn Forte } else { 1928fcf3ce44SJohn Forte channels = 1; 1929fcf3ce44SJohn Forte } 1930fcf3ce44SJohn Forte 1931fcf3ce44SJohn Forte /* If device ids are unique, then use them for search */ 1932fcf3ce44SJohn Forte if (device_id != ssdid) { 1933fcf3ce44SJohn Forte if (channels > 1) { 1934fcf3ce44SJohn Forte /* 1935fcf3ce44SJohn Forte * Find matching adapter model using 1936fcf3ce44SJohn Forte * device_id, ssdid and channels 1937fcf3ce44SJohn Forte */ 1938*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 1939291a2b48SSukumar Swaminathan if (emlxs_pci_model[i].device_id == 1940291a2b48SSukumar Swaminathan device_id && 1941291a2b48SSukumar Swaminathan emlxs_pci_model[i].ssdid == ssdid && 1942291a2b48SSukumar Swaminathan emlxs_pci_model[i].channels == 1943291a2b48SSukumar Swaminathan channels) { 1944fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 1945fcf3ce44SJohn Forte &hba->model_info, 1946fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1947fcf3ce44SJohn Forte found = 1; 1948fcf3ce44SJohn Forte break; 1949fcf3ce44SJohn Forte } 1950fcf3ce44SJohn Forte } 1951fcf3ce44SJohn Forte } else { 1952fcf3ce44SJohn Forte /* 1953fcf3ce44SJohn Forte * Find matching adapter model using 1954fcf3ce44SJohn Forte * device_id and ssdid 1955fcf3ce44SJohn Forte */ 1956*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 1957291a2b48SSukumar Swaminathan if (emlxs_pci_model[i].device_id == 1958291a2b48SSukumar Swaminathan device_id && 1959291a2b48SSukumar Swaminathan emlxs_pci_model[i].ssdid == ssdid) { 1960fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 1961fcf3ce44SJohn Forte &hba->model_info, 1962fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1963fcf3ce44SJohn Forte found = 1; 1964fcf3ce44SJohn Forte break; 1965fcf3ce44SJohn Forte } 1966fcf3ce44SJohn Forte } 1967fcf3ce44SJohn Forte } 1968fcf3ce44SJohn Forte } 1969291a2b48SSukumar Swaminathan 1970fcf3ce44SJohn Forte /* If adapter not found, try again */ 1971fcf3ce44SJohn Forte if (!found) { 1972fcf3ce44SJohn Forte /* Find matching adapter model */ 1973*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 1974fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id && 1975fcf3ce44SJohn Forte emlxs_pci_model[i].channels == channels) { 1976fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 1977fcf3ce44SJohn Forte &hba->model_info, 1978fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1979fcf3ce44SJohn Forte found = 1; 1980fcf3ce44SJohn Forte break; 1981fcf3ce44SJohn Forte } 1982fcf3ce44SJohn Forte } 1983fcf3ce44SJohn Forte } 1984291a2b48SSukumar Swaminathan 1985fcf3ce44SJohn Forte /* If adapter not found, try one last time */ 1986fcf3ce44SJohn Forte if (!found) { 1987fcf3ce44SJohn Forte /* Find matching adapter model */ 1988*82527734SSukumar Swaminathan for (i = 1; i < emlxs_pci_model_count; i++) { 1989fcf3ce44SJohn Forte if (emlxs_pci_model[i].device_id == device_id) { 1990fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[i], 1991fcf3ce44SJohn Forte &hba->model_info, 1992fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 1993fcf3ce44SJohn Forte found = 1; 1994fcf3ce44SJohn Forte break; 1995fcf3ce44SJohn Forte } 1996fcf3ce44SJohn Forte } 1997fcf3ce44SJohn Forte } 1998291a2b48SSukumar Swaminathan 1999fcf3ce44SJohn Forte /* If not found, set adapter to unknown */ 2000fcf3ce44SJohn Forte if (!found) { 2001fcf3ce44SJohn Forte bcopy(&emlxs_pci_model[0], &hba->model_info, 2002fcf3ce44SJohn Forte sizeof (emlxs_model_t)); 2003fcf3ce44SJohn Forte 2004fcf3ce44SJohn Forte hba->model_info.device_id = device_id; 2005fcf3ce44SJohn Forte hba->model_info.ssdid = ssdid; 2006fcf3ce44SJohn Forte 2007fcf3ce44SJohn Forte return (0); 2008fcf3ce44SJohn Forte } 2009fcf3ce44SJohn Forte 2010fcf3ce44SJohn Forte #ifndef SATURN_MSI_SUPPORT 2011fcf3ce44SJohn Forte /* 2012291a2b48SSukumar Swaminathan * This will disable MSI support for Saturn adapter's 2013291a2b48SSukumar Swaminathan * due to a PCI bus issue 2014fcf3ce44SJohn Forte */ 2015fcf3ce44SJohn Forte if (hba->model_info.chip == EMLXS_SATURN_CHIP) { 2016fcf3ce44SJohn Forte hba->model_info.flags &= 2017fcf3ce44SJohn Forte ~(EMLXS_MSI_SUPPORTED | EMLXS_MSIX_SUPPORTED); 2018fcf3ce44SJohn Forte } 2019291a2b48SSukumar Swaminathan #endif /* !SATURN_MSI_SUPPORT */ 2020fcf3ce44SJohn Forte 2021fcf3ce44SJohn Forte 2022fcf3ce44SJohn Forte #ifdef MSI_SUPPORT 2023fcf3ce44SJohn Forte /* Verify MSI support */ 2024fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSI_SUPPORTED) { 2025fcf3ce44SJohn Forte uint32_t offset; 2026fcf3ce44SJohn Forte uint32_t reg; 2027fcf3ce44SJohn Forte 2028fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 2029291a2b48SSukumar Swaminathan offset = 2030291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 2031fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 2032fcf3ce44SJohn Forte offset &= 0xff; 2033fcf3ce44SJohn Forte 2034fcf3ce44SJohn Forte while (offset) { 2035291a2b48SSukumar Swaminathan reg = 2036291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 2037fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 2038fcf3ce44SJohn Forte 2039fcf3ce44SJohn Forte if ((reg & 0xff) == MSI_CAP_ID) { 2040fcf3ce44SJohn Forte break; 2041fcf3ce44SJohn Forte } 2042fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 2043fcf3ce44SJohn Forte } 2044fcf3ce44SJohn Forte 2045fcf3ce44SJohn Forte if (offset) { 2046fcf3ce44SJohn Forte hba->msi_cap_offset = offset + 2; 2047fcf3ce44SJohn Forte } else { 2048fcf3ce44SJohn Forte hba->msi_cap_offset = 0; 2049fcf3ce44SJohn Forte hba->model_info.flags &= ~EMLXS_MSI_SUPPORTED; 2050fcf3ce44SJohn Forte 2051291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 2052291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 2053fcf3ce44SJohn Forte "MSI: control_reg capability not found!"); 2054fcf3ce44SJohn Forte } 2055fcf3ce44SJohn Forte } 2056291a2b48SSukumar Swaminathan 2057fcf3ce44SJohn Forte /* Verify MSI-X support */ 2058fcf3ce44SJohn Forte if (hba->model_info.flags & EMLXS_MSIX_SUPPORTED) { 2059fcf3ce44SJohn Forte uint32_t offset; 2060fcf3ce44SJohn Forte uint32_t reg; 2061fcf3ce44SJohn Forte 2062fcf3ce44SJohn Forte /* Scan for MSI capabilities register */ 2063291a2b48SSukumar Swaminathan offset = 2064291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 2065fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + PCI_CAP_POINTER)); 2066fcf3ce44SJohn Forte offset &= 0xff; 2067fcf3ce44SJohn Forte 2068fcf3ce44SJohn Forte while (offset) { 2069291a2b48SSukumar Swaminathan reg = 2070291a2b48SSukumar Swaminathan ddi_get32(hba->pci_acc_handle, 2071fcf3ce44SJohn Forte (uint32_t *)(hba->pci_addr + offset)); 2072fcf3ce44SJohn Forte 2073fcf3ce44SJohn Forte if ((reg & 0xff) == MSIX_CAP_ID) { 2074fcf3ce44SJohn Forte break; 2075fcf3ce44SJohn Forte } 2076fcf3ce44SJohn Forte offset = (reg >> 8) & 0xff; 2077fcf3ce44SJohn Forte } 2078fcf3ce44SJohn Forte 2079fcf3ce44SJohn Forte if (offset) { 2080fcf3ce44SJohn Forte hba->msix_cap_offset = offset; 2081fcf3ce44SJohn Forte } else { 2082fcf3ce44SJohn Forte hba->msix_cap_offset = 0; 2083291a2b48SSukumar Swaminathan hba->model_info.flags &= 2084291a2b48SSukumar Swaminathan ~EMLXS_MSIX_SUPPORTED; 2085fcf3ce44SJohn Forte 2086291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 2087291a2b48SSukumar Swaminathan &emlxs_init_debug_msg, 2088fcf3ce44SJohn Forte "MSIX: control_reg capability not found!"); 2089fcf3ce44SJohn Forte } 2090fcf3ce44SJohn Forte } 2091291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */ 2092291a2b48SSukumar Swaminathan 2093291a2b48SSukumar Swaminathan } 2094fcf3ce44SJohn Forte 2095*82527734SSukumar Swaminathan if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba->dip, 0, 2096*82527734SSukumar Swaminathan "reg", &prop, &num_prop) == DDI_PROP_SUCCESS) { 2097*82527734SSukumar Swaminathan /* Parse the property for PCI function, device and bus no. */ 2098*82527734SSukumar Swaminathan hba->pci_function_number = 2099*82527734SSukumar Swaminathan (uint8_t)((prop[0] & 0x00000700) >> 8); 2100*82527734SSukumar Swaminathan hba->pci_device_number = (uint8_t)((prop[0] & 0x00008100) >> 8); 2101*82527734SSukumar Swaminathan hba->pci_bus_number = (uint8_t)((prop[0] & 0x00ff0000) >> 16); 2102*82527734SSukumar Swaminathan ddi_prop_free((void *)prop); 2103*82527734SSukumar Swaminathan } 2104*82527734SSukumar Swaminathan 2105*82527734SSukumar Swaminathan if (hba->model_info.sli_mask & EMLXS_SLI4_MASK) { 2106*82527734SSukumar Swaminathan hba->sli_api = emlxs_sli4_api; 2107*82527734SSukumar Swaminathan } else { 2108*82527734SSukumar Swaminathan hba->sli_api = emlxs_sli3_api; 2109*82527734SSukumar Swaminathan } 2110*82527734SSukumar Swaminathan 21114baa2c25SSukumar Swaminathan #ifdef FMA_SUPPORT 21124baa2c25SSukumar Swaminathan if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle) 21134baa2c25SSukumar Swaminathan != DDI_FM_OK) { 21144baa2c25SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, 21154baa2c25SSukumar Swaminathan &emlxs_invalid_access_handle_msg, NULL); 21164baa2c25SSukumar Swaminathan return (0); 21174baa2c25SSukumar Swaminathan } 21184baa2c25SSukumar Swaminathan #endif /* FMA_SUPPORT */ 21194baa2c25SSukumar Swaminathan 2120fcf3ce44SJohn Forte return (1); 2121fcf3ce44SJohn Forte 2122*82527734SSukumar Swaminathan } /* emlxs_init_adapter_info() */ 2123fcf3ce44SJohn Forte 2124fcf3ce44SJohn Forte 2125291a2b48SSukumar Swaminathan /* ARGSUSED */ 2126291a2b48SSukumar Swaminathan static void 2127*82527734SSukumar Swaminathan emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2128fcf3ce44SJohn Forte { 2129291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2130291a2b48SSukumar Swaminathan IOCB *iocb; 2131291a2b48SSukumar Swaminathan uint32_t *w; 2132291a2b48SSukumar Swaminathan int i, j; 2133fcf3ce44SJohn Forte 2134291a2b48SSukumar Swaminathan iocb = &iocbq->iocb; 2135fcf3ce44SJohn Forte 2136*82527734SSukumar Swaminathan if (iocb->ULPSTATUS != 0) { 2137291a2b48SSukumar Swaminathan return; 2138fcf3ce44SJohn Forte } 2139fcf3ce44SJohn Forte 2140291a2b48SSukumar Swaminathan switch (iocb->un.astat.EventCode) { 2141291a2b48SSukumar Swaminathan case 0x0100: /* Temp Warning */ 2142291a2b48SSukumar Swaminathan 2143291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_warning_msg, 2144291a2b48SSukumar Swaminathan "Adapter is very hot (%d �C). Take corrective action.", 2145*82527734SSukumar Swaminathan iocb->ULPCONTEXT); 2146*82527734SSukumar Swaminathan 2147*82527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT; 2148*82527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x02, iocb->ULPCONTEXT); 2149fcf3ce44SJohn Forte 2150fcf3ce44SJohn Forte 2151291a2b48SSukumar Swaminathan break; 2152fcf3ce44SJohn Forte 2153fcf3ce44SJohn Forte 2154291a2b48SSukumar Swaminathan case 0x0101: /* Temp Safe */ 2155fcf3ce44SJohn Forte 2156291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_temp_msg, 2157291a2b48SSukumar Swaminathan "Adapter temperature now safe (%d �C).", 2158*82527734SSukumar Swaminathan iocb->ULPCONTEXT); 2159fcf3ce44SJohn Forte 2160*82527734SSukumar Swaminathan hba->temperature = iocb->ULPCONTEXT; 2161*82527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x03, iocb->ULPCONTEXT); 2162fcf3ce44SJohn Forte 2163291a2b48SSukumar Swaminathan break; 2164fcf3ce44SJohn Forte 2165291a2b48SSukumar Swaminathan default: 2166fcf3ce44SJohn Forte 2167291a2b48SSukumar Swaminathan w = (uint32_t *)iocb; 2168291a2b48SSukumar Swaminathan for (i = 0, j = 0; i < 8; i++, j += 2) { 2169291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_async_msg, 2170291a2b48SSukumar Swaminathan "(Word[%d]=%x Word[%d]=%x)", j, w[j], j + 1, 2171291a2b48SSukumar Swaminathan w[j + 1]); 2172291a2b48SSukumar Swaminathan } 2173fcf3ce44SJohn Forte 2174291a2b48SSukumar Swaminathan emlxs_log_async_event(port, iocb); 2175fcf3ce44SJohn Forte } 2176fcf3ce44SJohn Forte 2177fcf3ce44SJohn Forte return; 2178fcf3ce44SJohn Forte 2179*82527734SSukumar Swaminathan } /* emlxs_handle_async_event() */ 2180fcf3ce44SJohn Forte 2181fcf3ce44SJohn Forte 2182bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2183291a2b48SSukumar Swaminathan extern void 2184bb63f56eSSukumar Swaminathan emlxs_reset_link_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2185fcf3ce44SJohn Forte { 2186291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2187fcf3ce44SJohn Forte 2188291a2b48SSukumar Swaminathan /* Attempt a link reset to recover */ 2189291a2b48SSukumar Swaminathan (void) emlxs_reset(port, FC_FCA_LINK_RESET); 2190fcf3ce44SJohn Forte 2191bb63f56eSSukumar Swaminathan return; 2192fcf3ce44SJohn Forte 2193*82527734SSukumar Swaminathan } /* emlxs_reset_link_thread() */ 2194fcf3ce44SJohn Forte 2195fcf3ce44SJohn Forte 2196bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2197fcf3ce44SJohn Forte extern void 2198bb63f56eSSukumar Swaminathan emlxs_restart_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2199fcf3ce44SJohn Forte { 2200fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2201fcf3ce44SJohn Forte 2202fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, "Restarting..."); 2203fcf3ce44SJohn Forte 2204fcf3ce44SJohn Forte /* Attempt a full hardware reset to recover */ 2205fcf3ce44SJohn Forte if (emlxs_reset(port, FC_FCA_RESET) != FC_SUCCESS) { 2206*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_ERROR); 2207fcf3ce44SJohn Forte 2208*82527734SSukumar Swaminathan emlxs_shutdown_thread(hba, arg1, arg2); 2209fcf3ce44SJohn Forte } 2210fcf3ce44SJohn Forte 2211bb63f56eSSukumar Swaminathan return; 2212291a2b48SSukumar Swaminathan 2213*82527734SSukumar Swaminathan } /* emlxs_restart_thread() */ 2214fcf3ce44SJohn Forte 2215fcf3ce44SJohn Forte 2216bb63f56eSSukumar Swaminathan /* ARGSUSED */ 2217fcf3ce44SJohn Forte extern void 2218bb63f56eSSukumar Swaminathan emlxs_shutdown_thread(emlxs_hba_t *hba, void *arg1, void *arg2) 2219fcf3ce44SJohn Forte { 2220fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2221fcf3ce44SJohn Forte 2222fcf3ce44SJohn Forte mutex_enter(&EMLXS_PORT_LOCK); 2223fcf3ce44SJohn Forte if (hba->flag & FC_SHUTDOWN) { 2224fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2225bb63f56eSSukumar Swaminathan return; 2226fcf3ce44SJohn Forte } 2227fcf3ce44SJohn Forte hba->flag |= FC_SHUTDOWN; 2228fcf3ce44SJohn Forte mutex_exit(&EMLXS_PORT_LOCK); 2229fcf3ce44SJohn Forte 2230291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_trans_msg, 2231291a2b48SSukumar Swaminathan "Shutting down..."); 2232fcf3ce44SJohn Forte 2233fcf3ce44SJohn Forte /* Take adapter offline and leave it there */ 2234fcf3ce44SJohn Forte (void) emlxs_offline(hba); 2235fcf3ce44SJohn Forte 2236*82527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2237*82527734SSukumar Swaminathan /* 2238*82527734SSukumar Swaminathan * Dump is not defined for SLI4, so just 2239*82527734SSukumar Swaminathan * reset the HBA for now. 2240*82527734SSukumar Swaminathan */ 2241*82527734SSukumar Swaminathan EMLXS_SLI_HBA_RESET(hba, 1, 1, 0); 2242*82527734SSukumar Swaminathan 2243*82527734SSukumar Swaminathan } else { 2244*82527734SSukumar Swaminathan if (hba->flag & FC_OVERTEMP_EVENT) { 2245*82527734SSukumar Swaminathan emlxs_log_temp_event(port, 0x01, 2246*82527734SSukumar Swaminathan hba->temperature); 2247*82527734SSukumar Swaminathan } else { 2248*82527734SSukumar Swaminathan emlxs_log_dump_event(port, NULL, 0); 2249*82527734SSukumar Swaminathan } 2250*82527734SSukumar Swaminathan } 2251fcf3ce44SJohn Forte 2252fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_shutdown_msg, "Reboot required."); 2253fcf3ce44SJohn Forte 2254bb63f56eSSukumar Swaminathan return; 2255fcf3ce44SJohn Forte 2256*82527734SSukumar Swaminathan } /* emlxs_shutdown_thread() */ 2257fcf3ce44SJohn Forte 2258fcf3ce44SJohn Forte 2259fcf3ce44SJohn Forte /* ARGSUSED */ 2260fcf3ce44SJohn Forte extern void 2261*82527734SSukumar Swaminathan emlxs_proc_channel(emlxs_hba_t *hba, CHANNEL *cp, void *arg2) 2262fcf3ce44SJohn Forte { 2263fcf3ce44SJohn Forte IOCBQ *iocbq; 2264fcf3ce44SJohn Forte IOCBQ *rsp_head; 2265fcf3ce44SJohn Forte 2266fcf3ce44SJohn Forte /* 2267291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 2268*82527734SSukumar Swaminathan * "emlxs_proc_channel: channel=%d", cp->channelno); 2269fcf3ce44SJohn Forte */ 2270fcf3ce44SJohn Forte 2271*82527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 2272fcf3ce44SJohn Forte 2273*82527734SSukumar Swaminathan while ((rsp_head = cp->rsp_head) != NULL) { 2274*82527734SSukumar Swaminathan cp->rsp_head = NULL; 2275*82527734SSukumar Swaminathan cp->rsp_tail = NULL; 2276fcf3ce44SJohn Forte 2277*82527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 2278fcf3ce44SJohn Forte 2279fcf3ce44SJohn Forte while ((iocbq = rsp_head) != NULL) { 2280fcf3ce44SJohn Forte rsp_head = (IOCBQ *) iocbq->next; 2281fcf3ce44SJohn Forte 2282*82527734SSukumar Swaminathan emlxs_proc_channel_event(hba, cp, iocbq); 2283fcf3ce44SJohn Forte } 2284fcf3ce44SJohn Forte 2285*82527734SSukumar Swaminathan mutex_enter(&cp->rsp_lock); 2286fcf3ce44SJohn Forte } 2287fcf3ce44SJohn Forte 2288*82527734SSukumar Swaminathan mutex_exit(&cp->rsp_lock); 2289fcf3ce44SJohn Forte 2290*82527734SSukumar Swaminathan EMLXS_SLI_ISSUE_IOCB_CMD(hba, cp, 0); 2291fcf3ce44SJohn Forte 2292fcf3ce44SJohn Forte return; 2293fcf3ce44SJohn Forte 2294*82527734SSukumar Swaminathan } /* emlxs_proc_channel() */ 2295fcf3ce44SJohn Forte 2296fcf3ce44SJohn Forte 2297fcf3ce44SJohn Forte /* 2298291a2b48SSukumar Swaminathan * Called from SLI ring event routines to process a rsp ring IOCB. 2299fcf3ce44SJohn Forte */ 2300291a2b48SSukumar Swaminathan void 2301*82527734SSukumar Swaminathan emlxs_proc_channel_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq) 2302fcf3ce44SJohn Forte { 2303fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2304fcf3ce44SJohn Forte char buffer[MAX_MSG_DATA + 1]; 2305fcf3ce44SJohn Forte IOCB *iocb; 2306*82527734SSukumar Swaminathan emlxs_buf_t *sbp; 2307fcf3ce44SJohn Forte 2308fcf3ce44SJohn Forte iocb = &iocbq->iocb; 2309fcf3ce44SJohn Forte 2310*82527734SSukumar Swaminathan #ifdef DEBUG_CMPL_IOCB 2311*82527734SSukumar Swaminathan emlxs_data_dump(hba, "CMPL_IOCB", (uint32_t *)iocb, 8, 0); 2312*82527734SSukumar Swaminathan #endif 2313*82527734SSukumar Swaminathan 2314*82527734SSukumar Swaminathan sbp = (emlxs_buf_t *)iocbq->sbp; 2315*82527734SSukumar Swaminathan if (sbp) { 2316*82527734SSukumar Swaminathan if (!(sbp->pkt_flags & PACKET_VALID) || 2317*82527734SSukumar Swaminathan (sbp->pkt_flags & (PACKET_ULP_OWNED | 2318*82527734SSukumar Swaminathan PACKET_IN_COMPLETION))) { 2319*82527734SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_stale_msg, 2320*82527734SSukumar Swaminathan "Duplicate: iocb=%p cmd=%x status=%x " 2321*82527734SSukumar Swaminathan "error=%x iotag=%x context=%x info=%x", 2322*82527734SSukumar Swaminathan iocbq, (uint8_t)iocbq->iocb.ULPCOMMAND, 2323*82527734SSukumar Swaminathan iocbq->iocb.ULPSTATUS, 2324*82527734SSukumar Swaminathan (uint8_t)iocbq->iocb.un.grsp.perr.statLocalError, 2325*82527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPIOTAG, 2326*82527734SSukumar Swaminathan (uint16_t)iocbq->iocb.ULPCONTEXT, 2327*82527734SSukumar Swaminathan (uint8_t)iocbq->iocb.ULPRSVDBYTE); 2328*82527734SSukumar Swaminathan 2329*82527734SSukumar Swaminathan /* Drop this IO immediately */ 2330*82527734SSukumar Swaminathan return; 2331*82527734SSukumar Swaminathan } 2332*82527734SSukumar Swaminathan 2333*82527734SSukumar Swaminathan if (sbp->pkt_flags & PACKET_IN_TIMEOUT) { 2334*82527734SSukumar Swaminathan /* 2335*82527734SSukumar Swaminathan * If the packet is tagged for timeout then set the 2336*82527734SSukumar Swaminathan * return codes appropriately 2337*82527734SSukumar Swaminathan */ 2338*82527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 2339*82527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError = IOERR_ABORT_TIMEOUT; 2340*82527734SSukumar Swaminathan } else if (sbp->pkt_flags & 2341*82527734SSukumar Swaminathan (PACKET_IN_FLUSH | PACKET_IN_ABORT)) { 2342*82527734SSukumar Swaminathan /* 2343*82527734SSukumar Swaminathan * If the packet is tagged for abort then set the 2344*82527734SSukumar Swaminathan * return codes appropriately 2345*82527734SSukumar Swaminathan */ 2346*82527734SSukumar Swaminathan iocb->ULPSTATUS = IOSTAT_LOCAL_REJECT; 2347*82527734SSukumar Swaminathan iocb->un.grsp.perr.statLocalError = 2348*82527734SSukumar Swaminathan IOERR_ABORT_REQUESTED; 2349*82527734SSukumar Swaminathan } 2350*82527734SSukumar Swaminathan } 2351*82527734SSukumar Swaminathan 2352fcf3ce44SJohn Forte /* Check for IOCB local error */ 2353*82527734SSukumar Swaminathan if (iocb->ULPSTATUS == IOSTAT_LOCAL_REJECT) { 2354fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_event_msg, 2355291a2b48SSukumar Swaminathan "Local reject. ringno=%d iocb=%p cmd=%x " 2356291a2b48SSukumar Swaminathan "iotag=%x context=%x info=%x error=%x", 2357*82527734SSukumar Swaminathan cp->channelno, iocb, (uint8_t)iocb->ULPCOMMAND, 2358*82527734SSukumar Swaminathan (uint16_t)iocb->ULPIOTAG, (uint16_t)iocb->ULPCONTEXT, 2359*82527734SSukumar Swaminathan (uint8_t)iocb->ULPRSVDBYTE, 2360fcf3ce44SJohn Forte (uint8_t)iocb->un.grsp.perr.statLocalError); 2361fcf3ce44SJohn Forte } 2362291a2b48SSukumar Swaminathan 2363*82527734SSukumar Swaminathan switch (iocb->ULPCOMMAND) { 2364fcf3ce44SJohn Forte /* RING 0 FCP commands */ 2365fcf3ce44SJohn Forte case CMD_FCP_ICMND_CR: 2366fcf3ce44SJohn Forte case CMD_FCP_ICMND_CX: 2367fcf3ce44SJohn Forte case CMD_FCP_IREAD_CR: 2368fcf3ce44SJohn Forte case CMD_FCP_IREAD_CX: 2369fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CR: 2370fcf3ce44SJohn Forte case CMD_FCP_IWRITE_CX: 2371fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CR: 2372fcf3ce44SJohn Forte case CMD_FCP_ICMND64_CX: 2373fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CR: 2374fcf3ce44SJohn Forte case CMD_FCP_IREAD64_CX: 2375fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CR: 2376fcf3ce44SJohn Forte case CMD_FCP_IWRITE64_CX: 2377*82527734SSukumar Swaminathan emlxs_handle_fcp_event(hba, cp, iocbq); 2378fcf3ce44SJohn Forte break; 2379fcf3ce44SJohn Forte 2380fcf3ce44SJohn Forte #ifdef SFCT_SUPPORT 2381291a2b48SSukumar Swaminathan case CMD_FCP_TSEND_CX: /* FCP_TARGET IOCB command */ 2382fcf3ce44SJohn Forte case CMD_FCP_TSEND64_CX: /* FCP_TARGET IOCB command */ 2383fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE_CX: /* FCP_TARGET IOCB command */ 2384fcf3ce44SJohn Forte case CMD_FCP_TRECEIVE64_CX: /* FCP_TARGET IOCB command */ 2385291a2b48SSukumar Swaminathan case CMD_FCP_TRSP_CX: /* FCP_TARGET IOCB command */ 2386291a2b48SSukumar Swaminathan case CMD_FCP_TRSP64_CX: /* FCP_TARGET IOCB command */ 2387*82527734SSukumar Swaminathan (void) emlxs_fct_handle_fcp_event(hba, cp, iocbq); 2388fcf3ce44SJohn Forte break; 2389291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2390fcf3ce44SJohn Forte 2391fcf3ce44SJohn Forte /* RING 1 IP commands */ 2392fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CN: 2393fcf3ce44SJohn Forte case CMD_XMIT_BCAST_CX: 2394fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CN: 2395fcf3ce44SJohn Forte case CMD_XMIT_BCAST64_CX: 2396*82527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq); 2397fcf3ce44SJohn Forte break; 2398fcf3ce44SJohn Forte 2399fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CX: 2400fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE_CR: 2401fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CX: 2402fcf3ce44SJohn Forte case CMD_XMIT_SEQUENCE64_CR: 2403fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2404fcf3ce44SJohn Forte case FC_TYPE_IS8802_SNAP: 2405*82527734SSukumar Swaminathan (void) emlxs_ip_handle_event(hba, cp, iocbq); 2406fcf3ce44SJohn Forte break; 2407fcf3ce44SJohn Forte 2408fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 2409*82527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq); 2410fcf3ce44SJohn Forte break; 2411fcf3ce44SJohn Forte 2412fcf3ce44SJohn Forte default: 2413fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2414fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 2415*82527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 2416*82527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, 2417*82527734SSukumar Swaminathan iocb->ULPCONTEXT); 2418fcf3ce44SJohn Forte } 2419fcf3ce44SJohn Forte break; 2420fcf3ce44SJohn Forte 2421fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE_CX: 2422fcf3ce44SJohn Forte case CMD_RCV_SEQUENCE64_CX: 2423fcf3ce44SJohn Forte case CMD_RCV_SEQ64_CX: 2424fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ_CX: /* Unsolicited ELS frame */ 2425fcf3ce44SJohn Forte case CMD_RCV_ELS_REQ64_CX: /* Unsolicited ELS frame */ 2426291a2b48SSukumar Swaminathan case CMD_RCV_ELS64_CX: /* Unsolicited ELS frame */ 2427*82527734SSukumar Swaminathan if (hba->sli_mode <= EMLXS_HBA_SLI3_MODE) { 2428*82527734SSukumar Swaminathan (void) emlxs_handle_rcv_seq(hba, cp, iocbq); 2429*82527734SSukumar Swaminathan } 2430fcf3ce44SJohn Forte break; 2431fcf3ce44SJohn Forte 2432fcf3ce44SJohn Forte case CMD_RCV_SEQ_LIST64_CX: 2433*82527734SSukumar Swaminathan (void) emlxs_ip_handle_rcv_seq_list(hba, cp, iocbq); 2434fcf3ce44SJohn Forte break; 2435fcf3ce44SJohn Forte 2436fcf3ce44SJohn Forte case CMD_CREATE_XRI_CR: 2437fcf3ce44SJohn Forte case CMD_CREATE_XRI_CX: 2438*82527734SSukumar Swaminathan (void) emlxs_handle_create_xri(hba, cp, iocbq); 2439fcf3ce44SJohn Forte break; 2440fcf3ce44SJohn Forte 2441fcf3ce44SJohn Forte /* RING 2 ELS commands */ 2442fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CR: 2443fcf3ce44SJohn Forte case CMD_ELS_REQUEST_CX: 2444fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP_CX: 2445fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CR: 2446fcf3ce44SJohn Forte case CMD_ELS_REQUEST64_CX: 2447fcf3ce44SJohn Forte case CMD_XMIT_ELS_RSP64_CX: 2448*82527734SSukumar Swaminathan (void) emlxs_els_handle_event(hba, cp, iocbq); 2449fcf3ce44SJohn Forte break; 2450fcf3ce44SJohn Forte 2451fcf3ce44SJohn Forte /* RING 3 CT commands */ 2452fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CR: 2453fcf3ce44SJohn Forte case CMD_GEN_REQUEST64_CX: 2454fcf3ce44SJohn Forte switch (iocb->un.rcvseq64.w5.hcsw.Type) { 2455fcf3ce44SJohn Forte #ifdef MENLO_SUPPORT 2456fcf3ce44SJohn Forte case EMLXS_MENLO_TYPE: 2457*82527734SSukumar Swaminathan (void) emlxs_menlo_handle_event(hba, cp, iocbq); 2458fcf3ce44SJohn Forte break; 2459291a2b48SSukumar Swaminathan #endif /* MENLO_SUPPORT */ 2460fcf3ce44SJohn Forte 2461fcf3ce44SJohn Forte case FC_TYPE_FC_SERVICES: 2462*82527734SSukumar Swaminathan (void) emlxs_ct_handle_event(hba, cp, iocbq); 2463fcf3ce44SJohn Forte break; 2464fcf3ce44SJohn Forte 2465fcf3ce44SJohn Forte default: 2466fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2467fcf3ce44SJohn Forte "cmd=%x type=%x status=%x iotag=%x context=%x ", 2468*82527734SSukumar Swaminathan iocb->ULPCOMMAND, iocb->un.rcvseq64.w5.hcsw.Type, 2469*82527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, 2470*82527734SSukumar Swaminathan iocb->ULPCONTEXT); 2471fcf3ce44SJohn Forte } 2472fcf3ce44SJohn Forte break; 2473fcf3ce44SJohn Forte 2474fcf3ce44SJohn Forte case CMD_ABORT_XRI_CN: /* Abort fcp command */ 2475fcf3ce44SJohn Forte 2476fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2477fcf3ce44SJohn Forte "ABORT_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 2478fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 2479*82527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2480291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2481fcf3ce44SJohn Forte 2482291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 2483291a2b48SSukumar Swaminathan if (port->tgt_mode) { 2484*82527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2485291a2b48SSukumar Swaminathan } 2486291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2487fcf3ce44SJohn Forte break; 2488fcf3ce44SJohn Forte 2489fcf3ce44SJohn Forte case CMD_ABORT_XRI_CX: /* Abort command */ 2490fcf3ce44SJohn Forte 2491fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2492291a2b48SSukumar Swaminathan "ABORT_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 2493fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 2494*82527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2495291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 2496fcf3ce44SJohn Forte 2497291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 2498291a2b48SSukumar Swaminathan if (port->tgt_mode) { 2499*82527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2500291a2b48SSukumar Swaminathan } 2501291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2502fcf3ce44SJohn Forte break; 2503fcf3ce44SJohn Forte 2504fcf3ce44SJohn Forte case CMD_XRI_ABORTED_CX: /* Handle ABORT condition */ 2505fcf3ce44SJohn Forte 2506fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2507fcf3ce44SJohn Forte "XRI_ABORTED_CX: rpi=%d iotag=%x status=%x parm=%x", 2508fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 2509*82527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2510291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2511fcf3ce44SJohn Forte 2512291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 2513291a2b48SSukumar Swaminathan if (port->tgt_mode) { 2514*82527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2515291a2b48SSukumar Swaminathan } 2516291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2517fcf3ce44SJohn Forte break; 2518fcf3ce44SJohn Forte 2519fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CN: /* Handle CLOSE condition */ 2520fcf3ce44SJohn Forte 2521fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2522*82527734SSukumar Swaminathan "CLOSE_XRI_CN: rpi=%d iotag=%x status=%x parm=%x", 2523fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 2524*82527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2525291a2b48SSukumar Swaminathan iocb->un.acxri.parm); 2526fcf3ce44SJohn Forte 2527291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 2528291a2b48SSukumar Swaminathan if (port->tgt_mode) { 2529*82527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2530291a2b48SSukumar Swaminathan } 2531291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2532fcf3ce44SJohn Forte break; 2533fcf3ce44SJohn Forte 2534fcf3ce44SJohn Forte case CMD_CLOSE_XRI_CX: /* Handle CLOSE condition */ 2535fcf3ce44SJohn Forte 2536fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_pkt_flushed_msg, 2537291a2b48SSukumar Swaminathan "CLOSE_XRI_CX: rpi=%d iotag=%x status=%x parm=%x sbp=%p", 2538fcf3ce44SJohn Forte (uint32_t)iocb->un.acxri.abortContextTag, 2539*82527734SSukumar Swaminathan (uint32_t)iocb->un.acxri.abortIoTag, iocb->ULPSTATUS, 2540291a2b48SSukumar Swaminathan iocb->un.acxri.parm, iocbq->sbp); 2541fcf3ce44SJohn Forte 2542291a2b48SSukumar Swaminathan #ifdef SFCT_SUPPORT 2543291a2b48SSukumar Swaminathan if (port->tgt_mode) { 2544*82527734SSukumar Swaminathan (void) emlxs_fct_handle_abort(hba, cp, iocbq); 2545291a2b48SSukumar Swaminathan } 2546291a2b48SSukumar Swaminathan #endif /* SFCT_SUPPORT */ 2547fcf3ce44SJohn Forte break; 2548fcf3ce44SJohn Forte 2549fcf3ce44SJohn Forte case CMD_ADAPTER_MSG: 2550fcf3ce44SJohn Forte /* Allows debug adapter firmware messages to print on host */ 2551fcf3ce44SJohn Forte bzero(buffer, sizeof (buffer)); 2552fcf3ce44SJohn Forte bcopy((uint8_t *)iocb, buffer, MAX_MSG_DATA); 2553fcf3ce44SJohn Forte 2554fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_msg, "%s", buffer); 2555fcf3ce44SJohn Forte 2556fcf3ce44SJohn Forte break; 2557fcf3ce44SJohn Forte 2558fcf3ce44SJohn Forte case CMD_QUE_RING_LIST64_CN: 2559fcf3ce44SJohn Forte case CMD_QUE_RING_BUF64_CN: 2560fcf3ce44SJohn Forte break; 2561fcf3ce44SJohn Forte 2562fcf3ce44SJohn Forte case CMD_ASYNC_STATUS: 2563*82527734SSukumar Swaminathan emlxs_handle_async_event(hba, cp, iocbq); 2564fcf3ce44SJohn Forte break; 2565fcf3ce44SJohn Forte 2566fcf3ce44SJohn Forte default: 2567fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_iocb_invalid_msg, 2568*82527734SSukumar Swaminathan "cmd=%x status=%x iotag=%x context=%x", iocb->ULPCOMMAND, 2569*82527734SSukumar Swaminathan iocb->ULPSTATUS, iocb->ULPIOTAG, iocb->ULPCONTEXT); 2570fcf3ce44SJohn Forte 2571fcf3ce44SJohn Forte break; 2572*82527734SSukumar Swaminathan } /* switch(entry->ULPCOMMAND) */ 2573fcf3ce44SJohn Forte 2574fcf3ce44SJohn Forte return; 2575fcf3ce44SJohn Forte 2576*82527734SSukumar Swaminathan } /* emlxs_proc_channel_event() */ 2577fcf3ce44SJohn Forte 2578fcf3ce44SJohn Forte 2579291a2b48SSukumar Swaminathan extern char * 2580291a2b48SSukumar Swaminathan emlxs_ffstate_xlate(uint32_t state) 2581fcf3ce44SJohn Forte { 2582291a2b48SSukumar Swaminathan static char buffer[32]; 2583291a2b48SSukumar Swaminathan uint32_t i; 2584291a2b48SSukumar Swaminathan uint32_t count; 2585fcf3ce44SJohn Forte 2586291a2b48SSukumar Swaminathan count = sizeof (emlxs_ffstate_table) / sizeof (emlxs_table_t); 2587291a2b48SSukumar Swaminathan for (i = 0; i < count; i++) { 2588291a2b48SSukumar Swaminathan if (state == emlxs_ffstate_table[i].code) { 2589291a2b48SSukumar Swaminathan return (emlxs_ffstate_table[i].string); 2590fcf3ce44SJohn Forte } 2591fcf3ce44SJohn Forte } 2592fcf3ce44SJohn Forte 2593291a2b48SSukumar Swaminathan (void) sprintf(buffer, "state=0x%x", state); 2594291a2b48SSukumar Swaminathan return (buffer); 2595fcf3ce44SJohn Forte 2596*82527734SSukumar Swaminathan } /* emlxs_ffstate_xlate() */ 2597fcf3ce44SJohn Forte 2598fcf3ce44SJohn Forte 2599fcf3ce44SJohn Forte extern char * 2600fcf3ce44SJohn Forte emlxs_ring_xlate(uint32_t ringno) 2601fcf3ce44SJohn Forte { 2602fcf3ce44SJohn Forte static char buffer[32]; 2603fcf3ce44SJohn Forte uint32_t i; 2604fcf3ce44SJohn Forte uint32_t count; 2605fcf3ce44SJohn Forte 2606fcf3ce44SJohn Forte count = sizeof (emlxs_ring_table) / sizeof (emlxs_table_t); 2607fcf3ce44SJohn Forte for (i = 0; i < count; i++) { 2608fcf3ce44SJohn Forte if (ringno == emlxs_ring_table[i].code) { 2609fcf3ce44SJohn Forte return (emlxs_ring_table[i].string); 2610fcf3ce44SJohn Forte } 2611fcf3ce44SJohn Forte } 2612fcf3ce44SJohn Forte 2613fcf3ce44SJohn Forte (void) sprintf(buffer, "ring=0x%x", ringno); 2614fcf3ce44SJohn Forte return (buffer); 2615fcf3ce44SJohn Forte 2616*82527734SSukumar Swaminathan } /* emlxs_ring_xlate() */ 2617fcf3ce44SJohn Forte 2618fcf3ce44SJohn Forte 2619fcf3ce44SJohn Forte 2620fcf3ce44SJohn Forte extern void 2621fcf3ce44SJohn Forte emlxs_pcix_mxr_update(emlxs_hba_t *hba, uint32_t verbose) 2622fcf3ce44SJohn Forte { 2623fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2624*82527734SSukumar Swaminathan MAILBOXQ *mbq; 2625fcf3ce44SJohn Forte MAILBOX *mb; 2626fcf3ce44SJohn Forte emlxs_config_t *cfg; 2627fcf3ce44SJohn Forte uint32_t value; 2628fcf3ce44SJohn Forte 2629fcf3ce44SJohn Forte cfg = &CFG; 2630fcf3ce44SJohn Forte 2631fcf3ce44SJohn Forte xlate: 2632fcf3ce44SJohn Forte 2633fcf3ce44SJohn Forte switch (cfg[CFG_PCI_MAX_READ].current) { 2634fcf3ce44SJohn Forte case 512: 2635fcf3ce44SJohn Forte value = 0; 2636fcf3ce44SJohn Forte break; 2637fcf3ce44SJohn Forte 2638fcf3ce44SJohn Forte case 1024: 2639fcf3ce44SJohn Forte value = 1; 2640fcf3ce44SJohn Forte break; 2641fcf3ce44SJohn Forte 2642fcf3ce44SJohn Forte case 2048: 2643fcf3ce44SJohn Forte value = 2; 2644fcf3ce44SJohn Forte break; 2645fcf3ce44SJohn Forte 2646fcf3ce44SJohn Forte case 4096: 2647fcf3ce44SJohn Forte value = 3; 2648fcf3ce44SJohn Forte break; 2649fcf3ce44SJohn Forte 2650fcf3ce44SJohn Forte default: 2651fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2652fcf3ce44SJohn Forte "PCI_MAX_READ: Invalid parameter value. old=%d new=%d", 2653fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current, cfg[CFG_PCI_MAX_READ].def); 2654fcf3ce44SJohn Forte 2655fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current = cfg[CFG_PCI_MAX_READ].def; 2656fcf3ce44SJohn Forte goto xlate; 2657fcf3ce44SJohn Forte } 2658fcf3ce44SJohn Forte 2659*82527734SSukumar Swaminathan if ((mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1)) == 0) { 2660fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2661fcf3ce44SJohn Forte "PCI_MAX_READ: Unable to allocate mailbox buffer."); 2662fcf3ce44SJohn Forte return; 2663fcf3ce44SJohn Forte } 2664*82527734SSukumar Swaminathan mb = (MAILBOX *)mbq; 2665fcf3ce44SJohn Forte 2666*82527734SSukumar Swaminathan emlxs_mb_set_var(hba, mbq, 0x00100506, value); 2667291a2b48SSukumar Swaminathan 2668*82527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2669fcf3ce44SJohn Forte if (verbose || (mb->mbxStatus != 0x12)) { 2670fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2671291a2b48SSukumar Swaminathan "PCI_MAX_READ: Unable to update. " 2672291a2b48SSukumar Swaminathan "status=%x value=%d (%d bytes)", 2673291a2b48SSukumar Swaminathan mb->mbxStatus, value, 2674fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 2675fcf3ce44SJohn Forte } 2676fcf3ce44SJohn Forte } else { 2677291a2b48SSukumar Swaminathan if (verbose && 2678291a2b48SSukumar Swaminathan (cfg[CFG_PCI_MAX_READ].current != 2679fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].def)) { 2680fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2681fcf3ce44SJohn Forte "PCI_MAX_READ: Updated. %d bytes", 2682fcf3ce44SJohn Forte cfg[CFG_PCI_MAX_READ].current); 2683fcf3ce44SJohn Forte } 2684fcf3ce44SJohn Forte } 2685fcf3ce44SJohn Forte 2686*82527734SSukumar Swaminathan (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 2687fcf3ce44SJohn Forte 2688fcf3ce44SJohn Forte return; 2689fcf3ce44SJohn Forte 2690*82527734SSukumar Swaminathan } /* emlxs_pcix_mxr_update */ 2691fcf3ce44SJohn Forte 2692fcf3ce44SJohn Forte 2693fcf3ce44SJohn Forte 2694fcf3ce44SJohn Forte extern uint32_t 2695*82527734SSukumar Swaminathan emlxs_get_key(emlxs_hba_t *hba, MAILBOXQ *mbq) 2696fcf3ce44SJohn Forte { 2697fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT; 2698*82527734SSukumar Swaminathan MAILBOX *mb = (MAILBOX *)mbq; 2699fcf3ce44SJohn Forte uint32_t npname0, npname1; 2700fcf3ce44SJohn Forte uint32_t tmpkey, theKey; 2701fcf3ce44SJohn Forte uint16_t key850; 2702fcf3ce44SJohn Forte uint32_t t1, t2, t3, t4; 2703fcf3ce44SJohn Forte uint32_t ts; 2704fcf3ce44SJohn Forte 2705fcf3ce44SJohn Forte #define SEED 0x876EDC21 2706fcf3ce44SJohn Forte 2707fcf3ce44SJohn Forte /* This key is only used currently for SBUS adapters */ 2708fcf3ce44SJohn Forte if (hba->bus_type != SBUS_FC) { 2709fcf3ce44SJohn Forte return (0); 2710fcf3ce44SJohn Forte } 2711291a2b48SSukumar Swaminathan 2712fcf3ce44SJohn Forte tmpkey = mb->un.varWords[30]; 2713*82527734SSukumar Swaminathan EMLXS_STATE_CHANGE(hba, FC_INIT_NVPARAMS); 2714fcf3ce44SJohn Forte 2715*82527734SSukumar Swaminathan emlxs_mb_read_nv(hba, mbq); 2716*82527734SSukumar Swaminathan if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) { 2717fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2718291a2b48SSukumar Swaminathan "Unable to read nvram. cmd=%x status=%x", mb->mbxCommand, 2719291a2b48SSukumar Swaminathan mb->mbxStatus); 2720fcf3ce44SJohn Forte 2721fcf3ce44SJohn Forte return (0); 2722fcf3ce44SJohn Forte } 2723fcf3ce44SJohn Forte npname0 = mb->un.varRDnvp.portname[0]; 2724fcf3ce44SJohn Forte npname1 = mb->un.varRDnvp.portname[1]; 2725fcf3ce44SJohn Forte 2726fcf3ce44SJohn Forte key850 = (uint16_t)((tmpkey & 0x00FFFF00) >> 8); 2727fcf3ce44SJohn Forte ts = (uint16_t)(npname1 + 1); 2728fcf3ce44SJohn Forte t1 = ts * key850; 2729fcf3ce44SJohn Forte ts = (uint16_t)((npname1 >> 16) + 1); 2730fcf3ce44SJohn Forte t2 = ts * key850; 2731fcf3ce44SJohn Forte ts = (uint16_t)(npname0 + 1); 2732fcf3ce44SJohn Forte t3 = ts * key850; 2733fcf3ce44SJohn Forte ts = (uint16_t)((npname0 >> 16) + 1); 2734fcf3ce44SJohn Forte t4 = ts * key850; 2735fcf3ce44SJohn Forte theKey = SEED + t1 + t2 + t3 + t4; 2736fcf3ce44SJohn Forte 2737fcf3ce44SJohn Forte return (theKey); 2738fcf3ce44SJohn Forte 2739*82527734SSukumar Swaminathan } /* emlxs_get_key() */ 2740291a2b48SSukumar Swaminathan 2741291a2b48SSukumar Swaminathan 2742291a2b48SSukumar Swaminathan extern void 2743291a2b48SSukumar Swaminathan emlxs_fw_show(emlxs_hba_t *hba) 2744291a2b48SSukumar Swaminathan { 2745291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2746291a2b48SSukumar Swaminathan uint32_t i; 2747291a2b48SSukumar Swaminathan 2748291a2b48SSukumar Swaminathan /* Display firmware library one time */ 2749*82527734SSukumar Swaminathan for (i = 0; i < emlxs_fw_count; i++) { 2750291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_library_msg, "%s", 2751291a2b48SSukumar Swaminathan emlxs_fw_table[i].label); 2752291a2b48SSukumar Swaminathan } 2753291a2b48SSukumar Swaminathan 2754291a2b48SSukumar Swaminathan return; 2755291a2b48SSukumar Swaminathan 2756*82527734SSukumar Swaminathan } /* emlxs_fw_show() */ 2757291a2b48SSukumar Swaminathan 2758291a2b48SSukumar Swaminathan 2759291a2b48SSukumar Swaminathan #ifdef MODFW_SUPPORT 2760*82527734SSukumar Swaminathan extern void 2761291a2b48SSukumar Swaminathan emlxs_fw_load(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2762291a2b48SSukumar Swaminathan { 2763291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2764291a2b48SSukumar Swaminathan int (*emlxs_fw_get)(emlxs_firmware_t *); 2765291a2b48SSukumar Swaminathan int err; 2766291a2b48SSukumar Swaminathan 2767291a2b48SSukumar Swaminathan /* Make sure image is unloaded and image buffer pointer is clear */ 2768291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2769291a2b48SSukumar Swaminathan 2770291a2b48SSukumar Swaminathan err = 0; 2771291a2b48SSukumar Swaminathan hba->fw_modhandle = 2772291a2b48SSukumar Swaminathan ddi_modopen(EMLXS_FW_MODULE, KRTLD_MODE_FIRST, &err); 2773291a2b48SSukumar Swaminathan if (!hba->fw_modhandle) { 2774291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2775291a2b48SSukumar Swaminathan "Unable to load firmware module. error=%d", err); 2776291a2b48SSukumar Swaminathan 2777291a2b48SSukumar Swaminathan return; 2778291a2b48SSukumar Swaminathan } else { 2779291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2780291a2b48SSukumar Swaminathan "Firmware module loaded."); 2781291a2b48SSukumar Swaminathan } 2782291a2b48SSukumar Swaminathan 2783291a2b48SSukumar Swaminathan err = 0; 2784291a2b48SSukumar Swaminathan emlxs_fw_get = 2785291a2b48SSukumar Swaminathan (int (*)())ddi_modsym(hba->fw_modhandle, "emlxs_fw_get", &err); 2786291a2b48SSukumar Swaminathan if ((void *)emlxs_fw_get == NULL) { 2787291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2788291a2b48SSukumar Swaminathan "emlxs_fw_get not present. error=%d", err); 2789291a2b48SSukumar Swaminathan 2790291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2791291a2b48SSukumar Swaminathan return; 2792291a2b48SSukumar Swaminathan } 2793291a2b48SSukumar Swaminathan 2794291a2b48SSukumar Swaminathan if (emlxs_fw_get(fw)) { 2795291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg, 2796291a2b48SSukumar Swaminathan "Invalid firmware image module found. %s", fw->label); 2797291a2b48SSukumar Swaminathan 2798291a2b48SSukumar Swaminathan emlxs_fw_unload(hba, fw); 2799291a2b48SSukumar Swaminathan return; 2800291a2b48SSukumar Swaminathan } 2801291a2b48SSukumar Swaminathan 2802291a2b48SSukumar Swaminathan return; 2803291a2b48SSukumar Swaminathan 2804*82527734SSukumar Swaminathan } /* emlxs_fw_load() */ 2805291a2b48SSukumar Swaminathan 2806291a2b48SSukumar Swaminathan 2807*82527734SSukumar Swaminathan extern void 2808291a2b48SSukumar Swaminathan emlxs_fw_unload(emlxs_hba_t *hba, emlxs_firmware_t *fw) 2809291a2b48SSukumar Swaminathan { 2810291a2b48SSukumar Swaminathan emlxs_port_t *port = &PPORT; 2811291a2b48SSukumar Swaminathan 2812291a2b48SSukumar Swaminathan /* Clear the firmware image */ 2813291a2b48SSukumar Swaminathan fw->image = NULL; 2814291a2b48SSukumar Swaminathan fw->size = 0; 2815291a2b48SSukumar Swaminathan 2816291a2b48SSukumar Swaminathan if (hba->fw_modhandle) { 2817291a2b48SSukumar Swaminathan /* Close the module */ 2818291a2b48SSukumar Swaminathan (void) ddi_modclose(hba->fw_modhandle); 2819291a2b48SSukumar Swaminathan hba->fw_modhandle = NULL; 2820291a2b48SSukumar Swaminathan 2821291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_msg, 2822291a2b48SSukumar Swaminathan "Firmware module unloaded."); 2823291a2b48SSukumar Swaminathan } 2824291a2b48SSukumar Swaminathan 2825291a2b48SSukumar Swaminathan return; 2826291a2b48SSukumar Swaminathan 2827*82527734SSukumar Swaminathan } /* emlxs_fw_unload() */ 2828291a2b48SSukumar Swaminathan #endif /* MODFW_SUPPORT */ 2829