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 /* 23 * Copyright 2009 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 #include <emlxs.h> 28 29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 30 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C); 31 32 #define MAX_BOOTID 10 33 34 #define DATA32_SWAP(x) ((((x) & 0xFF)<<24) | (((x) & 0xFF00)<<8) | \ 35 (((x) & 0xFF0000)>>8) | \ 36 (((x) & 0xFF000000)>>24)) 37 38 static uint32_t emlxs_erase_fcode_flash(emlxs_hba_t *hba); 39 static uint32_t emlxs_write_fcode_flash(emlxs_hba_t *hba, 40 PIMAGE_HDR ImageHdr, caddr_t Buffer); 41 42 static int32_t emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms, 43 uint32_t BufferSize, PAIF_HDR AifHeader, 44 int32_t DwcFile); 45 46 static uint32_t emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, 47 uint32_t Size, emlxs_fw_image_t *fw_image); 48 49 static void emlxs_format_dump(MAILBOX *mb, uint32_t Type, uint32_t RegionId, 50 uint32_t WordCount, uint32_t BaseAddr); 51 52 static uint32_t emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr, 53 caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms, 54 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize, 55 PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile); 56 57 static uint32_t emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, 58 uint32_t len, uint32_t offline, 59 emlxs_fw_image_t *fw_image); 60 61 static uint32_t emlxs_proc_abs_2mb(emlxs_hba_t *hba, PAIF_HDR AifHdr, 62 caddr_t EntireBuffer, uint32_t FileType, 63 uint32_t BWCflag, uint32_t extType); 64 65 static void emlxs_format_load_area_cmd(MAILBOX *mb, uint32_t Base, 66 uint32_t DlByteCount, uint32_t Function, 67 uint32_t Complete, uint32_t DataOffset, uint32_t AreaId, 68 uint8_t MbxCmd, uint32_t StepCmd); 69 70 static uint32_t emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr, 71 uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms); 72 73 static uint32_t emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, caddr_t Buffer, 74 uint32_t BufferSize, PAIF_HDR AifHeader, 75 PWAKE_UP_PARMS AbsWakeUpParms, uint32_t BWCflag, 76 uint32_t extType, uint32_t *numBootImage); 77 78 static uint32_t emlxs_update_exp_rom(emlxs_hba_t *hba, 79 PWAKE_UP_PARMS WakeUpParms); 80 81 extern uint32_t emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize, 82 uint32_t *MaxIbusSize); 83 84 static void emlxs_format_prog_flash(MAILBOX *mb, uint32_t Base, 85 uint32_t DlByteCount, uint32_t Function, 86 uint32_t Complete, uint32_t BdeAddress, 87 uint32_t BdeSize, PROG_ID *ProgId); 88 89 static void emlxs_format_update_parms(MAILBOX *mb, 90 PWAKE_UP_PARMS WakeUpParms); 91 92 static void emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOX *mb, 93 uint32_t region_id, uint32_t size); 94 95 static uint32_t emlxs_update_wakeup_parms(emlxs_hba_t *hba, 96 PWAKE_UP_PARMS AbsWakeUpParms, 97 PWAKE_UP_PARMS WakeUpParms); 98 99 static uint32_t emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, 100 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id, 101 uint32_t proc_erom); 102 103 static uint32_t emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, 104 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 105 106 static uint32_t emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, 107 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 108 109 static uint32_t emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, 110 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 111 112 static uint32_t emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, 113 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 114 115 static uint32_t emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, 116 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 117 118 119 static uint32_t emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr, 120 caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms, 121 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize); 122 123 static uint32_t emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList); 124 125 static uint32_t emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr); 126 static void emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr); 127 static void emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image); 128 static uint32_t emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize); 129 130 static uint32_t emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer, 131 uint32_t BufferSize, PAIF_HDR AifHeader); 132 133 static uint32_t emlxs_type_check(uint32_t type); 134 static uint32_t emlxs_kern_check(emlxs_hba_t *hba, uint32_t version); 135 static uint32_t emlxs_stub_check(emlxs_hba_t *hba, uint32_t version); 136 static uint32_t emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version); 137 static uint32_t emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version); 138 static uint32_t emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version); 139 static uint32_t emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version); 140 static uint32_t emlxs_bios_check(emlxs_hba_t *hba, uint32_t version); 141 static uint32_t emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version); 142 static uint32_t emlxs_validate_version(emlxs_hba_t *hba, 143 emlxs_fw_file_t *file, uint32_t id, uint32_t type, 144 char *file_type); 145 146 /* ************************************************************************* */ 147 148 149 extern int32_t 150 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, 151 uint32_t offline) 152 { 153 emlxs_port_t *port = &PPORT; 154 uint32_t *Uptr; 155 IMAGE_HDR ImageHdr; 156 AIF_HDR AifHdr; 157 uint32_t ImageType; 158 WAKE_UP_PARMS WakeUpParms; 159 WAKE_UP_PARMS AbsWakeUpParms; 160 uint32_t MaxRbusSramSize; 161 uint32_t MaxIbusSramSize; 162 int32_t AbsChangeParams = 0; 163 int32_t DwcFile = FALSE; 164 uint32_t rval = 0; 165 emlxs_fw_image_t fw_image; 166 uint32_t i; 167 168 #ifdef EMLXS_I386 169 caddr_t local_buffer; 170 uint32_t *bptr1; 171 uint32_t *bptr2; 172 #endif /* EMLXS_I386 */ 173 174 if (buffer == NULL || len == 0) { 175 return (EMLXS_IMAGE_BAD); 176 } 177 #ifdef EMLXS_I386 178 /* We need to swap the image buffer before we start */ 179 180 /* 181 * Use KM_SLEEP to allocate a temporary buffer 182 */ 183 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP); 184 185 if (local_buffer == NULL) { 186 return (FC_NOMEM); 187 } 188 189 /* Perform a 32 bit swap of the image */ 190 bptr1 = (uint32_t *)local_buffer; 191 bptr2 = (uint32_t *)buffer; 192 for (i = 0; i < (len / 4); i++) { 193 *bptr1 = SWAP_DATA32(*bptr2); 194 bptr1++; 195 bptr2++; 196 } 197 198 /* Replace the original buffer */ 199 buffer = local_buffer; 200 #endif /* EMLXS_I386 */ 201 202 203 bzero(&fw_image, sizeof (emlxs_fw_image_t)); 204 for (i = 0; i < MAX_PROG_TYPES; i++) { 205 (void) strcpy(fw_image.prog[i].label, "none"); 206 } 207 208 /* Validate image */ 209 if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) { 210 goto done; 211 } 212 213 /* Get image type */ 214 Uptr = (uint32_t *)buffer; 215 ImageType = *Uptr; 216 217 /* 218 * Pegasus and beyond FW download is done differently 219 * for absolute download. 220 */ 221 222 /* Check for absolute image */ 223 if ((ImageType == NOP_IMAGE_TYPE) && 224 !(hba->model_info.chip & 225 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 226 /* 227 * Because 2Mb flash download file format is different from 228 * 512k, it needs to be handled differently 229 */ 230 if (rval = emlxs_start_abs_download_2mb(hba, buffer, len, 231 offline, &fw_image)) { 232 goto done; 233 } 234 235 /* Offline already handled */ 236 offline = 0; 237 238 goto SLI_DOWNLOAD_EXIT; 239 } 240 241 /* Pre-pegasus adapters only */ 242 243 /* Check for absolute image */ 244 else if (ImageType == NOP_IMAGE_TYPE) { 245 bcopy(buffer, &AifHdr, sizeof (AIF_HDR)); 246 bzero((void *)&ImageHdr, sizeof (IMAGE_HDR)); 247 248 if (AifHdr.ImageBase && (AifHdr.ImageBase == 0x20000)) { 249 DwcFile = TRUE; 250 } 251 252 AbsChangeParams = emlxs_build_parms(buffer, 253 &AbsWakeUpParms, len, &AifHdr, DwcFile); 254 } else { /* (ImageType != NOP_IMAGE_TYPE) Relative image */ 255 256 bzero((void *)&AifHdr, sizeof (AIF_HDR)); 257 bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR)); 258 } 259 260 /* 261 * Everything checks out, now to just do it 262 */ 263 264 if (offline) { 265 if (emlxs_offline(hba) != FC_SUCCESS) { 266 offline = 0; 267 268 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 269 "Unable to take adapter offline."); 270 271 rval = EMLXS_OFFLINE_FAILED; 272 273 goto SLI_DOWNLOAD_EXIT; 274 } 275 276 if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) { 277 offline = 0; 278 279 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 280 "Unable to restart adapter."); 281 282 rval = EMLXS_OFFLINE_FAILED; 283 284 goto SLI_DOWNLOAD_EXIT; 285 } 286 } 287 288 if (ImageHdr.Id.Type == SBUS_FCODE) { 289 /* Erase Flash */ 290 if (emlxs_erase_fcode_flash(hba)) { 291 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 292 "Unable to erase flash."); 293 294 rval = EMLXS_IMAGE_FAILED; 295 296 goto SLI_DOWNLOAD_EXIT; 297 } 298 299 /* Write FCODE */ 300 if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) { 301 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 302 "Unable to write flash."); 303 304 rval = EMLXS_IMAGE_FAILED; 305 306 goto SLI_DOWNLOAD_EXIT; 307 } 308 309 } else { /* !SBUS_FCODE */ 310 311 312 if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) { 313 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 314 "Unable to get parameters."); 315 316 rval = EMLXS_IMAGE_FAILED; 317 318 goto SLI_DOWNLOAD_EXIT; 319 } 320 321 if (emlxs_get_max_sram(hba, &MaxRbusSramSize, 322 &MaxIbusSramSize)) { 323 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 324 "Unable to get RAM size."); 325 326 rval = EMLXS_IMAGE_FAILED; 327 328 goto SLI_DOWNLOAD_EXIT; 329 } 330 331 if (ImageType == NOP_IMAGE_TYPE) { 332 if (emlxs_start_abs_download(hba, &AifHdr, buffer, 333 &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize, 334 (AbsChangeParams) ? &AbsWakeUpParms : NULL, 335 DwcFile)) { 336 EMLXS_MSGF(EMLXS_CONTEXT, 337 &emlxs_download_failed_msg, 338 "Failed to program flash."); 339 340 rval = EMLXS_IMAGE_FAILED; 341 342 goto SLI_DOWNLOAD_EXIT; 343 } 344 345 } else { 346 347 if (emlxs_start_rel_download(hba, &ImageHdr, buffer, 348 &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize)) { 349 EMLXS_MSGF(EMLXS_CONTEXT, 350 &emlxs_download_failed_msg, 351 "Failed to program flash."); 352 353 rval = EMLXS_IMAGE_FAILED; 354 355 goto SLI_DOWNLOAD_EXIT; 356 } 357 } 358 359 } /* !SBUS_FCODE */ 360 361 362 SLI_DOWNLOAD_EXIT: 363 364 if (offline) { 365 (void) emlxs_online(hba); 366 } 367 368 if (rval == 0) { 369 370 371 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg, 372 "Status good."); 373 } 374 375 done: 376 377 #ifdef EMLXS_I386 378 /* Free the local buffer */ 379 kmem_free(local_buffer, len); 380 #endif /* EMLXS_I386 */ 381 382 return (rval); 383 384 } /* emlxs_fw_download */ 385 386 387 388 extern int32_t 389 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer, 390 uint32_t len) 391 { 392 emlxs_port_t *port = &PPORT; 393 MAILBOXQ *mbox = NULL; 394 MAILBOX *mb; 395 uint32_t rval = 0; 396 uint32_t region_id; 397 uint32_t id; 398 399 #ifndef EMLXS_I386 400 caddr_t local_buffer; 401 uint32_t *bptr1; 402 uint32_t *bptr2; 403 uint32_t i; 404 #endif /* !EMLXS_I386 */ 405 406 if (buffer == NULL || len == 0) { 407 return (EMLXS_IMAGE_BAD); 408 } 409 #ifndef EMLXS_I386 410 /* We need to swap the image buffer before we start */ 411 412 /* 413 * Use KM_SLEEP to allocate a temporary buffer 414 */ 415 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP); 416 417 if (local_buffer == NULL) { 418 return (FC_NOMEM); 419 } 420 421 /* Perform a 32 bit swap of the image */ 422 bptr1 = (uint32_t *)local_buffer; 423 bptr2 = (uint32_t *)buffer; 424 425 for (i = 0; i < (len / 4); i++) { 426 *bptr1 = DATA32_SWAP(*bptr2); 427 bptr1++; 428 bptr2++; 429 } 430 431 /* Replace the original buffer */ 432 buffer = local_buffer; 433 434 #endif /* !EMLXS_I386 */ 435 436 if (len > 128) { 437 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 438 "Invalid image length: 0x%x > 128", len); 439 440 return (EMLXS_IMAGE_BAD); 441 } 442 443 /* Check the region number */ 444 if ((region > 2) && (region != 0xff)) { 445 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 446 "Invalid region id: 0x%x", region); 447 448 return (EMLXS_IMAGE_BAD); 449 450 } 451 452 /* Check the image vendor id */ 453 id = *(int32_t *)buffer; 454 if ((id & 0xffff) != 0x10df) { 455 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 456 "Invalid image id: 0x%x", id); 457 458 return (EMLXS_IMAGE_BAD); 459 } 460 461 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 462 KM_NOSLEEP)) == NULL) { 463 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 464 "Unable to allocate mailbox buffer."); 465 466 rval = 1; 467 468 goto done; 469 } 470 471 mb = (MAILBOX *)mbox; 472 473 /* 474 * Everything checks out, now to just do it 475 */ 476 if (emlxs_offline(hba) != FC_SUCCESS) { 477 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 478 "Unable to take HBA offline."); 479 480 rval = EMLXS_OFFLINE_FAILED; 481 482 goto done; 483 } 484 485 if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) { 486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 487 "Unable to restart adapter."); 488 489 rval = EMLXS_OFFLINE_FAILED; 490 491 goto done; 492 } 493 494 /* Check if default region is requested */ 495 if (region == 0xff) { 496 /* 497 * Sun-branded Helios and Zypher have different 498 * default PCI region 499 */ 500 if ((hba->model_info.flags & EMLXS_SUN_BRANDED) && 501 (hba->model_info.chip & 502 (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) { 503 region = 2; 504 } else { 505 region = 0; 506 } 507 } 508 509 /* Set region id based on PCI region requested */ 510 region_id = DEF_PCI_CFG_REGION_ID + region; 511 512 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 513 "PCI configuration: PCI%d region=%d id=0x%x size=%d", region, 514 region_id, id, len); 515 516 /* Copy the data buffer to SLIM */ 517 WRITE_SLIM_COPY(hba, (uint32_t *)buffer, 518 (volatile uint32_t *)((volatile char *)hba->slim_addr + 519 sizeof (MAILBOX)), (len / sizeof (uint32_t))); 520 521 emlxs_format_update_pci_cfg(hba, mb, region_id, len); 522 523 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 524 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 525 "Unable to update PCI configuration: Mailbox cmd=%x " 526 "status=%x info=%d", mb->mbxCommand, mb->mbxStatus, 527 mb->un.varUpdateCfg.rsp_info); 528 529 rval = 1; 530 } 531 532 (void) emlxs_online(hba); 533 534 if (rval == 0) { 535 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg, 536 "Status good."); 537 } 538 539 done: 540 541 if (mbox) { 542 kmem_free(mbox, sizeof (MAILBOXQ)); 543 } 544 #ifndef EMLXS_I386 545 /* Free the local buffer */ 546 kmem_free(local_buffer, len); 547 #endif /* !EMLXS_I386 */ 548 549 return (rval); 550 551 } /* emlxs_cfl_download */ 552 553 554 555 static uint32_t 556 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr) 557 { 558 uint32_t Temp; 559 uint32_t CkSum; 560 561 EndAddr++; 562 CkSum = SLI_CKSUM_SEED; 563 564 CkSum = (CkSum >> 1) | (CkSum << 31); 565 while (StartAddr != EndAddr) { 566 CkSum = (CkSum << 1) | (CkSum >> 31); 567 Temp = *StartAddr; 568 569 CkSum ^= Temp; 570 StartAddr++; 571 } 572 573 return (CkSum << 1) | (CkSum >> 31); 574 575 } /* emlxs_valid_cksum() */ 576 577 578 static void 579 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr) 580 { 581 emlxs_port_t *port = &PPORT; 582 583 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: "); 584 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 585 "AIF Header: compress_br = 0x%x", AifHdr->CompressBr); 586 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 587 "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr); 588 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 589 "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr); 590 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 591 "AIF Header: entry_br = 0x%x", AifHdr->EntryBr); 592 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 593 "AIF Header: area_id = 0x%x", AifHdr->Area_ID); 594 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 595 "AIF Header: rosize = 0x%x", AifHdr->RoSize); 596 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 597 "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize); 598 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 599 "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize); 600 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 601 "AIF Header: dbgtype = 0x%x", AifHdr->DbgType); 602 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 603 "AIF Header: imagebase = 0x%x", AifHdr->ImageBase); 604 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 605 "AIF Header: area_size = 0x%x", AifHdr->Area_Size); 606 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 607 "AIF Header: address_mode = 0x%x", AifHdr->AddressMode); 608 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 609 "AIF Header: database = 0x%x", AifHdr->DataBase); 610 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 611 "AIF Header: aversion = 0x%x", AifHdr->AVersion); 612 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 613 "AIF Header: spare2 = 0x%x", AifHdr->Spare2); 614 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 615 "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi); 616 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 617 "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]); 618 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 619 "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]); 620 621 } /* emlxs_disp_aif_header() */ 622 623 624 625 static void 626 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image) 627 { 628 emlxs_port_t *port = &PPORT; 629 630 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: "); 631 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 632 "Img Header: BlockSize = 0x%x", image->BlockSize); 633 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 634 "Img Header: PROG_ID Type = 0x%x", image->Id.Type); 635 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 636 "Img Header: PROG_ID Id = 0x%x", image->Id.Id); 637 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 638 "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver); 639 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 640 "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev); 641 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 642 "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp); 643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 644 "Img Header: Flags = 0x%x", image->Flags); 645 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 646 "Img Header: EntryAdr = 0x%x", image->EntryAdr); 647 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 648 "Img Header: InitAdr = 0x%x", image->InitAdr); 649 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 650 "Img Header: ExitAdr = 0x%x", image->ExitAdr); 651 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 652 "Img Header: ImageBase = 0x%x", image->ImageBase); 653 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 654 "Img Header: ImageSize = 0x%x", image->ImageSize); 655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 656 "Img Header: ZinitSize = 0x%x", image->ZinitSize); 657 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 658 "Img Header: RelocSize = 0x%x", image->RelocSize); 659 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 660 "Img Header: HdrCks = 0x%x", image->HdrCks); 661 662 } /* emlxs_dump_image_header() */ 663 664 665 static void 666 emlxs_format_dump(MAILBOX *mb, uint32_t Type, uint32_t RegionId, 667 uint32_t WordCount, uint32_t BaseAddr) 668 { 669 bzero((void *)mb, MAILBOX_CMD_BSIZE); 670 671 mb->mbxCommand = MBX_DUMP_MEMORY; 672 mb->un.varDmp.type = Type; 673 mb->un.varDmp.region_id = RegionId; 674 mb->un.varDmp.word_cnt = WordCount; 675 mb->un.varDmp.base_adr = BaseAddr; 676 mb->mbxOwner = OWN_HOST; 677 678 return; 679 680 } /* emlxs_format_dump() */ 681 682 683 /* ARGSUSED */ 684 static uint32_t 685 emlxs_start_abs_download(emlxs_hba_t *hba, 686 PAIF_HDR AifHdr, 687 caddr_t Buffer, 688 PWAKE_UP_PARMS WakeUpParms, 689 uint32_t MaxRbusSramSize, 690 uint32_t MaxIbusSramSize, PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile) 691 { 692 emlxs_port_t *port = &PPORT; 693 uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize; 694 IMAGE_HDR ImageHdr; 695 uint32_t *Src; 696 uint32_t *Dst; 697 caddr_t DataBuffer = NULL; 698 MAILBOXQ *mbox; 699 MAILBOX *mb; 700 uint32_t rval = 1; 701 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 702 uint32_t DlToAddr = AifHdr->ImageBase; 703 uint32_t DlCount; 704 uint32_t i; 705 706 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 707 "Performing absolute download..."); 708 709 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 710 KM_NOSLEEP)) == NULL) { 711 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 712 "Unable to allocate data buffer."); 713 714 return (rval); 715 } 716 717 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 718 KM_NOSLEEP)) == NULL) { 719 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 720 "Unable to allocate mailbox buffer."); 721 722 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 723 724 return (rval); 725 } 726 727 mb = (MAILBOX *)mbox; 728 729 Buffer += sizeof (AIF_HDR); 730 731 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash..."); 732 733 if (DwcFile) { 734 emlxs_format_prog_flash(mb, 0x20000, 0x50000, ERASE_FLASH, 0, 735 0, 0, NULL); 736 } else { 737 emlxs_format_prog_flash(mb, DlToAddr, DlByteCount, 738 ERASE_FLASH, 0, 0, 0, NULL); 739 } 740 741 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 742 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 743 "Unable to erase Flash: Mailbox cmd=%x status=%x", 744 mb->mbxCommand, mb->mbxStatus); 745 746 rval = 1; 747 748 goto EXIT_ABS_DOWNLOAD; 749 } 750 751 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 752 "Programming flash..."); 753 754 while (DlByteCount) { 755 756 if (DlByteCount > SegSize) { 757 DlCount = SegSize; 758 } else { 759 DlCount = DlByteCount; 760 } 761 DlByteCount -= DlCount; 762 763 Dst = (uint32_t *)DataBuffer; 764 Src = (uint32_t *)Buffer; 765 766 for (i = 0; i < (DlCount / 4); i++) { 767 *Dst = *Src; 768 Dst++; 769 Src++; 770 } 771 772 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 773 (volatile uint32_t *)((volatile char *)hba->slim_addr + 774 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t))); 775 776 emlxs_format_prog_flash(mb, DlToAddr, DlCount, 777 PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL); 778 779 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 780 MBX_SUCCESS) { 781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 782 "Unable to program Flash: Mailbox cmd=%x status=%x", 783 mb->mbxCommand, mb->mbxStatus); 784 785 rval = 1; 786 787 goto EXIT_ABS_DOWNLOAD; 788 } 789 790 Buffer += DlCount; 791 DlToAddr += DlCount; 792 } 793 794 bzero((caddr_t)&ImageHdr, sizeof (IMAGE_HDR)); 795 ImageHdr.Id.Type = FUNC_FIRMWARE; 796 797 switch (MaxRbusSramSize) { 798 case REDUCED_RBUS_SRAM_CFG: 799 ImageHdr.Id.Id = REDUCED_SRAM_CFG_PROG_ID; 800 break; 801 case FULL_RBUS_SRAM_CFG: 802 ImageHdr.Id.Id = FULL_SRAM_CFG_PROG_ID; 803 break; 804 default: 805 ImageHdr.Id.Id = OTHER_SRAM_CFG_PROG_ID; 806 break; 807 } 808 809 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params..."); 810 811 if (AbsWakeUpParms) { 812 rval = 813 emlxs_update_wakeup_parms(hba, AbsWakeUpParms, 814 WakeUpParms); 815 } else { 816 rval = 817 emlxs_update_boot_wakeup_parms(hba, WakeUpParms, 818 &ImageHdr.Id, 1); 819 } 820 821 EXIT_ABS_DOWNLOAD: 822 if (DataBuffer) { 823 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 824 } 825 826 if (mbox) { 827 kmem_free(mbox, sizeof (MAILBOXQ)); 828 } 829 830 return (rval); 831 832 } /* emlxs_start_abs_download() */ 833 834 835 /* ARGSUSED */ 836 static void 837 emlxs_format_prog_flash(MAILBOX *mb, 838 uint32_t Base, 839 uint32_t DlByteCount, 840 uint32_t Function, 841 uint32_t Complete, 842 uint32_t BdeAddress, uint32_t BdeSize, PROG_ID *ProgId) 843 { 844 bzero((void *)mb, MAILBOX_CMD_BSIZE); 845 846 if (ProgId) 847 mb->mbxCommand = MBX_DOWN_LOAD; 848 else 849 mb->mbxCommand = MBX_LOAD_SM; 850 851 mb->un.varLdSM.load_cmplt = Complete; 852 mb->un.varLdSM.method = DL_FROM_SLIM; 853 mb->un.varLdSM.update_flash = 1; 854 mb->un.varLdSM.erase_or_prog = Function; 855 mb->un.varLdSM.dl_to_adr = Base; 856 mb->un.varLdSM.dl_len = DlByteCount; 857 858 if (BdeSize) { 859 mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET; 860 } else if (ProgId) { 861 mb->un.varLdSM.un.prog_id = *ProgId; 862 } else { 863 mb->un.varLdSM.un.dl_from_slim_offset = 0; 864 } 865 866 mb->mbxOwner = OWN_HOST; 867 868 } /* emlxs_format_prog_flash() */ 869 870 871 static void 872 emlxs_format_update_parms(MAILBOX *mb, PWAKE_UP_PARMS WakeUpParms) 873 { 874 bzero((void *)mb, MAILBOX_CMD_BSIZE); 875 876 mb->mbxCommand = MBX_UPDATE_CFG; 877 mb->un.varUpdateCfg.req_type = UPDATE_DATA; 878 mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID; 879 mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS); 880 mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS); 881 882 bcopy((caddr_t)WakeUpParms, 883 (caddr_t)&(mb->un.varUpdateCfg.cfg_data), 884 sizeof (WAKE_UP_PARMS)); 885 886 } /* emlxs_format_update_parms () */ 887 888 889 /* ARGSUSED */ 890 static void 891 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOX *mb, 892 uint32_t region_id, uint32_t size) 893 { 894 bzero((void *)mb, MAILBOX_CMD_BSIZE); 895 896 mb->mbxCommand = MBX_UPDATE_CFG; 897 mb->un.varUpdateCfg.Vbit = 1; 898 mb->un.varUpdateCfg.Obit = 1; 899 mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET; 900 mb->un.varUpdateCfg.req_type = UPDATE_DATA; 901 mb->un.varUpdateCfg.region_id = region_id; 902 mb->un.varUpdateCfg.entry_len = size; 903 mb->un.varUpdateCfg.byte_len = size; 904 905 906 } /* emlxs_format_update_pci_cfg() */ 907 908 909 910 static uint32_t 911 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 912 PROG_ID * prog_id, uint32_t proc_erom) 913 { 914 emlxs_port_t *port = &PPORT; 915 MAILBOX *mb; 916 MAILBOXQ *mbox; 917 uint32_t rval = 0; 918 919 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 920 KM_NOSLEEP)) == NULL) { 921 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 922 "Unable to allocate mailbox buffer."); 923 924 return (1); 925 } 926 927 mb = (MAILBOX *)mbox; 928 929 if (proc_erom && !(hba->model_info.chip & 930 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 931 WakeUpParms->u1.EROM_prog_id = *prog_id; 932 (void) emlxs_update_exp_rom(hba, WakeUpParms); 933 } 934 935 WakeUpParms->u0.boot_bios_id = *prog_id; 936 937 emlxs_format_update_parms(mb, WakeUpParms); 938 939 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 940 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 941 "Unable to update boot wakeup parms: Mailbox cmd=%x " 942 "status=%x", mb->mbxCommand, mb->mbxStatus); 943 944 rval = 1; 945 } 946 947 if (mbox) { 948 kmem_free(mbox, sizeof (MAILBOXQ)); 949 } 950 951 return (rval); 952 953 } /* emlxs_update_boot_wakeup_parms() */ 954 955 956 957 static uint32_t 958 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 959 PROG_ID *prog_id) 960 { 961 emlxs_port_t *port = &PPORT; 962 uint32_t rval = 0; 963 MAILBOXQ *mbox; 964 MAILBOX *mb; 965 966 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 967 KM_NOSLEEP)) == NULL) { 968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 969 "Unable to allocate mailbox buffer."); 970 971 return (1); 972 } 973 974 mb = (MAILBOX *)mbox; 975 976 WakeUpParms->prog_id = *prog_id; 977 978 emlxs_format_update_parms(mb, WakeUpParms); 979 980 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 981 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 982 "Unable to update wakeup parameters: Mailbox cmd=%x " 983 "status=%x", mb->mbxCommand, mb->mbxStatus); 984 985 rval = 1; 986 } 987 988 if (mbox) { 989 kmem_free(mbox, sizeof (MAILBOXQ)); 990 } 991 992 return (rval); 993 994 } /* emlxs_update_ff_wakeup_parms() */ 995 996 997 static uint32_t 998 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 999 PROG_ID * prog_id) 1000 { 1001 emlxs_port_t *port = &PPORT; 1002 uint32_t rval = 0; 1003 MAILBOXQ *mbox; 1004 MAILBOX *mb; 1005 1006 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1007 KM_NOSLEEP)) == NULL) { 1008 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1009 "Unable to allocate mailbox buffer."); 1010 1011 return (1); 1012 } 1013 1014 mb = (MAILBOX *)mbox; 1015 1016 WakeUpParms->sli1_prog_id = *prog_id; 1017 1018 emlxs_format_update_parms(mb, WakeUpParms); 1019 1020 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1021 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1022 "Unable to update wakeup parameters. Mailbox cmd=%x " 1023 "status=%x", mb->mbxCommand, mb->mbxStatus); 1024 1025 rval = 1; 1026 } 1027 1028 if (mbox) { 1029 kmem_free(mbox, sizeof (MAILBOXQ)); 1030 } 1031 1032 return (rval); 1033 1034 } /* emlxs_update_sli1_wakeup_parms() */ 1035 1036 1037 static uint32_t 1038 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1039 PROG_ID * prog_id) 1040 { 1041 emlxs_port_t *port = &PPORT; 1042 uint32_t rval = 0; 1043 MAILBOXQ *mbox; 1044 MAILBOX *mb; 1045 1046 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1047 KM_NOSLEEP)) == NULL) { 1048 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1049 "Unable to allocate mailbox buffer."); 1050 1051 return (1); 1052 } 1053 1054 mb = (MAILBOX *)mbox; 1055 1056 WakeUpParms->sli2_prog_id = *prog_id; 1057 1058 emlxs_format_update_parms(mb, WakeUpParms); 1059 1060 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1061 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1062 "Unable to update wakeup parameters. Mailbox cmd=%x " 1063 "status=%x", mb->mbxCommand, mb->mbxStatus); 1064 1065 rval = 1; 1066 } 1067 1068 if (mbox) { 1069 kmem_free(mbox, sizeof (MAILBOXQ)); 1070 } 1071 1072 return (rval); 1073 1074 } /* emlxs_update_sli2_wakeup_parms() */ 1075 1076 1077 static uint32_t 1078 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1079 PROG_ID *prog_id) 1080 { 1081 emlxs_port_t *port = &PPORT; 1082 uint32_t rval = 0; 1083 MAILBOXQ *mbox; 1084 MAILBOX *mb; 1085 1086 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1087 KM_NOSLEEP)) == NULL) { 1088 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1089 "Unable to allocate mailbox buffer."); 1090 1091 return (1); 1092 } 1093 1094 mb = (MAILBOX *)mbox; 1095 1096 WakeUpParms->sli3_prog_id = *prog_id; 1097 1098 emlxs_format_update_parms(mb, WakeUpParms); 1099 1100 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1101 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1102 "Unable to update wakeup parameters. Mailbox cmd=%x " 1103 "status=%x", mb->mbxCommand, mb->mbxStatus); 1104 1105 rval = 1; 1106 } 1107 1108 if (mbox) { 1109 kmem_free(mbox, sizeof (MAILBOXQ)); 1110 } 1111 1112 return (rval); 1113 1114 } /* emlxs_update_sli3_wakeup_parms() */ 1115 1116 1117 static uint32_t 1118 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1119 PROG_ID *prog_id) 1120 { 1121 emlxs_port_t *port = &PPORT; 1122 uint32_t rval = 0; 1123 MAILBOXQ *mbox; 1124 MAILBOX *mb; 1125 1126 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1127 KM_NOSLEEP)) == NULL) { 1128 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1129 "Unable to allocate mailbox buffer."); 1130 1131 return (1); 1132 } 1133 1134 mb = (MAILBOX *)mbox; 1135 1136 WakeUpParms->sli4_prog_id = *prog_id; 1137 1138 emlxs_format_update_parms(mb, WakeUpParms); 1139 1140 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1141 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1142 "Unable to update wakeup parameters. Mailbox cmd=%x " 1143 "status=%x", mb->mbxCommand, mb->mbxStatus); 1144 1145 rval = 1; 1146 } 1147 1148 if (mbox) { 1149 kmem_free(mbox, sizeof (MAILBOXQ)); 1150 } 1151 1152 return (rval); 1153 1154 } /* emlxs_update_sli4_wakeup_parms() */ 1155 1156 1157 /* ARGSUSED */ 1158 static uint32_t 1159 emlxs_start_rel_download(emlxs_hba_t *hba, 1160 PIMAGE_HDR ImageHdr, 1161 caddr_t Buffer, 1162 PWAKE_UP_PARMS WakeUpParms, 1163 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize) 1164 { 1165 emlxs_port_t *port = &PPORT; 1166 MAILBOXQ *mbox; 1167 MAILBOX *mb; 1168 uint32_t *Src; 1169 uint32_t *Dst; 1170 caddr_t DataBuffer = NULL; 1171 uint32_t rval = 1; 1172 uint32_t DlByteCount = ImageHdr->BlockSize; 1173 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 1174 uint32_t DlCount; 1175 uint32_t i; 1176 1177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1178 "Performing relative download..."); 1179 1180 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 1181 KM_NOSLEEP)) == NULL) { 1182 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1183 "Unable to allocate data buffer."); 1184 1185 return (rval); 1186 } 1187 1188 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1189 KM_NOSLEEP)) == NULL) { 1190 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1191 "Unable to allocate mailbox buffer."); 1192 1193 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 1194 1195 return (rval); 1196 } 1197 1198 if (ImageHdr->Id.Type == FUNC_FIRMWARE) { 1199 switch (MaxRbusSramSize) { 1200 case REDUCED_RBUS_SRAM_CFG: 1201 if (ImageHdr->Id.Id != REDUCED_SRAM_CFG_PROG_ID) { 1202 EMLXS_MSGF(EMLXS_CONTEXT, 1203 &emlxs_image_bad_msg, 1204 "Invalid header id."); 1205 1206 return (1); 1207 } 1208 break; 1209 case FULL_RBUS_SRAM_CFG: 1210 if (ImageHdr->Id.Id != FULL_SRAM_CFG_PROG_ID) { 1211 EMLXS_MSGF(EMLXS_CONTEXT, 1212 &emlxs_image_bad_msg, 1213 "Invalid header id."); 1214 1215 return (1); 1216 } 1217 break; 1218 default: 1219 if (ImageHdr->Id.Id != OTHER_SRAM_CFG_PROG_ID) { 1220 EMLXS_MSGF(EMLXS_CONTEXT, 1221 &emlxs_image_bad_msg, 1222 "Invalid header id."); 1223 1224 return (1); 1225 } 1226 break; 1227 } 1228 } 1229 1230 mb = (MAILBOX *)mbox; 1231 1232 emlxs_format_prog_flash(mb, 0, DlByteCount, ERASE_FLASH, 0, 0, 0, 1233 &ImageHdr->Id); 1234 1235 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash..."); 1236 1237 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1238 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1239 "Unable to erase flash. Mailbox cmd=%x status=%x", 1240 mb->mbxCommand, mb->mbxStatus); 1241 1242 rval = 1; 1243 1244 goto EXIT_REL_DOWNLOAD; 1245 } 1246 1247 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1248 "Programming flash..."); 1249 1250 while (DlByteCount) { 1251 if (DlByteCount > SegSize) { 1252 DlCount = SegSize; 1253 } else { 1254 DlCount = DlByteCount; 1255 } 1256 DlByteCount -= DlCount; 1257 1258 Dst = (uint32_t *)DataBuffer; 1259 Src = (uint32_t *)Buffer; 1260 1261 for (i = 0; i < (DlCount / 4); i++) { 1262 *Dst = *Src; 1263 Dst++; 1264 Src++; 1265 } 1266 1267 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 1268 (volatile uint32_t *)((volatile char *)hba->slim_addr + 1269 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t))); 1270 1271 emlxs_format_prog_flash(mb, 1272 0, 1273 DlCount, 1274 PROGRAM_FLASH, 1275 (DlByteCount) ? 0 : 1, 0, DlCount, &ImageHdr->Id); 1276 1277 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1278 MBX_SUCCESS) { 1279 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1280 "Unable to program flash. Mailbox cmd=%x status=%x", 1281 mb->mbxCommand, mb->mbxStatus); 1282 1283 rval = 1; 1284 1285 goto EXIT_REL_DOWNLOAD; 1286 } 1287 1288 Buffer += DlCount; 1289 } 1290 1291 switch (ImageHdr->Id.Type) { 1292 case TEST_PROGRAM: 1293 rval = 0; 1294 break; 1295 1296 case FUNC_FIRMWARE: 1297 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1298 "FF: Updating parms..."); 1299 rval = 1300 emlxs_update_ff_wakeup_parms(hba, WakeUpParms, 1301 &ImageHdr->Id); 1302 break; 1303 1304 case BOOT_BIOS: 1305 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1306 "BOOT: Updating parms..."); 1307 rval = 1308 emlxs_update_boot_wakeup_parms(hba, WakeUpParms, 1309 &ImageHdr->Id, 1); 1310 break; 1311 1312 case SLI1_OVERLAY: 1313 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1314 "SLI1: Updating parms..."); 1315 rval = 1316 emlxs_update_sli1_wakeup_parms(hba, WakeUpParms, 1317 &ImageHdr->Id); 1318 break; 1319 1320 case SLI2_OVERLAY: 1321 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1322 "SLI2: Updating parms..."); 1323 rval = 1324 emlxs_update_sli2_wakeup_parms(hba, WakeUpParms, 1325 &ImageHdr->Id); 1326 break; 1327 1328 case SLI3_OVERLAY: 1329 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1330 "SLI3: Updating parms..."); 1331 rval = 1332 emlxs_update_sli3_wakeup_parms(hba, WakeUpParms, 1333 &ImageHdr->Id); 1334 break; 1335 1336 case SLI4_OVERLAY: 1337 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1338 "SLI4: Updating parms..."); 1339 rval = 1340 emlxs_update_sli4_wakeup_parms(hba, WakeUpParms, 1341 &ImageHdr->Id); 1342 break; 1343 1344 default: 1345 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 1346 "Image type not supported. Type=%x", ImageHdr->Id.Type); 1347 1348 break; 1349 } 1350 1351 EXIT_REL_DOWNLOAD: 1352 if (DataBuffer) { 1353 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 1354 } 1355 1356 if (mbox) { 1357 kmem_free(mbox, sizeof (MAILBOXQ)); 1358 } 1359 1360 return (rval); 1361 1362 } /* emlxs_start_rel_download() */ 1363 1364 1365 #define FLASH_POLLING_BIT 0x80 1366 #define FLASH_ERROR_BIT 0x20 1367 1368 typedef struct _flash_t 1369 { 1370 uint32_t offset; 1371 uint8_t val; 1372 } flash_t; 1373 1374 1375 1376 static uint32_t 1377 emlxs_write_fcode_flash(emlxs_hba_t *hba, 1378 PIMAGE_HDR ImageHdr, caddr_t Buffer) 1379 { 1380 emlxs_port_t *port = &PPORT; 1381 uint8_t bb; 1382 uint8_t cc; 1383 uint8_t *src; 1384 uint32_t DlByteCount = ImageHdr->BlockSize; 1385 uint32_t i; 1386 uint32_t j; 1387 uint32_t k; 1388 1389 flash_t wr[3] = { 1390 {0x555, 0xaa}, 1391 {0x2aa, 0x55}, 1392 {0x555, 0xa0} 1393 }; 1394 1395 /* Load Fcode */ 1396 src = (uint8_t *)Buffer + sizeof (IMAGE_HDR); 1397 for (i = 0; i < DlByteCount; i++) { 1398 for (k = 0; k < 3; k++) { 1399 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val); 1400 } 1401 1402 /* Reverse Endian word alignment */ 1403 j = (i & 3) ^ 3; 1404 1405 bb = src[j]; 1406 1407 if (j == 0) { 1408 src += 4; 1409 } 1410 1411 SBUS_WRITE_FLASH_COPY(hba, i, bb); 1412 1413 /* check for complete */ 1414 for (;;) { 1415 DELAYUS(20); 1416 1417 cc = SBUS_READ_FLASH_COPY(hba, i); 1418 1419 /* If data matches then continue */ 1420 if (cc == bb) { 1421 break; 1422 } 1423 1424 /* Polling bit will be inverse final value */ 1425 /* while active */ 1426 if ((cc ^ bb) & FLASH_POLLING_BIT) { 1427 /* Still busy */ 1428 1429 /* Check for error bit */ 1430 if (cc & FLASH_ERROR_BIT) { 1431 /* Read data one more time */ 1432 cc = SBUS_READ_FLASH_COPY(hba, i); 1433 1434 /* Check if data matches */ 1435 if (cc == bb) { 1436 break; 1437 } 1438 1439 EMLXS_MSGF(EMLXS_CONTEXT, 1440 &emlxs_download_failed_msg, 1441 "FCode write error: offset:%x " 1442 "wrote:%x read:%x\n", i, bb, cc); 1443 1444 return (1); 1445 } 1446 } 1447 } 1448 } 1449 1450 /* Load Header */ 1451 src = (uint8_t *)ImageHdr; 1452 1453 for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) { 1454 for (k = 0; k < 3; k++) { 1455 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val); 1456 } 1457 1458 /* Reverse Endian word alignment */ 1459 j = (i & 3) ^ 3; 1460 1461 bb = src[j]; 1462 1463 if (j == 0) { 1464 src += 4; 1465 } 1466 1467 SBUS_WRITE_FLASH_COPY(hba, i, bb); 1468 1469 /* check for complete */ 1470 for (;;) { 1471 DELAYUS(20); 1472 1473 cc = SBUS_READ_FLASH_COPY(hba, i); 1474 1475 /* If data matches then continue */ 1476 if (cc == bb) { 1477 break; 1478 } 1479 1480 /* Polling bit will be inverse final value */ 1481 /* while active */ 1482 if ((cc ^ bb) & FLASH_POLLING_BIT) { 1483 /* Still busy */ 1484 1485 /* Check for error bit */ 1486 if (cc & FLASH_ERROR_BIT) { 1487 /* Read data one more time */ 1488 cc = SBUS_READ_FLASH_COPY(hba, i); 1489 1490 /* Check if data matches */ 1491 if (cc == bb) { 1492 break; 1493 } 1494 1495 EMLXS_MSGF(EMLXS_CONTEXT, 1496 &emlxs_download_failed_msg, 1497 "FCode write error: offset:%x " 1498 "wrote:%x read:%x\n", i, bb, cc); 1499 1500 return (1); 1501 } 1502 } 1503 } 1504 } 1505 1506 1507 return (0); 1508 1509 } /* emlxs_write_fcode_flash() */ 1510 1511 1512 1513 static uint32_t 1514 emlxs_erase_fcode_flash(emlxs_hba_t *hba) 1515 { 1516 emlxs_port_t *port = &PPORT; 1517 int32_t i, j; 1518 uint8_t cc; 1519 uint32_t offset; 1520 1521 flash_t ef[6] = { 1522 {0x555, 0xaa}, 1523 {0x2aa, 0x55}, 1524 {0x555, 0x80}, 1525 {0x555, 0xaa}, 1526 {0x2aa, 0x55}, 1527 {0x555, 0x10} 1528 }; 1529 1530 /* Auto select */ 1531 flash_t as[3] = { 1532 {0x555, 0xaa}, 1533 {0x2aa, 0x55}, 1534 {0x555, 0x90} 1535 }; 1536 1537 1538 /* Check Manufacturers Code */ 1539 for (i = 0; i < 3; i++) { 1540 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 1541 } 1542 1543 cc = SBUS_READ_FLASH_COPY(hba, 0); 1544 1545 /* Check Device Code */ 1546 for (i = 0; i < 3; i++) { 1547 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 1548 } 1549 1550 cc = SBUS_READ_FLASH_COPY(hba, 1); 1551 1552 1553 /* Check block protections (up to 4 16K blocks = 64K) */ 1554 for (j = 0; j < 4; j++) { 1555 for (i = 0; i < 3; i++) { 1556 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 1557 } 1558 1559 offset = (j << 14) | 0x2; 1560 1561 cc = SBUS_READ_FLASH_COPY(hba, offset); 1562 1563 if (cc == 0x01) { 1564 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1565 "Block %d is protected and can't be erased.", j); 1566 } 1567 } 1568 1569 /* Write erase flash sequence */ 1570 for (i = 0; i < 6; i++) { 1571 SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val); 1572 } 1573 1574 /* check for complete */ 1575 for (;;) { 1576 /* Delay 3 seconds */ 1577 DELAYMS(3000); 1578 1579 cc = SBUS_READ_FLASH_COPY(hba, 0); 1580 1581 1582 /* If data matches then continue; */ 1583 if (cc == 0xff) { 1584 break; 1585 } 1586 1587 /* Polling bit will be inverse final value while active */ 1588 if ((cc ^ 0xff) & FLASH_POLLING_BIT) { 1589 /* Still busy */ 1590 1591 /* Check for error bit */ 1592 if (cc & FLASH_ERROR_BIT) { 1593 /* Read data one more time */ 1594 cc = SBUS_READ_FLASH_COPY(hba, 0); 1595 1596 /* Check if data matches */ 1597 if (cc == 0xff) { 1598 break; 1599 } 1600 1601 EMLXS_MSGF(EMLXS_CONTEXT, 1602 &emlxs_download_failed_msg, 1603 "FCode write error: offset:%x wrote:%x " 1604 "read:%x\n", i, 0xff, cc); 1605 1606 return (1); 1607 } 1608 } 1609 } 1610 1611 return (0); 1612 1613 } /* emlxs_erase_fcode_flash() */ 1614 1615 1616 extern uint32_t 1617 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list) 1618 { 1619 emlxs_port_t *port = &PPORT; 1620 LOAD_ENTRY *LoadEntry; 1621 LOAD_LIST *LoadList = NULL; 1622 uint32_t i; 1623 uint32_t rval = 0; 1624 1625 bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY)); 1626 1627 if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST), 1628 KM_NOSLEEP)) == NULL) { 1629 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1630 "Unable to allocate LOADLIST buffer."); 1631 1632 rval = 1; 1633 goto done; 1634 } 1635 1636 if (emlxs_read_load_list(hba, LoadList)) { 1637 rval = 1; 1638 goto done; 1639 } 1640 1641 for (i = 0; i < LoadList->entry_cnt; i++) { 1642 LoadEntry = &LoadList->load_entry[i]; 1643 if ((LoadEntry->un.wd[0] != 0) && 1644 (LoadEntry->un.wd[0] != 0xffffffff)) { 1645 load_list[i] = LoadEntry->un.id; 1646 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1647 "Load List[%d]: %08x %08x", i, 1648 LoadEntry->un.wd[0], LoadEntry->un.wd[1]); 1649 } 1650 } 1651 1652 done: 1653 1654 if (LoadList) { 1655 kmem_free(LoadList, sizeof (LOAD_LIST)); 1656 } 1657 1658 return (rval); 1659 1660 } /* emlxs_get_load_list() */ 1661 1662 1663 extern uint32_t 1664 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1665 uint32_t verbose) 1666 { 1667 emlxs_port_t *port = &PPORT; 1668 MAILBOXQ *mbox; 1669 MAILBOX *mb; 1670 uint32_t rval = 0; 1671 uint32_t *wd; 1672 1673 bzero(WakeUpParms, sizeof (WAKE_UP_PARMS)); 1674 1675 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1676 KM_NOSLEEP)) == NULL) { 1677 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1678 "Unable to allocate mailbox buffer."); 1679 1680 return (1); 1681 } 1682 1683 mb = (MAILBOX *)mbox; 1684 1685 emlxs_format_dump(mb, 1686 DMP_NV_PARAMS, 1687 WAKE_UP_PARMS_REGION_ID, 1688 sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0); 1689 1690 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1691 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1692 "Unable to get parameters: Mailbox cmd=%x status=%x", 1693 mb->mbxCommand, mb->mbxStatus); 1694 1695 if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) { 1696 rval = (uint32_t)CFG_DATA_NO_REGION; 1697 } else { 1698 rval = 1; 1699 } 1700 } else { 1701 bcopy((caddr_t)&mb->un.varDmp.resp_offset, 1702 (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS)); 1703 1704 if (verbose) { 1705 wd = (uint32_t *)&WakeUpParms->prog_id; 1706 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1707 "Wakeup: prog_id=%08x %08x", wd[0], wd[1]); 1708 1709 wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id; 1710 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1711 "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]); 1712 1713 wd = (uint32_t *)&WakeUpParms->sli1_prog_id; 1714 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1715 "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]); 1716 1717 wd = (uint32_t *)&WakeUpParms->sli2_prog_id; 1718 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1719 "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]); 1720 1721 wd = (uint32_t *)&WakeUpParms->sli3_prog_id; 1722 if (wd[0] || wd[1]) { 1723 EMLXS_MSGF(EMLXS_CONTEXT, 1724 &emlxs_init_debug_msg, 1725 "Wakeup: sli3_prog_id=%08x %08x", wd[0], 1726 wd[1]); 1727 } 1728 1729 wd = (uint32_t *)&WakeUpParms->sli4_prog_id; 1730 if (wd[0] || wd[1]) { 1731 EMLXS_MSGF(EMLXS_CONTEXT, 1732 &emlxs_init_debug_msg, 1733 "Wakeup: sli4_prog_id=%08x %08x", wd[0], 1734 wd[1]); 1735 } 1736 1737 wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id; 1738 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1739 "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]); 1740 1741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1742 "Wakeup: pci_cfg_rsvd=%x", 1743 WakeUpParms->pci_cfg_rsvd); 1744 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1745 "Wakeup: use_hdw_def=%x", 1746 WakeUpParms->use_hdw_def); 1747 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1748 "Wakeup: pci_cfg_sel=%x", 1749 WakeUpParms->pci_cfg_sel); 1750 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 1751 "Wakeup: cfg_lookup=%x", 1752 WakeUpParms->pci_cfg_lookup_sel); 1753 } 1754 } 1755 1756 done: 1757 1758 if (mbox) { 1759 kmem_free(mbox, sizeof (MAILBOXQ)); 1760 } 1761 1762 return (rval); 1763 1764 } /* emlxs_read_wakeup_parms() */ 1765 1766 1767 static uint32_t 1768 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList) 1769 { 1770 emlxs_port_t *port = &PPORT; 1771 LOAD_ENTRY *LoadEntry; 1772 uint32_t *Uptr; 1773 uint32_t CurEntryAddr; 1774 MAILBOXQ *mbox = NULL; 1775 MAILBOX *mb; 1776 1777 bzero((caddr_t)LoadList, sizeof (LOAD_LIST)); 1778 1779 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1780 KM_NOSLEEP)) == NULL) { 1781 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1782 "Unable to allocate mailbox buffer."); 1783 1784 return (1); 1785 } 1786 1787 mb = (MAILBOX *)mbox; 1788 1789 emlxs_format_dump(mb, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR); 1790 1791 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 1792 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1793 "Unable to get load list: Mailbox cmd=%x status=%x", 1794 mb->mbxCommand, mb->mbxStatus); 1795 1796 goto done; 1797 } 1798 1799 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset; 1800 1801 LoadList->head = Uptr[0]; 1802 LoadList->tail = Uptr[1]; 1803 1804 CurEntryAddr = LoadList->head; 1805 1806 while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) && 1807 (LoadList->entry_cnt < MAX_LOAD_ENTRY)) { 1808 LoadEntry = &LoadList->load_entry[LoadList->entry_cnt]; 1809 LoadList->entry_cnt++; 1810 1811 emlxs_format_dump(mb, 1812 DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr); 1813 1814 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 1815 MBX_SUCCESS) { 1816 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1817 "Unable to get load list (%d): Mailbox cmd=%x " 1818 "status=%x", LoadList->entry_cnt, mb->mbxCommand, 1819 mb->mbxStatus); 1820 1821 goto done; 1822 } 1823 1824 Uptr = (uint32_t *)&(mb->un.varDmp.resp_offset); 1825 1826 LoadEntry->next = Uptr[0]; 1827 LoadEntry->prev = Uptr[1]; 1828 LoadEntry->start_adr = Uptr[2]; 1829 LoadEntry->len = Uptr[3]; 1830 LoadEntry->un.wd[0] = Uptr[4]; 1831 LoadEntry->un.wd[1] = Uptr[5]; 1832 1833 /* update next current load entry address */ 1834 CurEntryAddr = LoadEntry->next; 1835 1836 } /* end of while (not end of list) */ 1837 1838 done: 1839 1840 if (mbox) { 1841 kmem_free(mbox, sizeof (MAILBOXQ)); 1842 } 1843 1844 return (0); 1845 1846 } /* emlxs_read_load_list() */ 1847 1848 1849 1850 1851 static uint32_t 1852 emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize) 1853 { 1854 uint32_t Version; 1855 1856 if (BufferSize < (SLI_VERSION_LOC + 4)) 1857 return (0xffffffff); 1858 1859 Buffer += SLI_VERSION_LOC; 1860 Version = *((uint32_t *)Buffer); 1861 1862 return (Version); 1863 1864 } /* emlxs_get_abs_image_type() */ 1865 1866 1867 static uint32_t 1868 emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer, 1869 uint32_t BufferSize, PAIF_HDR AifHeader) 1870 { 1871 emlxs_port_t *port = &PPORT; 1872 IMAGE_HDR ImageHdr; 1873 uint32_t NextImage; 1874 uint32_t i; 1875 uint8_t *Sptr; 1876 uint8_t *Dptr; 1877 uint32_t HwId = 0xffffffff; 1878 1879 NextImage = SLI_IMAGE_START - AifHeader->ImageBase; 1880 1881 while (BufferSize > NextImage) { 1882 Sptr = (uint8_t *)&Buffer[NextImage]; 1883 Dptr = (uint8_t *)&ImageHdr; 1884 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 1885 Dptr[i] = Sptr[i]; 1886 } 1887 1888 if (ImageHdr.BlockSize == 0xffffffff) 1889 break; 1890 1891 switch (ImageHdr.Id.Type) { 1892 case 6: 1893 case 7: 1894 if (HwId == 0xffffffff) { 1895 HwId = ImageHdr.Id.Id; 1896 } 1897 1898 if (HwId != ImageHdr.Id.Id) { 1899 EMLXS_MSGF(EMLXS_CONTEXT, 1900 &emlxs_image_bad_msg, 1901 "Invalid hardware id. %x %x", HwId, 1902 ImageHdr.Id.Id); 1903 } 1904 break; 1905 } 1906 1907 NextImage += ImageHdr.BlockSize; 1908 } 1909 1910 return (HwId); 1911 1912 } /* emlxs_get_dwc_image_type() */ 1913 1914 1915 static int 1916 emlxs_build_parms(caddr_t Buffer, 1917 PWAKE_UP_PARMS AbsWakeUpParms, 1918 uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile) 1919 { 1920 IMAGE_HDR ImageHdr; 1921 uint32_t NextImage; 1922 uint32_t i; 1923 int32_t ChangeParams = FALSE; 1924 caddr_t Sptr; 1925 caddr_t Dptr; 1926 1927 bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS)); 1928 1929 if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) { 1930 return (FALSE); 1931 } 1932 1933 NextImage = SLI_IMAGE_START - AifHeader->ImageBase; 1934 1935 while (BufferSize > NextImage) { 1936 Sptr = &Buffer[NextImage]; 1937 Dptr = (caddr_t)&ImageHdr; 1938 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 1939 Dptr[i] = Sptr[i]; 1940 } 1941 1942 if (ImageHdr.BlockSize == 0xffffffff) 1943 break; 1944 1945 switch (ImageHdr.Id.Type) { 1946 case TEST_PROGRAM: 1947 break; 1948 case FUNC_FIRMWARE: 1949 AbsWakeUpParms->prog_id = ImageHdr.Id; 1950 ChangeParams = TRUE; 1951 break; 1952 case BOOT_BIOS: 1953 AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id; 1954 ChangeParams = TRUE; 1955 break; 1956 case SLI1_OVERLAY: 1957 AbsWakeUpParms->sli1_prog_id = ImageHdr.Id; 1958 ChangeParams = TRUE; 1959 break; 1960 case SLI2_OVERLAY: 1961 AbsWakeUpParms->sli2_prog_id = ImageHdr.Id; 1962 ChangeParams = TRUE; 1963 break; 1964 case SLI3_OVERLAY: 1965 AbsWakeUpParms->sli3_prog_id = ImageHdr.Id; 1966 ChangeParams = TRUE; 1967 break; 1968 case SLI4_OVERLAY: 1969 AbsWakeUpParms->sli4_prog_id = ImageHdr.Id; 1970 ChangeParams = TRUE; 1971 break; 1972 default: 1973 break; 1974 } 1975 1976 NextImage += ImageHdr.BlockSize; 1977 } 1978 1979 return (ChangeParams); 1980 1981 } /* emlxs_build_parms() */ 1982 1983 1984 static uint32_t 1985 emlxs_update_wakeup_parms(emlxs_hba_t *hba, 1986 PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms) 1987 { 1988 emlxs_port_t *port = &PPORT; 1989 MAILBOX *mb; 1990 MAILBOXQ *mbox; 1991 uint32_t rval = 0; 1992 1993 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1994 KM_NOSLEEP)) == NULL) { 1995 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1996 "Unable to allocate mailbox buffer."); 1997 1998 return (1); 1999 } 2000 2001 mb = (MAILBOX *)mbox; 2002 2003 WakeUpParms->prog_id = AbsWakeUpParms->prog_id; 2004 WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id; 2005 WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id; 2006 WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id; 2007 WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id; 2008 WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id; 2009 2010 emlxs_format_update_parms(mb, WakeUpParms); 2011 2012 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 2013 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2014 "Unable to update wakeup parameters: Mailbox cmd=%x " 2015 "status=%x", mb->mbxCommand, mb->mbxStatus); 2016 2017 rval = 1; 2018 } 2019 2020 if (mbox) { 2021 kmem_free(mbox, sizeof (MAILBOXQ)); 2022 } 2023 2024 return (rval); 2025 2026 } /* emlxs_update_wakeup_parms() */ 2027 2028 2029 static uint32_t 2030 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id, 2031 uint32_t type, char *file_type) 2032 { 2033 emlxs_port_t *port = &PPORT; 2034 2035 /* Create the version label */ 2036 emlxs_decode_version(file->version, file->label); 2037 2038 /* Process the DWC type */ 2039 switch (type) { 2040 case TEST_PROGRAM: 2041 2042 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2043 "%s: TEST: offset=%08x version=%08x, %s", file_type, 2044 file->offset, file->version, file->label); 2045 2046 break; 2047 2048 case BOOT_BIOS: 2049 2050 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2051 "%s: BOOT: offset=%08x version=%08x, %s", file_type, 2052 file->offset, file->version, file->label); 2053 2054 if (!emlxs_bios_check(hba, id)) { 2055 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2056 "BOOT Check: Image not compatible with %s. id=%02x", 2057 hba->model_info.model, id); 2058 2059 return (EMLXS_IMAGE_INCOMPATIBLE); 2060 } 2061 2062 break; 2063 2064 case FUNC_FIRMWARE: /* Stub */ 2065 2066 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2067 "%s: STUB: offset=%08x version=%08x, %s", file_type, 2068 file->offset, file->version, file->label); 2069 2070 if (!emlxs_stub_check(hba, id)) { 2071 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2072 "STUB Check: Image not compatible with %s. id=%02x", 2073 hba->model_info.model, id); 2074 2075 return (EMLXS_IMAGE_INCOMPATIBLE); 2076 } 2077 2078 break; 2079 2080 case SLI1_OVERLAY: 2081 2082 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2083 "%s: SLI1: offset=%08x version=%08x, %s", file_type, 2084 file->offset, file->version, file->label); 2085 2086 if (!emlxs_sli1_check(hba, id)) { 2087 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2088 "SLI1 Check: Image not compatible with %s. id=%02x", 2089 hba->model_info.model, id); 2090 2091 return (EMLXS_IMAGE_INCOMPATIBLE); 2092 } 2093 2094 break; 2095 2096 case SLI2_OVERLAY: 2097 2098 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2099 "%s: SLI2: offset=%08x version=%08x, %s", file_type, 2100 file->offset, file->version, file->label); 2101 2102 if (!emlxs_sli2_check(hba, id)) { 2103 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2104 "SLI2 Check: Image not compatible with %s. id=%02x", 2105 hba->model_info.model, id); 2106 2107 return (EMLXS_IMAGE_INCOMPATIBLE); 2108 } 2109 2110 break; 2111 2112 case SLI3_OVERLAY: 2113 2114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2115 "%s: SLI3: offset=%08x version=%08x, %s", file_type, 2116 file->offset, file->version, file->label); 2117 2118 if (!emlxs_sli3_check(hba, id)) { 2119 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2120 "SLI3 Check: Image not compatible with %s. id=%02x", 2121 hba->model_info.model, id); 2122 2123 return (EMLXS_IMAGE_INCOMPATIBLE); 2124 } 2125 2126 break; 2127 2128 case SLI4_OVERLAY: 2129 2130 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2131 "%s: SLI4: offset=%08x version=%08x, %s", file_type, 2132 file->offset, file->version, file->label); 2133 2134 if (!emlxs_sli4_check(hba, id)) { 2135 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2136 "SLI4 Check: Image not compatible with %s. id=%02x", 2137 hba->model_info.model, id); 2138 2139 return (EMLXS_IMAGE_INCOMPATIBLE); 2140 } 2141 2142 break; 2143 2144 case SBUS_FCODE: 2145 2146 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2147 "%s: SBUS FCODE: offset=%08x version=%08x, %s", 2148 file_type, file->offset, file->version, file->label); 2149 2150 if (!emlxs_sbus_fcode_check(hba, id)) { 2151 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2152 "SBUS FCODE Check: Image not compatible with %s. " 2153 "id=%02x", hba->model_info.model, id); 2154 2155 return (EMLXS_IMAGE_INCOMPATIBLE); 2156 } 2157 2158 break; 2159 2160 case KERNEL_CODE: 2161 2162 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2163 "%s: KERN: offset=%08x version=%08x, %s", file_type, 2164 file->offset, file->version, file->label); 2165 2166 if (!emlxs_kern_check(hba, id)) { 2167 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2168 "KERN Check: Image not compatible with %s. id=%02x", 2169 hba->model_info.model, id); 2170 2171 return (EMLXS_IMAGE_INCOMPATIBLE); 2172 } 2173 2174 break; 2175 2176 default: 2177 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2178 "%s: Image type not supported. type=%x", file_type, type); 2179 2180 return (EMLXS_IMAGE_BAD); 2181 } 2182 2183 return (0); 2184 2185 } /* emlxs_validate_version() */ 2186 2187 2188 static uint32_t 2189 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size, 2190 emlxs_fw_image_t *image) 2191 { 2192 emlxs_port_t *port = &PPORT; 2193 uint32_t ImageType; 2194 AIF_HDR AifHdr; 2195 IMAGE_HDR ImageHdr; 2196 uint32_t NextImage; 2197 uint32_t FileType; 2198 uint32_t FileLen = 0; 2199 uint32_t TotalLen = 0; 2200 uint32_t *CkSumEnd; 2201 uint32_t id; 2202 uint32_t type; 2203 uint32_t ver; 2204 uint32_t ImageLength; 2205 uint32_t BufferSize; 2206 uint32_t rval = 0; 2207 caddr_t bptr; 2208 emlxs_vpd_t *vpd; 2209 2210 vpd = &VPD; 2211 2212 /* Get image type */ 2213 ImageType = *((uint32_t *)Buffer); 2214 2215 /* Pegasus and beyond adapters */ 2216 if ((ImageType == NOP_IMAGE_TYPE) && 2217 !(hba->model_info.chip & 2218 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 2219 bptr = Buffer; 2220 TotalLen = sizeof (uint32_t); 2221 2222 while (TotalLen < Size) { 2223 if (Size < sizeof (AIF_HDR)) { 2224 EMLXS_MSGF(EMLXS_CONTEXT, 2225 &emlxs_image_bad_msg, 2226 "Invalid image header length: 0x%x < 0x%x", 2227 Size, sizeof (AIF_HDR)); 2228 2229 return (EMLXS_IMAGE_BAD); 2230 } 2231 2232 bcopy(bptr, &AifHdr, sizeof (AIF_HDR)); 2233 emlxs_disp_aif_header(hba, &AifHdr); 2234 2235 ImageLength = AifHdr.RoSize; 2236 2237 /* Validate checksum */ 2238 CkSumEnd = 2239 (uint32_t *)(bptr + ImageLength + 2240 sizeof (AIF_HDR)); 2241 if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) { 2242 EMLXS_MSGF(EMLXS_CONTEXT, 2243 &emlxs_image_bad_msg, 2244 "Invalid checksum found."); 2245 2246 return (EMLXS_IMAGE_BAD); 2247 } 2248 2249 FileType = AifHdr.ZinitBr; 2250 switch (FileType) { 2251 case FILE_TYPE_AWC: 2252 image->awc.offset = 2253 (uint32_t)((uintptr_t)bptr - 2254 (uintptr_t)Buffer); 2255 image->awc.version = AifHdr.AVersion; 2256 image->awc.revcomp = 0; 2257 2258 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 2259 type = emlxs_type_check( 2260 (AifHdr.AVersion & 0xff000000) >> 24); 2261 2262 /* Validate the file version */ 2263 if ((rval = emlxs_validate_version(hba, 2264 &image->awc, id, type, "AWC file"))) { 2265 return (rval); 2266 } 2267 2268 break; 2269 2270 case FILE_TYPE_BWC: 2271 image->bwc.offset = 2272 (uint32_t)((uintptr_t)bptr - 2273 (uintptr_t)Buffer); 2274 image->bwc.version = AifHdr.AVersion; 2275 image->bwc.revcomp = 0; 2276 2277 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 2278 type = emlxs_type_check( 2279 (AifHdr.AVersion & 0xff000000) >> 24); 2280 2281 /* Validate the file version */ 2282 if ((rval = emlxs_validate_version(hba, 2283 &image->bwc, id, type, "BWC file"))) { 2284 return (rval); 2285 } 2286 2287 break; 2288 2289 case FILE_TYPE_DWC: 2290 image->dwc.offset = 2291 (uint32_t)((uintptr_t)bptr - 2292 (uintptr_t)Buffer); 2293 image->dwc.version = AifHdr.AVersion; 2294 image->dwc.revcomp = 0; 2295 2296 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 2297 type = emlxs_type_check( 2298 (AifHdr.AVersion & 0xff000000) >> 24); 2299 2300 /* Validate the file version */ 2301 if ((rval = emlxs_validate_version(hba, 2302 &image->dwc, id, type, "DWC file"))) { 2303 return (rval); 2304 } 2305 2306 /* Scan for program types */ 2307 NextImage = sizeof (AIF_HDR) + 4; 2308 BufferSize = AifHdr.RoSize + AifHdr.RwSize; 2309 2310 while (BufferSize > NextImage) { 2311 bcopy(&bptr[NextImage], &ImageHdr, 2312 sizeof (IMAGE_HDR)); 2313 emlxs_dump_image_header(hba, 2314 &ImageHdr); 2315 2316 /* Validate block size */ 2317 if (ImageHdr.BlockSize == 0xffffffff) { 2318 break; 2319 } 2320 2321 type = emlxs_type_check( 2322 ImageHdr.Id.Type); 2323 2324 /* Calculate the program offset */ 2325 image->prog[type].offset = 2326 (uint32_t)((uintptr_t) 2327 &bptr[NextImage] - 2328 (uintptr_t)Buffer); 2329 2330 /* Acquire the versions */ 2331 image->prog[type].version = 2332 (ImageHdr.Id.Type << 24) | 2333 (ImageHdr.Id.Id << 16) | 2334 (ImageHdr.Id.Ver << 8) | 2335 ImageHdr.Id.Rev; 2336 2337 image->prog[type].revcomp = 2338 ImageHdr.Id.un.revcomp; 2339 2340 /* Validate the file version */ 2341 if ((rval = emlxs_validate_version(hba, 2342 &image->prog[type], ImageHdr.Id.Id, 2343 type, "DWC prog"))) { 2344 return (rval); 2345 } 2346 2347 NextImage += ImageHdr.BlockSize; 2348 2349 } /* while() */ 2350 2351 break; 2352 } 2353 2354 FileLen = 2355 sizeof (AIF_HDR) + ImageLength + 2356 sizeof (uint32_t); 2357 TotalLen += FileLen; 2358 bptr += FileLen; 2359 } 2360 } 2361 2362 /* Pre-pegasus adapters */ 2363 2364 else if (ImageType == NOP_IMAGE_TYPE) { 2365 if (Size < sizeof (AIF_HDR)) { 2366 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2367 "Invalid image header length: 0x%x < 0x%x", Size, 2368 sizeof (AIF_HDR)); 2369 2370 return (EMLXS_IMAGE_BAD); 2371 } 2372 2373 bcopy(Buffer, &AifHdr, sizeof (AIF_HDR)); 2374 emlxs_disp_aif_header(hba, &AifHdr); 2375 2376 ImageLength = AifHdr.RoSize + AifHdr.RwSize; 2377 2378 if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) { 2379 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2380 "Image length incorrect: 0x%x != 0x%x", Size, 2381 sizeof (AIF_HDR) + ImageLength + 2382 sizeof (uint32_t)); 2383 2384 return (EMLXS_IMAGE_BAD); 2385 } 2386 2387 if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) { 2388 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2389 "Invalid imageBase value %x != 0x20000", 2390 AifHdr.ImageBase); 2391 2392 return (EMLXS_IMAGE_BAD); 2393 } 2394 2395 CkSumEnd = 2396 (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR)); 2397 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) { 2398 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2399 "Invalid checksum found."); 2400 2401 return (EMLXS_IMAGE_BAD); 2402 } 2403 2404 image->dwc.offset = 0; 2405 image->dwc.version = AifHdr.AVersion; 2406 image->dwc.revcomp = 0; 2407 2408 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 2409 type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24); 2410 2411 /* Validate the file version */ 2412 if ((rval = emlxs_validate_version(hba, &image->dwc, id, type, 2413 "DWC file"))) { 2414 return (rval); 2415 } 2416 2417 NextImage = SLI_IMAGE_START - AifHdr.ImageBase; 2418 while (Size > NextImage) { 2419 bcopy(&Buffer[NextImage], &ImageHdr, 2420 sizeof (IMAGE_HDR)); 2421 emlxs_dump_image_header(hba, &ImageHdr); 2422 2423 /* Validate block size */ 2424 if (ImageHdr.BlockSize == 0xffffffff) { 2425 break; 2426 } 2427 2428 type = emlxs_type_check(ImageHdr.Id.Type); 2429 2430 /* Calculate the program offset */ 2431 image->prog[type].offset = NextImage; 2432 2433 /* Acquire the versions */ 2434 image->prog[type].version = 2435 (ImageHdr.Id.Type << 24) | 2436 (ImageHdr.Id.Id << 16) | 2437 (ImageHdr.Id.Ver << 8) | 2438 ImageHdr.Id.Rev; 2439 2440 image->prog[type].revcomp = ImageHdr.Id.un.revcomp; 2441 2442 /* Validate the file version */ 2443 if ((rval = emlxs_validate_version(hba, 2444 &image->prog[type], ImageHdr.Id.Id, type, 2445 "DWC prog"))) { 2446 return (rval); 2447 } 2448 2449 NextImage += ImageHdr.BlockSize; 2450 } 2451 } else { 2452 /* Precheck image size */ 2453 if (Size < sizeof (IMAGE_HDR)) { 2454 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2455 "Invalid image header length: 0x%x < 0x%x", Size, 2456 sizeof (IMAGE_HDR)); 2457 2458 return (EMLXS_IMAGE_BAD); 2459 } 2460 2461 bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR)); 2462 emlxs_dump_image_header(hba, &ImageHdr); 2463 2464 /* Validate block size */ 2465 if (ImageHdr.BlockSize == 0xffffffff) { 2466 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2467 "Invalid block size."); 2468 2469 return (EMLXS_IMAGE_BAD); 2470 } 2471 2472 ImageLength = ImageHdr.BlockSize; 2473 2474 /* Validate image length */ 2475 if (Size != ImageLength) { 2476 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2477 "Invalid image length: 0x%x != 0x%x", Size, 2478 ImageLength); 2479 2480 return (EMLXS_IMAGE_BAD); 2481 } 2482 2483 /* Validate Checksum */ 2484 CkSumEnd = 2485 (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) - 2486 1; 2487 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) { 2488 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2489 "Invalid checksum found."); 2490 2491 return (EMLXS_IMAGE_BAD); 2492 } 2493 2494 type = emlxs_type_check(ImageHdr.Id.Type); 2495 2496 /* Calculate the program offset */ 2497 image->prog[type].offset = 0; 2498 2499 /* Acquire the versions */ 2500 image->prog[type].version = 2501 (ImageHdr.Id.Type << 24) | (ImageHdr.Id. 2502 Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev; 2503 2504 image->prog[type].revcomp = ImageHdr.Id.un.revcomp; 2505 2506 /* Validate the file version */ 2507 if ((rval = emlxs_validate_version(hba, &image->prog[type], 2508 ImageHdr.Id.Id, type, "DWC file"))) { 2509 return (rval); 2510 } 2511 } 2512 2513 /* 2514 * This checks if a DragonFly (pre-V2 ASIC) SLI2 2515 * image file is greater than version 3.8 2516 */ 2517 if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) { 2518 if (image->prog[SLI2_OVERLAY].version != 0) { 2519 ver = (image->prog[SLI2_OVERLAY].version & 2520 0x0000ff00) >> 8; 2521 2522 if ((((ver & 0xf0) == 0x30) && 2523 ((ver & 0x0f) >= 0x08)) || 2524 ((ver & 0xf0) > 0x30)) { 2525 EMLXS_MSGF(EMLXS_CONTEXT, 2526 &emlxs_image_incompat_msg, 2527 "ASIC Check: Image requires DragonFly " 2528 "V2 ASIC"); 2529 2530 return (EMLXS_IMAGE_INCOMPATIBLE); 2531 } 2532 } 2533 } 2534 2535 return (0); 2536 2537 } /* emlxs_validate_image() */ 2538 2539 2540 static uint32_t 2541 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms) 2542 { 2543 emlxs_port_t *port = &PPORT; 2544 MAILBOXQ *mbox; 2545 MAILBOX *mb; 2546 uint32_t next_address; 2547 uint32_t rval = 0; 2548 2549 if (WakeUpParms->u1.EROM_prog_wd[0] == 0) { 2550 return (1); 2551 } 2552 2553 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2554 KM_NOSLEEP)) == NULL) { 2555 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2556 "Unable to allocate mailbox buffer."); 2557 2558 return (1); 2559 } 2560 2561 bzero(mbox, sizeof (MAILBOXQ)); 2562 2563 mb = (MAILBOX *)mbox; 2564 mb->mbxCommand = MBX_LOAD_EXP_ROM; 2565 mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE; 2566 mb->un.varLdExpRom.progress = 0; 2567 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 2568 2569 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 2570 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2571 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 2572 mb->mbxCommand, mb->mbxStatus); 2573 2574 rval = 1; 2575 2576 goto SLI_DOWNLOAD_EXIT; 2577 } 2578 2579 if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) { 2580 (void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms); 2581 2582 rval = 1; 2583 goto SLI_DOWNLOAD_EXIT; 2584 } 2585 2586 if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) { 2587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2588 "Invalid exp ROM progress. progress=%x", 2589 mb->un.varLdExpRom.progress); 2590 2591 rval = 1; 2592 2593 goto SLI_DOWNLOAD_EXIT; 2594 } 2595 2596 /* 2597 * continue Erase 2598 */ 2599 while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) { 2600 2601 next_address = mb->un.varLdExpRom.dl_to_adr; 2602 2603 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2604 2605 mb->mbxCommand = MBX_LOAD_EXP_ROM; 2606 mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE; 2607 mb->un.varLdExpRom.dl_to_adr = next_address; 2608 mb->un.varLdExpRom.progress = 0; 2609 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 2610 2611 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 2612 MBX_SUCCESS) { 2613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2614 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 2615 mb->mbxCommand, mb->mbxStatus); 2616 2617 rval = 1; 2618 goto SLI_DOWNLOAD_EXIT; 2619 } 2620 2621 } 2622 2623 while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) { 2624 next_address = mb->un.varLdExpRom.dl_to_adr; 2625 2626 bzero((void *)mb, MAILBOX_CMD_BSIZE); 2627 2628 mb->mbxCommand = MBX_LOAD_EXP_ROM; 2629 mb->un.varLdExpRom.step = EROM_CMD_COPY; 2630 mb->un.varLdExpRom.dl_to_adr = next_address; 2631 mb->un.varLdExpRom.progress = 0; 2632 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 2633 2634 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 2635 MBX_SUCCESS) { 2636 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2637 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 2638 mb->mbxCommand, mb->mbxStatus); 2639 2640 rval = 1; 2641 2642 goto SLI_DOWNLOAD_EXIT; 2643 } 2644 } 2645 2646 rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms); 2647 2648 SLI_DOWNLOAD_EXIT: 2649 2650 if (mbox) { 2651 kmem_free(mbox, sizeof (MAILBOXQ)); 2652 } 2653 2654 return (rval); 2655 2656 } /* emlxs_update_exp_rom() */ 2657 2658 2659 /* 2660 * 2661 * FUNCTION NAME: emlxs_start_abs_download_2mb 2662 * 2663 * DESCRIPTION: Perform absolute download for 2 MB flash. A incoming 2664 * buffer may consist of more than 1 file. This function 2665 * will parse the buffer to find all the files. 2666 * 2667 * 2668 * PARAMETERS: 2669 * 2670 * 2671 * RETURNS: 2672 * 2673 */ 2674 /* ARGSUSED */ 2675 static uint32_t 2676 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, 2677 uint32_t offline, emlxs_fw_image_t *fw_image) 2678 { 2679 emlxs_port_t *port = &PPORT; 2680 caddr_t AwcBuffer = NULL; 2681 caddr_t BwcBuffer = NULL; 2682 caddr_t DwcBuffer = NULL; 2683 AIF_HDR *AwcAifHdr; 2684 AIF_HDR *BwcAifHdr; 2685 AIF_HDR *DwcAifHdr; 2686 uint32_t BWCflag; 2687 emlxs_vpd_t *vpd; 2688 uint32_t i; 2689 uint32_t count; 2690 uint32_t extType = 0; 2691 uint32_t rval = 0; 2692 2693 vpd = &VPD; 2694 2695 /* Check for AWC file */ 2696 if (fw_image->awc.version) { 2697 AwcBuffer = buffer + fw_image->awc.offset; 2698 AwcAifHdr = (AIF_HDR *)AwcBuffer; 2699 } 2700 2701 /* Check for BWC file */ 2702 if (fw_image->bwc.version) { 2703 extType = BWCext; 2704 BwcBuffer = buffer + fw_image->bwc.offset; 2705 BwcAifHdr = (AIF_HDR *)BwcBuffer; 2706 } 2707 2708 /* Check for DWC file */ 2709 if (fw_image->dwc.version) { 2710 extType = DWCext; 2711 DwcBuffer = buffer + fw_image->dwc.offset; 2712 DwcAifHdr = (AIF_HDR *)DwcBuffer; 2713 } 2714 2715 /* Check for program files */ 2716 count = 0; 2717 for (i = 0; i < MAX_PROG_TYPES; i++) { 2718 if (fw_image->prog[i].version) { 2719 count++; 2720 } 2721 } 2722 2723 if (count > 1) { 2724 extType = ALLext; 2725 2726 if (fw_image->bwc.version) { 2727 BWCflag = ALL_WITH_BWC; 2728 } else { 2729 BWCflag = ALL_WITHOUT_BWC; 2730 } 2731 } else { 2732 BWCflag = NO_ALL; 2733 } 2734 2735 /* If nothing to download then quit now */ 2736 if (!AwcBuffer && !DwcBuffer && !BwcBuffer) { 2737 return (0); 2738 } 2739 2740 /* 2741 * Everything checks out, now to just do it 2742 */ 2743 if (offline) { 2744 if (emlxs_offline(hba) != FC_SUCCESS) { 2745 return (EMLXS_OFFLINE_FAILED); 2746 } 2747 2748 if (emlxs_sli_hba_reset(hba, 1, 1) != FC_SUCCESS) { 2749 return (EMLXS_OFFLINE_FAILED); 2750 } 2751 } 2752 2753 if (AwcBuffer) { 2754 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2755 "AWC file: KERN: old=%s new=%s ", vpd->postKernName, 2756 fw_image->awc.label); 2757 2758 rval = emlxs_proc_abs_2mb(hba, 2759 AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType); 2760 2761 if (rval) { 2762 goto SLI_DOWNLOAD_2MB_EXIT; 2763 } 2764 } 2765 2766 if (DwcBuffer) { 2767 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2768 "DWC file: TEST: new=%s ", 2769 fw_image->prog[TEST_PROGRAM].label); 2770 2771 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2772 "DWC file: STUB: old=%s new=%s ", vpd->opFwName, 2773 fw_image->prog[FUNC_FIRMWARE].label); 2774 2775 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2776 "DWC file: SLI1: old=%s new=%s ", vpd->sli1FwName, 2777 fw_image->prog[SLI1_OVERLAY].label); 2778 2779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2780 "DWC file: SLI2: old=%s new=%s ", vpd->sli2FwName, 2781 fw_image->prog[SLI2_OVERLAY].label); 2782 2783 if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) { 2784 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2785 "DWC file: SLI3: old=%s new=%s ", 2786 vpd->sli3FwName, 2787 fw_image->prog[SLI3_OVERLAY].label); 2788 } 2789 2790 if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) { 2791 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2792 "DWC file: SLI4: old=%s new=%s ", 2793 vpd->sli4FwName, 2794 fw_image->prog[SLI4_OVERLAY].label); 2795 } 2796 2797 rval = emlxs_proc_abs_2mb(hba, 2798 DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType); 2799 2800 if (rval) { 2801 goto SLI_DOWNLOAD_2MB_EXIT; 2802 } 2803 } 2804 2805 if (BwcBuffer) { 2806 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2807 "BWC file: BOOT: old=%s new=%s ", vpd->fcode_version, 2808 fw_image->bwc.label); 2809 2810 rval = emlxs_proc_abs_2mb(hba, 2811 BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType); 2812 } 2813 2814 SLI_DOWNLOAD_2MB_EXIT: 2815 2816 if (offline) { 2817 (void) emlxs_online(hba); 2818 } 2819 2820 return (rval); 2821 2822 } /* emlxs_start_abs_download_2mb() */ 2823 2824 2825 /* 2826 * 2827 * FUNCTION NAME: emlxs_proc_abs_2mb 2828 * 2829 * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset 2830 * the port and download the file with sliIssueMbCommand() 2831 * 2832 * 2833 * PARAMETERS: 2834 * 2835 * 2836 * RETURNS: 2837 * 2838 */ 2839 static uint32_t 2840 emlxs_proc_abs_2mb(emlxs_hba_t *hba, 2841 PAIF_HDR AifHdr, 2842 caddr_t EntireBuffer, 2843 uint32_t FileType, uint32_t BWCflag, uint32_t extType) 2844 { 2845 emlxs_port_t *port = &PPORT; 2846 caddr_t Buffer = NULL; 2847 caddr_t DataBuffer = NULL; 2848 uint32_t *Src; 2849 uint32_t *Dst; 2850 MAILBOXQ *mbox; 2851 MAILBOX *mb; 2852 uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize; 2853 uint32_t rval = 0; 2854 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 2855 uint32_t DlToAddr = AifHdr->ImageBase; 2856 uint32_t DlCount; 2857 WAKE_UP_PARMS AbsWakeUpParms; 2858 uint32_t i; 2859 uint32_t NextAddr; 2860 uint32_t EraseByteCount; 2861 uint32_t AreaId; 2862 uint32_t RspProgress = 0; 2863 uint32_t numBootImage = 0; 2864 uint32_t ParamsChg = 0; 2865 uint32_t BufferSize; 2866 2867 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 2868 KM_NOSLEEP)) == NULL) { 2869 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2870 "%x: Unable to allocate data buffer.", FileType); 2871 2872 return (EMLXS_IMAGE_FAILED); 2873 } 2874 2875 bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT)); 2876 2877 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2878 KM_NOSLEEP)) == NULL) { 2879 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2880 "%x: Unable to allocate mailbox buffer.", FileType); 2881 2882 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 2883 2884 return (EMLXS_IMAGE_FAILED); 2885 } 2886 2887 mb = (MAILBOX *)mbox; 2888 2889 BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t); 2890 Buffer = EntireBuffer + sizeof (AIF_HDR); 2891 2892 switch (FileType) { 2893 case FILE_TYPE_AWC: 2894 break; 2895 2896 case FILE_TYPE_BWC: 2897 ParamsChg = emlxs_build_parms_2mb_bwc(hba, 2898 AifHdr, extType, &AbsWakeUpParms); 2899 2900 if (ParamsChg == FALSE) { 2901 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2902 "BWC build parms failed."); 2903 2904 rval = EMLXS_IMAGE_FAILED; 2905 2906 goto EXIT_ABS_DOWNLOAD; 2907 } 2908 break; 2909 2910 case FILE_TYPE_DWC: 2911 ParamsChg = emlxs_build_parms_2mb_dwc(hba, 2912 Buffer, 2913 BufferSize, 2914 AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage); 2915 2916 if (ParamsChg == FALSE) { 2917 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2918 "DWC build parms failed."); 2919 2920 rval = EMLXS_IMAGE_FAILED; 2921 2922 goto EXIT_ABS_DOWNLOAD; 2923 } 2924 break; 2925 2926 default: 2927 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 2928 "Invalid file type: %x", FileType); 2929 2930 rval = EMLXS_IMAGE_BAD; 2931 2932 goto EXIT_ABS_DOWNLOAD; 2933 2934 } 2935 2936 EraseByteCount = AifHdr->Area_Size; 2937 AreaId = AifHdr->Area_ID; 2938 2939 emlxs_format_load_area_cmd(mb, 2940 DlToAddr, 2941 EraseByteCount, 2942 ERASE_FLASH, 2943 0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE); 2944 2945 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != MBX_SUCCESS) { 2946 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2947 "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x", 2948 FileType, mb->mbxCommand, mb->mbxStatus); 2949 2950 rval = EMLXS_IMAGE_FAILED; 2951 2952 goto EXIT_ABS_DOWNLOAD; 2953 } 2954 2955 while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) { 2956 NextAddr = mb->un.varLdArea.dl_to_adr; 2957 2958 emlxs_format_load_area_cmd(mb, 2959 NextAddr, 2960 EraseByteCount, 2961 ERASE_FLASH, 2962 0, 2963 DL_FROM_SLIM_OFFSET, 2964 AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE); 2965 2966 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 2967 MBX_SUCCESS) { 2968 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2969 "%x: Could not erase 2MB Flash2: Mailbox cmd=%x " 2970 "status=%x", FileType, mb->mbxCommand, 2971 mb->mbxStatus); 2972 2973 rval = EMLXS_IMAGE_FAILED; 2974 2975 goto EXIT_ABS_DOWNLOAD; 2976 } 2977 } 2978 2979 while (DlByteCount) { 2980 if (DlByteCount >= SegSize) 2981 DlCount = SegSize; 2982 else 2983 DlCount = DlByteCount; 2984 2985 DlByteCount -= DlCount; 2986 2987 Dst = (uint32_t *)DataBuffer; 2988 Src = (uint32_t *)Buffer; 2989 2990 for (i = 0; i < (DlCount / 4); i++) { 2991 *Dst = *Src; 2992 Dst++; 2993 Src++; 2994 } 2995 2996 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 2997 (volatile uint32_t *)((volatile char *)hba->slim_addr + 2998 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t))); 2999 3000 if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) { 3001 emlxs_format_load_area_cmd(mb, 3002 DlToAddr, 3003 DlCount, 3004 PROGRAM_FLASH, 3005 (DlByteCount) ? 0 : 1, 3006 DL_FROM_SLIM_OFFSET, 3007 AreaId, 3008 MBX_LOAD_AREA, 3009 (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD); 3010 3011 if (emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0) != 3012 MBX_SUCCESS) { 3013 EMLXS_MSGF(EMLXS_CONTEXT, 3014 &emlxs_download_failed_msg, 3015 "%x: Could not program 2MB Flash: Mailbox " 3016 "cmd=%x status=%x", FileType, 3017 mb->mbxCommand, mb->mbxStatus); 3018 3019 rval = EMLXS_IMAGE_FAILED; 3020 3021 goto EXIT_ABS_DOWNLOAD; 3022 } 3023 } 3024 3025 RspProgress = mb->un.varLdArea.progress; 3026 3027 Buffer += DlCount; 3028 DlToAddr += DlCount; 3029 } 3030 3031 if (RspProgress != RSP_DOWNLOAD_DONE) { 3032 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3033 "%x: Failed download response received. %x", FileType, 3034 RspProgress); 3035 3036 rval = EMLXS_IMAGE_FAILED; 3037 3038 goto EXIT_ABS_DOWNLOAD; 3039 } 3040 3041 if (ParamsChg) { 3042 if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms, 3043 &AbsWakeUpParms)) { 3044 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3045 "%x: Unable to update parms.", FileType); 3046 3047 rval = EMLXS_IMAGE_FAILED; 3048 } 3049 } 3050 3051 EXIT_ABS_DOWNLOAD: 3052 3053 if (DataBuffer) { 3054 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 3055 } 3056 3057 if (mbox) { 3058 kmem_free(mbox, sizeof (MAILBOXQ)); 3059 } 3060 3061 return (rval); 3062 3063 } /* emlxs_proc_abs_2mb() */ 3064 3065 3066 static void 3067 emlxs_format_load_area_cmd(MAILBOX * mb, 3068 uint32_t Base, 3069 uint32_t DlByteCount, 3070 uint32_t Function, 3071 uint32_t Complete, 3072 uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd) 3073 { 3074 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3075 3076 mb->mbxCommand = MbxCmd; 3077 mb->mbxOwner = OWN_HOST; 3078 mb->un.varLdArea.update_flash = 1; 3079 mb->un.varLdArea.erase_or_prog = Function; 3080 mb->un.varLdArea.dl_to_adr = Base; 3081 mb->un.varLdArea.dl_len = DlByteCount; 3082 mb->un.varLdArea.load_cmplt = Complete; 3083 mb->un.varLdArea.method = DL_FROM_SLIM; 3084 mb->un.varLdArea.area_id = AreaId; 3085 mb->un.varLdArea.step = StepCmd; 3086 mb->un.varLdArea.un.dl_from_slim_offset = DataOffset; 3087 3088 } /* emlxs_format_load_area_cmd() */ 3089 3090 3091 /* ARGSUSED */ 3092 static uint32_t 3093 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, 3094 PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms) 3095 { 3096 emlxs_port_t *port = &PPORT; 3097 uint32_t pId[2]; 3098 uint32_t returnStat; 3099 3100 /* Read wakeup paramters */ 3101 if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) == 3102 CFG_DATA_NO_REGION) { 3103 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3104 "Unable to get BWC parameters."); 3105 return (FALSE); 3106 } 3107 3108 pId[0] = AifHdr->AVersion; 3109 pId[1] = 0; 3110 3111 if (extType == BWCext) { 3112 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0]; 3113 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1]; 3114 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 3115 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 3116 } 3117 3118 else if (extType == ALLext) { 3119 if (!AbsWakeUpParms->u0.boot_bios_wd[0]) { 3120 /* case of EROM inactive */ 3121 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 3122 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 3123 } else { 3124 /* case of EROM active */ 3125 if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) { 3126 /* same ID */ 3127 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0]; 3128 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1]; 3129 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 3130 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 3131 } else { 3132 /* different ID */ 3133 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 3134 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 3135 3136 returnStat = 3137 emlxs_update_exp_rom(hba, AbsWakeUpParms); 3138 3139 if (returnStat) { 3140 AbsWakeUpParms->u0.boot_bios_wd[0] = 3141 pId[0]; 3142 AbsWakeUpParms->u0.boot_bios_wd[1] = 3143 pId[1]; 3144 } 3145 } 3146 } 3147 } 3148 3149 return (TRUE); 3150 3151 } /* emlxs_build_parms_2mb_bwc() */ 3152 3153 3154 /* ARGSUSED */ 3155 static uint32_t 3156 emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, 3157 caddr_t Buffer, 3158 uint32_t BufferSize, 3159 PAIF_HDR AifHeader, 3160 PWAKE_UP_PARMS AbsWakeUpParms, 3161 uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage) 3162 { 3163 emlxs_port_t *port = &PPORT; 3164 uint32_t NextImage; 3165 uint32_t i; 3166 IMAGE_HDR ImageHdr; 3167 uint32_t *ptr1; 3168 uint32_t *ptr2; 3169 PROG_ID BootId[MAX_BOOTID]; 3170 uint32_t ChangeParams = FALSE; 3171 WAKE_UP_PARMS WakeUpParms; 3172 caddr_t Sptr; 3173 caddr_t Dptr; 3174 3175 bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID); 3176 3177 /* Read wakeup paramters */ 3178 if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) == 3179 CFG_DATA_NO_REGION) { 3180 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3181 "Unable to get DWC parameters."); 3182 return (FALSE); 3183 } 3184 3185 bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms, 3186 sizeof (WAKE_UP_PARMS)); 3187 3188 if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) && 3189 (WakeUpParms.u0.boot_bios_wd[0])) { 3190 *numBootImage = 0; 3191 } 3192 3193 /* incoming buffer is without aif header */ 3194 NextImage = 0x84 - sizeof (AIF_HDR); 3195 BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t)); 3196 3197 while (BufferSize > NextImage) { 3198 Sptr = &Buffer[NextImage]; 3199 Dptr = (caddr_t)&ImageHdr; 3200 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 3201 Dptr[i] = Sptr[i]; 3202 } 3203 3204 if (ImageHdr.BlockSize == 0xffffffff) { 3205 break; 3206 } 3207 3208 switch (ImageHdr.Id.Type) { 3209 case TEST_PROGRAM: 3210 break; 3211 3212 case FUNC_FIRMWARE: 3213 AbsWakeUpParms->prog_id = ImageHdr.Id; 3214 ChangeParams = TRUE; 3215 break; 3216 3217 case BOOT_BIOS: 3218 if (!WakeUpParms.u0.boot_bios_wd[0]) { 3219 if (extType == DWCext) { 3220 break; 3221 } else if (BWCflag == ALL_WITHOUT_BWC) { 3222 /* for possible future changes */ 3223 break; 3224 } 3225 } 3226 ChangeParams = TRUE; 3227 3228 if (*numBootImage < MAX_BOOTID) { 3229 BootId[*numBootImage] = ImageHdr.Id; 3230 (*numBootImage)++; 3231 } 3232 break; 3233 3234 case SLI1_OVERLAY: 3235 AbsWakeUpParms->sli1_prog_id = ImageHdr.Id; 3236 ChangeParams = TRUE; 3237 break; 3238 3239 case SLI2_OVERLAY: 3240 AbsWakeUpParms->sli2_prog_id = ImageHdr.Id; 3241 ChangeParams = TRUE; 3242 break; 3243 3244 case SLI3_OVERLAY: 3245 AbsWakeUpParms->sli3_prog_id = ImageHdr.Id; 3246 ChangeParams = TRUE; 3247 break; 3248 3249 case SLI4_OVERLAY: 3250 AbsWakeUpParms->sli4_prog_id = ImageHdr.Id; 3251 ChangeParams = TRUE; 3252 break; 3253 } 3254 3255 NextImage += ImageHdr.BlockSize; 3256 } 3257 3258 if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) || 3259 (extType == DWCext))) { 3260 3261 if (*numBootImage > 1) { 3262 for (i = 0; i < *numBootImage; i++) { 3263 ptr1 = 3264 (uint32_t *)&WakeUpParms.u0. 3265 boot_bios_id; 3266 ptr2 = (uint32_t *)&BootId[i]; 3267 3268 if (ptr1[0] == ptr2[0]) { 3269 AbsWakeUpParms->u1.EROM_prog_id = 3270 BootId[i]; 3271 (void) emlxs_update_exp_rom(hba, 3272 AbsWakeUpParms); 3273 break; 3274 } 3275 } 3276 } else { 3277 if (*numBootImage == 1) { 3278 ptr2 = (uint32_t *)&BootId[0]; 3279 3280 if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) { 3281 AbsWakeUpParms->u1.EROM_prog_id = 3282 BootId[0]; 3283 (void) emlxs_update_exp_rom(hba, 3284 AbsWakeUpParms); 3285 } 3286 } 3287 } 3288 } 3289 3290 return (ChangeParams); 3291 3292 3293 } /* emlxs_build_parms_2mb_dwc() */ 3294 3295 3296 extern uint32_t 3297 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize, 3298 uint32_t *MaxIbusSize) 3299 { 3300 emlxs_port_t *port = &PPORT; 3301 MAILBOXQ *mbox; 3302 MAILBOX *mb; 3303 uint32_t *Uptr; 3304 uint32_t rval = 0; 3305 3306 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 3307 KM_NOSLEEP)) == NULL) { 3308 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3309 "Unable to allocate mailbox buffer."); 3310 3311 return (1); 3312 } 3313 3314 mb = (MAILBOX *)mbox; 3315 3316 emlxs_format_dump(mb, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR); 3317 3318 if ((rval = emlxs_sli_issue_mbox_cmd(hba, mb, MBX_WAIT, 0)) != 3319 MBX_SUCCESS) { 3320 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3321 "Unable to get SRAM size: Mailbox cmd=%x status=%x", 3322 mb->mbxCommand, mb->mbxStatus); 3323 3324 rval = 1; 3325 3326 goto Exit_Function; 3327 } 3328 3329 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset; 3330 3331 *MaxRbusSize = Uptr[0]; 3332 *MaxIbusSize = Uptr[1]; 3333 3334 Exit_Function: 3335 3336 if (mbox) { 3337 kmem_free(mbox, sizeof (MAILBOXQ)); 3338 } 3339 3340 return (rval); 3341 3342 } /* emlxs_get_max_sram() */ 3343 3344 3345 static uint32_t 3346 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version) 3347 { 3348 uint8_t *ptr; 3349 uint8_t ver; 3350 3351 ver = version & 0xff; 3352 ptr = hba->model_info.pt_FF; 3353 3354 while (*ptr) { 3355 if (*ptr++ == ver) { 3356 return (1); 3357 } 3358 } 3359 3360 return (0); 3361 3362 } /* emlxs_kern_check() */ 3363 3364 static uint32_t 3365 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version) 3366 { 3367 uint8_t *ptr; 3368 uint8_t ver; 3369 3370 ver = version & 0xff; 3371 ptr = hba->model_info.pt_2; 3372 3373 while (*ptr) { 3374 if (*ptr++ == ver) { 3375 return (1); 3376 } 3377 } 3378 3379 return (0); 3380 3381 } /* emlxs_stub_check() */ 3382 3383 static uint32_t 3384 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version) 3385 { 3386 uint8_t *ptr; 3387 uint8_t ver; 3388 3389 ver = version & 0xff; 3390 ptr = hba->model_info.pt_3; 3391 3392 while (*ptr) { 3393 if (*ptr++ == ver) { 3394 return (1); 3395 } 3396 } 3397 3398 return (0); 3399 3400 } /* emlxs_bios_check() */ 3401 3402 static uint32_t 3403 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version) 3404 { 3405 uint8_t *ptr; 3406 uint8_t ver; 3407 3408 ver = version & 0xff; 3409 ptr = hba->model_info.pt_6; 3410 3411 while (*ptr) { 3412 if (*ptr++ == ver) { 3413 return (1); 3414 } 3415 } 3416 3417 return (0); 3418 3419 } /* emlxs_sli1_check() */ 3420 3421 static uint32_t 3422 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version) 3423 { 3424 uint8_t *ptr; 3425 uint8_t ver; 3426 3427 ver = version & 0xff; 3428 ptr = hba->model_info.pt_7; 3429 3430 while (*ptr) { 3431 if (*ptr++ == ver) { 3432 return (1); 3433 } 3434 } 3435 3436 return (0); 3437 3438 } /* emlxs_sli2_check() */ 3439 3440 static uint32_t 3441 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version) 3442 { 3443 uint8_t *ptr; 3444 uint8_t ver; 3445 3446 ver = version & 0xff; 3447 ptr = hba->model_info.pt_B; 3448 3449 while (*ptr) { 3450 if (*ptr++ == ver) { 3451 return (1); 3452 } 3453 } 3454 3455 return (0); 3456 3457 } /* emlxs_sli3_check() */ 3458 3459 3460 static uint32_t 3461 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version) 3462 { 3463 uint8_t *ptr; 3464 uint8_t ver; 3465 3466 ver = version & 0xff; 3467 ptr = hba->model_info.pt_E; 3468 3469 while (*ptr) { 3470 if (*ptr++ == ver) { 3471 return (1); 3472 } 3473 } 3474 3475 return (0); 3476 3477 } /* emlxs_sli4_check() */ 3478 3479 3480 static uint32_t 3481 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version) 3482 { 3483 uint8_t *ptr; 3484 uint8_t ver; 3485 3486 ver = version & 0xff; 3487 ptr = hba->model_info.pt_A; 3488 3489 while (*ptr) { 3490 if (*ptr++ == ver) { 3491 return (1); 3492 } 3493 } 3494 3495 return (0); 3496 3497 } /* emlxs_sbus_fcode_check() */ 3498 3499 static uint32_t 3500 emlxs_type_check(uint32_t type) 3501 { 3502 if (type == 0xff) { 3503 return (KERNEL_CODE); 3504 } 3505 3506 if (type >= MAX_PROG_TYPES) { 3507 return (RESERVED_D); 3508 } 3509 3510 return (type); 3511 3512 } /* emlxs_type_check() */ 3513 3514 3515 3516 extern int32_t 3517 emlxs_boot_code_disable(emlxs_hba_t *hba) 3518 { 3519 emlxs_port_t *port = &PPORT; 3520 PROG_ID Id; 3521 emlxs_vpd_t *vpd; 3522 3523 vpd = &VPD; 3524 3525 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) { 3526 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3527 "emlxs_boot_code_disable: Unable to read wake up parms."); 3528 3529 return (FC_FAILURE); 3530 } 3531 3532 /* Check if boot code is already disabled */ 3533 if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) { 3534 return (FC_SUCCESS); 3535 } 3536 3537 /* Make sure EROM entry has copy of boot bios entry */ 3538 if (!(hba->model_info.chip & 3539 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) && 3540 (hba->wakeup_parms.u0.boot_bios_wd[0] != 3541 hba->wakeup_parms.u1.EROM_prog_wd[0]) && 3542 (hba->wakeup_parms.u0.boot_bios_wd[1] != 3543 hba->wakeup_parms.u1.EROM_prog_wd[1])) { 3544 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, 3545 &hba->wakeup_parms.u0.boot_bios_id, 1); 3546 } 3547 3548 /* Update the bios id with a zero id */ 3549 /* Don't load the EROM this time */ 3550 bzero(&Id, sizeof (PROG_ID)); 3551 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0); 3552 3553 /* Now read the parms again to verify */ 3554 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 3555 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 3556 vpd->boot_version); 3557 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */ 3558 3559 /* Return the result */ 3560 return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ? 3561 FC_SUCCESS : FC_FAILURE); 3562 3563 } /* emlxs_boot_code_disable() */ 3564 3565 3566 extern int32_t 3567 emlxs_boot_code_enable(emlxs_hba_t *hba) 3568 { 3569 emlxs_port_t *port = &PPORT; 3570 emlxs_vpd_t *vpd; 3571 PROG_ID load_list[MAX_LOAD_ENTRY]; 3572 uint32_t i; 3573 3574 vpd = &VPD; 3575 3576 /* Read the wakeup parms */ 3577 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) { 3578 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3579 "emlxs_boot_code_enable: Unable to read wake up parms."); 3580 3581 return (FC_FAILURE); 3582 } 3583 3584 /* Check if boot code is already enabled */ 3585 if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) { 3586 return (FC_SUCCESS); 3587 } 3588 3589 if (!(hba->model_info.chip & 3590 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 3591 if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) { 3592 return (EMLXS_NO_BOOT_CODE); 3593 } 3594 3595 /* Update the parms with the boot image id */ 3596 /* Don't load the EROM this time */ 3597 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, 3598 &hba->wakeup_parms.u1.EROM_prog_id, 0); 3599 } else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */ 3600 3601 if (emlxs_get_load_list(hba, load_list)) { 3602 return (FC_FAILURE); 3603 } 3604 3605 /* Scan load list for a boot image */ 3606 for (i = 0; i < MAX_LOAD_ENTRY; i++) { 3607 if (load_list[i].Type == BOOT_BIOS) { 3608 /* Update the parms with the boot image id */ 3609 /* Don't load the EROM this time */ 3610 (void) emlxs_update_boot_wakeup_parms(hba, 3611 &hba->wakeup_parms, &load_list[i], 0); 3612 3613 break; 3614 } 3615 } 3616 3617 if (i == MAX_LOAD_ENTRY) { 3618 return (EMLXS_NO_BOOT_CODE); 3619 } 3620 } 3621 3622 /* Now read the parms again to verify */ 3623 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 3624 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 3625 vpd->boot_version); 3626 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */ 3627 3628 /* return the result */ 3629 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ? 3630 FC_SUCCESS : FC_FAILURE); 3631 3632 } /* emlxs_boot_code_enable() */ 3633 3634 3635 3636 extern int32_t 3637 emlxs_boot_code_state(emlxs_hba_t *hba) 3638 { 3639 emlxs_port_t *port = &PPORT; 3640 3641 /* Read the wakeup parms */ 3642 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) { 3643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 3644 "emlxs_boot_code_state: Unable to read wake up parms."); 3645 3646 return (FC_FAILURE); 3647 } 3648 3649 /* return the result */ 3650 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ? 3651 FC_SUCCESS : FC_FAILURE); 3652 3653 } /* emlxs_boot_code_state() */ 3654