1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* Copyright 2008 QLogic Corporation */ 23 24 /* 25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #pragma ident "Copyright 2008 QLogic Corporation; ql_ioctl.c" 30 31 /* 32 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 33 * Fibre Channel Adapter (FCA) driver IOCTL source file. 34 * 35 * *********************************************************************** 36 * * ** 37 * * NOTICE ** 38 * * COPYRIGHT (C) 1996-2008 QLOGIC CORPORATION ** 39 * * ALL RIGHTS RESERVED ** 40 * * ** 41 * *********************************************************************** 42 * 43 */ 44 45 #include <ql_apps.h> 46 #include <ql_api.h> 47 #include <ql_debug.h> 48 #include <ql_init.h> 49 #include <ql_ioctl.h> 50 #include <ql_mbx.h> 51 #include <ql_xioctl.h> 52 53 /* 54 * Local Function Prototypes. 55 */ 56 static int ql_busy_notification(ql_adapter_state_t *); 57 static int ql_idle_notification(ql_adapter_state_t *); 58 static int ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features); 59 static int ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features); 60 static int ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha); 61 static void ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr, 62 uint16_t value); 63 static int ql_24xx_load_nvram(ql_adapter_state_t *, uint32_t, uint32_t); 64 static int ql_adm_op(ql_adapter_state_t *, void *, int); 65 static int ql_adm_adapter_info(ql_adapter_state_t *, ql_adm_op_t *, int); 66 static int ql_adm_extended_logging(ql_adapter_state_t *, ql_adm_op_t *); 67 static int ql_adm_device_list(ql_adapter_state_t *, ql_adm_op_t *, int); 68 static int ql_adm_update_properties(ql_adapter_state_t *); 69 static int ql_adm_prop_update_int(ql_adapter_state_t *, ql_adm_op_t *, int); 70 static int ql_adm_loop_reset(ql_adapter_state_t *); 71 static int ql_adm_fw_dump(ql_adapter_state_t *, ql_adm_op_t *, void *, int); 72 static int ql_adm_nvram_dump(ql_adapter_state_t *, ql_adm_op_t *, int); 73 static int ql_adm_nvram_load(ql_adapter_state_t *, ql_adm_op_t *, int); 74 static int ql_adm_flash_load(ql_adapter_state_t *, ql_adm_op_t *, int); 75 static int ql_adm_vpd_dump(ql_adapter_state_t *, ql_adm_op_t *, int); 76 static int ql_adm_vpd_load(ql_adapter_state_t *, ql_adm_op_t *, int); 77 static int ql_adm_vpd_gettag(ql_adapter_state_t *, ql_adm_op_t *, int); 78 static int ql_adm_updfwmodule(ql_adapter_state_t *, ql_adm_op_t *, int); 79 static uint8_t *ql_vpd_findtag(ql_adapter_state_t *, uint8_t *, int8_t *); 80 static int ql_25xx_load_nv_vpd(ql_adapter_state_t *, uint8_t *, uint32_t, 81 uint32_t); 82 83 /* ************************************************************************ */ 84 /* cb_ops functions */ 85 /* ************************************************************************ */ 86 87 /* 88 * ql_open 89 * opens device 90 * 91 * Input: 92 * dev_p = device pointer 93 * flags = open flags 94 * otype = open type 95 * cred_p = credentials pointer 96 * 97 * Returns: 98 * 0 = success 99 * 100 * Context: 101 * Kernel context. 102 */ 103 /* ARGSUSED */ 104 int 105 ql_open(dev_t *dev_p, int flags, int otyp, cred_t *cred_p) 106 { 107 ql_adapter_state_t *ha; 108 int rval = 0; 109 110 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(*dev_p)); 111 if (ha == NULL) { 112 QL_PRINT_2(CE_CONT, "failed, no adapter\n"); 113 return (ENXIO); 114 } 115 116 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 117 118 /* Allow only character opens */ 119 if (otyp != OTYP_CHR) { 120 QL_PRINT_2(CE_CONT, "(%d): failed, open type\n", 121 ha->instance); 122 return (EINVAL); 123 } 124 125 /* Acquire adapter state lock. */ 126 ADAPTER_STATE_LOCK(ha); 127 if (flags & FEXCL && ha->flags & QL_OPENED) { 128 /* Release adapter state lock. */ 129 ADAPTER_STATE_UNLOCK(ha); 130 rval = EBUSY; 131 } else { 132 ha->flags |= QL_OPENED; 133 134 /* Release adapter state lock. */ 135 ADAPTER_STATE_UNLOCK(ha); 136 } 137 138 if (rval != 0) { 139 EL(ha, "failed, rval = %xh\n", rval); 140 } else { 141 /*EMPTY*/ 142 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 143 } 144 return (rval); 145 } 146 147 /* 148 * ql_close 149 * opens device 150 * 151 * Input: 152 * dev_p = device pointer 153 * flags = open flags 154 * otype = open type 155 * cred_p = credentials pointer 156 * 157 * Returns: 158 * 0 = success 159 * 160 * Context: 161 * Kernel context. 162 */ 163 /* ARGSUSED */ 164 int 165 ql_close(dev_t dev, int flags, int otyp, cred_t *cred_p) 166 { 167 ql_adapter_state_t *ha; 168 int rval = 0; 169 170 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev)); 171 if (ha == NULL) { 172 QL_PRINT_2(CE_CONT, "failed, no adapter\n"); 173 return (ENXIO); 174 } 175 176 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 177 178 if (otyp != OTYP_CHR) { 179 QL_PRINT_2(CE_CONT, "(%d): failed, open type\n", 180 ha->instance); 181 return (EINVAL); 182 } 183 184 /* Acquire adapter state lock. */ 185 ADAPTER_STATE_LOCK(ha); 186 187 ha->flags &= ~QL_OPENED; 188 189 /* Release adapter state lock. */ 190 ADAPTER_STATE_UNLOCK(ha); 191 192 if (rval != 0) { 193 EL(ha, "failed, rval = %xh\n", rval); 194 } else { 195 /*EMPTY*/ 196 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 197 } 198 return (rval); 199 } 200 201 /* 202 * ql_ioctl 203 * control a character device 204 * 205 * Input: 206 * dev = device number 207 * cmd = function to perform 208 * arg = data type varies with request 209 * mode = flags 210 * cred_p = credentials pointer 211 * rval_p = pointer to result value 212 * 213 * Returns: 214 * 0 = success 215 * 216 * Context: 217 * Kernel context. 218 */ 219 /* ARGSUSED */ 220 int 221 ql_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, 222 int *rval_p) 223 { 224 ql_adapter_state_t *ha; 225 int rval = 0; 226 227 if (ddi_in_panic()) { 228 QL_PRINT_2(CE_CONT, "qla_ioctl: ddi_in_panic exit\n"); 229 return (ENOPROTOOPT); 230 } 231 232 ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev)); 233 if (ha == NULL) { 234 QL_PRINT_2(CE_CONT, "failed, no adapter\n"); 235 return (ENXIO); 236 } 237 238 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 239 240 /* 241 * Quick clean exit for qla2x00 foapi calls which are 242 * not supported in qlc. 243 */ 244 if (cmd >= QL_FOAPI_START && cmd <= QL_FOAPI_END) { 245 QL_PRINT_9(CE_CONT, "failed, fo api not supported\n"); 246 return (ENOTTY); 247 } 248 249 /* PWR management busy. */ 250 rval = ql_busy_notification(ha); 251 if (rval != FC_SUCCESS) { 252 EL(ha, "failed, ql_busy_notification\n"); 253 return (ENXIO); 254 } 255 256 rval = ql_xioctl(ha, cmd, arg, mode, cred_p, rval_p); 257 if (rval == ENOPROTOOPT || rval == EINVAL) { 258 switch (cmd) { 259 case QL_GET_ADAPTER_FEATURE_BITS: 260 { 261 uint16_t bits; 262 263 rval = ql_get_feature_bits(ha, &bits); 264 265 if (!rval && ddi_copyout((void *)&bits, (void *)arg, 266 sizeof (bits), mode)) { 267 rval = EFAULT; 268 } 269 break; 270 } 271 272 case QL_SET_ADAPTER_FEATURE_BITS: 273 { 274 uint16_t bits; 275 276 if (ddi_copyin((void *)arg, (void *)&bits, 277 sizeof (bits), mode)) { 278 rval = EFAULT; 279 break; 280 } 281 282 rval = ql_set_feature_bits(ha, bits); 283 break; 284 } 285 286 case QL_SET_ADAPTER_NVRAM_DEFAULTS: 287 rval = ql_set_nvram_adapter_defaults(ha); 288 break; 289 290 case QL_UTIL_LOAD: 291 rval = ql_nv_util_load(ha, (void *)arg, mode); 292 break; 293 294 case QL_UTIL_DUMP: 295 rval = ql_nv_util_dump(ha, (void *)arg, mode); 296 break; 297 298 case QL_ADM_OP: 299 rval = ql_adm_op(ha, (void *)arg, mode); 300 break; 301 302 default: 303 EL(ha, "unknown command = %d\n", cmd); 304 rval = ENOTTY; 305 break; 306 } 307 } 308 309 /* PWR management idle. */ 310 (void) ql_idle_notification(ha); 311 312 if (rval != 0) { 313 EL(ha, "failed, rval = %d\n", rval); 314 } else { 315 /*EMPTY*/ 316 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 317 } 318 return (rval); 319 } 320 321 /* 322 * ql_busy_notification 323 * Adapter busy notification. 324 * 325 * Input: 326 * ha = adapter state pointer. 327 * 328 * Returns: 329 * FC_SUCCESS 330 * FC_FAILURE 331 * 332 * Context: 333 * Kernel context. 334 */ 335 static int 336 ql_busy_notification(ql_adapter_state_t *ha) 337 { 338 if (!ha->pm_capable) { 339 return (FC_SUCCESS); 340 } 341 342 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 343 344 QL_PM_LOCK(ha); 345 ha->busy++; 346 QL_PM_UNLOCK(ha); 347 348 if (pm_busy_component(ha->dip, 0) != DDI_SUCCESS) { 349 QL_PM_LOCK(ha); 350 ha->busy--; 351 QL_PM_UNLOCK(ha); 352 353 EL(ha, "pm_busy_component failed = %xh\n", FC_FAILURE); 354 return (FC_FAILURE); 355 } 356 357 QL_PM_LOCK(ha); 358 if (ha->power_level != PM_LEVEL_D0) { 359 ASSERT(ha->power_level == PM_LEVEL_D3); 360 361 QL_PM_UNLOCK(ha); 362 if (pm_raise_power(ha->dip, 0, 1) != DDI_SUCCESS) { 363 QL_PM_LOCK(ha); 364 ha->busy--; 365 QL_PM_UNLOCK(ha); 366 return (FC_FAILURE); 367 } 368 } else { 369 QL_PM_UNLOCK(ha); 370 } 371 372 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 373 374 return (FC_SUCCESS); 375 } 376 377 /* 378 * ql_idle_notification 379 * Adapter idle notification. 380 * 381 * Input: 382 * ha = adapter state pointer. 383 * 384 * Returns: 385 * FC_SUCCESS 386 * FC_FAILURE 387 * 388 * Context: 389 * Kernel context. 390 */ 391 static int 392 ql_idle_notification(ql_adapter_state_t *ha) 393 { 394 if (!ha->pm_capable) { 395 return (FC_SUCCESS); 396 } 397 398 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 399 400 if (pm_idle_component(ha->dip, 0) != DDI_SUCCESS) { 401 EL(ha, "pm_idle_component failed = %xh\n", FC_FAILURE); 402 return (FC_FAILURE); 403 } 404 405 QL_PM_LOCK(ha); 406 ASSERT(ha->busy > 0); 407 ha->busy--; 408 QL_PM_UNLOCK(ha); 409 410 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 411 412 return (FC_SUCCESS); 413 } 414 415 /* 416 * Get adapter feature bits from NVRAM 417 */ 418 static int 419 ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features) 420 { 421 int count; 422 volatile uint16_t data; 423 uint32_t nv_cmd; 424 uint32_t start_addr; 425 int rval; 426 uint32_t offset = offsetof(nvram_t, adapter_features); 427 428 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 429 430 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 431 EL(ha, "Not supported for 24xx\n"); 432 return (EINVAL); 433 } 434 435 /* 436 * The offset can't be greater than max of 8 bits and 437 * the following code breaks if the offset isn't at 438 * 2 byte boundary. 439 */ 440 ASSERT(offset <= 0xFF && (offset & 0x1) == 0); 441 442 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA); 443 if (rval != QL_SUCCESS) { 444 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 445 return (EIO); 446 } 447 448 /* 449 * Have the most significant 3 bits represent the read operation 450 * followed by the 8 bits representing the offset at which we 451 * are going to perform the read operation 452 */ 453 offset >>= 1; 454 offset += start_addr; 455 nv_cmd = (offset << 16) | NV_READ_OP; 456 nv_cmd <<= 5; 457 458 /* 459 * Select the chip and feed the command and address 460 */ 461 for (count = 0; count < 11; count++) { 462 if (nv_cmd & BIT_31) { 463 ql_nv_write(ha, NV_DATA_OUT); 464 } else { 465 ql_nv_write(ha, 0); 466 } 467 nv_cmd <<= 1; 468 } 469 470 *features = 0; 471 for (count = 0; count < 16; count++) { 472 WRT16_IO_REG(ha, nvram, NV_SELECT | NV_CLOCK); 473 ql_nv_delay(); 474 475 data = RD16_IO_REG(ha, nvram); 476 *features <<= 1; 477 if (data & NV_DATA_IN) { 478 *features = (uint16_t)(*features | 0x1); 479 } 480 481 WRT16_IO_REG(ha, nvram, NV_SELECT); 482 ql_nv_delay(); 483 } 484 485 /* 486 * Deselect the chip 487 */ 488 WRT16_IO_REG(ha, nvram, NV_DESELECT); 489 490 ql_release_nvram(ha); 491 492 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 493 494 return (0); 495 } 496 497 /* 498 * Set adapter feature bits in NVRAM 499 */ 500 static int 501 ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features) 502 { 503 int rval; 504 uint32_t count; 505 nvram_t *nv; 506 uint16_t *wptr; 507 uint8_t *bptr; 508 uint8_t csum; 509 uint32_t start_addr; 510 511 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 512 513 if (CFG_IST(ha, CFG_CTRL_2425)) { 514 EL(ha, "Not supported for 24xx\n"); 515 return (EINVAL); 516 } 517 518 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP); 519 if (nv == NULL) { 520 EL(ha, "failed, kmem_zalloc\n"); 521 return (ENOMEM); 522 } 523 524 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA); 525 if (rval != QL_SUCCESS) { 526 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 527 kmem_free(nv, sizeof (*nv)); 528 return (EIO); 529 } 530 rval = 0; 531 532 /* 533 * Read off the whole NVRAM 534 */ 535 wptr = (uint16_t *)nv; 536 csum = 0; 537 for (count = 0; count < sizeof (nvram_t) / 2; count++) { 538 *wptr = (uint16_t)ql_get_nvram_word(ha, count + start_addr); 539 csum = (uint8_t)(csum + (uint8_t)*wptr); 540 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8)); 541 wptr++; 542 } 543 544 /* 545 * If the checksum is BAD then fail it right here. 546 */ 547 if (csum) { 548 kmem_free(nv, sizeof (*nv)); 549 ql_release_nvram(ha); 550 return (EBADF); 551 } 552 553 nv->adapter_features[0] = (uint8_t)((features & 0xFF00) >> 8); 554 nv->adapter_features[1] = (uint8_t)(features & 0xFF); 555 556 /* 557 * Recompute the chesksum now 558 */ 559 bptr = (uint8_t *)nv; 560 for (count = 0; count < sizeof (nvram_t) - 1; count++) { 561 csum = (uint8_t)(csum + *bptr++); 562 } 563 csum = (uint8_t)(~csum + 1); 564 nv->checksum = csum; 565 566 /* 567 * Now load the NVRAM 568 */ 569 wptr = (uint16_t *)nv; 570 for (count = 0; count < sizeof (nvram_t) / 2; count++) { 571 ql_load_nvram(ha, (uint8_t)(count + start_addr), *wptr++); 572 } 573 574 /* 575 * Read NVRAM and verify the contents 576 */ 577 wptr = (uint16_t *)nv; 578 csum = 0; 579 for (count = 0; count < sizeof (nvram_t) / 2; count++) { 580 if (ql_get_nvram_word(ha, count + start_addr) != *wptr) { 581 rval = EIO; 582 break; 583 } 584 csum = (uint8_t)(csum + (uint8_t)*wptr); 585 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8)); 586 wptr++; 587 } 588 589 if (csum) { 590 rval = EINVAL; 591 } 592 593 kmem_free(nv, sizeof (*nv)); 594 ql_release_nvram(ha); 595 596 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 597 598 return (rval); 599 } 600 601 /* 602 * Fix this function to update just feature bits and checksum in NVRAM 603 */ 604 static int 605 ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha) 606 { 607 int rval; 608 uint32_t count; 609 uint32_t start_addr; 610 611 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 612 613 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA); 614 if (rval != QL_SUCCESS) { 615 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 616 return (EIO); 617 } 618 rval = 0; 619 620 if (CFG_IST(ha, CFG_CTRL_2425)) { 621 nvram_24xx_t *nv; 622 uint32_t *longptr; 623 uint32_t csum = 0; 624 625 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP); 626 if (nv == NULL) { 627 EL(ha, "failed, kmem_zalloc\n"); 628 return (ENOMEM); 629 } 630 631 nv->nvram_version[0] = LSB(ICB_24XX_VERSION); 632 nv->nvram_version[1] = MSB(ICB_24XX_VERSION); 633 634 nv->version[0] = 1; 635 nv->max_frame_length[1] = 8; 636 nv->execution_throttle[0] = 16; 637 nv->login_retry_count[0] = 8; 638 639 nv->firmware_options_1[0] = BIT_2 | BIT_1; 640 nv->firmware_options_1[1] = BIT_5; 641 nv->firmware_options_2[0] = BIT_5; 642 nv->firmware_options_2[1] = BIT_4; 643 nv->firmware_options_3[1] = BIT_6; 644 645 /* 646 * Set default host adapter parameters 647 */ 648 nv->host_p[0] = BIT_4 | BIT_1; 649 nv->host_p[1] = BIT_3 | BIT_2; 650 nv->reset_delay = 5; 651 nv->max_luns_per_target[0] = 128; 652 nv->port_down_retry_count[0] = 30; 653 nv->link_down_timeout[0] = 30; 654 655 /* 656 * compute the chesksum now 657 */ 658 longptr = (uint32_t *)nv; 659 csum = 0; 660 for (count = 0; count < (sizeof (nvram_24xx_t)/4)-1; count++) { 661 csum += *longptr; 662 longptr++; 663 } 664 csum = (uint32_t)(~csum + 1); 665 LITTLE_ENDIAN_32((long)csum); 666 *longptr = csum; 667 668 /* 669 * Now load the NVRAM 670 */ 671 longptr = (uint32_t *)nv; 672 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) { 673 (void) ql_24xx_load_nvram(ha, 674 (uint32_t)(count + start_addr), *longptr++); 675 } 676 677 /* 678 * Read NVRAM and verify the contents 679 */ 680 csum = 0; 681 longptr = (uint32_t *)nv; 682 for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) { 683 rval = ql_24xx_read_flash(ha, count + start_addr, 684 longptr); 685 if (rval != QL_SUCCESS) { 686 EL(ha, "24xx_read_flash failed=%xh\n", rval); 687 break; 688 } 689 csum += *longptr; 690 } 691 692 if (csum) { 693 rval = EINVAL; 694 } 695 kmem_free(nv, sizeof (nvram_24xx_t)); 696 } else { 697 nvram_t *nv; 698 uint16_t *wptr; 699 uint8_t *bptr; 700 uint8_t csum; 701 702 nv = kmem_zalloc(sizeof (*nv), KM_SLEEP); 703 if (nv == NULL) { 704 EL(ha, "failed, kmem_zalloc\n"); 705 return (ENOMEM); 706 } 707 /* 708 * Set default initialization control block. 709 */ 710 nv->parameter_block_version = ICB_VERSION; 711 nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1; 712 nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2; 713 714 nv->max_frame_length[1] = 4; 715 nv->max_iocb_allocation[1] = 1; 716 nv->execution_throttle[0] = 16; 717 nv->login_retry_count = 8; 718 nv->port_name[0] = 33; 719 nv->port_name[3] = 224; 720 nv->port_name[4] = 139; 721 nv->login_timeout = 4; 722 723 /* 724 * Set default host adapter parameters 725 */ 726 nv->host_p[0] = BIT_1; 727 nv->host_p[1] = BIT_2; 728 nv->reset_delay = 5; 729 nv->port_down_retry_count = 8; 730 nv->maximum_luns_per_target[0] = 8; 731 732 /* 733 * compute the chesksum now 734 */ 735 bptr = (uint8_t *)nv; 736 csum = 0; 737 for (count = 0; count < sizeof (nvram_t) - 1; count++) { 738 csum = (uint8_t)(csum + *bptr++); 739 } 740 csum = (uint8_t)(~csum + 1); 741 nv->checksum = csum; 742 743 /* 744 * Now load the NVRAM 745 */ 746 wptr = (uint16_t *)nv; 747 for (count = 0; count < sizeof (nvram_t) / 2; count++) { 748 ql_load_nvram(ha, (uint8_t)(count + start_addr), 749 *wptr++); 750 } 751 752 /* 753 * Read NVRAM and verify the contents 754 */ 755 wptr = (uint16_t *)nv; 756 csum = 0; 757 for (count = 0; count < sizeof (nvram_t) / 2; count++) { 758 if (ql_get_nvram_word(ha, count + start_addr) != 759 *wptr) { 760 rval = EIO; 761 break; 762 } 763 csum = (uint8_t)(csum + (uint8_t)*wptr); 764 csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8)); 765 wptr++; 766 } 767 if (csum) { 768 rval = EINVAL; 769 } 770 kmem_free(nv, sizeof (*nv)); 771 } 772 ql_release_nvram(ha); 773 774 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 775 776 return (rval); 777 } 778 779 static void 780 ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr, uint16_t value) 781 { 782 int count; 783 volatile uint16_t word; 784 volatile uint32_t nv_cmd; 785 786 ql_nv_write(ha, NV_DATA_OUT); 787 ql_nv_write(ha, 0); 788 ql_nv_write(ha, 0); 789 790 for (word = 0; word < 8; word++) { 791 ql_nv_write(ha, NV_DATA_OUT); 792 } 793 794 /* 795 * Deselect the chip 796 */ 797 WRT16_IO_REG(ha, nvram, NV_DESELECT); 798 ql_nv_delay(); 799 800 /* 801 * Erase Location 802 */ 803 nv_cmd = (addr << 16) | NV_ERASE_OP; 804 nv_cmd <<= 5; 805 for (count = 0; count < 11; count++) { 806 if (nv_cmd & BIT_31) { 807 ql_nv_write(ha, NV_DATA_OUT); 808 } else { 809 ql_nv_write(ha, 0); 810 } 811 nv_cmd <<= 1; 812 } 813 814 /* 815 * Wait for Erase to Finish 816 */ 817 WRT16_IO_REG(ha, nvram, NV_DESELECT); 818 ql_nv_delay(); 819 WRT16_IO_REG(ha, nvram, NV_SELECT); 820 word = 0; 821 while ((word & NV_DATA_IN) == 0) { 822 ql_nv_delay(); 823 word = RD16_IO_REG(ha, nvram); 824 } 825 WRT16_IO_REG(ha, nvram, NV_DESELECT); 826 ql_nv_delay(); 827 828 /* 829 * Write data now 830 */ 831 nv_cmd = (addr << 16) | NV_WRITE_OP; 832 nv_cmd |= value; 833 nv_cmd <<= 5; 834 for (count = 0; count < 27; count++) { 835 if (nv_cmd & BIT_31) { 836 ql_nv_write(ha, NV_DATA_OUT); 837 } else { 838 ql_nv_write(ha, 0); 839 } 840 nv_cmd <<= 1; 841 } 842 843 /* 844 * Wait for NVRAM to become ready 845 */ 846 WRT16_IO_REG(ha, nvram, NV_DESELECT); 847 ql_nv_delay(); 848 WRT16_IO_REG(ha, nvram, NV_SELECT); 849 word = 0; 850 while ((word & NV_DATA_IN) == 0) { 851 ql_nv_delay(); 852 word = RD16_IO_REG(ha, nvram); 853 } 854 WRT16_IO_REG(ha, nvram, NV_DESELECT); 855 ql_nv_delay(); 856 857 /* 858 * Disable writes 859 */ 860 ql_nv_write(ha, NV_DATA_OUT); 861 for (count = 0; count < 10; count++) { 862 ql_nv_write(ha, 0); 863 } 864 865 /* 866 * Deselect the chip now 867 */ 868 WRT16_IO_REG(ha, nvram, NV_DESELECT); 869 } 870 871 /* 872 * ql_24xx_load_nvram 873 * Enable NVRAM and writes a 32bit word to ISP24xx NVRAM. 874 * 875 * Input: 876 * ha: adapter state pointer. 877 * addr: NVRAM address. 878 * value: data. 879 * 880 * Returns: 881 * ql local function return status code. 882 * 883 * Context: 884 * Kernel context. 885 */ 886 static int 887 ql_24xx_load_nvram(ql_adapter_state_t *ha, uint32_t addr, uint32_t value) 888 { 889 int rval; 890 891 /* Enable flash write. */ 892 WRT32_IO_REG(ha, ctrl_status, 893 RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE); 894 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */ 895 896 /* Disable NVRAM write-protection. */ 897 if (CFG_IST(ha, CFG_CTRL_2422)) { 898 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0); 899 } else { 900 ql_24xx_unprotect_flash(ha); 901 } 902 903 /* Write to flash. */ 904 rval = ql_24xx_write_flash(ha, addr, value); 905 906 /* Enable NVRAM write-protection. */ 907 if (CFG_IST(ha, CFG_CTRL_2422)) { 908 /* TODO: Check if 0x8c is correct -- sb: 0x9c ? */ 909 (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0x8c); 910 } else { 911 ql_24xx_protect_flash(ha); 912 } 913 914 /* Disable flash write. */ 915 WRT32_IO_REG(ha, ctrl_status, 916 RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE); 917 RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */ 918 919 return (rval); 920 } 921 922 /* 923 * ql_nv_util_load 924 * Loads NVRAM from application. 925 * 926 * Input: 927 * ha = adapter state pointer. 928 * bp = user buffer address. 929 * 930 * Returns: 931 * 932 * Context: 933 * Kernel context. 934 */ 935 int 936 ql_nv_util_load(ql_adapter_state_t *ha, void *bp, int mode) 937 { 938 uint8_t cnt; 939 void *nv; 940 uint16_t *wptr; 941 uint16_t data; 942 uint32_t start_addr, nv_size, *lptr, data32; 943 nvram_t *nptr; 944 int rval; 945 946 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 947 948 nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_2425) ? 949 sizeof (nvram_24xx_t) : sizeof (nvram_t)); 950 951 if ((nv = kmem_zalloc(nv_size, KM_SLEEP)) == NULL) { 952 EL(ha, "failed, kmem_zalloc\n"); 953 return (ENOMEM); 954 } 955 956 if (ddi_copyin(bp, nv, nv_size, mode) != 0) { 957 EL(ha, "Buffer copy failed\n"); 958 kmem_free(nv, nv_size); 959 return (EFAULT); 960 } 961 962 /* See if the buffer passed to us looks sane */ 963 nptr = (nvram_t *)nv; 964 if (nptr->id[0] != 'I' || nptr->id[1] != 'S' || nptr->id[2] != 'P' || 965 nptr->id[3] != ' ') { 966 EL(ha, "failed, buffer sanity check\n"); 967 kmem_free(nv, nv_size); 968 return (EINVAL); 969 } 970 971 /* Quiesce I/O */ 972 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 973 EL(ha, "ql_stall_driver failed\n"); 974 kmem_free(nv, nv_size); 975 return (EBUSY); 976 } 977 978 rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA); 979 if (rval != QL_SUCCESS) { 980 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 981 kmem_free(nv, nv_size); 982 ql_restart_driver(ha); 983 return (EIO); 984 } 985 986 /* Load NVRAM. */ 987 if (CFG_IST(ha, CFG_CTRL_25XX)) { 988 GLOBAL_HW_UNLOCK(); 989 if ((rval = ql_25xx_load_nv_vpd(ha, (uint8_t *)nv, start_addr, 990 nv_size)) != QL_SUCCESS) { 991 EL(ha, "nvram load failed, rval = %0xh\n", rval); 992 } 993 GLOBAL_HW_LOCK(); 994 } else if (CFG_IST(ha, CFG_CTRL_2422)) { 995 lptr = (uint32_t *)nv; 996 for (cnt = 0; cnt < nv_size / 4; cnt++) { 997 data32 = *lptr++; 998 LITTLE_ENDIAN_32(&data32); 999 rval = ql_24xx_load_nvram(ha, cnt + start_addr, 1000 data32); 1001 if (rval != QL_SUCCESS) { 1002 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval); 1003 break; 1004 } 1005 } 1006 } else { 1007 wptr = (uint16_t *)nv; 1008 for (cnt = 0; cnt < nv_size / 2; cnt++) { 1009 data = *wptr++; 1010 LITTLE_ENDIAN_16(&data); 1011 ql_load_nvram(ha, (uint8_t)(cnt + start_addr), data); 1012 } 1013 } 1014 1015 kmem_free(nv, nv_size); 1016 ql_release_nvram(ha); 1017 ql_restart_driver(ha); 1018 1019 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1020 1021 if (rval == QL_SUCCESS) { 1022 return (0); 1023 } 1024 1025 return (EFAULT); 1026 } 1027 1028 /* 1029 * ql_nv_util_dump 1030 * Dumps NVRAM to application. 1031 * 1032 * Input: 1033 * ha = adapter state pointer. 1034 * bp = user buffer address. 1035 * 1036 * Returns: 1037 * 1038 * Context: 1039 * Kernel context. 1040 */ 1041 int 1042 ql_nv_util_dump(ql_adapter_state_t *ha, void *bp, int mode) 1043 { 1044 uint32_t cnt, nv_size; 1045 void *nv; 1046 uint32_t start_addr; 1047 int rval2, rval = 0; 1048 1049 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1050 1051 nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_2425) ? 1052 sizeof (nvram_24xx_t) : sizeof (nvram_t)); 1053 1054 if ((nv = kmem_zalloc(nv_size, KM_SLEEP)) == NULL) { 1055 EL(ha, "failed, kmem_zalloc\n"); 1056 return (ENOMEM); 1057 } 1058 1059 /* Quiesce I/O */ 1060 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 1061 EL(ha, "ql_stall_driver failed\n"); 1062 kmem_free(nv, nv_size); 1063 return (EBUSY); 1064 } 1065 1066 if ((rval2 = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA)) != 1067 QL_SUCCESS) { 1068 EL(ha, "failed, ql_lock_nvram=%xh\n", rval2); 1069 kmem_free(nv, nv_size); 1070 ql_restart_driver(ha); 1071 return (EIO); 1072 } 1073 1074 /* Dump NVRAM. */ 1075 if (CFG_IST(ha, CFG_CTRL_2425)) { 1076 1077 uint32_t *lptr = (uint32_t *)nv; 1078 1079 for (cnt = 0; cnt < nv_size / 4; cnt++) { 1080 rval2 = ql_24xx_read_flash(ha, start_addr++, lptr); 1081 if (rval2 != QL_SUCCESS) { 1082 EL(ha, "read_flash failed=%xh\n", rval2); 1083 rval = EAGAIN; 1084 break; 1085 } 1086 1087 LITTLE_ENDIAN_32(lptr); 1088 lptr++; 1089 } 1090 } else { 1091 uint16_t data; 1092 uint16_t *wptr = (uint16_t *)nv; 1093 1094 for (cnt = 0; cnt < nv_size / 2; cnt++) { 1095 data = (uint16_t)ql_get_nvram_word(ha, cnt + 1096 start_addr); 1097 LITTLE_ENDIAN_16(&data); 1098 *wptr++ = data; 1099 } 1100 } 1101 1102 ql_release_nvram(ha); 1103 ql_restart_driver(ha); 1104 1105 if (rval != 0) { 1106 EL(ha, "failed to dump nvram\n"); 1107 kmem_free(nv, nv_size); 1108 return (rval); 1109 } 1110 1111 if (ddi_copyout(nv, bp, nv_size, mode) != 0) { 1112 EL(ha, "Buffer copy failed\n"); 1113 kmem_free(nv, nv_size); 1114 return (EFAULT); 1115 } 1116 1117 kmem_free(nv, nv_size); 1118 1119 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1120 1121 return (0); 1122 } 1123 1124 /* 1125 * ql_vpd_load 1126 * Loads VPD from application. 1127 * 1128 * Input: 1129 * ha = adapter state pointer. 1130 * bp = user buffer address. 1131 * 1132 * Returns: 1133 * 1134 * Context: 1135 * Kernel context. 1136 */ 1137 int 1138 ql_vpd_load(ql_adapter_state_t *ha, void *bp, int mode) 1139 { 1140 uint8_t cnt; 1141 uint8_t *vpd, *vpdptr, *vbuf; 1142 uint32_t start_addr, vpd_size, *lptr, data32; 1143 int rval; 1144 1145 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1146 1147 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 1148 EL(ha, "unsupported adapter feature\n"); 1149 return (ENOTSUP); 1150 } 1151 1152 vpd_size = QL_24XX_VPD_SIZE; 1153 1154 if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) { 1155 EL(ha, "failed, kmem_zalloc\n"); 1156 return (ENOMEM); 1157 } 1158 1159 if (ddi_copyin(bp, vpd, vpd_size, mode) != 0) { 1160 EL(ha, "Buffer copy failed\n"); 1161 kmem_free(vpd, vpd_size); 1162 return (EFAULT); 1163 } 1164 1165 /* Sanity check the user supplied data via checksum */ 1166 if ((vpdptr = ql_vpd_findtag(ha, vpd, "RV")) == NULL) { 1167 EL(ha, "vpd RV tag missing\n"); 1168 kmem_free(vpd, vpd_size); 1169 return (EINVAL); 1170 } 1171 1172 vpdptr += 3; 1173 cnt = 0; 1174 vbuf = vpd; 1175 while (vbuf <= vpdptr) { 1176 cnt += *vbuf++; 1177 } 1178 if (cnt != 0) { 1179 EL(ha, "mismatched checksum, cal=%xh, passed=%xh\n", 1180 (uint8_t)cnt, (uintptr_t)vpdptr); 1181 kmem_free(vpd, vpd_size); 1182 return (EINVAL); 1183 } 1184 1185 /* Quiesce I/O */ 1186 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 1187 EL(ha, "ql_stall_driver failed\n"); 1188 kmem_free(vpd, vpd_size); 1189 return (EBUSY); 1190 } 1191 1192 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA); 1193 if (rval != QL_SUCCESS) { 1194 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 1195 kmem_free(vpd, vpd_size); 1196 ql_restart_driver(ha); 1197 return (EIO); 1198 } 1199 1200 /* Load VPD. */ 1201 if (CFG_IST(ha, CFG_CTRL_25XX)) { 1202 GLOBAL_HW_UNLOCK(); 1203 if ((rval = ql_25xx_load_nv_vpd(ha, vpd, start_addr, 1204 vpd_size)) != QL_SUCCESS) { 1205 EL(ha, "vpd load error: %xh\n", rval); 1206 } 1207 GLOBAL_HW_LOCK(); 1208 } else { 1209 lptr = (uint32_t *)vpd; 1210 for (cnt = 0; cnt < vpd_size / 4; cnt++) { 1211 data32 = *lptr++; 1212 LITTLE_ENDIAN_32(&data32); 1213 rval = ql_24xx_load_nvram(ha, cnt + start_addr, 1214 data32); 1215 if (rval != QL_SUCCESS) { 1216 EL(ha, "failed, 24xx_load_nvram=%xh\n", rval); 1217 break; 1218 } 1219 } 1220 } 1221 1222 kmem_free(vpd, vpd_size); 1223 1224 /* Update the vcache */ 1225 CACHE_LOCK(ha); 1226 1227 if (rval != QL_SUCCESS) { 1228 EL(ha, "failed, load\n"); 1229 } else if ((ha->vcache == NULL) && ((ha->vcache = 1230 kmem_zalloc(vpd_size, KM_SLEEP)) == NULL)) { 1231 EL(ha, "failed, kmem_zalloc2\n"); 1232 } else if (ddi_copyin(bp, ha->vcache, vpd_size, mode) != 0) { 1233 EL(ha, "Buffer copy2 failed\n"); 1234 kmem_free(ha->vcache, vpd_size); 1235 ha->vcache = NULL; 1236 } 1237 1238 CACHE_UNLOCK(ha); 1239 1240 ql_release_nvram(ha); 1241 ql_restart_driver(ha); 1242 1243 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1244 1245 if (rval == QL_SUCCESS) { 1246 return (0); 1247 } 1248 1249 return (EFAULT); 1250 } 1251 1252 /* 1253 * ql_vpd_dump 1254 * Dumps VPD to application buffer. 1255 * 1256 * Input: 1257 * ha = adapter state pointer. 1258 * bp = user buffer address. 1259 * 1260 * Returns: 1261 * 1262 * Context: 1263 * Kernel context. 1264 */ 1265 int 1266 ql_vpd_dump(ql_adapter_state_t *ha, void *bp, int mode) 1267 { 1268 uint8_t cnt; 1269 void *vpd; 1270 uint32_t start_addr, vpd_size, *lptr; 1271 int rval = 0; 1272 1273 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1274 1275 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 1276 EL(ha, "unsupported adapter feature\n"); 1277 return (EACCES); 1278 } 1279 1280 vpd_size = QL_24XX_VPD_SIZE; 1281 1282 CACHE_LOCK(ha); 1283 1284 if (ha->vcache != NULL) { 1285 /* copy back the vpd cache data */ 1286 if (ddi_copyout(ha->vcache, bp, vpd_size, mode) != 0) { 1287 EL(ha, "Buffer copy failed\n"); 1288 rval = EFAULT; 1289 } 1290 CACHE_UNLOCK(ha); 1291 return (rval); 1292 } 1293 1294 if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) { 1295 CACHE_UNLOCK(ha); 1296 EL(ha, "failed, kmem_zalloc\n"); 1297 return (ENOMEM); 1298 } 1299 1300 /* Quiesce I/O */ 1301 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 1302 CACHE_UNLOCK(ha); 1303 EL(ha, "ql_stall_driver failed\n"); 1304 kmem_free(vpd, vpd_size); 1305 return (EBUSY); 1306 } 1307 1308 rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA); 1309 if (rval != QL_SUCCESS) { 1310 CACHE_UNLOCK(ha); 1311 EL(ha, "failed, ql_lock_nvram=%xh\n", rval); 1312 kmem_free(vpd, vpd_size); 1313 ql_restart_driver(ha); 1314 return (EIO); 1315 } 1316 1317 /* Dump VPD. */ 1318 lptr = (uint32_t *)vpd; 1319 1320 for (cnt = 0; cnt < vpd_size / 4; cnt++) { 1321 rval = ql_24xx_read_flash(ha, start_addr++, lptr); 1322 if (rval != QL_SUCCESS) { 1323 EL(ha, "read_flash failed=%xh\n", rval); 1324 rval = EAGAIN; 1325 break; 1326 } 1327 LITTLE_ENDIAN_32(lptr); 1328 lptr++; 1329 } 1330 1331 ql_release_nvram(ha); 1332 ql_restart_driver(ha); 1333 1334 if (ddi_copyout(vpd, bp, vpd_size, mode) != 0) { 1335 CACHE_UNLOCK(ha); 1336 EL(ha, "Buffer copy failed\n"); 1337 kmem_free(vpd, vpd_size); 1338 return (EFAULT); 1339 } 1340 1341 ha->vcache = vpd; 1342 1343 CACHE_UNLOCK(ha); 1344 1345 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1346 1347 if (rval != QL_SUCCESS) { 1348 return (EFAULT); 1349 } else { 1350 return (0); 1351 } 1352 } 1353 1354 /* 1355 * ql_vpd_findtag 1356 * Search the passed vpd buffer for the requested VPD tag type. 1357 * 1358 * Input: 1359 * ha = adapter state pointer. 1360 * vpdbuf = Pointer to start of the buffer to search 1361 * op = VPD opcode to find (must be NULL terminated). 1362 * 1363 * Returns: 1364 * Pointer to the opcode in the buffer if opcode found. 1365 * NULL if opcode is not found. 1366 * 1367 * Context: 1368 * Kernel context. 1369 */ 1370 static uint8_t * 1371 ql_vpd_findtag(ql_adapter_state_t *ha, uint8_t *vpdbuf, int8_t *opcode) 1372 { 1373 uint8_t *vpd = vpdbuf; 1374 uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE; 1375 uint32_t found = 0; 1376 1377 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1378 1379 if (vpdbuf == NULL || opcode == NULL) { 1380 EL(ha, "null parameter passed!\n"); 1381 return (NULL); 1382 } 1383 1384 while (vpd < end) { 1385 1386 /* check for end of vpd */ 1387 if (vpd[0] == VPD_TAG_END) { 1388 if (opcode[0] == VPD_TAG_END) { 1389 found = 1; 1390 } else { 1391 found = 0; 1392 } 1393 break; 1394 } 1395 1396 /* check opcode */ 1397 if (bcmp(opcode, vpd, strlen(opcode)) == 0) { 1398 /* found opcode requested */ 1399 found = 1; 1400 break; 1401 } 1402 1403 /* 1404 * Didn't find the opcode, so calculate start of 1405 * next tag. Depending on the current tag type, 1406 * the length field can be 1 or 2 bytes 1407 */ 1408 if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) { 1409 vpd += (vpd[2] << 8) + vpd[1] + 3; 1410 } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) { 1411 vpd += 3; 1412 } else { 1413 vpd += vpd[2] +3; 1414 } 1415 } 1416 1417 QL_PRINT_9(CE_CONT, "(%d): exiting\n", ha->instance); 1418 1419 return (found == 1 ? vpd : NULL); 1420 } 1421 1422 /* 1423 * ql_vpd_lookup 1424 * Return the VPD data for the request VPD tag 1425 * 1426 * Input: 1427 * ha = adapter state pointer. 1428 * opcode = VPD opcode to find (must be NULL terminated). 1429 * bp = Pointer to returned data buffer. 1430 * bplen = Length of returned data buffer. 1431 * 1432 * Returns: 1433 * Length of data copied into returned data buffer. 1434 * >0 = VPD data field (NULL terminated) 1435 * 0 = no data. 1436 * -1 = Could not find opcode in vpd buffer / error. 1437 * 1438 * Context: 1439 * Kernel context. 1440 * 1441 * NB: The opcode buffer and the bp buffer *could* be the same buffer! 1442 * 1443 */ 1444 int32_t 1445 ql_vpd_lookup(ql_adapter_state_t *ha, uint8_t *opcode, uint8_t *bp, 1446 int32_t bplen) 1447 { 1448 uint8_t *vpd; 1449 uint8_t *vpdbuf; 1450 int32_t len = -1; 1451 1452 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1453 1454 if (opcode == NULL || bp == NULL || bplen < 1) { 1455 EL(ha, "invalid parameter passed: opcode=%ph, " 1456 "bp=%ph, bplen=%xh\n", opcode, bp, bplen); 1457 return (len); 1458 } 1459 1460 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 1461 return (len); 1462 } 1463 1464 if ((vpdbuf = (uint8_t *)kmem_zalloc(QL_24XX_VPD_SIZE, 1465 KM_SLEEP)) == NULL) { 1466 EL(ha, "unable to allocate vpd memory\n"); 1467 return (len); 1468 } 1469 1470 if ((ql_vpd_dump(ha, vpdbuf, (int)FKIOCTL)) != 0) { 1471 kmem_free(vpdbuf, QL_24XX_VPD_SIZE); 1472 EL(ha, "unable to retrieve VPD data\n"); 1473 return (len); 1474 } 1475 1476 if ((vpd = ql_vpd_findtag(ha, vpdbuf, (int8_t *)opcode)) != NULL) { 1477 /* 1478 * Found the tag 1479 */ 1480 if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT || 1481 *opcode == VPD_TAG_LRTC) { 1482 /* 1483 * we found it, but the tag doesn't have a data 1484 * field. 1485 */ 1486 len = 0; 1487 } else if (!(strncmp((char *)vpd, (char *) 1488 VPD_TAG_PRODID, 1))) { 1489 len = vpd[2] << 8; 1490 len += vpd[1]; 1491 } else { 1492 len = vpd[2]; 1493 } 1494 1495 /* 1496 * make sure that the vpd len doesn't exceed the 1497 * vpd end 1498 */ 1499 if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) { 1500 EL(ha, "vpd tag len (%xh) exceeds vpd buffer " 1501 "length\n", len); 1502 len = -1; 1503 } 1504 } 1505 1506 if (len >= 0) { 1507 /* 1508 * make sure we don't exceed callers buffer space len 1509 */ 1510 if (len > bplen) { 1511 len = bplen-1; 1512 } 1513 1514 /* copy the data back */ 1515 (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len); 1516 bp[len] = NULL; 1517 } else { 1518 /* error -- couldn't find tag */ 1519 bp[0] = NULL; 1520 if (opcode[1] != NULL) { 1521 EL(ha, "unable to find tag '%s'\n", opcode); 1522 } else { 1523 EL(ha, "unable to find tag '%xh'\n", opcode[0]); 1524 } 1525 } 1526 1527 kmem_free(vpdbuf, QL_24XX_VPD_SIZE); 1528 1529 QL_PRINT_9(CE_CONT, "(%d): exiting\n", ha->instance); 1530 1531 return (len); 1532 } 1533 1534 static int 1535 ql_25xx_load_nv_vpd(ql_adapter_state_t *ha, uint8_t *buf, uint32_t faddr, 1536 uint32_t bufsize) 1537 { 1538 uint8_t *bp; 1539 int rval; 1540 uint32_t bsize = 0x10000; 1541 uint32_t saddr, ofst; 1542 1543 if ((bp = kmem_zalloc(bsize, KM_SLEEP)) == NULL) { 1544 EL(ha, "failed kmem_zalloc\n"); 1545 return (ENOMEM); 1546 } 1547 1548 saddr = ((faddr & 0xff000) << 2) & 0xffff0000; 1549 ofst = (faddr & 0xfff) << 2; 1550 1551 /* Dump Flash sector. */ 1552 if ((rval = ql_dump_fcode(ha, bp, bsize, saddr)) == QL_SUCCESS) { 1553 /* Set new data. */ 1554 bcopy(buf, bp + ofst, bufsize); 1555 1556 /* Write to flash. */ 1557 (void) ql_24xx_load_flash(ha, bp, bsize, saddr); 1558 } else { 1559 EL(ha, "failed dump_fcode=%x\n", rval); 1560 } 1561 1562 kmem_free(bp, bsize); 1563 1564 return (rval); 1565 } 1566 1567 /* 1568 * ql_adm_op 1569 * Performs qladm utility operations 1570 * 1571 * Input: 1572 * ha: adapter state pointer. 1573 * arg: driver_op_t structure pointer. 1574 * mode: flags. 1575 * 1576 * Returns: 1577 * 1578 * Context: 1579 * Kernel context. 1580 */ 1581 static int 1582 ql_adm_op(ql_adapter_state_t *ha, void *arg, int mode) 1583 { 1584 ql_adm_op_t dop; 1585 int rval = 0; 1586 1587 if (ddi_copyin(arg, &dop, sizeof (ql_adm_op_t), mode) != 0) { 1588 EL(ha, "failed, driver_op_t ddi_copyin\n"); 1589 return (EFAULT); 1590 } 1591 1592 QL_PRINT_9(CE_CONT, "(%d): entered, cmd=%xh, buffer=%llx," 1593 " length=%xh, option=%xh\n", ha->instance, dop.cmd, dop.buffer, 1594 dop.length, dop.option); 1595 1596 switch (dop.cmd) { 1597 case QL_ADAPTER_INFO: 1598 rval = ql_adm_adapter_info(ha, &dop, mode); 1599 break; 1600 1601 case QL_EXTENDED_LOGGING: 1602 rval = ql_adm_extended_logging(ha, &dop); 1603 break; 1604 1605 case QL_LOOP_RESET: 1606 rval = ql_adm_loop_reset(ha); 1607 break; 1608 1609 case QL_DEVICE_LIST: 1610 rval = ql_adm_device_list(ha, &dop, mode); 1611 break; 1612 1613 case QL_PROP_UPDATE_INT: 1614 rval = ql_adm_prop_update_int(ha, &dop, mode); 1615 break; 1616 1617 case QL_UPDATE_PROPERTIES: 1618 rval = ql_adm_update_properties(ha); 1619 break; 1620 1621 case QL_FW_DUMP: 1622 rval = ql_adm_fw_dump(ha, &dop, arg, mode); 1623 break; 1624 1625 case QL_NVRAM_LOAD: 1626 rval = ql_adm_nvram_load(ha, &dop, mode); 1627 break; 1628 1629 case QL_NVRAM_DUMP: 1630 rval = ql_adm_nvram_dump(ha, &dop, mode); 1631 break; 1632 1633 case QL_FLASH_LOAD: 1634 rval = ql_adm_flash_load(ha, &dop, mode); 1635 break; 1636 1637 case QL_VPD_LOAD: 1638 rval = ql_adm_vpd_load(ha, &dop, mode); 1639 break; 1640 1641 case QL_VPD_DUMP: 1642 rval = ql_adm_vpd_dump(ha, &dop, mode); 1643 break; 1644 1645 case QL_VPD_GETTAG: 1646 rval = ql_adm_vpd_gettag(ha, &dop, mode); 1647 break; 1648 1649 case QL_UPD_FWMODULE: 1650 rval = ql_adm_updfwmodule(ha, &dop, mode); 1651 break; 1652 1653 default: 1654 EL(ha, "unsupported driver op cmd: %x\n", dop.cmd); 1655 return (EINVAL); 1656 } 1657 1658 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1659 1660 return (rval); 1661 } 1662 1663 /* 1664 * ql_adm_adapter_info 1665 * Performs qladm QL_ADAPTER_INFO command 1666 * 1667 * Input: 1668 * ha: adapter state pointer. 1669 * dop: ql_adm_op_t structure pointer. 1670 * mode: flags. 1671 * 1672 * Returns: 1673 * 1674 * Context: 1675 * Kernel context. 1676 */ 1677 static int 1678 ql_adm_adapter_info(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 1679 { 1680 ql_adapter_info_t hba; 1681 uint8_t *dp; 1682 uint32_t length; 1683 int rval, i; 1684 1685 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1686 1687 hba.device_id = ha->device_id; 1688 1689 dp = CFG_IST(ha, CFG_CTRL_2425) ? 1690 &ha->init_ctrl_blk.cb24.port_name[0] : 1691 &ha->init_ctrl_blk.cb.port_name[0]; 1692 bcopy(dp, hba.wwpn, 8); 1693 1694 hba.d_id = ha->d_id.b24; 1695 1696 if (ha->xioctl->fdesc.flash_size == 0 && 1697 !(CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id)) { 1698 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 1699 EL(ha, "ql_stall_driver failed\n"); 1700 return (EBUSY); 1701 } 1702 1703 if ((rval = ql_setup_flash(ha)) != QL_SUCCESS) { 1704 EL(ha, "ql_setup_flash failed=%xh\n", rval); 1705 if (rval == QL_FUNCTION_TIMEOUT) { 1706 return (EBUSY); 1707 } 1708 return (EIO); 1709 } 1710 1711 /* Resume I/O */ 1712 if (CFG_IST(ha, CFG_CTRL_2425)) { 1713 ql_restart_driver(ha); 1714 } else { 1715 EL(ha, "isp_abort_needed for restart\n"); 1716 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 1717 DRIVER_STALL); 1718 } 1719 } 1720 hba.flash_size = ha->xioctl->fdesc.flash_size; 1721 1722 (void) strcpy(hba.driver_ver, QL_VERSION); 1723 1724 (void) sprintf(hba.fw_ver, "%d.%d.%d", ha->fw_major_version, 1725 ha->fw_minor_version, ha->fw_subminor_version); 1726 1727 bzero(hba.fcode_ver, sizeof (hba.fcode_ver)); 1728 1729 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 1730 rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip, 1731 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&dp, 1732 &i); 1733 length = i; 1734 if (rval != DDI_PROP_SUCCESS) { 1735 EL(ha, "failed, ddi_getlongprop=%xh\n", rval); 1736 } else { 1737 if (length > (uint32_t)sizeof (hba.fcode_ver)) { 1738 length = sizeof (hba.fcode_ver) - 1; 1739 } 1740 bcopy((void *)dp, (void *)hba.fcode_ver, length); 1741 kmem_free(dp, length); 1742 } 1743 1744 if (ddi_copyout((void *)&hba, (void *)(uintptr_t)dop->buffer, 1745 dop->length, mode) 1746 != 0) { 1747 EL(ha, "failed, ddi_copyout\n"); 1748 return (EFAULT); 1749 } 1750 1751 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1752 1753 return (0); 1754 } 1755 1756 /* 1757 * ql_adm_extended_logging 1758 * Performs qladm QL_EXTENDED_LOGGING command 1759 * 1760 * Input: 1761 * ha: adapter state pointer. 1762 * dop: ql_adm_op_t structure pointer. 1763 * 1764 * Returns: 1765 * 1766 * Context: 1767 * Kernel context. 1768 */ 1769 static int 1770 ql_adm_extended_logging(ql_adapter_state_t *ha, ql_adm_op_t *dop) 1771 { 1772 char prop_name[MAX_PROP_LENGTH]; 1773 int rval; 1774 1775 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1776 1777 (void) sprintf(prop_name, "hba%d-extended-logging", ha->instance); 1778 1779 /*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/ 1780 rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name, 1781 (int)dop->option); 1782 if (rval != DDI_PROP_SUCCESS) { 1783 EL(ha, "failed, prop_update = %xh\n", rval); 1784 return (EINVAL); 1785 } else { 1786 dop->option ? 1787 (ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING) : 1788 (ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING); 1789 } 1790 1791 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1792 1793 return (0); 1794 } 1795 1796 /* 1797 * ql_adm_loop_reset 1798 * Performs qladm QL_LOOP_RESET command 1799 * 1800 * Input: 1801 * ha: adapter state pointer. 1802 * 1803 * Returns: 1804 * 1805 * Context: 1806 * Kernel context. 1807 */ 1808 static int 1809 ql_adm_loop_reset(ql_adapter_state_t *ha) 1810 { 1811 int rval; 1812 1813 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1814 1815 if (ha->task_daemon_flags & LOOP_DOWN) { 1816 (void) ql_full_login_lip(ha); 1817 } else if ((rval = ql_full_login_lip(ha)) != QL_SUCCESS) { 1818 EL(ha, "failed, ql_initiate_lip=%xh\n", rval); 1819 return (EIO); 1820 } 1821 1822 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1823 1824 return (0); 1825 } 1826 1827 /* 1828 * ql_adm_device_list 1829 * Performs qladm QL_DEVICE_LIST command 1830 * 1831 * Input: 1832 * ha: adapter state pointer. 1833 * dop: ql_adm_op_t structure pointer. 1834 * mode: flags. 1835 * 1836 * Returns: 1837 * 1838 * Context: 1839 * Kernel context. 1840 */ 1841 static int 1842 ql_adm_device_list(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 1843 { 1844 ql_device_info_t dev; 1845 ql_link_t *link; 1846 ql_tgt_t *tq; 1847 uint32_t index, cnt; 1848 1849 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1850 1851 cnt = 0; 1852 dev.address = 0xffffffff; 1853 1854 /* Scan port list for requested target and fill in the values */ 1855 for (link = NULL, index = 0; 1856 index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) { 1857 for (link = ha->dev[index].first; link != NULL; 1858 link = link->next) { 1859 tq = link->base_address; 1860 1861 if (!VALID_TARGET_ID(ha, tq->loop_id)) { 1862 continue; 1863 } 1864 if (cnt != dop->option) { 1865 cnt++; 1866 continue; 1867 } 1868 /* fill in the values */ 1869 bcopy(tq->port_name, dev.wwpn, 8); 1870 dev.address = tq->d_id.b24; 1871 dev.loop_id = tq->loop_id; 1872 if (tq->flags & TQF_TAPE_DEVICE) { 1873 dev.type = FCT_TAPE; 1874 } else if (tq->flags & TQF_INITIATOR_DEVICE) { 1875 dev.type = FCT_INITIATOR; 1876 } else { 1877 dev.type = FCT_TARGET; 1878 } 1879 break; 1880 } 1881 } 1882 1883 if (ddi_copyout((void *)&dev, (void *)(uintptr_t)dop->buffer, 1884 dop->length, mode) 1885 != 0) { 1886 EL(ha, "failed, ddi_copyout\n"); 1887 return (EFAULT); 1888 } 1889 1890 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1891 1892 return (0); 1893 } 1894 1895 /* 1896 * ql_adm_update_properties 1897 * Performs qladm QL_UPDATE_PROPERTIES command 1898 * 1899 * Input: 1900 * ha: adapter state pointer. 1901 * 1902 * Returns: 1903 * 1904 * Context: 1905 * Kernel context. 1906 */ 1907 static int 1908 ql_adm_update_properties(ql_adapter_state_t *ha) 1909 { 1910 ql_comb_init_cb_t init_ctrl_blk; 1911 ql_comb_ip_init_cb_t ip_init_ctrl_blk; 1912 1913 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1914 1915 /* Stall driver instance. */ 1916 (void) ql_stall_driver(ha, 0); 1917 1918 /* Save init control blocks. */ 1919 bcopy(&ha->init_ctrl_blk, &init_ctrl_blk, sizeof (ql_comb_init_cb_t)); 1920 bcopy(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk, 1921 sizeof (ql_comb_ip_init_cb_t)); 1922 1923 /* Update PCI configration. */ 1924 (void) ql_pci_sbus_config(ha); 1925 1926 /* Get configuration properties. */ 1927 (void) ql_nvram_config(ha); 1928 1929 /* Check for init firmware required. */ 1930 if (bcmp(&ha->init_ctrl_blk, &init_ctrl_blk, 1931 sizeof (ql_comb_init_cb_t)) != 0 || 1932 bcmp(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk, 1933 sizeof (ql_comb_ip_init_cb_t)) != 0) { 1934 1935 EL(ha, "isp_abort_needed\n"); 1936 ha->loop_down_timer = LOOP_DOWN_TIMER_START; 1937 TASK_DAEMON_LOCK(ha); 1938 ha->task_daemon_flags |= LOOP_DOWN | ISP_ABORT_NEEDED; 1939 TASK_DAEMON_UNLOCK(ha); 1940 } 1941 1942 /* Update AEN queue. */ 1943 if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1944 ql_enqueue_aen(ha, MBA_PORT_UPDATE, NULL); 1945 } 1946 1947 /* Restart driver instance. */ 1948 ql_restart_driver(ha); 1949 1950 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 1951 1952 return (0); 1953 } 1954 1955 /* 1956 * ql_adm_prop_update_int 1957 * Performs qladm QL_PROP_UPDATE_INT command 1958 * 1959 * Input: 1960 * ha: adapter state pointer. 1961 * dop: ql_adm_op_t structure pointer. 1962 * mode: flags. 1963 * 1964 * Returns: 1965 * 1966 * Context: 1967 * Kernel context. 1968 */ 1969 static int 1970 ql_adm_prop_update_int(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 1971 { 1972 char *prop_name; 1973 int rval; 1974 1975 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 1976 1977 prop_name = kmem_zalloc(dop->length, KM_SLEEP); 1978 if (prop_name == NULL) { 1979 EL(ha, "failed, kmem_zalloc\n"); 1980 return (ENOMEM); 1981 } 1982 1983 if (ddi_copyin((void *)(uintptr_t)dop->buffer, prop_name, dop->length, 1984 mode) != 0) { 1985 EL(ha, "failed, prop_name ddi_copyin\n"); 1986 kmem_free(prop_name, dop->length); 1987 return (EFAULT); 1988 } 1989 1990 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/ 1991 if ((rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name, 1992 (int)dop->option)) != DDI_PROP_SUCCESS) { 1993 EL(ha, "failed, prop_update=%xh\n", rval); 1994 kmem_free(prop_name, dop->length); 1995 return (EINVAL); 1996 } 1997 1998 kmem_free(prop_name, dop->length); 1999 2000 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2001 2002 return (0); 2003 } 2004 2005 /* 2006 * ql_adm_fw_dump 2007 * Performs qladm QL_FW_DUMP command 2008 * 2009 * Input: 2010 * ha: adapter state pointer. 2011 * dop: ql_adm_op_t structure pointer. 2012 * udop: user space ql_adm_op_t structure pointer. 2013 * mode: flags. 2014 * 2015 * Returns: 2016 * 2017 * Context: 2018 * Kernel context. 2019 */ 2020 static int 2021 ql_adm_fw_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, void *udop, int mode) 2022 { 2023 caddr_t dmp; 2024 2025 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2026 2027 if (dop->length < ha->risc_dump_size) { 2028 EL(ha, "failed, incorrect length=%xh, size=%xh\n", 2029 dop->length, ha->risc_dump_size); 2030 return (EINVAL); 2031 } 2032 2033 if (ql_dump_state & QL_DUMP_VALID) { 2034 dmp = kmem_zalloc(ha->risc_dump_size, KM_SLEEP); 2035 if (dmp == NULL) { 2036 EL(ha, "failed, kmem_zalloc\n"); 2037 return (ENOMEM); 2038 } 2039 2040 dop->length = (uint32_t)ql_ascii_fw_dump(ha, dmp); 2041 if (ddi_copyout((void *)dmp, (void *)(uintptr_t)dop->buffer, 2042 dop->length, mode) != 0) { 2043 EL(ha, "failed, ddi_copyout\n"); 2044 kmem_free(dmp, ha->risc_dump_size); 2045 return (EFAULT); 2046 } 2047 2048 kmem_free(dmp, ha->risc_dump_size); 2049 ql_dump_state |= QL_DUMP_UPLOADED; 2050 2051 } else { 2052 EL(ha, "failed, no dump file\n"); 2053 dop->length = 0; 2054 } 2055 2056 if (ddi_copyout(dop, udop, sizeof (ql_adm_op_t), mode) != 0) { 2057 EL(ha, "failed, driver_op_t ddi_copyout\n"); 2058 return (EFAULT); 2059 } 2060 2061 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2062 2063 return (0); 2064 } 2065 2066 /* 2067 * ql_adm_nvram_dump 2068 * Performs qladm QL_NVRAM_DUMP command 2069 * 2070 * Input: 2071 * ha: adapter state pointer. 2072 * dop: ql_adm_op_t structure pointer. 2073 * mode: flags. 2074 * 2075 * Returns: 2076 * 2077 * Context: 2078 * Kernel context. 2079 */ 2080 static int 2081 ql_adm_nvram_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2082 { 2083 uint32_t nv_size; 2084 int rval; 2085 2086 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2087 2088 nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_2425) ? 2089 sizeof (nvram_24xx_t) : sizeof (nvram_t)); 2090 2091 if (dop->length < nv_size) { 2092 EL(ha, "failed, length=%xh, size=%xh\n", dop->length, nv_size); 2093 return (EINVAL); 2094 } 2095 2096 if ((rval = ql_nv_util_dump(ha, (void *)(uintptr_t)dop->buffer, 2097 mode)) != 0) { 2098 EL(ha, "failed, ql_nv_util_dump\n"); 2099 } else { 2100 /*EMPTY*/ 2101 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2102 } 2103 2104 return (rval); 2105 } 2106 2107 /* 2108 * ql_adm_nvram_load 2109 * Performs qladm QL_NVRAM_LOAD command 2110 * 2111 * Input: 2112 * ha: adapter state pointer. 2113 * dop: ql_adm_op_t structure pointer. 2114 * mode: flags. 2115 * 2116 * Returns: 2117 * 2118 * Context: 2119 * Kernel context. 2120 */ 2121 static int 2122 ql_adm_nvram_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2123 { 2124 uint32_t nv_size; 2125 int rval; 2126 2127 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2128 2129 nv_size = (uint32_t)(CFG_IST(ha, CFG_CTRL_2425) ? 2130 sizeof (nvram_24xx_t) : sizeof (nvram_t)); 2131 2132 if (dop->length < nv_size) { 2133 EL(ha, "failed, length=%xh, size=%xh\n", dop->length, nv_size); 2134 return (EINVAL); 2135 } 2136 2137 if ((rval = ql_nv_util_load(ha, (void *)(uintptr_t)dop->buffer, 2138 mode)) != 0) { 2139 EL(ha, "failed, ql_nv_util_dump\n"); 2140 } else { 2141 /*EMPTY*/ 2142 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2143 } 2144 2145 return (rval); 2146 } 2147 2148 /* 2149 * ql_adm_flash_load 2150 * Performs qladm QL_FLASH_LOAD command 2151 * 2152 * Input: 2153 * ha: adapter state pointer. 2154 * dop: ql_adm_op_t structure pointer. 2155 * mode: flags. 2156 * 2157 * Returns: 2158 * 2159 * Context: 2160 * Kernel context. 2161 */ 2162 static int 2163 ql_adm_flash_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2164 { 2165 uint8_t *dp; 2166 int rval; 2167 2168 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2169 2170 if ((dp = kmem_zalloc(dop->length, KM_SLEEP)) == NULL) { 2171 EL(ha, "failed, kmem_zalloc\n"); 2172 return (ENOMEM); 2173 } 2174 2175 if (ddi_copyin((void *)(uintptr_t)dop->buffer, dp, dop->length, 2176 mode) != 0) { 2177 EL(ha, "ddi_copyin failed\n"); 2178 kmem_free(dp, dop->length); 2179 return (EFAULT); 2180 } 2181 2182 if (ql_stall_driver(ha, 0) != QL_SUCCESS) { 2183 EL(ha, "ql_stall_driver failed\n"); 2184 kmem_free(dp, dop->length); 2185 return (EBUSY); 2186 } 2187 2188 rval = (CFG_IST(ha, CFG_CTRL_2425) ? 2189 ql_24xx_load_flash(ha, dp, dop->length, dop->option) : 2190 ql_load_flash(ha, dp, dop->length)); 2191 2192 ql_restart_driver(ha); 2193 2194 kmem_free(dp, dop->length); 2195 2196 if (rval != QL_SUCCESS) { 2197 EL(ha, "failed\n"); 2198 return (EIO); 2199 } 2200 2201 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2202 2203 return (0); 2204 } 2205 2206 /* 2207 * ql_adm_vpd_dump 2208 * Performs qladm QL_VPD_DUMP command 2209 * 2210 * Input: 2211 * ha: adapter state pointer. 2212 * dop: ql_adm_op_t structure pointer. 2213 * mode: flags. 2214 * 2215 * Returns: 2216 * 2217 * Context: 2218 * Kernel context. 2219 */ 2220 static int 2221 ql_adm_vpd_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2222 { 2223 int rval; 2224 2225 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2226 2227 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 2228 EL(ha, "hba does not support VPD\n"); 2229 return (EINVAL); 2230 } 2231 2232 if (dop->length < QL_24XX_VPD_SIZE) { 2233 EL(ha, "failed, length=%xh, size=%xh\n", dop->length, 2234 QL_24XX_VPD_SIZE); 2235 return (EINVAL); 2236 } 2237 2238 if ((rval = ql_vpd_dump(ha, (void *)(uintptr_t)dop->buffer, 2239 mode)) != 0) { 2240 EL(ha, "failed, ql_vpd_dump\n"); 2241 } else { 2242 /*EMPTY*/ 2243 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2244 } 2245 2246 return (rval); 2247 } 2248 2249 /* 2250 * ql_adm_vpd_load 2251 * Performs qladm QL_VPD_LOAD command 2252 * 2253 * Input: 2254 * ha: adapter state pointer. 2255 * dop: ql_adm_op_t structure pointer. 2256 * mode: flags. 2257 * 2258 * Returns: 2259 * 2260 * Context: 2261 * Kernel context. 2262 */ 2263 static int 2264 ql_adm_vpd_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2265 { 2266 int rval; 2267 2268 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2269 2270 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 2271 EL(ha, "hba does not support VPD\n"); 2272 return (EINVAL); 2273 } 2274 2275 if (dop->length < QL_24XX_VPD_SIZE) { 2276 EL(ha, "failed, length=%xh, size=%xh\n", dop->length, 2277 QL_24XX_VPD_SIZE); 2278 return (EINVAL); 2279 } 2280 2281 if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)dop->buffer, 2282 mode)) != 0) { 2283 EL(ha, "failed, ql_vpd_dump\n"); 2284 } else { 2285 /*EMPTY*/ 2286 QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance); 2287 } 2288 2289 return (rval); 2290 } 2291 2292 /* 2293 * ql_adm_vpd_gettag 2294 * Performs qladm QL_VPD_GETTAG command 2295 * 2296 * Input: 2297 * ha: adapter state pointer. 2298 * dop: ql_adm_op_t structure pointer. 2299 * mode: flags. 2300 * 2301 * Returns: 2302 * 2303 * Context: 2304 * Kernel context. 2305 */ 2306 static int 2307 ql_adm_vpd_gettag(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2308 { 2309 int rval = 0; 2310 uint8_t *lbuf; 2311 2312 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2313 2314 if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 2315 EL(ha, "hba does not support VPD\n"); 2316 return (EINVAL); 2317 } 2318 2319 if ((lbuf = (uint8_t *)kmem_zalloc(dop->length, KM_SLEEP)) == NULL) { 2320 EL(ha, "mem alloc failure of %xh bytes\n", dop->length); 2321 rval = EFAULT; 2322 } else { 2323 if (ddi_copyin((void *)(uintptr_t)dop->buffer, lbuf, 2324 dop->length, mode) != 0) { 2325 EL(ha, "ddi_copyin failed\n"); 2326 kmem_free(lbuf, dop->length); 2327 return (EFAULT); 2328 } 2329 2330 if ((rval = ql_vpd_lookup(ha, lbuf, lbuf, (int32_t) 2331 dop->length)) < 0) { 2332 EL(ha, "failed vpd_lookup\n"); 2333 } else { 2334 if (ddi_copyout(lbuf, (void *)(uintptr_t)dop->buffer, 2335 strlen((int8_t *)lbuf)+1, mode) != 0) { 2336 EL(ha, "failed, ddi_copyout\n"); 2337 rval = EFAULT; 2338 } else { 2339 rval = 0; 2340 } 2341 } 2342 kmem_free(lbuf, dop->length); 2343 } 2344 2345 QL_PRINT_9(CE_CONT, "(%d): exiting\n", ha->instance); 2346 2347 return (rval); 2348 } 2349 2350 /* 2351 * ql_adm_updfwmodule 2352 * Performs qladm QL_UPD_FWMODULE command 2353 * 2354 * Input: 2355 * ha: adapter state pointer. 2356 * dop: ql_adm_op_t structure pointer. 2357 * mode: flags. 2358 * 2359 * Returns: 2360 * 2361 * Context: 2362 * Kernel context. 2363 */ 2364 /* ARGSUSED */ 2365 static int 2366 ql_adm_updfwmodule(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode) 2367 { 2368 int rval = DDI_SUCCESS; 2369 ql_link_t *link; 2370 ql_adapter_state_t *ha2 = NULL; 2371 uint16_t fw_class = (uint16_t)dop->option; 2372 2373 QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance); 2374 2375 /* zero the firmware module reference count */ 2376 for (link = ql_hba.first; link != NULL; link = link->next) { 2377 ha2 = link->base_address; 2378 if (fw_class == ha2->fw_class) { 2379 if ((rval = ddi_modclose(ha2->fw_module)) != 2380 DDI_SUCCESS) { 2381 EL(ha2, "modclose rval=%xh\n", rval); 2382 break; 2383 } 2384 ha2->fw_module = NULL; 2385 } 2386 } 2387 2388 /* reload the f/w modules */ 2389 for (link = ql_hba.first; link != NULL; link = link->next) { 2390 ha2 = link->base_address; 2391 2392 if ((fw_class == ha2->fw_class) && (ha2->fw_class == NULL)) { 2393 if ((rval = (int32_t)ql_fwmodule_resolve(ha2)) != 2394 QL_SUCCESS) { 2395 EL(ha2, "unable to load f/w module: '%x' " 2396 "(rval=%xh)\n", ha2->fw_class, rval); 2397 rval = EFAULT; 2398 } else { 2399 EL(ha2, "f/w module updated: '%x'\n", 2400 ha2->fw_class); 2401 } 2402 2403 EL(ha2, "isp abort needed (%d)\n", ha->instance); 2404 2405 ql_awaken_task_daemon(ha2, NULL, ISP_ABORT_NEEDED, 0); 2406 2407 rval = 0; 2408 } 2409 } 2410 2411 QL_PRINT_9(CE_CONT, "(%d): exiting\n", ha->instance); 2412 2413 return (rval); 2414 } 2415