1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains firmware log routines. 28 */ 29 30 #include <sys/scsi/adapters/pmcs/pmcs.h> 31 #include <sys/scsi/adapters/pmcs/pmcs_fwlog.h> 32 33 static int pmcs_dump_ioqs(pmcs_hw_t *, caddr_t, uint32_t); 34 static int pmcs_dump_spc_ver(pmcs_hw_t *, caddr_t, uint32_t); 35 static int pmcs_dump_mpi_table(pmcs_hw_t *, caddr_t, uint32_t); 36 static int pmcs_dump_gsm_conf(pmcs_hw_t *, caddr_t, uint32_t); 37 static int pmcs_dump_pcie_conf(pmcs_hw_t *, caddr_t, uint32_t); 38 static uint32_t pmcs_get_axil(pmcs_hw_t *); 39 static boolean_t pmcs_shift_axil(pmcs_hw_t *, uint32_t); 40 static void pmcs_restore_axil(pmcs_hw_t *, uint32_t); 41 static int pmcs_dump_gsm(pmcs_hw_t *, caddr_t, uint32_t); 42 static int pmcs_dump_gsm_addiregs(pmcs_hw_t *, caddr_t, uint32_t); 43 static int pmcs_dump_hsst_sregs(pmcs_hw_t *, caddr_t, uint32_t); 44 static int pmcs_dump_sspa_sregs(pmcs_hw_t *, caddr_t, uint32_t); 45 static int pmcs_dump_fwlog(pmcs_hw_t *, caddr_t, uint32_t); 46 47 /* 48 * Dump internal registers. Used after a firmware crash. 49 * Here dump various registers for firmware forensics, 50 * including MPI, GSM configuration, firmware log, IO Queues etc. 51 */ 52 void 53 pmcs_register_dump_int(pmcs_hw_t *pwp) 54 { 55 int n = 0; 56 uint32_t size_left = 0; 57 uint8_t slice = 0; 58 caddr_t buf = NULL; 59 60 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 61 "pmcs%d: Internal register dump", ddi_get_instance(pwp->dip)); 62 ASSERT(mutex_owned(&pwp->lock)); 63 64 if (pwp->regdumpp == NULL) { 65 pwp->regdumpp = 66 kmem_zalloc(PMCS_REG_DUMP_SIZE, KM_NOSLEEP); 67 if (pwp->regdumpp == NULL) { 68 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 69 "%s: register dump memory not allocated", __func__); 70 return; 71 } 72 } 73 buf = pwp->regdumpp; 74 size_left = PMCS_REG_DUMP_SIZE - 1; 75 76 n = pmcs_dump_spc_ver(pwp, buf, size_left); 77 ASSERT(size_left >= n); 78 buf += n; size_left -= n; 79 n = pmcs_dump_gsm_conf(pwp, buf, size_left); 80 ASSERT(size_left >= n); 81 buf += n; size_left -= n; 82 n = pmcs_dump_pcie_conf(pwp, buf, size_left); 83 ASSERT(size_left >= n); 84 buf += n; size_left -= n; 85 n = pmcs_dump_mpi_table(pwp, buf, size_left); 86 ASSERT(size_left >= n); 87 buf += n; size_left -= n; 88 n = pmcs_dump_ioqs(pwp, buf, size_left); 89 ASSERT(size_left >= n); 90 buf += n; size_left -= n; 91 mutex_exit(&pwp->lock); 92 slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE); 93 n = snprintf(buf, size_left, "\nDump AAP1 register: \n" 94 "-----------------\n"); 95 ASSERT(size_left >= n); 96 buf += n; size_left -= n; 97 for (uint8_t j = 0; j < slice; j++) { 98 n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP, 99 PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE), 100 buf, size_left); 101 if (n == PMCS_FLASH_CHUNK_SIZE) { 102 ASSERT(size_left >= n); 103 buf += n; size_left -= n; 104 } else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) { 105 ASSERT(size_left >= n); 106 buf += n; size_left -= n; 107 break; 108 } else if (n == 0) { 109 n = snprintf(buf, size_left, "AAP1: Content of " 110 "register dump on flash is NULL\n"); 111 ASSERT(size_left >= n); 112 buf += n; size_left -= n; 113 break; 114 } else { 115 n = snprintf(buf, size_left, 116 "AAP1: Unable to obtain internal register dump\n"); 117 ASSERT(size_left >= n); 118 buf += n; size_left -= n; 119 break; 120 } 121 122 } 123 124 n = snprintf(buf, size_left, "\nDump IOP register: \n" 125 "-----------------\n"); 126 ASSERT(size_left >= n); 127 buf += n; size_left -= n; 128 for (uint8_t j = 0; j < slice; j++) { 129 n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP, 130 PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE), 131 buf, size_left); 132 if (n == PMCS_FLASH_CHUNK_SIZE) { 133 ASSERT(size_left >= n); 134 buf += n; size_left -= n; 135 } else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) { 136 ASSERT(size_left >= n); 137 buf += n; size_left -= n; 138 break; 139 } else if (n == 0) { 140 n = snprintf(buf, size_left, 141 "IOP: Content of internal register dump is NULL\n"); 142 ASSERT(size_left >= n); 143 buf += n; size_left -= n; 144 break; 145 } else { 146 n = snprintf(buf, size_left, 147 "IOP: Unable to obtain internal register dump\n"); 148 ASSERT(size_left >= n); 149 buf += n; size_left -= n; 150 break; 151 } 152 153 } 154 155 n = snprintf(buf, size_left, "\nDump AAP1 event log: \n" 156 "-----------------\n"); 157 ASSERT(size_left >= n); 158 buf += n; size_left -= n; 159 for (uint8_t j = 0; j < slice; j++) { 160 n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG, 161 PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE), 162 buf, size_left); 163 if (n > 0) { 164 ASSERT(size_left >= n); 165 buf += n; size_left -= n; 166 } else { 167 n = snprintf(buf, size_left, 168 "AAP1: Unable to obtain event log on flash\n"); 169 ASSERT(size_left >= n); 170 buf += n; size_left -= n; 171 break; 172 } 173 } 174 175 n = snprintf(buf, size_left, "\nDump IOP event log: \n" 176 "-----------------\n"); 177 ASSERT(size_left >= n); 178 buf += n; size_left -= n; 179 for (uint8_t j = 0; j < slice; j++) { 180 n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG, 181 PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE), 182 buf, size_left); 183 if (n > 0) { 184 ASSERT(size_left >= n); 185 buf += n; size_left -= n; 186 } else { 187 n = snprintf(buf, size_left, 188 "IOP: Unable to obtain event log dump\n"); 189 ASSERT(size_left >= n); 190 buf += n; size_left -= n; 191 break; 192 } 193 } 194 mutex_enter(&pwp->lock); 195 196 n = pmcs_dump_gsm_addiregs(pwp, buf, size_left); 197 ASSERT(size_left >= n); 198 buf += n; size_left -= n; 199 200 n = pmcs_dump_hsst_sregs(pwp, buf, size_left); 201 ASSERT(size_left >= n); 202 buf += n; size_left -= n; 203 204 n = pmcs_dump_sspa_sregs(pwp, buf, size_left); 205 ASSERT(size_left >= n); 206 buf += n; size_left -= n; 207 n = snprintf(buf, size_left, "\nDump firmware log: \n" 208 "-----------------\n"); 209 ASSERT(size_left >= n); 210 buf += n; size_left -= n; 211 212 n = pmcs_dump_fwlog(pwp, buf, size_left); 213 ASSERT(size_left >= n); 214 buf += n; size_left -= n; 215 216 n = pmcs_dump_gsm(pwp, buf, size_left); 217 ASSERT(size_left >= n); 218 buf += n; size_left -= n; 219 220 n = snprintf(buf, size_left, "-----------------\n" 221 "\n------------ Dump internal registers end -------------\n"); 222 ASSERT(size_left >= n); 223 buf += n; size_left -= n; 224 } 225 226 static int 227 pmcs_dump_fwlog(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 228 { 229 pmcs_fw_event_hdr_t *evl_hdr; 230 int n = 0, retries = 0; 231 uint32_t evlog_latest_idx; 232 boolean_t log_is_current = B_FALSE; 233 234 if (pwp->fwlogp == NULL) { 235 n = snprintf(buf, size_left, "\nFirmware logging " 236 "not enabled\n"); 237 return (n); 238 } 239 240 /* 241 * First, check to make sure all entries have been DMAed to the 242 * log buffer. 243 * 244 * We'll wait the required 50ms, but if the latest entry keeps 245 * changing, we'll only retry twice 246 */ 247 evl_hdr = (pmcs_fw_event_hdr_t *)pwp->fwlogp; 248 evlog_latest_idx = evl_hdr->fw_el_latest_idx; 249 250 while ((log_is_current == B_FALSE) && (retries < 3)) { 251 drv_usecwait(50 * 1000); 252 if (evl_hdr->fw_el_latest_idx == evlog_latest_idx) { 253 log_is_current = B_TRUE; 254 } else { 255 ++retries; 256 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 257 "%s: event log is still being updated... waiting", 258 __func__); 259 evlog_latest_idx = evl_hdr->fw_el_latest_idx; 260 } 261 } 262 263 n = pmcs_dump_binary(pwp, pwp->fwlogp, 0, (PMCS_FWLOG_SIZE >> 2), 264 buf, size_left); 265 266 return (n); 267 } 268 269 /* 270 * Dump Inbound and Outbound Queues. 271 */ 272 static int 273 pmcs_dump_ioqs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 274 { 275 uint8_t i = 0, k = 0; 276 uint32_t j = 0, depth = 0; 277 int n = 0; 278 uint32_t *ptr = NULL; 279 280 n += snprintf(&buf[n], (size_left - n), "\nDump I/O queues: \n" 281 "-----------------\n"); 282 for (i = 0; i < PMCS_NIQ; i++) { 283 depth = PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))); 284 n += snprintf(&buf[n], (size_left - n), 285 "IQ[%d] Details:\n-----------------\n", i); 286 n += snprintf(&buf[n], (size_left - n), 287 " depth = 0x%04x\n", depth); 288 n += snprintf(&buf[n], (size_left - n), 289 " latest ci = 0x%02x\n", pmcs_rd_iqci(pwp, i)); 290 n += snprintf(&buf[n], (size_left - n), 291 " latest pi = 0x%02x\n", pmcs_rd_iqpi(pwp, i)); 292 for (j = 0; j < depth; j++) { 293 n += snprintf(&buf[n], (size_left - n), 294 "IOMB[%d]:\n", j); 295 ptr = &pwp->iqp[i][(j * PMCS_QENTRY_SIZE) >> 2]; 296 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); 297 k += 8) { 298 n += snprintf(&buf[n], (size_left - n), 299 "0x%08x 0x%08x 0x%08x 0x%08x " 300 "0x%08x 0x%08x 0x%08x 0x%08x\n", 301 LE_32(ptr[k]), LE_32(ptr[k+1]), 302 LE_32(ptr[k+2]), LE_32(ptr[k+3]), 303 LE_32(ptr[k+4]), LE_32(ptr[k+5]), 304 LE_32(ptr[k+6]), LE_32(ptr[k+7])); 305 } 306 } 307 } 308 for (i = 0; i < PMCS_NOQ; i++) { 309 depth = PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))); 310 n += snprintf(&buf[n], (size_left - n), 311 "OQ[%d] Details:\n", i); 312 n += snprintf(&buf[n], (size_left - n), 313 " depth = 0x%04x\n", depth); 314 n += snprintf(&buf[n], (size_left - n), 315 " latest ci = 0x%02x\n", pmcs_rd_oqci(pwp, i)); 316 n += snprintf(&buf[n], (size_left - n), 317 " latest pi = 0x%02x\n", pmcs_rd_oqpi(pwp, i)); 318 for (j = 0; j < depth; j++) { 319 n += snprintf(&buf[n], (size_left - n), 320 "IOMB[%d]:\n", j); 321 ptr = &pwp->oqp[i][(j * PMCS_QENTRY_SIZE) >> 2]; 322 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); 323 k += 8) { 324 n += snprintf(&buf[n], (size_left - n), 325 "0x%08x 0x%08x 0x%08x 0x%08x " 326 "0x%08x 0x%08x 0x%08x 0x%08x\n", 327 LE_32(ptr[k]), LE_32(ptr[k+1]), 328 LE_32(ptr[k+2]), LE_32(ptr[k+3]), 329 LE_32(ptr[k+4]), LE_32(ptr[k+5]), 330 LE_32(ptr[k+6]), LE_32(ptr[k+7])); 331 } 332 } 333 334 } 335 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 336 "Dump I/O queues end \n"); 337 return (n); 338 } 339 340 /* 341 * Dump SPC Version. 342 */ 343 static int 344 pmcs_dump_spc_ver(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 345 { 346 int n = 0; 347 348 n += snprintf(&buf[n], (size_left - n), "\nDump SPC version: \n" 349 "-----------------\n"); 350 n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = " 351 "0x%02x\n", PMCS_FW_TYPE(pwp)); 352 n += snprintf(&buf[n], (size_left - n), " Sub-Minor Release " 353 "Number = 0x%02x\n", PMCS_FW_MICRO(pwp)); 354 n += snprintf(&buf[n], (size_left - n), " Minor Release " 355 "Number = 0x%02x\n", PMCS_FW_MINOR(pwp)); 356 n += snprintf(&buf[n], (size_left - n), " Major Release " 357 "Number = 0x%02x\n", PMCS_FW_MAJOR(pwp)); 358 n += snprintf(&buf[n], (size_left - n), "SPC DeviceID = 0x%04x\n", 359 pmcs_rd_topunit(pwp, PMCS_SPC_DEVICE_ID)); 360 n += snprintf(&buf[n], (size_left - n), "SPC Device Revision = " 361 "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION)); 362 n += snprintf(&buf[n], (size_left - n), "SPC BootStrap Register = " 363 "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_SPC_BOOT_STRAP)); 364 n += snprintf(&buf[n], (size_left - n), "SPC Reset Register = 0x%08x\n", 365 pmcs_rd_topunit(pwp, PMCS_SPC_RESET)); 366 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 367 "Dump SPC version end \n"); 368 return (n); 369 } 370 371 /* 372 * Dump MPI Table. 373 */ 374 static int 375 pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 376 { 377 int n = 0; 378 379 n += snprintf(&buf[n], (size_left - n), "\nDump MSGU registers: \n" 380 "-----------------\n"); 381 n += snprintf(&buf[n], (size_left - n), "inb_doorbell = 0x%08x\n", 382 pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB)); 383 n += snprintf(&buf[n], (size_left - n), "inb_doorbell_clear = 0x%08x" 384 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR)); 385 n += snprintf(&buf[n], (size_left - n), "outb_doorbell = 0x%08x" 386 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB)); 387 n += snprintf(&buf[n], (size_left - n), "outb_doorbell_clear = 0x%08x" 388 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR)); 389 n += snprintf(&buf[n], (size_left - n), "scratch_pad0 = 0x%08x" 390 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0)); 391 n += snprintf(&buf[n], (size_left - n), "scratch_pad1 = 0x%08x" 392 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1)); 393 n += snprintf(&buf[n], (size_left - n), "scratch_pad2 = 0x%08x" 394 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2)); 395 n += snprintf(&buf[n], (size_left - n), "scratch_pad3 = 0x%08x" 396 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3)); 397 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad0 = 0x%08x" 398 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0)); 399 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad1 = 0x%08x" 400 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH1)); 401 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad2 = 0x%08x" 402 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH2)); 403 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad3 = 0x%08x" 404 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH3)); 405 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad4 = 0x%08x" 406 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH4)); 407 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad5 = 0x%08x" 408 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH5)); 409 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad6 = 0x%08x" 410 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH6)); 411 n += snprintf(&buf[n], (size_left - n), "host_scratch_pad7 = 0x%08x" 412 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH7)); 413 n += snprintf(&buf[n], (size_left - n), "outb_doorbell_mask = 0x%08x" 414 "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK)); 415 416 n += snprintf(&buf[n], (size_left - n), "MPI Configuration Table: \n" 417 "-----------------\n"); 418 n += snprintf(&buf[n], (size_left - n), "ASCII Signature = 0x%08x\n", 419 pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS)); 420 n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = " 421 "0x%08x\n", PMCS_FW_TYPE(pwp)); 422 n += snprintf(&buf[n], (size_left - n), "Firmware Release Variant = " 423 "0x%08x\n", PMCS_FW_VARIANT(pwp)); 424 n += snprintf(&buf[n], (size_left - n), "Firmware Sub-Minor Release " 425 "Number = 0x%08x\n", PMCS_FW_MICRO(pwp)); 426 n += snprintf(&buf[n], (size_left - n), "Firmware Minor Release " 427 "Number = 0x%08x\n", PMCS_FW_MINOR(pwp)); 428 n += snprintf(&buf[n], (size_left - n), "Firmware Major Release " 429 "Number = 0x%08x\n", PMCS_FW_MAJOR(pwp)); 430 n += snprintf(&buf[n], (size_left - n), "Maximum Outstanding I/Os " 431 "supported = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO)); 432 n += snprintf(&buf[n], (size_left - n), "Maximum Scatter-Gather List " 433 "Elements = 0x%08x\n", 434 PMCS_MSGL(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0))); 435 n += snprintf(&buf[n], (size_left - n), "Maximum number of devices " 436 "connected to the SPC = 0x%08x\n", 437 PMCS_MD(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0))); 438 n += snprintf(&buf[n], (size_left - n), "Maximum Number of IQs " 439 "supported = 0x%08x\n", 440 PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 441 n += snprintf(&buf[n], (size_left - n), "Maximum Number of OQs " 442 "supported = 0x%08x\n", 443 PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 444 n += snprintf(&buf[n], (size_left - n), "High Priority Queue supported" 445 " = 0x%08x\n", PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 446 n += snprintf(&buf[n], (size_left - n), "Interrupt Coalescing supported" 447 " = 0x%08x\n", PMCS_ICS(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 448 n += snprintf(&buf[n], (size_left - n), "Number of Phys = " 449 "0x%08x\n", PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 450 n += snprintf(&buf[n], (size_left - n), "SAS Revision Specification = " 451 "0x%08x\n", PMCS_SASREV(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))); 452 n += snprintf(&buf[n], (size_left - n), "General Status Table Offset = " 453 "0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO)); 454 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Configuration " 455 "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO)); 456 n += snprintf(&buf[n], (size_left - n), "Outbound Queue Configuration " 457 "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO)); 458 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Normal/High " 459 "Priority Processing Depth = 0x%02x 0x%02x\n", 460 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & IQ_NORMAL_PRI_DEPTH_MASK), 461 ((pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & 462 IQ_HIPRI_PRI_DEPTH_MASK) >> IQ_HIPRI_PRI_DEPTH_SHIFT)); 463 n += snprintf(&buf[n], (size_left - n), "General Event Notification " 464 "Queue = 0x%02x\n", (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & 465 GENERAL_EVENT_OQ_MASK) >> GENERAL_EVENT_OQ_SHIFT); 466 n += snprintf(&buf[n], (size_left - n), "Device Handle Removed " 467 "Notification Queue = 0x%02x\n", 468 (uint32_t)(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & 469 DEVICE_HANDLE_REMOVED_MASK) >> DEVICE_HANDLE_REMOVED_SHIFT); 470 for (uint8_t i = 0; i < pwp->nphy; i++) { 471 uint32_t woff = i / 4; 472 uint32_t shf = (i % 4) * 8; 473 n += snprintf(&buf[n], (size_left - n), "SAS HW Event " 474 "Notification Queue - PHY ID %d = 0x%02x\n", i, 475 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)) >> shf) 476 & 0xff); 477 } 478 for (uint8_t i = 0; i < pwp->nphy; i++) { 479 uint32_t woff = i / 4; 480 uint32_t shf = (i % 4) * 8; 481 n += snprintf(&buf[n], (size_left - n), "SATA NCQ Error " 482 "Event Notification Queue - PHY ID %d = 0x%02x\n", i, 483 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)) >> shf) 484 & 0xff); 485 } 486 for (uint8_t i = 0; i < pwp->nphy; i++) { 487 uint32_t woff = i / 4; 488 uint32_t shf = (i % 4) * 8; 489 n += snprintf(&buf[n], (size_left - n), "I_T Nexus Target " 490 "Event Notification Queue - PHY ID %d = 0x%02x\n", i, 491 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IT_NTENQ + 492 (woff << 2)) >> shf) & 0xff); 493 } 494 for (uint8_t i = 0; i < pwp->nphy; i++) { 495 uint32_t woff = i / 4; 496 uint32_t shf = (i % 4) * 8; 497 n += snprintf(&buf[n], (size_left - n), "SSP Target " 498 "Event Notification Queue - PHY ID %d = 0x%02x\n", i, 499 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ + 500 (woff << 2)) >> shf) & 0xff); 501 } 502 for (uint8_t i = 0; i < pwp->nphy; i++) { 503 uint32_t woff = i / 4; 504 uint32_t shf = (i % 4) * 8; 505 n += snprintf(&buf[n], (size_left - n), "SMP Target " 506 "Event Notification Queue - PHY ID %d = 0x%02x\n", i, 507 (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SMP_TENQ + 508 (woff << 2)) >> shf) & 0xff); 509 } 510 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address " 511 "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH)); 512 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address " 513 "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAL)); 514 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Size " 515 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBS)); 516 n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Severity " 517 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELSEV)); 518 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address " 519 "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAH)); 520 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address " 521 "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAL)); 522 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Size " 523 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBS)); 524 n += snprintf(&buf[n], (size_left - n), "IOP Event Log Severity " 525 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELSEV)); 526 n += snprintf(&buf[n], (size_left - n), "Fatal Error Interrupt " 527 "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR)); 528 n += snprintf(&buf[n], (size_left - n), 529 "Fatal Error Register Dump Offset " 530 "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU)); 531 n += snprintf(&buf[n], (size_left - n), 532 "Fatal Error Register Dump Length " 533 "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU)); 534 n += snprintf(&buf[n], (size_left - n), 535 "Fatal Error Register Dump Offset " 536 "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP)); 537 n += snprintf(&buf[n], (size_left - n), 538 "Fatal Error Register Dump Length " 539 "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP)); 540 541 n += snprintf(&buf[n], (size_left - n), "Dump GS Table: \n" 542 "-----------------\n"); 543 n += snprintf(&buf[n], (size_left - n), "GST MPI State: 0x%08x\n", 544 pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE)); 545 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 0 " 546 "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0)); 547 n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 1 " 548 "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1)); 549 n += snprintf(&buf[n], (size_left - n), "MSGU Tick Count = 0x%08x \n", 550 pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK)); 551 n += snprintf(&buf[n], (size_left - n), "IOP Tick Count = 0x%08x\n", 552 pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK)); 553 for (uint8_t i = 0; i < pwp->nphy; i++) { 554 n += snprintf(&buf[n], (size_left - n), " Phy %d state = " 555 "0x%08x\n", i, pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i))); 556 } 557 for (uint8_t i = 0; i < pwp->nphy; i++) { 558 n += snprintf(&buf[n], (size_left - n), " Recoverable Error " 559 "Information %d = 0x%08x\n", i, 560 pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i))); 561 } 562 563 n += snprintf(&buf[n], (size_left - n), "Dump IQCT Table\n" 564 "-----------------\n"); 565 for (uint8_t i = 0; i < PMCS_NIQ; i++) { 566 n += snprintf(&buf[n], (size_left - n), "Inbound Queue " 567 "Configuration Table - [%d]:\n", i); 568 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 569 "Depth = 0x%08x\n", 570 PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)))); 571 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 572 "Element Size and Priority = 0x%08x 0x%08x\n", 573 PMCS_IQESX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))), 574 PMCS_IQPX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)))); 575 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 576 "Base Address High = 0x%08x\n", 577 pmcs_rd_iqc_tbl(pwp, PMCS_IQBAHX(i))); 578 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 579 "Base Address Low = 0x%08x\n", 580 pmcs_rd_iqc_tbl(pwp, PMCS_IQBALX(i))); 581 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 582 "Consumer Index Base Address High = 0x%08x\n", 583 pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBAHX(i))); 584 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 585 "Consumer Index Base Address Low = 0x%08x\n", 586 pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBALX(i))); 587 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 588 "Producer Index PCI BAR = 0x%08x\n", 589 pmcs_rd_iqc_tbl(pwp, PMCS_IQPIBARX(i))); 590 n += snprintf(&buf[n], (size_left - n), " Inbound Queue " 591 "Producer Index PCI BAR offset = 0x%08x\n", 592 pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i))); 593 } 594 595 n += snprintf(&buf[n], (size_left - n), "Dump OQCT Table: \n" 596 "-----------------\n"); 597 for (uint8_t i = 0; i < PMCS_NOQ; i++) { 598 n += snprintf(&buf[n], (size_left - n), "Outbound Queue " 599 "Configuration Table - [%d]:\n", i); 600 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 601 "Depth = 0x%08x\n", 602 PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)))); 603 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 604 "Element Size = 0x%08x\n", 605 PMCS_OQESX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)))); 606 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 607 "Base Address High = 0x%08x\n", 608 pmcs_rd_oqc_tbl(pwp, PMCS_OQBAHX(i))); 609 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 610 "Base Address Low = 0x%08x\n", 611 pmcs_rd_oqc_tbl(pwp, PMCS_OQBALX(i))); 612 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 613 "Producer Index Base Address High = 0x%08x\n", 614 pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBAHX(i))); 615 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 616 "Producer Index Base Address Low = 0x%08x\n", 617 pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBALX(i))); 618 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 619 "Consumer Index PCI BAR = 0x%08x\n", 620 pmcs_rd_oqc_tbl(pwp, PMCS_OQCIBARX(i))); 621 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 622 "Consumer Index PCI BAR offset = 0x%08x\n", 623 pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i))); 624 625 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 626 "Interrupt Coalescing Timeout = 0x%08x\n", 627 PMCS_OQICT(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i)))); 628 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 629 "Interrupt Coalescing Count = 0x%08x\n", 630 PMCS_OQICC(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i)))); 631 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 632 "Interrupt Vector = 0x%08x\n", 633 PMCS_OQIV(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i)))); 634 n += snprintf(&buf[n], (size_left - n), " Outbound Queue " 635 "Dynamic Interrupt Coalescing Timeout = 0x%08x\n", 636 pmcs_rd_oqc_tbl(pwp, PMCS_OQDICX(i))); 637 638 } 639 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 640 "Dump MPI Table end\n"); 641 return (n); 642 } 643 644 /*ARGSUSED*/ 645 int 646 pmcs_dump_binary(pmcs_hw_t *pwp, uint32_t *addr, uint32_t off, 647 uint32_t words_to_read, caddr_t buf, uint32_t size_left) 648 { 649 uint32_t i; 650 int n = 0; 651 char c = ' '; 652 653 for (i = 0, n = 0; i < words_to_read; i++) { 654 if ((i & 7) == 0) { 655 n += snprintf(&buf[n], (size_left - n), 656 "%08x: ", (i << 2) + off); 657 } 658 if ((i + 1) & 7) { 659 c = ' '; 660 } else { 661 c = '\n'; 662 } 663 n += snprintf(&buf[n], (size_left - n), "%08x%c", addr[i], c); 664 } 665 return (n); 666 } 667 668 /* 669 * Dump Global Shared Memory Configuration Registers 670 */ 671 static int 672 pmcs_dump_gsm_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 673 { 674 int n = 0; 675 676 n += snprintf(&buf[n], (size_left - n), "\nDump GSM configuration " 677 "registers: \n -----------------\n"); 678 n += snprintf(&buf[n], (size_left - n), "RB6 Access Register = " 679 "0x%08x\n", pmcs_rd_gsm_reg(pwp, RB6_ACCESS)); 680 n += snprintf(&buf[n], (size_left - n), "CFG and RST = 0x%08x\n", 681 pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET)); 682 n += snprintf(&buf[n], (size_left - n), "RAM ECC ERR INDICATOR= " 683 "0x%08x\n", pmcs_rd_gsm_reg(pwp, RAM_ECC_DOUBLE_ERROR_INDICATOR)); 684 n += snprintf(&buf[n], (size_left - n), "READ ADR PARITY CHK EN = " 685 "0x%08x\n", pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN)); 686 n += snprintf(&buf[n], (size_left - n), "WRITE ADR PARITY CHK EN = " 687 "0x%08x\n", pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN)); 688 n += snprintf(&buf[n], (size_left - n), "WRITE DATA PARITY CHK EN= " 689 "0x%08x\n", pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN)); 690 n += snprintf(&buf[n], (size_left - n), 691 "READ ADR PARITY ERROR INDICATOR = 0x%08x\n", 692 pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_ERROR_INDICATOR)); 693 n += snprintf(&buf[n], (size_left - n), 694 "WRITE ADR PARITY ERROR INDICATOR = 0x%08x\n", 695 pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_ERROR_INDICATOR)); 696 n += snprintf(&buf[n], (size_left - n), 697 "WRITE DATA PARITY ERROR INDICATOR = 0x%08x\n", 698 pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_ERROR_INDICATOR)); 699 n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 IOP Register" 700 " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, NMI_EN_VPE0_IOP)); 701 n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 AAP1 Register" 702 " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, NMI_EN_VPE0_AAP1)); 703 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 704 "Dump GSM configuration registers end \n"); 705 return (n); 706 } 707 708 /* 709 * Dump PCIe Configuration Registers. 710 */ 711 static int 712 pmcs_dump_pcie_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 713 { 714 int n = 0; 715 uint32_t i = 0; 716 717 n += snprintf(&buf[n], (size_left - n), "\nDump PCIe configuration " 718 "registers: \n -----------------\n"); 719 n += snprintf(&buf[n], (size_left - n), "VENID = 0x%04x\n", 720 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_VENID)); 721 n += snprintf(&buf[n], (size_left - n), "DEVICE_ID = 0x%04x\n", 722 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_DEVID)); 723 n += snprintf(&buf[n], (size_left - n), "CFGCMD = 0x%04x\n", 724 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_COMM)); 725 n += snprintf(&buf[n], (size_left - n), "CFGSTAT = 0x%04x\n", 726 pci_config_get16(pwp->pci_acc_handle, PCI_CONF_STAT)); 727 n += snprintf(&buf[n], (size_left - n), "CLSCODE and REVID = 0x%08x\n", 728 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_REVID)); 729 n += snprintf(&buf[n], (size_left - n), "BIST HDRTYPE LATTIM CLSIZE = " 730 "0x%08x\n", 731 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_CACHE_LINESZ)); 732 n += snprintf(&buf[n], (size_left - n), "MEMBASE-I LOWER = 0x%08x\n", 733 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE0)); 734 n += snprintf(&buf[n], (size_left - n), "MEMBASE-I UPPER = 0x%08x\n", 735 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE1)); 736 n += snprintf(&buf[n], (size_left - n), "MEMBASE-II LOWER = 0x%08x\n", 737 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE2)); 738 n += snprintf(&buf[n], (size_left - n), "MEMBASE-II UPPER = 0x%08x\n", 739 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE3)); 740 n += snprintf(&buf[n], (size_left - n), "MEMBASE-III = 0x%08x\n", 741 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE4)); 742 n += snprintf(&buf[n], (size_left - n), "MEMBASE-IV = 0x%08x\n", 743 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE5)); 744 n += snprintf(&buf[n], (size_left - n), "SVID = 0x%08x\n", 745 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_SUBVENID)); 746 n += snprintf(&buf[n], (size_left - n), "ROMBASE = 0x%08x\n", 747 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ROM)); 748 n += snprintf(&buf[n], (size_left - n), "CAP_PTR = 0x%02x\n", 749 pci_config_get8(pwp->pci_acc_handle, PCI_CONF_CAP_PTR)); 750 n += snprintf(&buf[n], (size_left - n), "MAXLAT MINGNT INTPIN " 751 "INTLINE = 0x%08x\n", 752 pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ILINE)); 753 n += snprintf(&buf[n], (size_left - n), "PMC PM_NEXT_CAP PM_CAP_ID = " 754 "0x%08x\n", pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMC)); 755 n += snprintf(&buf[n], (size_left - n), "PMCSR = 0x%08x\n", 756 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMCSR)); 757 n += snprintf(&buf[n], (size_left - n), 758 "MC MSI_NEXT_CAP MSI_CAP_ID = 0x%08x\n", 759 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSI)); 760 n += snprintf(&buf[n], (size_left - n), "MAL = 0x%08x\n", 761 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAL)); 762 n += snprintf(&buf[n], (size_left - n), "MAU = 0x%08x\n", 763 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAU)); 764 n += snprintf(&buf[n], (size_left - n), "MD = 0x%04x\n", 765 pci_config_get16(pwp->pci_acc_handle, PMCS_PCI_MD)); 766 n += snprintf(&buf[n], (size_left - n), 767 "PCIE_CAP PCIE_NEXT_CAP PCIE_CAP_ID = 0x%08x\n", 768 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE)); 769 n += snprintf(&buf[n], (size_left - n), "DEVICE_CAP = 0x%08x\n", 770 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CAP)); 771 n += snprintf(&buf[n], (size_left - n), 772 "DEVICE_STAT DEVICE_CTRL = 0x%08x\n", 773 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CTRL)); 774 n += snprintf(&buf[n], (size_left - n), "LINK_CAP = 0x%08x\n", 775 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CAP)); 776 n += snprintf(&buf[n], (size_left - n), 777 "LINK_STAT LINK_CTRL = 0x%08x\n", 778 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CTRL)); 779 n += snprintf(&buf[n], (size_left - n), "MSIX_CAP = 0x%08x\n", 780 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSIX_CAP)); 781 n += snprintf(&buf[n], (size_left - n), "TBL_OFFSET = 0x%08x\n", 782 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_TBL_OFFSET)); 783 n += snprintf(&buf[n], (size_left - n), "PBA_OFFSET = 0x%08x\n", 784 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PBA_OFFSET)); 785 n += snprintf(&buf[n], (size_left - n), "PCIE_CAP_HD = 0x%08x\n", 786 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE_CAP_HD)); 787 n += snprintf(&buf[n], (size_left - n), "UE_STAT = 0x%08x\n", 788 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_STAT)); 789 n += snprintf(&buf[n], (size_left - n), "UE_MASK = 0x%08x\n", 790 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_MASK)); 791 n += snprintf(&buf[n], (size_left - n), "UE_SEV = 0x%08x\n", 792 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_SEV)); 793 n += snprintf(&buf[n], (size_left - n), "CE_STAT = 0x%08x\n", 794 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_STAT)); 795 n += snprintf(&buf[n], (size_left - n), "CE_MASK = 0x%08x\n", 796 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_MASK)); 797 n += snprintf(&buf[n], (size_left - n), "ADV_ERR_CTRL = 0x%08x\n", 798 pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_ADV_ERR_CTRL)); 799 for (i = 0; i < 4; i++) { 800 n += snprintf(&buf[n], (size_left - n), "HD_LOG_DW%d = " 801 "0x%08x\n", i, pci_config_get32(pwp->pci_acc_handle, 802 (PMCS_PCI_HD_LOG_DW + i * 4))); 803 } 804 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 805 "Dump PCIe configuration registers end \n"); 806 return (n); 807 } 808 /* 809 * Called with axil_lock held 810 */ 811 static boolean_t 812 pmcs_shift_axil(pmcs_hw_t *pwp, uint32_t offset) 813 { 814 uint32_t newaxil = offset & ~GSM_BASE_MASK; 815 816 ASSERT(mutex_owned(&pwp->axil_lock)); 817 ddi_put32(pwp->top_acc_handle, 818 &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil); 819 drv_usecwait(10); 820 821 if (ddi_get32(pwp->top_acc_handle, 822 &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) { 823 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 824 "AXIL register update failed"); 825 return (B_FALSE); 826 } 827 return (B_TRUE); 828 } 829 830 static uint32_t 831 pmcs_get_axil(pmcs_hw_t *pwp) 832 { 833 uint32_t regval = 0; 834 mutex_enter(&pwp->axil_lock); 835 regval = ddi_get32(pwp->top_acc_handle, 836 &pwp->top_regs[PMCS_AXI_TRANS >> 2]); 837 mutex_exit(&pwp->axil_lock); 838 return (regval); 839 } 840 841 static void 842 pmcs_restore_axil(pmcs_hw_t *pwp, uint32_t oldaxil) 843 { 844 mutex_enter(&pwp->axil_lock); 845 ddi_put32(pwp->top_acc_handle, 846 &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil); 847 drv_usecwait(10); 848 849 if (ddi_get32(pwp->top_acc_handle, 850 &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) { 851 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 852 "AXIL register restore failed"); 853 } 854 mutex_exit(&pwp->axil_lock); 855 } 856 857 /* 858 * Dump Additional GSM Registers. 859 */ 860 static int 861 pmcs_dump_gsm_addiregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 862 { 863 uint32_t i = 0; 864 int n = 0, j = 0, nums = 0; 865 uint32_t gsm_addr = 0, addr = 0; 866 867 n += snprintf(&buf[n], (size_left - n), "\nDump GSM Sparse Registers:" 868 "\n-----------------\n"); 869 for (i = 0; i < sizeof (gsm_spregs) / sizeof (pmcs_sparse_regs_t); 870 i++) { 871 gsm_addr = 872 gsm_spregs[i].shift_addr + gsm_spregs[i].offset_start; 873 nums = gsm_spregs[i].offset_end - gsm_spregs[i].offset_start; 874 if (gsm_spregs[i].flag & PMCS_SPREGS_BLOCK_START) { 875 n += snprintf(&buf[n], (size_left - n), "\n%s - 0x%08X" 876 "[MEMBASE-III SHIFT = 0x%08X]\nOffset:\n", 877 gsm_spregs[i].desc ? gsm_spregs[i].desc : "NULL", 878 gsm_spregs[i].base_addr, gsm_spregs[i].shift_addr); 879 } 880 881 if (nums == 0) { 882 n += snprintf(&buf[n], (size_left - n), 883 "[%04X]: %08X\n", gsm_spregs[i].offset_start, 884 pmcs_rd_gsm_reg(pwp, gsm_addr)); 885 } else if (nums > 0) { 886 n += snprintf(&buf[n], (size_left - n), 887 "\n[%04X] - [%04X]: \n", gsm_spregs[i].offset_start, 888 gsm_spregs[i].offset_end); 889 890 j = 0; 891 while (nums > 0) { 892 addr = gsm_addr + j * 4; 893 n += snprintf(&buf[n], (size_left - n), 894 "[%04X]: %08X\n", addr & GSM_BASE_MASK, 895 pmcs_rd_gsm_reg(pwp, addr)); 896 j++; 897 nums -= 4; 898 } 899 } 900 901 } 902 903 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 904 "------------ Dump GSM Sparse Registers end ------------\n"); 905 return (n); 906 907 } 908 909 /* 910 * Dump GSM Memory Regions. 911 */ 912 static int 913 pmcs_dump_gsm(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 914 { 915 int n = 0; 916 uint32_t i = 0; 917 uint32_t oldaxil = 0; 918 uint32_t gsm_addr = 0; 919 uint32_t *local_buf = NULL; 920 921 local_buf = kmem_zalloc(GSM_SM_BLKSZ, KM_NOSLEEP); 922 if (local_buf == NULL) { 923 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 924 "%s: local_buf memory not allocated", __func__); 925 return (0); 926 } 927 928 oldaxil = pmcs_get_axil(pwp); 929 mutex_enter(&pwp->axil_lock); 930 n += snprintf(&buf[n], (size_left - n), "\nDump GSM IO Status Table: \n" 931 " -----------------\n"); 932 for (i = 0; i < 4; i++) { 933 gsm_addr = IO_STATUS_TABLE_BASE + GSM_SM_BLKSZ * i; 934 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) { 935 gsm_addr &= GSM_BASE_MASK; 936 ddi_rep_get32(pwp->gsm_acc_handle, local_buf, 937 &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2, 938 DDI_DEV_AUTOINCR); 939 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ, 940 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n); 941 } 942 } 943 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n" 944 "Dump GSM IO Status Table end \n"); 945 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Storage: \n" 946 " -----------------\n"); 947 for (i = 0; i < 2; i++) { 948 gsm_addr = RING_BUF_STORAGE_0 + GSM_SM_BLKSZ * i; 949 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) { 950 gsm_addr &= GSM_BASE_MASK; 951 ddi_rep_get32(pwp->gsm_acc_handle, local_buf, 952 &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2, 953 DDI_DEV_AUTOINCR); 954 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ, 955 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n); 956 } 957 } 958 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n" 959 "Dump Ring Buffer Storage end \n"); 960 961 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Pointers:\n" 962 " -----------------\n"); 963 gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_PTR_OFF; 964 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) { 965 gsm_addr &= GSM_BASE_MASK; 966 ddi_rep_get32(pwp->gsm_acc_handle, local_buf, 967 &pwp->gsm_regs[gsm_addr >> 2], 968 RING_BUF_PTR_SIZE >> 2, DDI_DEV_AUTOINCR); 969 n += pmcs_dump_binary(pwp, local_buf, 0, 970 RING_BUF_PTR_SIZE >> 2, &buf[n], size_left - n); 971 } 972 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n" 973 "Dump Ring Buffer Pointers end \n"); 974 975 n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Access: \n" 976 " -----------------\n"); 977 gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_ACC_OFF; 978 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) { 979 gsm_addr &= GSM_BASE_MASK; 980 ddi_rep_get32(pwp->gsm_acc_handle, local_buf, 981 &pwp->gsm_regs[gsm_addr >> 2], 982 RING_BUF_ACC_SIZE >> 2, DDI_DEV_AUTOINCR); 983 n += pmcs_dump_binary(pwp, local_buf, 0, 984 RING_BUF_ACC_SIZE >> 2, &buf[n], size_left - n); 985 } 986 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n" 987 "Dump Ring Buffer Access end \n"); 988 989 n += snprintf(&buf[n], (size_left - n), "\nDump GSM SM: \n" 990 " -----------------\n"); 991 for (i = 0; i < 16; i++) { 992 gsm_addr = GSM_SM_BASE + GSM_SM_BLKSZ * i; 993 if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) { 994 gsm_addr &= GSM_BASE_MASK; 995 ddi_rep_get32(pwp->gsm_acc_handle, local_buf, 996 &pwp->gsm_regs[gsm_addr >> 2], 997 GSM_SM_BLKSZ >> 2, DDI_DEV_AUTOINCR); 998 n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ, 999 GSM_SM_BLKSZ >> 2, &buf[n], size_left - n); 1000 } 1001 } 1002 mutex_exit(&pwp->axil_lock); 1003 pmcs_restore_axil(pwp, oldaxil); 1004 1005 n += snprintf(&buf[n], (size_left - n), "\n-----------------\n" 1006 "Dump GSM SM end \n"); 1007 n += snprintf(&buf[n], (size_left - n), "-----------------\n" 1008 "\n------------ Dump GSM Memory Regions end -------------\n"); 1009 if (local_buf) { 1010 kmem_free(local_buf, GSM_SM_BLKSZ); 1011 } 1012 return (n); 1013 } 1014 1015 /* 1016 * Trace current Inbound Message host sent to SPC. 1017 */ 1018 void 1019 pmcs_iqp_trace(pmcs_hw_t *pwp, uint32_t qnum) 1020 { 1021 uint32_t k = 0; 1022 int n = 0; 1023 uint32_t *ptr = NULL; 1024 char *tbuf = pwp->iqpt->curpos; 1025 uint32_t size_left = pwp->iqpt->size_left; 1026 1027 if (tbuf == NULL) { 1028 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1029 "%s: trace buffer is not ready," 1030 " Inbound Message from host to SPC is not traced", 1031 __func__); 1032 return; 1033 } else if (size_left < PMCS_QENTRY_SIZE * PMCS_QENTRY_SIZE) { 1034 tbuf = pwp->iqpt->curpos = pwp->iqpt->head; 1035 size_left = pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE; 1036 } 1037 1038 ptr = &pwp->iqp[qnum][pwp->shadow_iqpi[qnum] * 1039 (PMCS_QENTRY_SIZE >> 2)]; 1040 for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); 1041 k += 8) { 1042 n += snprintf(&tbuf[n], (size_left - n), 1043 "0x%08x 0x%08x 0x%08x 0x%08x " 1044 "0x%08x 0x%08x 0x%08x 0x%08x\n", 1045 LE_32(ptr[k]), LE_32(ptr[k+1]), 1046 LE_32(ptr[k+2]), LE_32(ptr[k+3]), 1047 LE_32(ptr[k+4]), LE_32(ptr[k+5]), 1048 LE_32(ptr[k+6]), LE_32(ptr[k+7])); 1049 } 1050 pwp->iqpt->size_left -= n; 1051 if (pwp->iqpt->size_left > 0) { 1052 pwp->iqpt->curpos += n; 1053 } else { 1054 pwp->iqpt->curpos = 1055 pwp->iqpt->head + PMCS_IQP_TRACE_BUFFER_SIZE - 1; 1056 } 1057 } 1058 1059 /* 1060 * Capture HSST State Registers. 1061 */ 1062 static int 1063 pmcs_dump_hsst_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 1064 { 1065 uint32_t i = 0, j = 0, addr = 0; 1066 int n = 0; 1067 1068 n += snprintf(&buf[n], (size_left - n), "\nHSST State Capture : \n" 1069 "-----------------\n"); 1070 n += snprintf(&buf[n], (size_left - n), "%s \t %s \n", 1071 hsst_state[8].desc ? hsst_state[8].desc : "NULL", 1072 hsst_state[16].desc ? hsst_state[16].desc : "NULL"); 1073 1074 for (i = 0; i < 8; i++) { 1075 addr = hsst_state[i].offset_start + 1076 hsst_state[i].shift_addr; 1077 n += snprintf(&buf[n], (size_left - n), "Phy[%1d]\n", i); 1078 for (j = 0; j < 6; j++) { 1079 pmcs_wr_gsm_reg(pwp, addr, j); 1080 pmcs_wr_gsm_reg(pwp, addr, (0x0100 + j)); 1081 addr = hsst_state[i+8].offset_start + 1082 hsst_state[i+8].shift_addr; 1083 n += snprintf(&buf[n], (size_left - n), 1084 "[%08X]: %08X\t", addr, pmcs_rd_gsm_reg(pwp, addr)); 1085 addr = hsst_state[i+16].offset_start + 1086 hsst_state[i+16].shift_addr; 1087 n += snprintf(&buf[n], (size_left - n), 1088 "[%08X]: %08X\n", addr, pmcs_rd_gsm_reg(pwp, addr)); 1089 } 1090 1091 } 1092 return (n); 1093 1094 } 1095 1096 /* 1097 * Capture SSPA State Registers. 1098 */ 1099 static int 1100 pmcs_dump_sspa_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) 1101 { 1102 uint32_t i = 0, rv = 0, addr = 0; 1103 int n = 0; 1104 1105 n += snprintf(&buf[n], (size_left - n), "\nSSPA State Capture : \n" 1106 "-----------------\n"); 1107 for (i = 0; i < 8; i++) { 1108 if (sspa_state[i].flag & PMCS_SPREGS_BLOCK_START) { 1109 n += snprintf(&buf[n], (size_left - n), "%s \n", 1110 sspa_state[i].desc ? sspa_state[i].desc : "NULL"); 1111 } 1112 addr = sspa_state[i].offset_start + sspa_state[i].shift_addr; 1113 rv = pmcs_rd_gsm_reg(pwp, addr); 1114 rv |= PMCS_SSPA_CONTROL_REGISTER_BIT27; 1115 pmcs_wr_gsm_reg(pwp, addr, rv); 1116 n += snprintf(&buf[n], (size_left - n), "[%08X]: %08X \n", 1117 addr, pmcs_rd_gsm_reg(pwp, addr)); 1118 1119 } 1120 return (n); 1121 } 1122 1123 /* 1124 * Dump fatal error register content from GSM. 1125 */ 1126 int 1127 pmcs_dump_feregs(pmcs_hw_t *pwp, uint32_t *addr, uint8_t nvmd, 1128 caddr_t buf, uint32_t size_left) 1129 { 1130 uint32_t offset = 0, length = 0; 1131 int i = 0; 1132 uint8_t *ptr = (uint8_t *)addr; 1133 1134 if ((addr == NULL) || (buf == NULL)) { 1135 return (0); 1136 } 1137 switch (nvmd) { 1138 case PMCIN_NVMD_AAP1: 1139 offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU); 1140 length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU); 1141 break; 1142 case PMCIN_NVMD_IOP: 1143 offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP); 1144 length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP); 1145 break; 1146 default: 1147 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1148 "UNKNOWN NVMD DEVICE %s():%d", __func__, __LINE__); 1149 return (0); 1150 } 1151 1152 while ((i < length) && (ptr[i + offset] != 0xff) && 1153 (ptr[i + offset] != '\0')) { 1154 i += snprintf(&buf[i], (size_left - i), 1155 "%c", ptr[i + offset]); 1156 } 1157 return (i); 1158 } 1159