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