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