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