14c06356bSdh142964 /* 24c06356bSdh142964 * CDDL HEADER START 34c06356bSdh142964 * 44c06356bSdh142964 * The contents of this file are subject to the terms of the 54c06356bSdh142964 * Common Development and Distribution License (the "License"). 64c06356bSdh142964 * You may not use this file except in compliance with the License. 74c06356bSdh142964 * 84c06356bSdh142964 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 94c06356bSdh142964 * or http://www.opensolaris.org/os/licensing. 104c06356bSdh142964 * See the License for the specific language governing permissions 114c06356bSdh142964 * and limitations under the License. 124c06356bSdh142964 * 134c06356bSdh142964 * When distributing Covered Code, include this CDDL HEADER in each 144c06356bSdh142964 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 154c06356bSdh142964 * If applicable, add the following below this CDDL HEADER, with the 164c06356bSdh142964 * fields enclosed by brackets "[]" replaced with your own identifying 174c06356bSdh142964 * information: Portions Copyright [yyyy] [name of copyright owner] 184c06356bSdh142964 * 194c06356bSdh142964 * CDDL HEADER END 204c06356bSdh142964 */ 214c06356bSdh142964 /* 22658280b6SDavid Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23*33f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 244c06356bSdh142964 */ 254c06356bSdh142964 264c06356bSdh142964 #include <limits.h> 274c06356bSdh142964 #include <sys/mdb_modapi.h> 28f7aef0b0SReed #include <mdb/mdb_ctf.h> 294c06356bSdh142964 #include <sys/sysinfo.h> 30c3bc407cSdh142964 #include <sys/byteorder.h> 31f7aef0b0SReed #include <sys/nvpair.h> 32f7aef0b0SReed #include <sys/damap.h> 334c06356bSdh142964 #include <sys/scsi/scsi.h> 344c06356bSdh142964 #include <sys/scsi/adapters/pmcs/pmcs.h> 359719310aSDavid Hollister #ifndef _KMDB 369719310aSDavid Hollister #include <sys/types.h> 379719310aSDavid Hollister #include <sys/stat.h> 389719310aSDavid Hollister #include <fcntl.h> 399719310aSDavid Hollister #include <unistd.h> 409719310aSDavid Hollister #endif /* _KMDB */ 414c06356bSdh142964 42f7aef0b0SReed /* 43f7aef0b0SReed * We need use this to pass the settings when display_iport 44f7aef0b0SReed */ 45f7aef0b0SReed typedef struct per_iport_setting { 46f7aef0b0SReed uint_t pis_damap_info; /* -m: DAM/damap */ 47f7aef0b0SReed uint_t pis_dtc_info; /* -d: device tree children: dev_info/path_info */ 48f7aef0b0SReed } per_iport_setting_t; 49f7aef0b0SReed 50658280b6SDavid Hollister /* 51658280b6SDavid Hollister * This structure is used for sorting work structures by the wserno 52658280b6SDavid Hollister */ 53658280b6SDavid Hollister typedef struct wserno_list { 54658280b6SDavid Hollister int serno; 55658280b6SDavid Hollister int idx; 56658280b6SDavid Hollister struct wserno_list *next; 57658280b6SDavid Hollister struct wserno_list *prev; 58658280b6SDavid Hollister } wserno_list_t; 59658280b6SDavid Hollister 604c06356bSdh142964 #define MDB_RD(a, b, c) mdb_vread(a, b, (uintptr_t)c) 614c06356bSdh142964 #define NOREAD(a, b) mdb_warn("could not read " #a " at 0x%p", b) 624c06356bSdh142964 634c06356bSdh142964 static pmcs_hw_t ss; 644c06356bSdh142964 static pmcs_xscsi_t **targets = NULL; 654c06356bSdh142964 static int target_idx; 664c06356bSdh142964 674c06356bSdh142964 static uint32_t sas_phys, sata_phys, exp_phys, num_expanders, empty_phys; 684c06356bSdh142964 694c06356bSdh142964 static pmcs_phy_t *pmcs_next_sibling(pmcs_phy_t *phyp); 7014d6cf0aSdh142964 static void display_one_work(pmcwork_t *wp, int verbose, int idx); 714c06356bSdh142964 724c06356bSdh142964 static void 734c06356bSdh142964 print_sas_address(pmcs_phy_t *phy) 744c06356bSdh142964 { 754c06356bSdh142964 int idx; 764c06356bSdh142964 774c06356bSdh142964 for (idx = 0; idx < 8; idx++) { 784c06356bSdh142964 mdb_printf("%02x", phy->sas_address[idx]); 794c06356bSdh142964 } 804c06356bSdh142964 } 814c06356bSdh142964 821f81b464SDavid Hollister static void 831f81b464SDavid Hollister pmcs_fwtime_to_systime(struct pmcs_hw ss, uint32_t fw_hi, uint32_t fw_lo, 841f81b464SDavid Hollister struct timespec *stime) 851f81b464SDavid Hollister { 861f81b464SDavid Hollister uint64_t fwtime; 871f81b464SDavid Hollister time_t secs; 881f81b464SDavid Hollister long nsecs; 891f81b464SDavid Hollister boolean_t backward_time = B_FALSE; 901f81b464SDavid Hollister 911f81b464SDavid Hollister fwtime = ((uint64_t)fw_hi << 32) | fw_lo; 921f81b464SDavid Hollister 931f81b464SDavid Hollister /* 941f81b464SDavid Hollister * If fwtime < ss.fw_timestamp, then we need to adjust the clock 951f81b464SDavid Hollister * time backwards from ss.sys_timestamp. Otherwise, the adjustment 961f81b464SDavid Hollister * goes forward in time 971f81b464SDavid Hollister */ 981f81b464SDavid Hollister if (fwtime >= ss.fw_timestamp) { 991f81b464SDavid Hollister fwtime -= ss.fw_timestamp; 1001f81b464SDavid Hollister } else { 1011f81b464SDavid Hollister fwtime = ss.fw_timestamp - fwtime; 1021f81b464SDavid Hollister backward_time = B_TRUE; 1031f81b464SDavid Hollister } 1041f81b464SDavid Hollister 1051f81b464SDavid Hollister secs = ((time_t)fwtime / NSECS_PER_SEC); 1061f81b464SDavid Hollister nsecs = ((long)fwtime % NSECS_PER_SEC); 1071f81b464SDavid Hollister 1081f81b464SDavid Hollister stime->tv_sec = ss.sys_timestamp.tv_sec; 1091f81b464SDavid Hollister stime->tv_nsec = ss.sys_timestamp.tv_nsec; 1101f81b464SDavid Hollister 1111f81b464SDavid Hollister if (backward_time) { 1121f81b464SDavid Hollister if (stime->tv_nsec < nsecs) { 1131f81b464SDavid Hollister stime->tv_sec--; 1141f81b464SDavid Hollister stime->tv_nsec = stime->tv_nsec + NSECS_PER_SEC - nsecs; 1151f81b464SDavid Hollister } else { 1161f81b464SDavid Hollister stime->tv_nsec -= nsecs; 1171f81b464SDavid Hollister } 1181f81b464SDavid Hollister stime->tv_sec -= secs; 1191f81b464SDavid Hollister } else { 1201f81b464SDavid Hollister if (stime->tv_nsec + nsecs > NSECS_PER_SEC) { 1211f81b464SDavid Hollister stime->tv_sec++; 1221f81b464SDavid Hollister } 1231f81b464SDavid Hollister stime->tv_nsec = (stime->tv_nsec + nsecs) % NSECS_PER_SEC; 1241f81b464SDavid Hollister stime->tv_sec += secs; 1251f81b464SDavid Hollister } 1261f81b464SDavid Hollister } 1271f81b464SDavid Hollister 1284c06356bSdh142964 /*ARGSUSED*/ 1294c06356bSdh142964 static void 1304c06356bSdh142964 display_ic(struct pmcs_hw m, int verbose) 1314c06356bSdh142964 { 1324c06356bSdh142964 int msec_per_tick; 1334c06356bSdh142964 1344c06356bSdh142964 if (mdb_readvar(&msec_per_tick, "msec_per_tick") == -1) { 1354c06356bSdh142964 mdb_warn("can't read msec_per_tick"); 1364c06356bSdh142964 msec_per_tick = 0; 1374c06356bSdh142964 } 1384c06356bSdh142964 1394c06356bSdh142964 mdb_printf("\n"); 1404c06356bSdh142964 mdb_printf("Interrupt coalescing timer info\n"); 1414c06356bSdh142964 mdb_printf("-------------------------------\n"); 1424c06356bSdh142964 if (msec_per_tick == 0) { 1434c06356bSdh142964 mdb_printf("Quantum : ?? ms\n"); 1444c06356bSdh142964 } else { 1454c06356bSdh142964 mdb_printf("Quantum : %d ms\n", 1464c06356bSdh142964 m.io_intr_coal.quantum * msec_per_tick); 1474c06356bSdh142964 } 1484c06356bSdh142964 mdb_printf("Timer enabled : "); 1494c06356bSdh142964 if (m.io_intr_coal.timer_on) { 1504c06356bSdh142964 mdb_printf("Yes\n"); 1514c06356bSdh142964 mdb_printf("Coalescing timer value : %d us\n", 1524c06356bSdh142964 m.io_intr_coal.intr_coal_timer); 1534c06356bSdh142964 } else { 1544c06356bSdh142964 mdb_printf("No\n"); 1554c06356bSdh142964 } 1564c06356bSdh142964 mdb_printf("Total nsecs between interrupts: %ld\n", 1574c06356bSdh142964 m.io_intr_coal.nsecs_between_intrs); 1584c06356bSdh142964 mdb_printf("Time of last I/O interrupt : %ld\n", 1594c06356bSdh142964 m.io_intr_coal.last_io_comp); 1604c06356bSdh142964 mdb_printf("Number of I/O interrupts : %d\n", 1614c06356bSdh142964 m.io_intr_coal.num_intrs); 1624c06356bSdh142964 mdb_printf("Number of I/O completions : %d\n", 1634c06356bSdh142964 m.io_intr_coal.num_io_completions); 1644c06356bSdh142964 mdb_printf("Max I/O completion interrupts : %d\n", 1654c06356bSdh142964 m.io_intr_coal.max_io_completions); 1664c06356bSdh142964 mdb_printf("Measured ECHO int latency : %d ns\n", 1674c06356bSdh142964 m.io_intr_coal.intr_latency); 1684c06356bSdh142964 mdb_printf("Interrupt threshold : %d\n", 1694c06356bSdh142964 m.io_intr_coal.intr_threshold); 1704c06356bSdh142964 } 1714c06356bSdh142964 1724c06356bSdh142964 /*ARGSUSED*/ 1734c06356bSdh142964 static int 1744c06356bSdh142964 pmcs_iport_phy_walk_cb(uintptr_t addr, const void *wdata, void *priv) 1754c06356bSdh142964 { 1764c06356bSdh142964 struct pmcs_phy phy; 1774c06356bSdh142964 1784c06356bSdh142964 if (mdb_vread(&phy, sizeof (struct pmcs_phy), addr) != 1794c06356bSdh142964 sizeof (struct pmcs_phy)) { 1804c06356bSdh142964 return (DCMD_ERR); 1814c06356bSdh142964 } 1824c06356bSdh142964 1834c06356bSdh142964 mdb_printf("%16p %2d\n", addr, phy.phynum); 1844c06356bSdh142964 1854c06356bSdh142964 return (0); 1864c06356bSdh142964 } 1874c06356bSdh142964 188f7aef0b0SReed static int 189f7aef0b0SReed display_iport_damap(dev_info_t *pdip) 190f7aef0b0SReed { 191f7aef0b0SReed int rval = DCMD_ERR; 192f7aef0b0SReed struct dev_info dip; 193f7aef0b0SReed scsi_hba_tran_t sht; 194f7aef0b0SReed mdb_ctf_id_t istm_ctfid; /* impl_scsi_tgtmap_t ctf_id */ 195f7aef0b0SReed ulong_t tmd_offset = 0; /* tgtmap_dam offset to impl_scsi_tgtmap_t */ 196f7aef0b0SReed uintptr_t dam0; 197f7aef0b0SReed uintptr_t dam1; 198f7aef0b0SReed 199f7aef0b0SReed if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) != 200f7aef0b0SReed sizeof (struct dev_info)) { 201f7aef0b0SReed return (rval); 202f7aef0b0SReed } 203f7aef0b0SReed 204f7aef0b0SReed if (dip.devi_driver_data == NULL) { 205f7aef0b0SReed return (rval); 206f7aef0b0SReed } 207f7aef0b0SReed 208f7aef0b0SReed if (mdb_vread(&sht, sizeof (scsi_hba_tran_t), 209f7aef0b0SReed (uintptr_t)dip.devi_driver_data) != sizeof (scsi_hba_tran_t)) { 210f7aef0b0SReed return (rval); 211f7aef0b0SReed } 212f7aef0b0SReed 213f7aef0b0SReed if (sht.tran_tgtmap == NULL) { 214f7aef0b0SReed return (rval); 215f7aef0b0SReed } 216f7aef0b0SReed 217f7aef0b0SReed if (mdb_ctf_lookup_by_name("impl_scsi_tgtmap_t", &istm_ctfid) != 0) { 218f7aef0b0SReed return (rval); 219f7aef0b0SReed } 220f7aef0b0SReed 221f7aef0b0SReed if (mdb_ctf_offsetof(istm_ctfid, "tgtmap_dam", &tmd_offset) != 0) { 222f7aef0b0SReed return (rval); 223f7aef0b0SReed } 224f7aef0b0SReed 225f7aef0b0SReed tmd_offset /= NBBY; 226f7aef0b0SReed mdb_vread(&dam0, sizeof (dam0), 227f7aef0b0SReed (uintptr_t)(tmd_offset + (char *)sht.tran_tgtmap)); 228f7aef0b0SReed mdb_vread(&dam1, sizeof (dam1), 229f7aef0b0SReed (uintptr_t)(sizeof (dam0) + tmd_offset + (char *)sht.tran_tgtmap)); 230f7aef0b0SReed 231f7aef0b0SReed if (dam0 != NULL) { 232f7aef0b0SReed rval = mdb_call_dcmd("damap", dam0, DCMD_ADDRSPEC, 0, NULL); 233f7aef0b0SReed mdb_printf("\n"); 234f7aef0b0SReed if (rval != DCMD_OK) { 235f7aef0b0SReed return (rval); 236f7aef0b0SReed } 237f7aef0b0SReed } 238f7aef0b0SReed 239f7aef0b0SReed if (dam1 != NULL) { 240f7aef0b0SReed rval = mdb_call_dcmd("damap", dam1, DCMD_ADDRSPEC, 0, NULL); 241f7aef0b0SReed mdb_printf("\n"); 242f7aef0b0SReed } 243f7aef0b0SReed 244f7aef0b0SReed return (rval); 245f7aef0b0SReed } 246f7aef0b0SReed 247f7aef0b0SReed /* ARGSUSED */ 248f7aef0b0SReed static int 249f7aef0b0SReed display_iport_di_cb(uintptr_t addr, const void *wdata, void *priv) 250f7aef0b0SReed { 251f7aef0b0SReed uint_t *idx = (uint_t *)priv; 252f7aef0b0SReed struct dev_info dip; 253f7aef0b0SReed char devi_name[MAXNAMELEN]; 254f7aef0b0SReed char devi_addr[MAXNAMELEN]; 255f7aef0b0SReed 256f7aef0b0SReed if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)addr) != 257f7aef0b0SReed sizeof (struct dev_info)) { 258f7aef0b0SReed return (DCMD_ERR); 259f7aef0b0SReed } 260f7aef0b0SReed 261f7aef0b0SReed if (mdb_readstr(devi_name, sizeof (devi_name), 262f7aef0b0SReed (uintptr_t)dip.devi_node_name) == -1) { 263f7aef0b0SReed devi_name[0] = '?'; 264f7aef0b0SReed devi_name[1] = '\0'; 265f7aef0b0SReed } 266f7aef0b0SReed 267f7aef0b0SReed if (mdb_readstr(devi_addr, sizeof (devi_addr), 268f7aef0b0SReed (uintptr_t)dip.devi_addr) == -1) { 269f7aef0b0SReed devi_addr[0] = '?'; 270f7aef0b0SReed devi_addr[1] = '\0'; 271f7aef0b0SReed } 272f7aef0b0SReed 273f7aef0b0SReed mdb_printf(" %3d: @%-21s%10s@\t%p::devinfo -s\n", 274f7aef0b0SReed (*idx)++, devi_addr, devi_name, addr); 275f7aef0b0SReed return (DCMD_OK); 276f7aef0b0SReed } 277f7aef0b0SReed 278f7aef0b0SReed /* ARGSUSED */ 279f7aef0b0SReed static int 280f7aef0b0SReed display_iport_pi_cb(uintptr_t addr, const void *wdata, void *priv) 281f7aef0b0SReed { 282f7aef0b0SReed uint_t *idx = (uint_t *)priv; 283f7aef0b0SReed struct mdi_pathinfo mpi; 284f7aef0b0SReed char pi_addr[MAXNAMELEN]; 285f7aef0b0SReed 286f7aef0b0SReed if (mdb_vread(&mpi, sizeof (struct mdi_pathinfo), (uintptr_t)addr) != 287f7aef0b0SReed sizeof (struct mdi_pathinfo)) { 288f7aef0b0SReed return (DCMD_ERR); 289f7aef0b0SReed } 290f7aef0b0SReed 291f7aef0b0SReed if (mdb_readstr(pi_addr, sizeof (pi_addr), 292f7aef0b0SReed (uintptr_t)mpi.pi_addr) == -1) { 293f7aef0b0SReed pi_addr[0] = '?'; 294f7aef0b0SReed pi_addr[1] = '\0'; 295f7aef0b0SReed } 296f7aef0b0SReed 297f7aef0b0SReed mdb_printf(" %3d: @%-21s %p::print struct mdi_pathinfo\n", 298f7aef0b0SReed (*idx)++, pi_addr, addr); 299f7aef0b0SReed return (DCMD_OK); 300f7aef0b0SReed } 301f7aef0b0SReed 302f7aef0b0SReed static int 303f7aef0b0SReed display_iport_dtc(dev_info_t *pdip) 304f7aef0b0SReed { 305f7aef0b0SReed int rval = DCMD_ERR; 306f7aef0b0SReed struct dev_info dip; 307f7aef0b0SReed struct mdi_phci phci; 308f7aef0b0SReed uint_t didx = 1; 309f7aef0b0SReed uint_t pidx = 1; 310f7aef0b0SReed 311f7aef0b0SReed if (mdb_vread(&dip, sizeof (struct dev_info), (uintptr_t)pdip) != 312f7aef0b0SReed sizeof (struct dev_info)) { 313f7aef0b0SReed return (rval); 314f7aef0b0SReed } 315f7aef0b0SReed 316f7aef0b0SReed mdb_printf("Device tree children - dev_info:\n"); 317f7aef0b0SReed if (dip.devi_child == NULL) { 318f7aef0b0SReed mdb_printf("\tdevi_child is NULL, no dev_info\n\n"); 319f7aef0b0SReed goto skip_di; 320f7aef0b0SReed } 321f7aef0b0SReed 322f7aef0b0SReed /* 323f7aef0b0SReed * First, we dump the iport's children dev_info node information. 324f7aef0b0SReed * use existing walker: devinfo_siblings 325f7aef0b0SReed */ 326f7aef0b0SReed mdb_printf("\t#: @unit-address name@\tdrill-down\n"); 327f7aef0b0SReed rval = mdb_pwalk("devinfo_siblings", display_iport_di_cb, 328f7aef0b0SReed (void *)&didx, (uintptr_t)dip.devi_child); 329f7aef0b0SReed mdb_printf("\n"); 330f7aef0b0SReed 331f7aef0b0SReed skip_di: 332f7aef0b0SReed /* 333f7aef0b0SReed * Then we try to dump the iport's path_info node information. 334f7aef0b0SReed * use existing walker: mdipi_phci_list 335f7aef0b0SReed */ 336f7aef0b0SReed mdb_printf("Device tree children - path_info:\n"); 337f7aef0b0SReed if (mdb_vread(&phci, sizeof (struct mdi_phci), 338f7aef0b0SReed (uintptr_t)dip.devi_mdi_xhci) != sizeof (struct mdi_phci)) { 339f7aef0b0SReed mdb_printf("\tdevi_mdi_xhci is NULL, no path_info\n\n"); 340f7aef0b0SReed return (rval); 341f7aef0b0SReed } 342f7aef0b0SReed 343f7aef0b0SReed if (phci.ph_path_head == NULL) { 344f7aef0b0SReed mdb_printf("\tph_path_head is NULL, no path_info\n\n"); 345f7aef0b0SReed return (rval); 346f7aef0b0SReed } 347f7aef0b0SReed 348f7aef0b0SReed mdb_printf("\t#: @unit-address drill-down\n"); 349f7aef0b0SReed rval = mdb_pwalk("mdipi_phci_list", display_iport_pi_cb, 350f7aef0b0SReed (void *)&pidx, (uintptr_t)phci.ph_path_head); 351f7aef0b0SReed mdb_printf("\n"); 352f7aef0b0SReed return (rval); 353f7aef0b0SReed } 354f7aef0b0SReed 355f7aef0b0SReed static void 356f7aef0b0SReed display_iport_more(dev_info_t *dip, per_iport_setting_t *pis) 357f7aef0b0SReed { 358f7aef0b0SReed if (pis->pis_damap_info) { 359f7aef0b0SReed (void) display_iport_damap(dip); 360f7aef0b0SReed } 361f7aef0b0SReed 362f7aef0b0SReed if (pis->pis_dtc_info) { 363f7aef0b0SReed (void) display_iport_dtc(dip); 364f7aef0b0SReed } 365f7aef0b0SReed } 366f7aef0b0SReed 3674c06356bSdh142964 /*ARGSUSED*/ 3684c06356bSdh142964 static int 3694c06356bSdh142964 pmcs_iport_walk_cb(uintptr_t addr, const void *wdata, void *priv) 3704c06356bSdh142964 { 3714c06356bSdh142964 struct pmcs_iport iport; 3724c06356bSdh142964 uintptr_t list_addr; 3734c06356bSdh142964 char *ua_state; 3744c06356bSdh142964 char portid[4]; 3754c06356bSdh142964 char unit_address[34]; 376f7aef0b0SReed per_iport_setting_t *pis = (per_iport_setting_t *)priv; 3774c06356bSdh142964 3784c06356bSdh142964 if (mdb_vread(&iport, sizeof (struct pmcs_iport), addr) != 3794c06356bSdh142964 sizeof (struct pmcs_iport)) { 3804c06356bSdh142964 return (DCMD_ERR); 3814c06356bSdh142964 } 3824c06356bSdh142964 3834c06356bSdh142964 if (mdb_readstr(unit_address, sizeof (unit_address), 3844c06356bSdh142964 (uintptr_t)(iport.ua)) == -1) { 3854c06356bSdh142964 strncpy(unit_address, "Unset", sizeof (unit_address)); 3864c06356bSdh142964 } 3874c06356bSdh142964 3884c06356bSdh142964 if (iport.portid == 0xffff) { 3894c06356bSdh142964 mdb_snprintf(portid, sizeof (portid), "%s", "-"); 390601c90f1SSrikanth, Ramana } else if (iport.portid == PMCS_IPORT_INVALID_PORT_ID) { 391601c90f1SSrikanth, Ramana mdb_snprintf(portid, sizeof (portid), "%s", "N/A"); 3924c06356bSdh142964 } else { 3934c06356bSdh142964 mdb_snprintf(portid, sizeof (portid), "%d", iport.portid); 3944c06356bSdh142964 } 3954c06356bSdh142964 3964c06356bSdh142964 switch (iport.ua_state) { 3974c06356bSdh142964 case UA_INACTIVE: 3984c06356bSdh142964 ua_state = "Inactive"; 3994c06356bSdh142964 break; 4004c06356bSdh142964 case UA_PEND_ACTIVATE: 4014c06356bSdh142964 ua_state = "PendActivate"; 4024c06356bSdh142964 break; 4034c06356bSdh142964 case UA_ACTIVE: 4044c06356bSdh142964 ua_state = "Active"; 4054c06356bSdh142964 break; 4064c06356bSdh142964 case UA_PEND_DEACTIVATE: 4074c06356bSdh142964 ua_state = "PendDeactivate"; 4084c06356bSdh142964 break; 4094c06356bSdh142964 default: 4104c06356bSdh142964 ua_state = "Unknown"; 4114c06356bSdh142964 } 4124c06356bSdh142964 4134c06356bSdh142964 if (strlen(unit_address) < 3) { 4144c06356bSdh142964 /* Standard iport unit address */ 4154c06356bSdh142964 mdb_printf("UA %-16s %16s %8s %8s %16s", "Iport", "UA State", 4164c06356bSdh142964 "PortID", "NumPhys", "DIP\n"); 4174c06356bSdh142964 mdb_printf("%2s %16p %16s %8s %8d %16p\n", unit_address, addr, 4184c06356bSdh142964 ua_state, portid, iport.nphy, iport.dip); 4194c06356bSdh142964 } else { 4204c06356bSdh142964 /* Temporary iport unit address */ 4214c06356bSdh142964 mdb_printf("%-32s %16s %20s %8s %8s %16s", "UA", "Iport", 4224c06356bSdh142964 "UA State", "PortID", "NumPhys", "DIP\n"); 4234c06356bSdh142964 mdb_printf("%32s %16p %20s %8s %8d %16p\n", unit_address, addr, 4244c06356bSdh142964 ua_state, portid, iport.nphy, iport.dip); 4254c06356bSdh142964 } 4264c06356bSdh142964 4274c06356bSdh142964 if (iport.nphy > 0) { 4284c06356bSdh142964 mdb_inc_indent(4); 4294c06356bSdh142964 mdb_printf("%-18s %8s", "Phy", "PhyNum\n"); 4304c06356bSdh142964 mdb_inc_indent(2); 4314c06356bSdh142964 list_addr = 4324c06356bSdh142964 (uintptr_t)(addr + offsetof(struct pmcs_iport, phys)); 4334c06356bSdh142964 if (mdb_pwalk("list", pmcs_iport_phy_walk_cb, NULL, 4344c06356bSdh142964 list_addr) == -1) { 4354c06356bSdh142964 mdb_warn("pmcs iport walk failed"); 4364c06356bSdh142964 } 4374c06356bSdh142964 mdb_dec_indent(6); 4384c06356bSdh142964 mdb_printf("\n"); 4394c06356bSdh142964 } 4404c06356bSdh142964 441f7aef0b0SReed /* 442f7aef0b0SReed * See if we need to show more information based on 'd' or 'm' options 443f7aef0b0SReed */ 444f7aef0b0SReed display_iport_more(iport.dip, pis); 445f7aef0b0SReed 4464c06356bSdh142964 return (0); 4474c06356bSdh142964 } 4484c06356bSdh142964 4494c06356bSdh142964 /*ARGSUSED*/ 4504c06356bSdh142964 static void 451f7aef0b0SReed display_iport(struct pmcs_hw m, uintptr_t addr, int verbose, 452f7aef0b0SReed per_iport_setting_t *pis) 4534c06356bSdh142964 { 4544c06356bSdh142964 uintptr_t list_addr; 4554c06356bSdh142964 4564c06356bSdh142964 if (m.iports_attached) { 4574c06356bSdh142964 mdb_printf("Iport information:\n"); 4584c06356bSdh142964 mdb_printf("-----------------\n"); 4594c06356bSdh142964 } else { 4604c06356bSdh142964 mdb_printf("No Iports found.\n\n"); 4614c06356bSdh142964 return; 4624c06356bSdh142964 } 4634c06356bSdh142964 4644c06356bSdh142964 list_addr = (uintptr_t)(addr + offsetof(struct pmcs_hw, iports)); 4654c06356bSdh142964 466f7aef0b0SReed if (mdb_pwalk("list", pmcs_iport_walk_cb, pis, list_addr) == -1) { 4674c06356bSdh142964 mdb_warn("pmcs iport walk failed"); 4684c06356bSdh142964 } 4694c06356bSdh142964 4704c06356bSdh142964 mdb_printf("\n"); 4714c06356bSdh142964 } 4724c06356bSdh142964 473c3bc407cSdh142964 /* ARGSUSED */ 474c3bc407cSdh142964 static int 475c3bc407cSdh142964 pmcs_utarget_walk_cb(uintptr_t addr, const void *wdata, void *priv) 476c3bc407cSdh142964 { 477c3bc407cSdh142964 pmcs_phy_t phy; 478c3bc407cSdh142964 479c3bc407cSdh142964 if (mdb_vread(&phy, sizeof (pmcs_phy_t), (uintptr_t)addr) == -1) { 480c3bc407cSdh142964 mdb_warn("pmcs_utarget_walk_cb: Failed to read PHY at %p", 481c3bc407cSdh142964 (void *)addr); 482c3bc407cSdh142964 return (DCMD_ERR); 483c3bc407cSdh142964 } 484c3bc407cSdh142964 485c3bc407cSdh142964 if (phy.configured && (phy.target == NULL)) { 486c3bc407cSdh142964 mdb_printf("SAS address: "); 487c3bc407cSdh142964 print_sas_address(&phy); 488c3bc407cSdh142964 mdb_printf(" DType: "); 489c3bc407cSdh142964 switch (phy.dtype) { 490c3bc407cSdh142964 case SAS: 491c3bc407cSdh142964 mdb_printf("%4s", "SAS"); 492c3bc407cSdh142964 break; 493c3bc407cSdh142964 case SATA: 494c3bc407cSdh142964 mdb_printf("%4s", "SATA"); 495c3bc407cSdh142964 break; 496c3bc407cSdh142964 case EXPANDER: 497c3bc407cSdh142964 mdb_printf("%4s", "SMP"); 498c3bc407cSdh142964 break; 499c3bc407cSdh142964 default: 500c3bc407cSdh142964 mdb_printf("%4s", "N/A"); 501c3bc407cSdh142964 break; 502c3bc407cSdh142964 } 503c3bc407cSdh142964 mdb_printf(" Path: %s\n", phy.path); 504c3bc407cSdh142964 } 505c3bc407cSdh142964 506c3bc407cSdh142964 return (0); 507c3bc407cSdh142964 } 508c3bc407cSdh142964 509c3bc407cSdh142964 static void 510c3bc407cSdh142964 display_unconfigured_targets(uintptr_t addr) 511c3bc407cSdh142964 { 512c3bc407cSdh142964 mdb_printf("Unconfigured target SAS address:\n\n"); 513c3bc407cSdh142964 514c3bc407cSdh142964 if (mdb_pwalk("pmcs_phys", pmcs_utarget_walk_cb, NULL, addr) == -1) { 515c3bc407cSdh142964 mdb_warn("pmcs phys walk failed"); 516c3bc407cSdh142964 } 517c3bc407cSdh142964 } 518c3bc407cSdh142964 51914d6cf0aSdh142964 static void 52014d6cf0aSdh142964 display_completion_queue(struct pmcs_hw ss) 52114d6cf0aSdh142964 { 52214d6cf0aSdh142964 pmcs_iocomp_cb_t ccb, *ccbp; 52314d6cf0aSdh142964 pmcwork_t work; 52414d6cf0aSdh142964 52514d6cf0aSdh142964 if (ss.iocomp_cb_head == NULL) { 52614d6cf0aSdh142964 mdb_printf("Completion queue is empty.\n"); 52714d6cf0aSdh142964 return; 52814d6cf0aSdh142964 } 52914d6cf0aSdh142964 53014d6cf0aSdh142964 ccbp = ss.iocomp_cb_head; 53114d6cf0aSdh142964 mdb_printf("%8s %10s %20s %8s %8s O D\n", 53214d6cf0aSdh142964 "HTag", "State", "Phy Path", "Target", "Timer"); 53314d6cf0aSdh142964 53414d6cf0aSdh142964 while (ccbp) { 53514d6cf0aSdh142964 if (mdb_vread(&ccb, sizeof (pmcs_iocomp_cb_t), 53614d6cf0aSdh142964 (uintptr_t)ccbp) != sizeof (pmcs_iocomp_cb_t)) { 53714d6cf0aSdh142964 mdb_warn("Unable to read completion queue entry\n"); 53814d6cf0aSdh142964 return; 53914d6cf0aSdh142964 } 54014d6cf0aSdh142964 54114d6cf0aSdh142964 if (mdb_vread(&work, sizeof (pmcwork_t), (uintptr_t)ccb.pwrk) 54214d6cf0aSdh142964 != sizeof (pmcwork_t)) { 54314d6cf0aSdh142964 mdb_warn("Unable to read work structure\n"); 54414d6cf0aSdh142964 return; 54514d6cf0aSdh142964 } 54614d6cf0aSdh142964 54714d6cf0aSdh142964 /* 54814d6cf0aSdh142964 * Only print the work structure if it's still active. If 54914d6cf0aSdh142964 * it's not, it's been completed since we started looking at 55014d6cf0aSdh142964 * it. 55114d6cf0aSdh142964 */ 55214d6cf0aSdh142964 if (work.state != PMCS_WORK_STATE_NIL) { 55314d6cf0aSdh142964 display_one_work(&work, 0, 0); 55414d6cf0aSdh142964 } 55514d6cf0aSdh142964 ccbp = ccb.next; 55614d6cf0aSdh142964 } 55714d6cf0aSdh142964 } 55814d6cf0aSdh142964 5591f81b464SDavid Hollister static void 5601f81b464SDavid Hollister display_event_log(struct pmcs_hw ss) 5611f81b464SDavid Hollister { 5621f81b464SDavid Hollister pmcs_fw_event_hdr_t fwhdr; 5631f81b464SDavid Hollister char *header_id, *entry, *fwlogp; 5641f81b464SDavid Hollister uint32_t total_size = PMCS_FWLOG_SIZE, log_size, index, *swapp, sidx; 5651f81b464SDavid Hollister pmcs_fw_event_entry_t *fw_entryp; 5661f81b464SDavid Hollister struct timespec systime; 5671f81b464SDavid Hollister 5681f81b464SDavid Hollister if (ss.fwlogp == NULL) { 5691f81b464SDavid Hollister mdb_printf("There is no firmware event log.\n"); 5701f81b464SDavid Hollister return; 5711f81b464SDavid Hollister } 5721f81b464SDavid Hollister 5731f81b464SDavid Hollister fwlogp = (char *)ss.fwlogp; 5741f81b464SDavid Hollister 5751f81b464SDavid Hollister while (total_size != 0) { 5761f81b464SDavid Hollister if (mdb_vread(&fwhdr, sizeof (pmcs_fw_event_hdr_t), 5771f81b464SDavid Hollister (uintptr_t)fwlogp) != sizeof (pmcs_fw_event_hdr_t)) { 5781f81b464SDavid Hollister mdb_warn("Unable to read firmware event log header\n"); 5791f81b464SDavid Hollister return; 5801f81b464SDavid Hollister } 5811f81b464SDavid Hollister 5821f81b464SDavid Hollister /* 5831f81b464SDavid Hollister * Firmware event log is little-endian 5841f81b464SDavid Hollister */ 5851f81b464SDavid Hollister swapp = (uint32_t *)&fwhdr; 5861f81b464SDavid Hollister for (sidx = 0; sidx < (sizeof (pmcs_fw_event_hdr_t) / 5871f81b464SDavid Hollister sizeof (uint32_t)); sidx++) { 5881f81b464SDavid Hollister *swapp = LE_32(*swapp); 5891f81b464SDavid Hollister swapp++; 5901f81b464SDavid Hollister } 5911f81b464SDavid Hollister 5921f81b464SDavid Hollister if (fwhdr.fw_el_signature == PMCS_FWLOG_AAP1_SIG) { 5931f81b464SDavid Hollister header_id = "AAP1"; 5941f81b464SDavid Hollister } else if (fwhdr.fw_el_signature == PMCS_FWLOG_IOP_SIG) { 5951f81b464SDavid Hollister header_id = "IOP"; 5961f81b464SDavid Hollister } else { 5971f81b464SDavid Hollister mdb_warn("Invalid firmware event log signature\n"); 5981f81b464SDavid Hollister return; 5991f81b464SDavid Hollister } 6001f81b464SDavid Hollister 6011f81b464SDavid Hollister mdb_printf("Event Log: %s\n", header_id); 6021f81b464SDavid Hollister mdb_printf("Oldest entry: %d\n", fwhdr.fw_el_oldest_idx); 6031f81b464SDavid Hollister mdb_printf("Latest entry: %d\n", fwhdr.fw_el_latest_idx); 6041f81b464SDavid Hollister 6051f81b464SDavid Hollister entry = mdb_alloc(fwhdr.fw_el_entry_size, UM_SLEEP); 6061f81b464SDavid Hollister fw_entryp = (pmcs_fw_event_entry_t *)((void *)entry); 6071f81b464SDavid Hollister total_size -= sizeof (pmcs_fw_event_hdr_t); 6081f81b464SDavid Hollister log_size = fwhdr.fw_el_buf_size; 6091f81b464SDavid Hollister fwlogp += fwhdr.fw_el_entry_start_offset; 6101f81b464SDavid Hollister swapp = (uint32_t *)((void *)entry); 6111f81b464SDavid Hollister index = 0; 6121f81b464SDavid Hollister 6131f81b464SDavid Hollister mdb_printf("%8s %16s %32s %8s %3s %8s %8s %8s %8s", 6141f81b464SDavid Hollister "Index", "Timestamp", "Time", "Seq Num", "Sev", "Word 0", 6151f81b464SDavid Hollister "Word 1", "Word 2", "Word 3"); 6161f81b464SDavid Hollister mdb_printf("\n"); 6171f81b464SDavid Hollister 6181f81b464SDavid Hollister while (log_size != 0) { 6191f81b464SDavid Hollister if (mdb_vread(entry, fwhdr.fw_el_entry_size, 6201f81b464SDavid Hollister (uintptr_t)fwlogp) != fwhdr.fw_el_entry_size) { 6211f81b464SDavid Hollister mdb_warn("Unable to read event log entry\n"); 6221f81b464SDavid Hollister goto bail_out; 6231f81b464SDavid Hollister } 6241f81b464SDavid Hollister 6251f81b464SDavid Hollister for (sidx = 0; sidx < (fwhdr.fw_el_entry_size / 6261f81b464SDavid Hollister sizeof (uint32_t)); sidx++) { 6271f81b464SDavid Hollister *(swapp + sidx) = LE_32(*(swapp + sidx)); 6281f81b464SDavid Hollister } 6291f81b464SDavid Hollister 6301f81b464SDavid Hollister if (fw_entryp->ts_upper || fw_entryp->ts_lower) { 6311f81b464SDavid Hollister pmcs_fwtime_to_systime(ss, fw_entryp->ts_upper, 6321f81b464SDavid Hollister fw_entryp->ts_lower, &systime); 6331f81b464SDavid Hollister mdb_printf("%8d %08x%08x [%Y.%09ld] %8d %3d " 6341f81b464SDavid Hollister "%08x %08x %08x %08x\n", index, 6351f81b464SDavid Hollister fw_entryp->ts_upper, fw_entryp->ts_lower, 6361f81b464SDavid Hollister systime, fw_entryp->seq_num, 6371f81b464SDavid Hollister fw_entryp->severity, fw_entryp->logw0, 6381f81b464SDavid Hollister fw_entryp->logw1, fw_entryp->logw2, 6391f81b464SDavid Hollister fw_entryp->logw3); 6401f81b464SDavid Hollister } 6411f81b464SDavid Hollister 6421f81b464SDavid Hollister fwlogp += fwhdr.fw_el_entry_size; 6431f81b464SDavid Hollister total_size -= fwhdr.fw_el_entry_size; 6441f81b464SDavid Hollister log_size -= fwhdr.fw_el_entry_size; 6451f81b464SDavid Hollister index++; 6461f81b464SDavid Hollister } 6471f81b464SDavid Hollister 6481f81b464SDavid Hollister mdb_printf("\n"); 6491f81b464SDavid Hollister } 6501f81b464SDavid Hollister 6511f81b464SDavid Hollister bail_out: 6521f81b464SDavid Hollister mdb_free(entry, fwhdr.fw_el_entry_size); 6531f81b464SDavid Hollister } 6541f81b464SDavid Hollister 6554c06356bSdh142964 /*ARGSUSED*/ 6564c06356bSdh142964 static void 6574c06356bSdh142964 display_hwinfo(struct pmcs_hw m, int verbose) 6584c06356bSdh142964 { 6594c06356bSdh142964 struct pmcs_hw *mp = &m; 6604c06356bSdh142964 char *fwsupport; 6614c06356bSdh142964 6624c06356bSdh142964 switch (PMCS_FW_TYPE(mp)) { 6634c06356bSdh142964 case PMCS_FW_TYPE_RELEASED: 6644c06356bSdh142964 fwsupport = "Released"; 6654c06356bSdh142964 break; 6664c06356bSdh142964 case PMCS_FW_TYPE_DEVELOPMENT: 6674c06356bSdh142964 fwsupport = "Development"; 6684c06356bSdh142964 break; 6694c06356bSdh142964 case PMCS_FW_TYPE_ALPHA: 6704c06356bSdh142964 fwsupport = "Alpha"; 6714c06356bSdh142964 break; 6724c06356bSdh142964 case PMCS_FW_TYPE_BETA: 6734c06356bSdh142964 fwsupport = "Beta"; 6744c06356bSdh142964 break; 6754c06356bSdh142964 default: 6764c06356bSdh142964 fwsupport = "Special"; 6774c06356bSdh142964 break; 6784c06356bSdh142964 } 6794c06356bSdh142964 6804c06356bSdh142964 mdb_printf("\nHardware information:\n"); 6814c06356bSdh142964 mdb_printf("---------------------\n"); 6824c06356bSdh142964 6834c06356bSdh142964 mdb_printf("Chip revision: %c\n", 'A' + m.chiprev); 6844c06356bSdh142964 mdb_printf("SAS WWID: %"PRIx64"\n", m.sas_wwns[0]); 6854c06356bSdh142964 mdb_printf("Firmware version: %x.%x.%x (%s)\n", 6864c06356bSdh142964 PMCS_FW_MAJOR(mp), PMCS_FW_MINOR(mp), PMCS_FW_MICRO(mp), 6874c06356bSdh142964 fwsupport); 6882ac4abe8SDavid Hollister mdb_printf("ILA version: %08x\n", m.ila_ver); 6892ac4abe8SDavid Hollister mdb_printf("Active f/w img: %c\n", (m.fw_active_img) ? 'A' : 'B'); 6904c06356bSdh142964 6914c06356bSdh142964 mdb_printf("Number of PHYs: %d\n", m.nphy); 6924c06356bSdh142964 mdb_printf("Maximum commands: %d\n", m.max_cmd); 6934c06356bSdh142964 mdb_printf("Maximum devices: %d\n", m.max_dev); 6944c06356bSdh142964 mdb_printf("I/O queue depth: %d\n", m.ioq_depth); 695658280b6SDavid Hollister mdb_printf("Open retry intvl: %d usecs\n", m.open_retry_interval); 6964c06356bSdh142964 if (m.fwlog == 0) { 6974c06356bSdh142964 mdb_printf("Firmware logging: Disabled\n"); 6984c06356bSdh142964 } else { 6994c06356bSdh142964 mdb_printf("Firmware logging: Enabled (%d)\n", m.fwlog); 7004c06356bSdh142964 } 7012ac4abe8SDavid Hollister if (m.fwlog_file == 0) { 7022ac4abe8SDavid Hollister mdb_printf("Firmware logfile: Not configured\n"); 7032ac4abe8SDavid Hollister } else { 7042ac4abe8SDavid Hollister mdb_printf("Firmware logfile: Configured\n"); 7052ac4abe8SDavid Hollister mdb_inc_indent(2); 7062ac4abe8SDavid Hollister mdb_printf("AAP1 log file: %s\n", m.fwlogfile_aap1); 7072ac4abe8SDavid Hollister mdb_printf("IOP logfile: %s\n", m.fwlogfile_iop); 7082ac4abe8SDavid Hollister mdb_dec_indent(2); 7092ac4abe8SDavid Hollister } 7104c06356bSdh142964 } 7114c06356bSdh142964 7124c06356bSdh142964 static void 7134c06356bSdh142964 display_targets(struct pmcs_hw m, int verbose, int totals_only) 7144c06356bSdh142964 { 7154c06356bSdh142964 char *dtype; 7164c06356bSdh142964 pmcs_xscsi_t xs; 7174c06356bSdh142964 pmcs_phy_t phy; 7184c06356bSdh142964 uint16_t max_dev, idx; 7194c06356bSdh142964 uint32_t sas_targets = 0, smp_targets = 0, sata_targets = 0; 7204c06356bSdh142964 7214c06356bSdh142964 max_dev = m.max_dev; 7224c06356bSdh142964 7234c06356bSdh142964 if (targets == NULL) { 7244c06356bSdh142964 targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP); 7254c06356bSdh142964 } 7264c06356bSdh142964 7274c06356bSdh142964 if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) { 7284c06356bSdh142964 NOREAD(targets, m.targets); 7294c06356bSdh142964 return; 7304c06356bSdh142964 } 7314c06356bSdh142964 7324c06356bSdh142964 if (!totals_only) { 7334c06356bSdh142964 mdb_printf("\nTarget information:\n"); 7344c06356bSdh142964 mdb_printf("---------------------------------------\n"); 735601c90f1SSrikanth, Ramana mdb_printf("VTGT %-16s %-16s %-5s %4s %6s %s", "SAS Address", 736601c90f1SSrikanth, Ramana "PHY Address", "DType", "Actv", "OnChip", "DS"); 7374c06356bSdh142964 mdb_printf("\n"); 7384c06356bSdh142964 } 7394c06356bSdh142964 7404c06356bSdh142964 for (idx = 0; idx < max_dev; idx++) { 7414c06356bSdh142964 if (targets[idx] == NULL) { 7424c06356bSdh142964 continue; 7434c06356bSdh142964 } 7444c06356bSdh142964 7454c06356bSdh142964 if (MDB_RD(&xs, sizeof (xs), targets[idx]) == -1) { 7464c06356bSdh142964 NOREAD(pmcs_xscsi_t, targets[idx]); 7474c06356bSdh142964 continue; 7484c06356bSdh142964 } 7494c06356bSdh142964 7504c06356bSdh142964 /* 751b18a19c2SJesse Butler * It has to be new or assigned to be of interest. 7524c06356bSdh142964 */ 753b18a19c2SJesse Butler if (xs.new == 0 && xs.assigned == 0) { 7544c06356bSdh142964 continue; 7554c06356bSdh142964 } 7564c06356bSdh142964 7574c06356bSdh142964 switch (xs.dtype) { 7584c06356bSdh142964 case NOTHING: 7594c06356bSdh142964 dtype = "None"; 7604c06356bSdh142964 break; 7614c06356bSdh142964 case SATA: 7624c06356bSdh142964 dtype = "SATA"; 7634c06356bSdh142964 sata_targets++; 7644c06356bSdh142964 break; 7654c06356bSdh142964 case SAS: 7664c06356bSdh142964 dtype = "SAS"; 7674c06356bSdh142964 sas_targets++; 7684c06356bSdh142964 break; 7694c06356bSdh142964 case EXPANDER: 7704c06356bSdh142964 dtype = "SMP"; 7714c06356bSdh142964 smp_targets++; 7724c06356bSdh142964 break; 7734c06356bSdh142964 } 7744c06356bSdh142964 7754c06356bSdh142964 if (totals_only) { 7764c06356bSdh142964 continue; 7774c06356bSdh142964 } 7784c06356bSdh142964 7794c06356bSdh142964 if (xs.phy) { 7804c06356bSdh142964 if (MDB_RD(&phy, sizeof (phy), xs.phy) == -1) { 7814c06356bSdh142964 NOREAD(pmcs_phy_t, xs.phy); 7824c06356bSdh142964 continue; 7834c06356bSdh142964 } 7844c06356bSdh142964 mdb_printf("%4d ", idx); 7854c06356bSdh142964 print_sas_address(&phy); 7864c06356bSdh142964 mdb_printf(" %16p", xs.phy); 7874c06356bSdh142964 } else { 7884c06356bSdh142964 mdb_printf("%4d %16s", idx, "<no phy avail>"); 7894c06356bSdh142964 } 7904c06356bSdh142964 mdb_printf(" %5s", dtype); 791601c90f1SSrikanth, Ramana mdb_printf(" %4d", xs.actv_pkts); 792601c90f1SSrikanth, Ramana mdb_printf(" %6d", xs.actv_cnt); 7934c06356bSdh142964 mdb_printf(" %2d", xs.dev_state); 7944c06356bSdh142964 7954c06356bSdh142964 if (verbose) { 7964c06356bSdh142964 if (xs.new) { 7974c06356bSdh142964 mdb_printf(" new"); 798b18a19c2SJesse Butler } 799b18a19c2SJesse Butler if (xs.assigned) { 8004c06356bSdh142964 mdb_printf(" assigned"); 8014c06356bSdh142964 } 8024c06356bSdh142964 if (xs.draining) { 8034c06356bSdh142964 mdb_printf(" draining"); 8044c06356bSdh142964 } 8054c06356bSdh142964 if (xs.reset_wait) { 8064c06356bSdh142964 mdb_printf(" reset_wait"); 8074c06356bSdh142964 } 8084c06356bSdh142964 if (xs.resetting) { 8094c06356bSdh142964 mdb_printf(" resetting"); 8104c06356bSdh142964 } 8114c06356bSdh142964 if (xs.recover_wait) { 8124c06356bSdh142964 mdb_printf(" recover_wait"); 8134c06356bSdh142964 } 8144c06356bSdh142964 if (xs.recovering) { 8154c06356bSdh142964 mdb_printf(" recovering"); 8164c06356bSdh142964 } 8174c06356bSdh142964 if (xs.event_recovery) { 8184c06356bSdh142964 mdb_printf(" event recovery"); 8194c06356bSdh142964 } 8204c06356bSdh142964 if (xs.special_running) { 8214c06356bSdh142964 mdb_printf(" special_active"); 8224c06356bSdh142964 } 8234c06356bSdh142964 if (xs.ncq) { 8244c06356bSdh142964 mdb_printf(" ncq_tagmap=0x%x qdepth=%d", 8254c06356bSdh142964 xs.tagmap, xs.qdepth); 8264c06356bSdh142964 } else if (xs.pio) { 8274c06356bSdh142964 mdb_printf(" pio"); 8284c06356bSdh142964 } 8294c06356bSdh142964 } 8304c06356bSdh142964 8314c06356bSdh142964 mdb_printf("\n"); 8324c06356bSdh142964 } 8334c06356bSdh142964 8344c06356bSdh142964 if (!totals_only) { 8354c06356bSdh142964 mdb_printf("\n"); 8364c06356bSdh142964 } 8374c06356bSdh142964 8384c06356bSdh142964 mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n", 8394c06356bSdh142964 "Configured targets:", (sas_targets + sata_targets + smp_targets), 8404c06356bSdh142964 sas_targets, sata_targets, smp_targets); 8414c06356bSdh142964 } 8424c06356bSdh142964 84314d6cf0aSdh142964 static char * 84414d6cf0aSdh142964 work_state_to_string(uint32_t state) 8454c06356bSdh142964 { 84614d6cf0aSdh142964 char *state_string; 8474c06356bSdh142964 84814d6cf0aSdh142964 switch (state) { 8494c06356bSdh142964 case PMCS_WORK_STATE_NIL: 85014d6cf0aSdh142964 state_string = "Free"; 8514c06356bSdh142964 break; 8524c06356bSdh142964 case PMCS_WORK_STATE_READY: 85314d6cf0aSdh142964 state_string = "Ready"; 8544c06356bSdh142964 break; 8554c06356bSdh142964 case PMCS_WORK_STATE_ONCHIP: 85614d6cf0aSdh142964 state_string = "On Chip"; 8574c06356bSdh142964 break; 8584c06356bSdh142964 case PMCS_WORK_STATE_INTR: 85914d6cf0aSdh142964 state_string = "In Intr"; 8604c06356bSdh142964 break; 8614c06356bSdh142964 case PMCS_WORK_STATE_IOCOMPQ: 86214d6cf0aSdh142964 state_string = "I/O Comp"; 8634c06356bSdh142964 break; 8644c06356bSdh142964 case PMCS_WORK_STATE_ABORTED: 86514d6cf0aSdh142964 state_string = "I/O Aborted"; 8664c06356bSdh142964 break; 8674c06356bSdh142964 case PMCS_WORK_STATE_TIMED_OUT: 86814d6cf0aSdh142964 state_string = "I/O Timed Out"; 8694c06356bSdh142964 break; 8704c06356bSdh142964 default: 87114d6cf0aSdh142964 state_string = "INVALID"; 8724c06356bSdh142964 break; 8734c06356bSdh142964 } 87414d6cf0aSdh142964 87514d6cf0aSdh142964 return (state_string); 87614d6cf0aSdh142964 } 87714d6cf0aSdh142964 87814d6cf0aSdh142964 static void 87914d6cf0aSdh142964 display_one_work(pmcwork_t *wp, int verbose, int idx) 88014d6cf0aSdh142964 { 88114d6cf0aSdh142964 char *state, *last_state; 88214d6cf0aSdh142964 char *path; 88314d6cf0aSdh142964 pmcs_xscsi_t xs; 88414d6cf0aSdh142964 pmcs_phy_t phy; 88514d6cf0aSdh142964 int tgt; 88614d6cf0aSdh142964 88714d6cf0aSdh142964 state = work_state_to_string(wp->state); 88814d6cf0aSdh142964 last_state = work_state_to_string(wp->last_state); 88914d6cf0aSdh142964 8904c06356bSdh142964 if (wp->ssp_event && wp->ssp_event != 0xffffffff) { 8914c06356bSdh142964 mdb_printf("SSP event 0x%x", wp->ssp_event); 8924c06356bSdh142964 } 89314d6cf0aSdh142964 8944c06356bSdh142964 tgt = -1; 8954c06356bSdh142964 if (wp->xp) { 8964c06356bSdh142964 if (MDB_RD(&xs, sizeof (xs), wp->xp) == -1) { 8974c06356bSdh142964 NOREAD(pmcs_xscsi_t, wp->xp); 8984c06356bSdh142964 } else { 8994c06356bSdh142964 tgt = xs.target_num; 9004c06356bSdh142964 } 9014c06356bSdh142964 } 9024c06356bSdh142964 if (wp->phy) { 9034c06356bSdh142964 if (MDB_RD(&phy, sizeof (phy), wp->phy) == -1) { 9044c06356bSdh142964 NOREAD(pmcs_phy_t, wp->phy); 9054c06356bSdh142964 } 9064c06356bSdh142964 path = phy.path; 9074c06356bSdh142964 } else { 90814d6cf0aSdh142964 path = "N/A"; 9094c06356bSdh142964 } 91014d6cf0aSdh142964 91114d6cf0aSdh142964 if (verbose) { 91214d6cf0aSdh142964 mdb_printf("%4d ", idx); 91314d6cf0aSdh142964 } 91414d6cf0aSdh142964 if (tgt == -1) { 91514d6cf0aSdh142964 mdb_printf("%08x %10s %20s N/A %8u %1d %1d ", 91614d6cf0aSdh142964 wp->htag, state, path, wp->timer, 91714d6cf0aSdh142964 wp->onwire, wp->dead); 91814d6cf0aSdh142964 } else { 91914d6cf0aSdh142964 mdb_printf("%08x %10s %20s %8d %8u %1d %1d ", 9204c06356bSdh142964 wp->htag, state, path, tgt, wp->timer, 9214c06356bSdh142964 wp->onwire, wp->dead); 9224c06356bSdh142964 } 92314d6cf0aSdh142964 if (verbose) { 9249aed1621SDavid Hollister mdb_printf("%08x %10s 0x%016p 0x%016p 0x%016p\n", 9259aed1621SDavid Hollister wp->last_htag, last_state, wp->last_phy, wp->last_xp, 9269aed1621SDavid Hollister wp->last_arg); 92714d6cf0aSdh142964 } else { 92814d6cf0aSdh142964 mdb_printf("\n"); 92914d6cf0aSdh142964 } 9304c06356bSdh142964 } 9314c06356bSdh142964 9324c06356bSdh142964 static void 933658280b6SDavid Hollister display_work(struct pmcs_hw m, int verbose, int wserno) 9344c06356bSdh142964 { 93514d6cf0aSdh142964 int idx; 93614d6cf0aSdh142964 boolean_t header_printed = B_FALSE; 937658280b6SDavid Hollister pmcwork_t *wp; 938658280b6SDavid Hollister wserno_list_t *sernop, *sp, *newsp, *sphead = NULL; 93914d6cf0aSdh142964 uintptr_t _wp; 940658280b6SDavid Hollister int serno; 941658280b6SDavid Hollister 942658280b6SDavid Hollister wp = mdb_alloc(sizeof (pmcwork_t) * m.max_cmd, UM_SLEEP); 943658280b6SDavid Hollister _wp = (uintptr_t)m.work; 944658280b6SDavid Hollister sernop = mdb_alloc(sizeof (wserno_list_t) * m.max_cmd, UM_SLEEP); 945658280b6SDavid Hollister bzero(sernop, sizeof (wserno_list_t) * m.max_cmd); 94614d6cf0aSdh142964 94714d6cf0aSdh142964 mdb_printf("\nActive Work structure information:\n"); 94814d6cf0aSdh142964 mdb_printf("----------------------------------\n"); 94914d6cf0aSdh142964 950658280b6SDavid Hollister /* 951658280b6SDavid Hollister * Read in all the work structures 952658280b6SDavid Hollister */ 95314d6cf0aSdh142964 for (idx = 0; idx < m.max_cmd; idx++, _wp += sizeof (pmcwork_t)) { 954658280b6SDavid Hollister if (MDB_RD(wp + idx, sizeof (pmcwork_t), _wp) == -1) { 95514d6cf0aSdh142964 NOREAD(pmcwork_t, _wp); 95614d6cf0aSdh142964 continue; 9574c06356bSdh142964 } 958658280b6SDavid Hollister } 95914d6cf0aSdh142964 960658280b6SDavid Hollister /* 961658280b6SDavid Hollister * Sort by serial number? 962658280b6SDavid Hollister */ 963658280b6SDavid Hollister if (wserno) { 964658280b6SDavid Hollister for (idx = 0; idx < m.max_cmd; idx++) { 965658280b6SDavid Hollister if ((wp + idx)->htag == 0) { 966658280b6SDavid Hollister serno = PMCS_TAG_SERNO((wp + idx)->last_htag); 967658280b6SDavid Hollister } else { 968658280b6SDavid Hollister serno = PMCS_TAG_SERNO((wp + idx)->htag); 969658280b6SDavid Hollister } 970658280b6SDavid Hollister 971658280b6SDavid Hollister /* Start at the beginning of the list */ 972658280b6SDavid Hollister sp = sphead; 973658280b6SDavid Hollister newsp = sernop + idx; 974658280b6SDavid Hollister /* If this is the first entry, just add it */ 975658280b6SDavid Hollister if (sphead == NULL) { 976658280b6SDavid Hollister sphead = sernop; 977658280b6SDavid Hollister sphead->serno = serno; 978658280b6SDavid Hollister sphead->idx = idx; 979658280b6SDavid Hollister sphead->next = NULL; 980658280b6SDavid Hollister sphead->prev = NULL; 981658280b6SDavid Hollister continue; 982658280b6SDavid Hollister } 983658280b6SDavid Hollister 984658280b6SDavid Hollister newsp->serno = serno; 985658280b6SDavid Hollister newsp->idx = idx; 986658280b6SDavid Hollister 987658280b6SDavid Hollister /* Find out where in the list this goes */ 988658280b6SDavid Hollister while (sp) { 989658280b6SDavid Hollister /* This item goes before sp */ 990658280b6SDavid Hollister if (serno < sp->serno) { 991658280b6SDavid Hollister newsp->next = sp; 992658280b6SDavid Hollister newsp->prev = sp->prev; 993658280b6SDavid Hollister if (newsp->prev == NULL) { 994658280b6SDavid Hollister sphead = newsp; 995658280b6SDavid Hollister } else { 996658280b6SDavid Hollister newsp->prev->next = newsp; 997658280b6SDavid Hollister } 998658280b6SDavid Hollister sp->prev = newsp; 999658280b6SDavid Hollister break; 1000658280b6SDavid Hollister } 1001658280b6SDavid Hollister 1002658280b6SDavid Hollister /* 1003658280b6SDavid Hollister * If sp->next is NULL, this entry goes at the 1004658280b6SDavid Hollister * end of the list 1005658280b6SDavid Hollister */ 1006658280b6SDavid Hollister if (sp->next == NULL) { 1007658280b6SDavid Hollister sp->next = newsp; 1008658280b6SDavid Hollister newsp->next = NULL; 1009658280b6SDavid Hollister newsp->prev = sp; 1010658280b6SDavid Hollister break; 1011658280b6SDavid Hollister } 1012658280b6SDavid Hollister 1013658280b6SDavid Hollister sp = sp->next; 1014658280b6SDavid Hollister } 1015658280b6SDavid Hollister } 1016658280b6SDavid Hollister 1017658280b6SDavid Hollister /* 1018658280b6SDavid Hollister * Now print the sorted list 1019658280b6SDavid Hollister */ 1020658280b6SDavid Hollister mdb_printf(" Idx %8s %10s %20s %8s %8s O D ", 1021658280b6SDavid Hollister "HTag", "State", "Phy Path", "Target", "Timer"); 1022658280b6SDavid Hollister mdb_printf("%8s %10s %18s %18s %18s\n", "LastHTAG", 1023658280b6SDavid Hollister "LastState", "LastPHY", "LastTgt", "LastArg"); 1024658280b6SDavid Hollister 1025658280b6SDavid Hollister sp = sphead; 1026658280b6SDavid Hollister while (sp) { 1027658280b6SDavid Hollister display_one_work(wp + sp->idx, 1, sp->idx); 1028658280b6SDavid Hollister sp = sp->next; 1029658280b6SDavid Hollister } 1030658280b6SDavid Hollister 1031658280b6SDavid Hollister goto out; 1032658280b6SDavid Hollister } 1033658280b6SDavid Hollister 1034658280b6SDavid Hollister /* 1035658280b6SDavid Hollister * Now print the list, sorted by index 1036658280b6SDavid Hollister */ 1037658280b6SDavid Hollister for (idx = 0; idx < m.max_cmd; idx++) { 1038658280b6SDavid Hollister if (!verbose && ((wp + idx)->htag == PMCS_TAG_TYPE_FREE)) { 103914d6cf0aSdh142964 continue; 104014d6cf0aSdh142964 } 104114d6cf0aSdh142964 104214d6cf0aSdh142964 if (header_printed == B_FALSE) { 104314d6cf0aSdh142964 if (verbose) { 104414d6cf0aSdh142964 mdb_printf("%4s ", "Idx"); 104514d6cf0aSdh142964 } 104614d6cf0aSdh142964 mdb_printf("%8s %10s %20s %8s %8s O D ", 104714d6cf0aSdh142964 "HTag", "State", "Phy Path", "Target", "Timer"); 104814d6cf0aSdh142964 if (verbose) { 10499aed1621SDavid Hollister mdb_printf("%8s %10s %18s %18s %18s\n", 10509aed1621SDavid Hollister "LastHTAG", "LastState", "LastPHY", 10519aed1621SDavid Hollister "LastTgt", "LastArg"); 105214d6cf0aSdh142964 } else { 105314d6cf0aSdh142964 mdb_printf("\n"); 105414d6cf0aSdh142964 } 105514d6cf0aSdh142964 header_printed = B_TRUE; 105614d6cf0aSdh142964 } 105714d6cf0aSdh142964 1058658280b6SDavid Hollister display_one_work(wp + idx, verbose, idx); 105914d6cf0aSdh142964 } 1060658280b6SDavid Hollister 1061658280b6SDavid Hollister out: 1062658280b6SDavid Hollister mdb_free(wp, sizeof (pmcwork_t) * m.max_cmd); 1063658280b6SDavid Hollister mdb_free(sernop, sizeof (wserno_list_t) * m.max_cmd); 106414d6cf0aSdh142964 } 106514d6cf0aSdh142964 106614d6cf0aSdh142964 static void 106714d6cf0aSdh142964 print_spcmd(pmcs_cmd_t *sp, void *kaddr, int printhdr, int verbose) 106814d6cf0aSdh142964 { 106914d6cf0aSdh142964 int cdb_size, idx; 107014d6cf0aSdh142964 struct scsi_pkt pkt; 107114d6cf0aSdh142964 uchar_t cdb[256]; 107214d6cf0aSdh142964 107314d6cf0aSdh142964 if (printhdr) { 107414d6cf0aSdh142964 if (verbose) { 107514d6cf0aSdh142964 mdb_printf("%16s %16s %16s %8s %s CDB\n", "Command", 107614d6cf0aSdh142964 "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag"); 107714d6cf0aSdh142964 } else { 107814d6cf0aSdh142964 mdb_printf("%16s %16s %16s %8s %s\n", "Command", 107914d6cf0aSdh142964 "SCSA pkt", "DMA Chunks", "HTAG", "SATL Tag"); 108014d6cf0aSdh142964 } 108114d6cf0aSdh142964 } 108214d6cf0aSdh142964 108314d6cf0aSdh142964 mdb_printf("%16p %16p %16p %08x %08x ", 10844c06356bSdh142964 kaddr, sp->cmd_pkt, sp->cmd_clist, sp->cmd_tag, sp->cmd_satltag); 108514d6cf0aSdh142964 108614d6cf0aSdh142964 /* 108714d6cf0aSdh142964 * If we're printing verbose, dump the CDB as well. 108814d6cf0aSdh142964 */ 108914d6cf0aSdh142964 if (verbose) { 109014d6cf0aSdh142964 if (sp->cmd_pkt) { 109114d6cf0aSdh142964 if (mdb_vread(&pkt, sizeof (struct scsi_pkt), 109214d6cf0aSdh142964 (uintptr_t)sp->cmd_pkt) != 109314d6cf0aSdh142964 sizeof (struct scsi_pkt)) { 109414d6cf0aSdh142964 mdb_warn("Unable to read SCSI pkt\n"); 109514d6cf0aSdh142964 return; 109614d6cf0aSdh142964 } 109714d6cf0aSdh142964 cdb_size = pkt.pkt_cdblen; 109814d6cf0aSdh142964 if (mdb_vread(&cdb[0], cdb_size, 109914d6cf0aSdh142964 (uintptr_t)pkt.pkt_cdbp) != cdb_size) { 110014d6cf0aSdh142964 mdb_warn("Unable to read CDB\n"); 110114d6cf0aSdh142964 return; 110214d6cf0aSdh142964 } 110314d6cf0aSdh142964 110414d6cf0aSdh142964 for (idx = 0; idx < cdb_size; idx++) { 110514d6cf0aSdh142964 mdb_printf("%02x ", cdb[idx]); 110614d6cf0aSdh142964 } 110714d6cf0aSdh142964 } else { 110814d6cf0aSdh142964 mdb_printf("N/A"); 110914d6cf0aSdh142964 } 111014d6cf0aSdh142964 111114d6cf0aSdh142964 mdb_printf("\n"); 111214d6cf0aSdh142964 } else { 111314d6cf0aSdh142964 mdb_printf("\n"); 111414d6cf0aSdh142964 } 11154c06356bSdh142964 } 11164c06356bSdh142964 11174c06356bSdh142964 /*ARGSUSED1*/ 11184c06356bSdh142964 static void 11194c06356bSdh142964 display_waitqs(struct pmcs_hw m, int verbose) 11204c06356bSdh142964 { 11214c06356bSdh142964 pmcs_cmd_t *sp, s; 11224c06356bSdh142964 pmcs_xscsi_t xs; 11234c06356bSdh142964 int first, i; 11244c06356bSdh142964 int max_dev = m.max_dev; 11254c06356bSdh142964 11264c06356bSdh142964 sp = m.dq.stqh_first; 11274c06356bSdh142964 first = 1; 11284c06356bSdh142964 while (sp) { 11294c06356bSdh142964 if (first) { 11304c06356bSdh142964 mdb_printf("\nDead Command Queue:\n"); 11314c06356bSdh142964 mdb_printf("---------------------------\n"); 11324c06356bSdh142964 } 11334c06356bSdh142964 if (MDB_RD(&s, sizeof (s), sp) == -1) { 11344c06356bSdh142964 NOREAD(pmcs_cmd_t, sp); 11354c06356bSdh142964 break; 11364c06356bSdh142964 } 113714d6cf0aSdh142964 print_spcmd(&s, sp, first, verbose); 11384c06356bSdh142964 sp = s.cmd_next.stqe_next; 11394c06356bSdh142964 first = 0; 11404c06356bSdh142964 } 11414c06356bSdh142964 11424c06356bSdh142964 sp = m.cq.stqh_first; 11434c06356bSdh142964 first = 1; 11444c06356bSdh142964 while (sp) { 11454c06356bSdh142964 if (first) { 11464c06356bSdh142964 mdb_printf("\nCompletion Command Queue:\n"); 11474c06356bSdh142964 mdb_printf("---------------------------\n"); 11484c06356bSdh142964 } 11494c06356bSdh142964 if (MDB_RD(&s, sizeof (s), sp) == -1) { 11504c06356bSdh142964 NOREAD(pmcs_cmd_t, sp); 11514c06356bSdh142964 break; 11524c06356bSdh142964 } 115314d6cf0aSdh142964 print_spcmd(&s, sp, first, verbose); 11544c06356bSdh142964 sp = s.cmd_next.stqe_next; 11554c06356bSdh142964 first = 0; 11564c06356bSdh142964 } 11574c06356bSdh142964 11584c06356bSdh142964 11594c06356bSdh142964 if (targets == NULL) { 11604c06356bSdh142964 targets = mdb_alloc(sizeof (targets) * max_dev, UM_SLEEP); 11614c06356bSdh142964 } 11624c06356bSdh142964 11634c06356bSdh142964 if (MDB_RD(targets, sizeof (targets) * max_dev, m.targets) == -1) { 11644c06356bSdh142964 NOREAD(targets, m.targets); 11654c06356bSdh142964 return; 11664c06356bSdh142964 } 11674c06356bSdh142964 11684c06356bSdh142964 for (i = 0; i < max_dev; i++) { 11694c06356bSdh142964 if (targets[i] == NULL) { 11704c06356bSdh142964 continue; 11714c06356bSdh142964 } 11724c06356bSdh142964 if (MDB_RD(&xs, sizeof (xs), targets[i]) == -1) { 11734c06356bSdh142964 NOREAD(pmcs_xscsi_t, targets[i]); 11744c06356bSdh142964 continue; 11754c06356bSdh142964 } 11764c06356bSdh142964 sp = xs.wq.stqh_first; 11774c06356bSdh142964 first = 1; 11784c06356bSdh142964 while (sp) { 11794c06356bSdh142964 if (first) { 11804c06356bSdh142964 mdb_printf("\nTarget %u Wait Queue:\n", 11814c06356bSdh142964 xs.target_num); 11824c06356bSdh142964 mdb_printf("---------------------------\n"); 11834c06356bSdh142964 } 11844c06356bSdh142964 if (MDB_RD(&s, sizeof (s), sp) == -1) { 11854c06356bSdh142964 NOREAD(pmcs_cmd_t, sp); 11864c06356bSdh142964 break; 11874c06356bSdh142964 } 118814d6cf0aSdh142964 print_spcmd(&s, sp, first, verbose); 11894c06356bSdh142964 sp = s.cmd_next.stqe_next; 11904c06356bSdh142964 first = 0; 11914c06356bSdh142964 } 11924c06356bSdh142964 sp = xs.aq.stqh_first; 11934c06356bSdh142964 first = 1; 11944c06356bSdh142964 while (sp) { 11954c06356bSdh142964 if (first) { 11964c06356bSdh142964 mdb_printf("\nTarget %u Active Queue:\n", 11974c06356bSdh142964 xs.target_num); 11984c06356bSdh142964 mdb_printf("---------------------------\n"); 11994c06356bSdh142964 } 12004c06356bSdh142964 if (MDB_RD(&s, sizeof (s), sp) == -1) { 12014c06356bSdh142964 NOREAD(pmcs_cmd_t, sp); 12024c06356bSdh142964 break; 12034c06356bSdh142964 } 120414d6cf0aSdh142964 print_spcmd(&s, sp, first, verbose); 12054c06356bSdh142964 sp = s.cmd_next.stqe_next; 12064c06356bSdh142964 first = 0; 12074c06356bSdh142964 } 12084c06356bSdh142964 sp = xs.sq.stqh_first; 12094c06356bSdh142964 first = 1; 12104c06356bSdh142964 while (sp) { 12114c06356bSdh142964 if (first) { 12124c06356bSdh142964 mdb_printf("\nTarget %u Special Queue:\n", 12134c06356bSdh142964 xs.target_num); 12144c06356bSdh142964 mdb_printf("---------------------------\n"); 12154c06356bSdh142964 } 12164c06356bSdh142964 if (MDB_RD(&s, sizeof (s), sp) == -1) { 12174c06356bSdh142964 NOREAD(pmcs_cmd_t, sp); 12184c06356bSdh142964 break; 12194c06356bSdh142964 } 122014d6cf0aSdh142964 print_spcmd(&s, sp, first, verbose); 12214c06356bSdh142964 sp = s.cmd_next.stqe_next; 12224c06356bSdh142964 first = 0; 12234c06356bSdh142964 } 12244c06356bSdh142964 } 12254c06356bSdh142964 } 12264c06356bSdh142964 12274c06356bSdh142964 static char * 12284c06356bSdh142964 ibq_type(int qnum) 12294c06356bSdh142964 { 12304c06356bSdh142964 if (qnum < 0 || qnum >= PMCS_NIQ) { 12314c06356bSdh142964 return ("UNKNOWN"); 12324c06356bSdh142964 } 12334c06356bSdh142964 12344c06356bSdh142964 if (qnum < PMCS_IQ_OTHER) { 12354c06356bSdh142964 return ("I/O"); 12364c06356bSdh142964 } 12374c06356bSdh142964 12384c06356bSdh142964 return ("Other"); 12394c06356bSdh142964 } 12404c06356bSdh142964 12414c06356bSdh142964 static char * 12424c06356bSdh142964 obq_type(int qnum) 12434c06356bSdh142964 { 12444c06356bSdh142964 switch (qnum) { 12454c06356bSdh142964 case PMCS_OQ_IODONE: 12464c06356bSdh142964 return ("I/O"); 12474c06356bSdh142964 case PMCS_OQ_GENERAL: 12484c06356bSdh142964 return ("General"); 12494c06356bSdh142964 case PMCS_OQ_EVENTS: 12504c06356bSdh142964 return ("Events"); 12514c06356bSdh142964 default: 12524c06356bSdh142964 return ("UNKNOWN"); 12534c06356bSdh142964 } 12544c06356bSdh142964 } 12554c06356bSdh142964 12564c06356bSdh142964 static char * 12574c06356bSdh142964 iomb_cat(uint32_t cat) 12584c06356bSdh142964 { 12594c06356bSdh142964 switch (cat) { 12604c06356bSdh142964 case PMCS_IOMB_CAT_NET: 12614c06356bSdh142964 return ("NET"); 12624c06356bSdh142964 case PMCS_IOMB_CAT_FC: 12634c06356bSdh142964 return ("FC"); 12644c06356bSdh142964 case PMCS_IOMB_CAT_SAS: 12654c06356bSdh142964 return ("SAS"); 12664c06356bSdh142964 case PMCS_IOMB_CAT_SCSI: 12674c06356bSdh142964 return ("SCSI"); 12684c06356bSdh142964 default: 12694c06356bSdh142964 return ("???"); 12704c06356bSdh142964 } 12714c06356bSdh142964 } 12724c06356bSdh142964 12734c06356bSdh142964 static char * 12749aed1621SDavid Hollister iomb_event(uint8_t event) 12759aed1621SDavid Hollister { 12769aed1621SDavid Hollister switch (event) { 12779aed1621SDavid Hollister case IOP_EVENT_PHY_STOP_STATUS: 12789aed1621SDavid Hollister return ("PHY STOP"); 12799aed1621SDavid Hollister case IOP_EVENT_SAS_PHY_UP: 12809aed1621SDavid Hollister return ("PHY UP"); 12819aed1621SDavid Hollister case IOP_EVENT_SATA_PHY_UP: 12829aed1621SDavid Hollister return ("SATA PHY UP"); 12839aed1621SDavid Hollister case IOP_EVENT_SATA_SPINUP_HOLD: 12849aed1621SDavid Hollister return ("SATA SPINUP HOLD"); 12859aed1621SDavid Hollister case IOP_EVENT_PHY_DOWN: 12869aed1621SDavid Hollister return ("PHY DOWN"); 12879aed1621SDavid Hollister case IOP_EVENT_BROADCAST_CHANGE: 12889aed1621SDavid Hollister return ("BROADCAST CHANGE"); 12899aed1621SDavid Hollister case IOP_EVENT_BROADCAST_SES: 12909aed1621SDavid Hollister return ("BROADCAST SES"); 12919aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_INBOUND_CRC: 12929aed1621SDavid Hollister return ("INBOUND CRC ERROR"); 12939aed1621SDavid Hollister case IOP_EVENT_HARD_RESET_RECEIVED: 12949aed1621SDavid Hollister return ("HARD RESET"); 12959aed1621SDavid Hollister case IOP_EVENT_EVENT_ID_FRAME_TIMO: 12969aed1621SDavid Hollister return ("IDENTIFY FRAME TIMEOUT"); 12979aed1621SDavid Hollister case IOP_EVENT_BROADCAST_EXP: 12989aed1621SDavid Hollister return ("BROADCAST EXPANDER"); 12999aed1621SDavid Hollister case IOP_EVENT_PHY_START_STATUS: 13009aed1621SDavid Hollister return ("PHY START"); 13019aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_INVALID_DWORD: 13029aed1621SDavid Hollister return ("INVALID DWORD"); 13039aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_DISPARITY_ERROR: 13049aed1621SDavid Hollister return ("DISPARITY ERROR"); 13059aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_CODE_VIOLATION: 13069aed1621SDavid Hollister return ("CODE VIOLATION"); 13079aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN: 13089aed1621SDavid Hollister return ("LOSS OF DWORD SYNC"); 13099aed1621SDavid Hollister case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD: 13109aed1621SDavid Hollister return ("PHY RESET FAILED"); 13119aed1621SDavid Hollister case IOP_EVENT_PORT_RECOVERY_TIMER_TMO: 13129aed1621SDavid Hollister return ("PORT RECOVERY TIMEOUT"); 13139aed1621SDavid Hollister case IOP_EVENT_PORT_RECOVER: 13149aed1621SDavid Hollister return ("PORT RECOVERY"); 13159aed1621SDavid Hollister case IOP_EVENT_PORT_RESET_TIMER_TMO: 13169aed1621SDavid Hollister return ("PORT RESET TIMEOUT"); 13179aed1621SDavid Hollister case IOP_EVENT_PORT_RESET_COMPLETE: 13189aed1621SDavid Hollister return ("PORT RESET COMPLETE"); 13199aed1621SDavid Hollister case IOP_EVENT_BROADCAST_ASYNC_EVENT: 13209aed1621SDavid Hollister return ("BROADCAST ASYNC"); 13219aed1621SDavid Hollister case IOP_EVENT_IT_NEXUS_LOSS: 13229aed1621SDavid Hollister return ("I/T NEXUS LOSS"); 13239aed1621SDavid Hollister default: 13249aed1621SDavid Hollister return ("Unknown Event"); 13259aed1621SDavid Hollister } 13269aed1621SDavid Hollister } 13279aed1621SDavid Hollister 13289aed1621SDavid Hollister static char * 13294c06356bSdh142964 inbound_iomb_opcode(uint32_t opcode) 13304c06356bSdh142964 { 13314c06356bSdh142964 switch (opcode) { 13324c06356bSdh142964 case PMCIN_ECHO: 13334c06356bSdh142964 return ("ECHO"); 13344c06356bSdh142964 case PMCIN_GET_INFO: 13354c06356bSdh142964 return ("GET_INFO"); 13364c06356bSdh142964 case PMCIN_GET_VPD: 13374c06356bSdh142964 return ("GET_VPD"); 13384c06356bSdh142964 case PMCIN_PHY_START: 13394c06356bSdh142964 return ("PHY_START"); 13404c06356bSdh142964 case PMCIN_PHY_STOP: 13414c06356bSdh142964 return ("PHY_STOP"); 13424c06356bSdh142964 case PMCIN_SSP_INI_IO_START: 13434c06356bSdh142964 return ("INI_IO_START"); 13444c06356bSdh142964 case PMCIN_SSP_INI_TM_START: 13454c06356bSdh142964 return ("INI_TM_START"); 13464c06356bSdh142964 case PMCIN_SSP_INI_EXT_IO_START: 13474c06356bSdh142964 return ("INI_EXT_IO_START"); 13484c06356bSdh142964 case PMCIN_DEVICE_HANDLE_ACCEPT: 13494c06356bSdh142964 return ("DEVICE_HANDLE_ACCEPT"); 13504c06356bSdh142964 case PMCIN_SSP_TGT_IO_START: 13514c06356bSdh142964 return ("TGT_IO_START"); 13524c06356bSdh142964 case PMCIN_SSP_TGT_RESPONSE_START: 13534c06356bSdh142964 return ("TGT_RESPONSE_START"); 13544c06356bSdh142964 case PMCIN_SSP_INI_EDC_EXT_IO_START: 13554c06356bSdh142964 return ("INI_EDC_EXT_IO_START"); 13564c06356bSdh142964 case PMCIN_SSP_INI_EDC_EXT_IO_START1: 13574c06356bSdh142964 return ("INI_EDC_EXT_IO_START1"); 13584c06356bSdh142964 case PMCIN_SSP_TGT_EDC_IO_START: 13594c06356bSdh142964 return ("TGT_EDC_IO_START"); 13604c06356bSdh142964 case PMCIN_SSP_ABORT: 13614c06356bSdh142964 return ("SSP_ABORT"); 13624c06356bSdh142964 case PMCIN_DEREGISTER_DEVICE_HANDLE: 13634c06356bSdh142964 return ("DEREGISTER_DEVICE_HANDLE"); 13644c06356bSdh142964 case PMCIN_GET_DEVICE_HANDLE: 13654c06356bSdh142964 return ("GET_DEVICE_HANDLE"); 13664c06356bSdh142964 case PMCIN_SMP_REQUEST: 13674c06356bSdh142964 return ("SMP_REQUEST"); 13684c06356bSdh142964 case PMCIN_SMP_RESPONSE: 13694c06356bSdh142964 return ("SMP_RESPONSE"); 13704c06356bSdh142964 case PMCIN_SMP_ABORT: 13714c06356bSdh142964 return ("SMP_ABORT"); 13724c06356bSdh142964 case PMCIN_ASSISTED_DISCOVERY: 13734c06356bSdh142964 return ("ASSISTED_DISCOVERY"); 13744c06356bSdh142964 case PMCIN_REGISTER_DEVICE: 13754c06356bSdh142964 return ("REGISTER_DEVICE"); 13764c06356bSdh142964 case PMCIN_SATA_HOST_IO_START: 13774c06356bSdh142964 return ("SATA_HOST_IO_START"); 13784c06356bSdh142964 case PMCIN_SATA_ABORT: 13794c06356bSdh142964 return ("SATA_ABORT"); 13804c06356bSdh142964 case PMCIN_LOCAL_PHY_CONTROL: 13814c06356bSdh142964 return ("LOCAL_PHY_CONTROL"); 13824c06356bSdh142964 case PMCIN_GET_DEVICE_INFO: 13834c06356bSdh142964 return ("GET_DEVICE_INFO"); 13844c06356bSdh142964 case PMCIN_TWI: 13854c06356bSdh142964 return ("TWI"); 13864c06356bSdh142964 case PMCIN_FW_FLASH_UPDATE: 13874c06356bSdh142964 return ("FW_FLASH_UPDATE"); 13884c06356bSdh142964 case PMCIN_SET_VPD: 13894c06356bSdh142964 return ("SET_VPD"); 13904c06356bSdh142964 case PMCIN_GPIO: 13914c06356bSdh142964 return ("GPIO"); 13924c06356bSdh142964 case PMCIN_SAS_DIAG_MODE_START_END: 13934c06356bSdh142964 return ("SAS_DIAG_MODE_START_END"); 13944c06356bSdh142964 case PMCIN_SAS_DIAG_EXECUTE: 13954c06356bSdh142964 return ("SAS_DIAG_EXECUTE"); 1396978d7443SSrikanth Suravajhala case PMCIN_SAS_HW_EVENT_ACK: 13974c06356bSdh142964 return ("SAS_HW_EVENT_ACK"); 13984c06356bSdh142964 case PMCIN_GET_TIME_STAMP: 13994c06356bSdh142964 return ("GET_TIME_STAMP"); 14004c06356bSdh142964 case PMCIN_PORT_CONTROL: 14014c06356bSdh142964 return ("PORT_CONTROL"); 14024c06356bSdh142964 case PMCIN_GET_NVMD_DATA: 14034c06356bSdh142964 return ("GET_NVMD_DATA"); 14044c06356bSdh142964 case PMCIN_SET_NVMD_DATA: 14054c06356bSdh142964 return ("SET_NVMD_DATA"); 14064c06356bSdh142964 case PMCIN_SET_DEVICE_STATE: 14074c06356bSdh142964 return ("SET_DEVICE_STATE"); 14084c06356bSdh142964 case PMCIN_GET_DEVICE_STATE: 14094c06356bSdh142964 return ("GET_DEVICE_STATE"); 14104c06356bSdh142964 default: 14114c06356bSdh142964 return ("UNKNOWN"); 14124c06356bSdh142964 } 14134c06356bSdh142964 } 14144c06356bSdh142964 14154c06356bSdh142964 static char * 14164c06356bSdh142964 outbound_iomb_opcode(uint32_t opcode) 14174c06356bSdh142964 { 14184c06356bSdh142964 switch (opcode) { 14194c06356bSdh142964 case PMCOUT_ECHO: 14204c06356bSdh142964 return ("ECHO"); 14214c06356bSdh142964 case PMCOUT_GET_INFO: 14224c06356bSdh142964 return ("GET_INFO"); 14234c06356bSdh142964 case PMCOUT_GET_VPD: 14244c06356bSdh142964 return ("GET_VPD"); 14254c06356bSdh142964 case PMCOUT_SAS_HW_EVENT: 14264c06356bSdh142964 return ("SAS_HW_EVENT"); 14274c06356bSdh142964 case PMCOUT_SSP_COMPLETION: 14284c06356bSdh142964 return ("SSP_COMPLETION"); 14294c06356bSdh142964 case PMCOUT_SMP_COMPLETION: 14304c06356bSdh142964 return ("SMP_COMPLETION"); 14314c06356bSdh142964 case PMCOUT_LOCAL_PHY_CONTROL: 14324c06356bSdh142964 return ("LOCAL_PHY_CONTROL"); 14334c06356bSdh142964 case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT: 14344c06356bSdh142964 return ("SAS_ASSISTED_DISCOVERY_SENT"); 14354c06356bSdh142964 case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT: 14364c06356bSdh142964 return ("SATA_ASSISTED_DISCOVERY_SENT"); 14374c06356bSdh142964 case PMCOUT_DEVICE_REGISTRATION: 14384c06356bSdh142964 return ("DEVICE_REGISTRATION"); 14394c06356bSdh142964 case PMCOUT_DEREGISTER_DEVICE_HANDLE: 14404c06356bSdh142964 return ("DEREGISTER_DEVICE_HANDLE"); 14414c06356bSdh142964 case PMCOUT_GET_DEVICE_HANDLE: 14424c06356bSdh142964 return ("GET_DEVICE_HANDLE"); 14434c06356bSdh142964 case PMCOUT_SATA_COMPLETION: 14444c06356bSdh142964 return ("SATA_COMPLETION"); 14454c06356bSdh142964 case PMCOUT_SATA_EVENT: 14464c06356bSdh142964 return ("SATA_EVENT"); 14474c06356bSdh142964 case PMCOUT_SSP_EVENT: 14484c06356bSdh142964 return ("SSP_EVENT"); 14494c06356bSdh142964 case PMCOUT_DEVICE_HANDLE_ARRIVED: 14504c06356bSdh142964 return ("DEVICE_HANDLE_ARRIVED"); 14514c06356bSdh142964 case PMCOUT_SSP_REQUEST_RECEIVED: 14524c06356bSdh142964 return ("SSP_REQUEST_RECEIVED"); 14534c06356bSdh142964 case PMCOUT_DEVICE_INFO: 14544c06356bSdh142964 return ("DEVICE_INFO"); 14554c06356bSdh142964 case PMCOUT_FW_FLASH_UPDATE: 14564c06356bSdh142964 return ("FW_FLASH_UPDATE"); 14574c06356bSdh142964 case PMCOUT_SET_VPD: 14584c06356bSdh142964 return ("SET_VPD"); 14594c06356bSdh142964 case PMCOUT_GPIO: 14604c06356bSdh142964 return ("GPIO"); 14614c06356bSdh142964 case PMCOUT_GPIO_EVENT: 14624c06356bSdh142964 return ("GPIO_EVENT"); 14634c06356bSdh142964 case PMCOUT_GENERAL_EVENT: 14644c06356bSdh142964 return ("GENERAL_EVENT"); 14654c06356bSdh142964 case PMCOUT_TWI: 14664c06356bSdh142964 return ("TWI"); 14674c06356bSdh142964 case PMCOUT_SSP_ABORT: 14684c06356bSdh142964 return ("SSP_ABORT"); 14694c06356bSdh142964 case PMCOUT_SATA_ABORT: 14704c06356bSdh142964 return ("SATA_ABORT"); 14714c06356bSdh142964 case PMCOUT_SAS_DIAG_MODE_START_END: 14724c06356bSdh142964 return ("SAS_DIAG_MODE_START_END"); 14734c06356bSdh142964 case PMCOUT_SAS_DIAG_EXECUTE: 14744c06356bSdh142964 return ("SAS_DIAG_EXECUTE"); 14754c06356bSdh142964 case PMCOUT_GET_TIME_STAMP: 14764c06356bSdh142964 return ("GET_TIME_STAMP"); 14774c06356bSdh142964 case PMCOUT_SAS_HW_EVENT_ACK_ACK: 14784c06356bSdh142964 return ("SAS_HW_EVENT_ACK_ACK"); 14794c06356bSdh142964 case PMCOUT_PORT_CONTROL: 14804c06356bSdh142964 return ("PORT_CONTROL"); 14814c06356bSdh142964 case PMCOUT_SKIP_ENTRIES: 14824c06356bSdh142964 return ("SKIP_ENTRIES"); 14834c06356bSdh142964 case PMCOUT_SMP_ABORT: 14844c06356bSdh142964 return ("SMP_ABORT"); 14854c06356bSdh142964 case PMCOUT_GET_NVMD_DATA: 14864c06356bSdh142964 return ("GET_NVMD_DATA"); 14874c06356bSdh142964 case PMCOUT_SET_NVMD_DATA: 14884c06356bSdh142964 return ("SET_NVMD_DATA"); 14894c06356bSdh142964 case PMCOUT_DEVICE_HANDLE_REMOVED: 14904c06356bSdh142964 return ("DEVICE_HANDLE_REMOVED"); 14914c06356bSdh142964 case PMCOUT_SET_DEVICE_STATE: 14924c06356bSdh142964 return ("SET_DEVICE_STATE"); 14934c06356bSdh142964 case PMCOUT_GET_DEVICE_STATE: 14944c06356bSdh142964 return ("GET_DEVICE_STATE"); 14954c06356bSdh142964 case PMCOUT_SET_DEVICE_INFO: 14964c06356bSdh142964 return ("SET_DEVICE_INFO"); 14974c06356bSdh142964 default: 14984c06356bSdh142964 return ("UNKNOWN"); 14994c06356bSdh142964 } 15004c06356bSdh142964 } 15014c06356bSdh142964 150265e70c04SDavid Hollister static uint32_t 150365e70c04SDavid Hollister get_devid_from_ob_iomb(struct pmcs_hw ss, uint32_t *qentryp, uint16_t opcode) 150465e70c04SDavid Hollister { 150565e70c04SDavid Hollister uint32_t devid = PMCS_INVALID_DEVICE_ID; 150665e70c04SDavid Hollister 150765e70c04SDavid Hollister switch (opcode) { 150865e70c04SDavid Hollister /* 150965e70c04SDavid Hollister * These are obtained via the HTAG which is in word 1 151065e70c04SDavid Hollister */ 151165e70c04SDavid Hollister case PMCOUT_SSP_COMPLETION: 151265e70c04SDavid Hollister case PMCOUT_SMP_COMPLETION: 151365e70c04SDavid Hollister case PMCOUT_DEREGISTER_DEVICE_HANDLE: 151465e70c04SDavid Hollister case PMCOUT_GET_DEVICE_HANDLE: 151565e70c04SDavid Hollister case PMCOUT_SATA_COMPLETION: 151665e70c04SDavid Hollister case PMCOUT_SSP_ABORT: 151765e70c04SDavid Hollister case PMCOUT_SATA_ABORT: 151865e70c04SDavid Hollister case PMCOUT_SMP_ABORT: 151965e70c04SDavid Hollister case PMCOUT_SAS_HW_EVENT_ACK_ACK: { 152065e70c04SDavid Hollister uint32_t htag; 152165e70c04SDavid Hollister pmcwork_t *wp; 152265e70c04SDavid Hollister pmcs_phy_t *phy; 152365e70c04SDavid Hollister uintptr_t _wp, _phy; 152465e70c04SDavid Hollister uint16_t index; 152565e70c04SDavid Hollister 152665e70c04SDavid Hollister htag = LE_32(*(qentryp + 1)); 152765e70c04SDavid Hollister index = htag & PMCS_TAG_INDEX_MASK; 152865e70c04SDavid Hollister 152965e70c04SDavid Hollister wp = mdb_alloc(sizeof (pmcwork_t), UM_SLEEP); 153065e70c04SDavid Hollister _wp = (uintptr_t)ss.work + (sizeof (pmcwork_t) * index); 153165e70c04SDavid Hollister 153265e70c04SDavid Hollister if (MDB_RD(wp, sizeof (pmcwork_t), _wp) == -1) { 153365e70c04SDavid Hollister NOREAD(pmcwork_t, _wp); 153465e70c04SDavid Hollister mdb_free(wp, sizeof (pmcwork_t)); 153565e70c04SDavid Hollister break; 153665e70c04SDavid Hollister } 153765e70c04SDavid Hollister 153865e70c04SDavid Hollister phy = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP); 153965e70c04SDavid Hollister if (wp->phy == NULL) { 154065e70c04SDavid Hollister _phy = (uintptr_t)wp->last_phy; 154165e70c04SDavid Hollister } else { 154265e70c04SDavid Hollister _phy = (uintptr_t)wp->phy; 154365e70c04SDavid Hollister } 154465e70c04SDavid Hollister 154565e70c04SDavid Hollister /* 154665e70c04SDavid Hollister * If we have a PHY, read it in and get it's handle 154765e70c04SDavid Hollister */ 154865e70c04SDavid Hollister if (_phy != NULL) { 154965e70c04SDavid Hollister if (MDB_RD(phy, sizeof (*phy), _phy) == -1) { 155065e70c04SDavid Hollister NOREAD(pmcs_phy_t, phy); 155165e70c04SDavid Hollister } else { 155265e70c04SDavid Hollister devid = phy->device_id; 155365e70c04SDavid Hollister } 155465e70c04SDavid Hollister } 155565e70c04SDavid Hollister 155665e70c04SDavid Hollister mdb_free(phy, sizeof (pmcs_phy_t)); 155765e70c04SDavid Hollister mdb_free(wp, sizeof (pmcwork_t)); 155865e70c04SDavid Hollister break; 155965e70c04SDavid Hollister } 156065e70c04SDavid Hollister 156165e70c04SDavid Hollister /* 156265e70c04SDavid Hollister * The device ID is in the outbound IOMB at word 1 156365e70c04SDavid Hollister */ 156465e70c04SDavid Hollister case PMCOUT_SSP_REQUEST_RECEIVED: 156565e70c04SDavid Hollister devid = LE_32(*(qentryp + 1)) & PMCS_DEVICE_ID_MASK; 156665e70c04SDavid Hollister break; 156765e70c04SDavid Hollister 156865e70c04SDavid Hollister /* 156965e70c04SDavid Hollister * The device ID is in the outbound IOMB at word 2 157065e70c04SDavid Hollister */ 157165e70c04SDavid Hollister case PMCOUT_DEVICE_HANDLE_ARRIVED: 157265e70c04SDavid Hollister case PMCOUT_DEVICE_HANDLE_REMOVED: 157365e70c04SDavid Hollister devid = LE_32(*(qentryp + 2)) & PMCS_DEVICE_ID_MASK; 157465e70c04SDavid Hollister break; 157565e70c04SDavid Hollister 157665e70c04SDavid Hollister /* 157765e70c04SDavid Hollister * In this (very rare - never seen it) state, the device ID 157865e70c04SDavid Hollister * comes from the HTAG in the inbound IOMB, which would be word 157965e70c04SDavid Hollister * 3 in the outbound IOMB 158065e70c04SDavid Hollister */ 158165e70c04SDavid Hollister case PMCOUT_GENERAL_EVENT: 158265e70c04SDavid Hollister /* 158365e70c04SDavid Hollister * The device ID is in the outbound IOMB at word 3 158465e70c04SDavid Hollister */ 158565e70c04SDavid Hollister case PMCOUT_DEVICE_REGISTRATION: 158665e70c04SDavid Hollister case PMCOUT_DEVICE_INFO: 158765e70c04SDavid Hollister case PMCOUT_SET_DEVICE_STATE: 158865e70c04SDavid Hollister case PMCOUT_GET_DEVICE_STATE: 158965e70c04SDavid Hollister case PMCOUT_SET_DEVICE_INFO: 159065e70c04SDavid Hollister devid = LE_32(*(qentryp + 3)) & PMCS_DEVICE_ID_MASK; 159165e70c04SDavid Hollister break; 159265e70c04SDavid Hollister 159365e70c04SDavid Hollister /* 159465e70c04SDavid Hollister * Device ID is in the outbound IOMB at word 4 159565e70c04SDavid Hollister */ 159665e70c04SDavid Hollister case PMCOUT_SATA_EVENT: 159765e70c04SDavid Hollister case PMCOUT_SSP_EVENT: 159865e70c04SDavid Hollister devid = LE_32(*(qentryp + 4)) & PMCS_DEVICE_ID_MASK; 159965e70c04SDavid Hollister break; 160065e70c04SDavid Hollister } 160165e70c04SDavid Hollister 160265e70c04SDavid Hollister return (devid); 160365e70c04SDavid Hollister } 160465e70c04SDavid Hollister 160565e70c04SDavid Hollister static boolean_t 160665e70c04SDavid Hollister iomb_is_dev_hdl_specific(uint32_t word0, boolean_t inbound) 160765e70c04SDavid Hollister { 160865e70c04SDavid Hollister uint16_t opcode = word0 & PMCS_IOMB_OPCODE_MASK; 160965e70c04SDavid Hollister 161065e70c04SDavid Hollister if (inbound) { 161165e70c04SDavid Hollister switch (opcode) { 161265e70c04SDavid Hollister case PMCIN_SSP_INI_IO_START: 161365e70c04SDavid Hollister case PMCIN_SSP_INI_TM_START: 161465e70c04SDavid Hollister case PMCIN_SSP_INI_EXT_IO_START: 161565e70c04SDavid Hollister case PMCIN_SSP_TGT_IO_START: 161665e70c04SDavid Hollister case PMCIN_SSP_TGT_RESPONSE_START: 161765e70c04SDavid Hollister case PMCIN_SSP_ABORT: 161865e70c04SDavid Hollister case PMCIN_DEREGISTER_DEVICE_HANDLE: 161965e70c04SDavid Hollister case PMCIN_SMP_REQUEST: 162065e70c04SDavid Hollister case PMCIN_SMP_RESPONSE: 162165e70c04SDavid Hollister case PMCIN_SMP_ABORT: 162265e70c04SDavid Hollister case PMCIN_ASSISTED_DISCOVERY: 162365e70c04SDavid Hollister case PMCIN_SATA_HOST_IO_START: 162465e70c04SDavid Hollister case PMCIN_SATA_ABORT: 162565e70c04SDavid Hollister case PMCIN_GET_DEVICE_INFO: 162665e70c04SDavid Hollister case PMCIN_SET_DEVICE_STATE: 162765e70c04SDavid Hollister case PMCIN_GET_DEVICE_STATE: 162865e70c04SDavid Hollister return (B_TRUE); 162965e70c04SDavid Hollister } 163065e70c04SDavid Hollister 163165e70c04SDavid Hollister return (B_FALSE); 163265e70c04SDavid Hollister } 163365e70c04SDavid Hollister 163465e70c04SDavid Hollister switch (opcode) { 163565e70c04SDavid Hollister case PMCOUT_SSP_COMPLETION: 163665e70c04SDavid Hollister case PMCOUT_SMP_COMPLETION: 163765e70c04SDavid Hollister case PMCOUT_DEVICE_REGISTRATION: 163865e70c04SDavid Hollister case PMCOUT_DEREGISTER_DEVICE_HANDLE: 163965e70c04SDavid Hollister case PMCOUT_GET_DEVICE_HANDLE: 164065e70c04SDavid Hollister case PMCOUT_SATA_COMPLETION: 164165e70c04SDavid Hollister case PMCOUT_SATA_EVENT: 164265e70c04SDavid Hollister case PMCOUT_SSP_EVENT: 164365e70c04SDavid Hollister case PMCOUT_DEVICE_HANDLE_ARRIVED: 164465e70c04SDavid Hollister case PMCOUT_SSP_REQUEST_RECEIVED: 164565e70c04SDavid Hollister case PMCOUT_DEVICE_INFO: 164665e70c04SDavid Hollister case PMCOUT_FW_FLASH_UPDATE: 164765e70c04SDavid Hollister case PMCOUT_GENERAL_EVENT: 164865e70c04SDavid Hollister case PMCOUT_SSP_ABORT: 164965e70c04SDavid Hollister case PMCOUT_SATA_ABORT: 165065e70c04SDavid Hollister case PMCOUT_SAS_HW_EVENT_ACK_ACK: 165165e70c04SDavid Hollister case PMCOUT_SMP_ABORT: 165265e70c04SDavid Hollister case PMCOUT_DEVICE_HANDLE_REMOVED: 165365e70c04SDavid Hollister case PMCOUT_SET_DEVICE_STATE: 165465e70c04SDavid Hollister case PMCOUT_GET_DEVICE_STATE: 165565e70c04SDavid Hollister case PMCOUT_SET_DEVICE_INFO: 165665e70c04SDavid Hollister return (B_TRUE); 165765e70c04SDavid Hollister } 165865e70c04SDavid Hollister 165965e70c04SDavid Hollister return (B_FALSE); 166065e70c04SDavid Hollister } 166165e70c04SDavid Hollister 16624c06356bSdh142964 static void 166365e70c04SDavid Hollister dump_one_qentry_outbound(struct pmcs_hw ss, uint32_t *qentryp, int idx, 166465e70c04SDavid Hollister uint64_t devid_filter) 16654c06356bSdh142964 { 16664c06356bSdh142964 int qeidx; 16674c06356bSdh142964 uint32_t word0 = LE_32(*qentryp); 16689aed1621SDavid Hollister uint32_t word1 = LE_32(*(qentryp + 1)); 16699aed1621SDavid Hollister uint8_t iop_event; 167065e70c04SDavid Hollister uint32_t devid; 167165e70c04SDavid Hollister 167265e70c04SDavid Hollister /* 167365e70c04SDavid Hollister * Check to see if we're filtering on a device ID 167465e70c04SDavid Hollister */ 167565e70c04SDavid Hollister if (devid_filter != PMCS_INVALID_DEVICE_ID) { 167665e70c04SDavid Hollister if (!iomb_is_dev_hdl_specific(word0, B_FALSE)) { 167765e70c04SDavid Hollister return; 167865e70c04SDavid Hollister } 167965e70c04SDavid Hollister 168065e70c04SDavid Hollister /* 168165e70c04SDavid Hollister * Go find the device id. It might be in the outbound 168265e70c04SDavid Hollister * IOMB or we may have to go find the work structure and 168365e70c04SDavid Hollister * get it from there. 168465e70c04SDavid Hollister */ 168565e70c04SDavid Hollister devid = get_devid_from_ob_iomb(ss, qentryp, 168665e70c04SDavid Hollister word0 & PMCS_IOMB_OPCODE_MASK); 168765e70c04SDavid Hollister if ((devid == PMCS_INVALID_DEVICE_ID) || 168865e70c04SDavid Hollister (devid_filter != devid)) { 168965e70c04SDavid Hollister return; 169065e70c04SDavid Hollister } 169165e70c04SDavid Hollister } 16924c06356bSdh142964 16934c06356bSdh142964 mdb_printf("Entry #%02d\n", idx); 16944c06356bSdh142964 mdb_inc_indent(2); 16954c06356bSdh142964 16964c06356bSdh142964 mdb_printf("Header: 0x%08x (", word0); 16974c06356bSdh142964 if (word0 & PMCS_IOMB_VALID) { 16984c06356bSdh142964 mdb_printf("VALID, "); 16994c06356bSdh142964 } 17004c06356bSdh142964 if (word0 & PMCS_IOMB_HIPRI) { 17014c06356bSdh142964 mdb_printf("HIPRI, "); 17024c06356bSdh142964 } 17034c06356bSdh142964 mdb_printf("OBID=%d, ", 17044c06356bSdh142964 (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT); 17054c06356bSdh142964 mdb_printf("CAT=%s, ", 17064c06356bSdh142964 iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT)); 17074c06356bSdh142964 mdb_printf("OPCODE=%s", 17084c06356bSdh142964 outbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK)); 17099aed1621SDavid Hollister if ((word0 & PMCS_IOMB_OPCODE_MASK) == PMCOUT_SAS_HW_EVENT) { 17109aed1621SDavid Hollister iop_event = IOP_EVENT_EVENT(word1); 17119aed1621SDavid Hollister mdb_printf(" <%s>", iomb_event(iop_event)); 17129aed1621SDavid Hollister } 17134c06356bSdh142964 mdb_printf(")\n"); 17144c06356bSdh142964 17154c06356bSdh142964 mdb_printf("Remaining Payload:\n"); 17164c06356bSdh142964 17174c06356bSdh142964 mdb_inc_indent(2); 17184c06356bSdh142964 for (qeidx = 1; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) { 17194c06356bSdh142964 mdb_printf("%08x ", LE_32(*(qentryp + qeidx))); 17204c06356bSdh142964 } 17214c06356bSdh142964 mdb_printf("\n"); 17224c06356bSdh142964 mdb_dec_indent(4); 17234c06356bSdh142964 } 17244c06356bSdh142964 17254c06356bSdh142964 static void 172665e70c04SDavid Hollister display_outbound_queues(struct pmcs_hw ss, uint64_t devid_filter, 172765e70c04SDavid Hollister uint_t verbose) 17284c06356bSdh142964 { 17294c06356bSdh142964 int idx, qidx; 17304c06356bSdh142964 uintptr_t obqp; 17314c06356bSdh142964 uint32_t *cip; 17324c06356bSdh142964 uint32_t *qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP); 17334c06356bSdh142964 uint32_t last_consumed, oqpi; 17344c06356bSdh142964 17354c06356bSdh142964 mdb_printf("\n"); 17364c06356bSdh142964 mdb_printf("Outbound Queues\n"); 17374c06356bSdh142964 mdb_printf("---------------\n"); 17384c06356bSdh142964 17394c06356bSdh142964 mdb_inc_indent(2); 17404c06356bSdh142964 17414c06356bSdh142964 for (qidx = 0; qidx < PMCS_NOQ; qidx++) { 17424c06356bSdh142964 obqp = (uintptr_t)ss.oqp[qidx]; 17434c06356bSdh142964 17444c06356bSdh142964 if (obqp == NULL) { 17454c06356bSdh142964 mdb_printf("No outbound queue ptr for queue #%d\n", 17464c06356bSdh142964 qidx); 17474c06356bSdh142964 continue; 17484c06356bSdh142964 } 17494c06356bSdh142964 17504c06356bSdh142964 mdb_printf("Outbound Queue #%d (Queue Type = %s)\n", qidx, 17514c06356bSdh142964 obq_type(qidx)); 17524c06356bSdh142964 /* 17534c06356bSdh142964 * Chip is the producer, so read the actual producer index 17544c06356bSdh142964 * and not the driver's version 17554c06356bSdh142964 */ 17564c06356bSdh142964 cip = (uint32_t *)((void *)ss.cip); 17574c06356bSdh142964 if (MDB_RD(&oqpi, 4, cip + OQPI_BASE_OFFSET + 17584c06356bSdh142964 (qidx * 4)) == -1) { 17594c06356bSdh142964 mdb_warn("Couldn't read oqpi\n"); 17604c06356bSdh142964 break; 17614c06356bSdh142964 } 17624c06356bSdh142964 17634c06356bSdh142964 mdb_printf("Producer index: %d Consumer index: %d\n\n", 17644c06356bSdh142964 LE_32(oqpi), ss.oqci[qidx]); 17654c06356bSdh142964 mdb_inc_indent(2); 17664c06356bSdh142964 17674c06356bSdh142964 if (ss.oqci[qidx] == 0) { 17684c06356bSdh142964 last_consumed = ss.ioq_depth - 1; 17694c06356bSdh142964 } else { 17704c06356bSdh142964 last_consumed = ss.oqci[qidx] - 1; 17714c06356bSdh142964 } 17724c06356bSdh142964 17734c06356bSdh142964 17744c06356bSdh142964 if (!verbose) { 17754c06356bSdh142964 mdb_printf("Last processed entry:\n"); 17764c06356bSdh142964 if (MDB_RD(qentryp, PMCS_QENTRY_SIZE, 17774c06356bSdh142964 (obqp + (PMCS_QENTRY_SIZE * last_consumed))) 17784c06356bSdh142964 == -1) { 17794c06356bSdh142964 mdb_warn("Couldn't read queue entry at 0x%p\n", 17804c06356bSdh142964 (obqp + (PMCS_QENTRY_SIZE * 17814c06356bSdh142964 last_consumed))); 17824c06356bSdh142964 break; 17834c06356bSdh142964 } 178465e70c04SDavid Hollister dump_one_qentry_outbound(ss, qentryp, last_consumed, 178565e70c04SDavid Hollister devid_filter); 17864c06356bSdh142964 mdb_printf("\n"); 17874c06356bSdh142964 mdb_dec_indent(2); 17884c06356bSdh142964 continue; 17894c06356bSdh142964 } 17904c06356bSdh142964 17914c06356bSdh142964 for (idx = 0; idx < ss.ioq_depth; idx++) { 17924c06356bSdh142964 if (MDB_RD(qentryp, PMCS_QENTRY_SIZE, 17934c06356bSdh142964 (obqp + (PMCS_QENTRY_SIZE * idx))) == -1) { 17944c06356bSdh142964 mdb_warn("Couldn't read queue entry at 0x%p\n", 17954c06356bSdh142964 (obqp + (PMCS_QENTRY_SIZE * idx))); 17964c06356bSdh142964 break; 17974c06356bSdh142964 } 179865e70c04SDavid Hollister dump_one_qentry_outbound(ss, qentryp, idx, 179965e70c04SDavid Hollister devid_filter); 18004c06356bSdh142964 } 18014c06356bSdh142964 18024c06356bSdh142964 mdb_printf("\n"); 18034c06356bSdh142964 mdb_dec_indent(2); 18044c06356bSdh142964 } 18054c06356bSdh142964 18064c06356bSdh142964 mdb_dec_indent(2); 18074c06356bSdh142964 mdb_free(qentryp, PMCS_QENTRY_SIZE); 18084c06356bSdh142964 } 18094c06356bSdh142964 18104c06356bSdh142964 static void 181165e70c04SDavid Hollister dump_one_qentry_inbound(uint32_t *qentryp, int idx, uint64_t devid_filter) 18124c06356bSdh142964 { 18134c06356bSdh142964 int qeidx; 18144c06356bSdh142964 uint32_t word0 = LE_32(*qentryp); 181565e70c04SDavid Hollister uint32_t devid = LE_32(*(qentryp + 2)); 181665e70c04SDavid Hollister 181765e70c04SDavid Hollister /* 181865e70c04SDavid Hollister * Check to see if we're filtering on a device ID 181965e70c04SDavid Hollister */ 182065e70c04SDavid Hollister if (devid_filter != PMCS_INVALID_DEVICE_ID) { 182165e70c04SDavid Hollister if (iomb_is_dev_hdl_specific(word0, B_TRUE)) { 182265e70c04SDavid Hollister if (devid_filter != devid) { 182365e70c04SDavid Hollister return; 182465e70c04SDavid Hollister } 182565e70c04SDavid Hollister } else { 182665e70c04SDavid Hollister return; 182765e70c04SDavid Hollister } 182865e70c04SDavid Hollister } 18294c06356bSdh142964 18304c06356bSdh142964 mdb_printf("Entry #%02d\n", idx); 18314c06356bSdh142964 mdb_inc_indent(2); 18324c06356bSdh142964 18334c06356bSdh142964 mdb_printf("Header: 0x%08x (", word0); 18344c06356bSdh142964 if (word0 & PMCS_IOMB_VALID) { 18354c06356bSdh142964 mdb_printf("VALID, "); 18364c06356bSdh142964 } 18374c06356bSdh142964 if (word0 & PMCS_IOMB_HIPRI) { 18384c06356bSdh142964 mdb_printf("HIPRI, "); 18394c06356bSdh142964 } 18404c06356bSdh142964 mdb_printf("OBID=%d, ", 18414c06356bSdh142964 (word0 & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT); 18424c06356bSdh142964 mdb_printf("CAT=%s, ", 18434c06356bSdh142964 iomb_cat((word0 & PMCS_IOMB_CAT_MASK) >> PMCS_IOMB_CAT_SHIFT)); 18444c06356bSdh142964 mdb_printf("OPCODE=%s", 18454c06356bSdh142964 inbound_iomb_opcode(word0 & PMCS_IOMB_OPCODE_MASK)); 18464c06356bSdh142964 mdb_printf(")\n"); 18474c06356bSdh142964 18484c06356bSdh142964 mdb_printf("HTAG: 0x%08x\n", LE_32(*(qentryp + 1))); 18494c06356bSdh142964 mdb_printf("Remaining Payload:\n"); 18504c06356bSdh142964 18514c06356bSdh142964 mdb_inc_indent(2); 18524c06356bSdh142964 for (qeidx = 2; qeidx < (PMCS_QENTRY_SIZE / 4); qeidx++) { 18534c06356bSdh142964 mdb_printf("%08x ", LE_32(*(qentryp + qeidx))); 18544c06356bSdh142964 } 18554c06356bSdh142964 mdb_printf("\n"); 18564c06356bSdh142964 mdb_dec_indent(4); 18574c06356bSdh142964 } 18584c06356bSdh142964 18594c06356bSdh142964 static void 186065e70c04SDavid Hollister display_inbound_queues(struct pmcs_hw ss, uint64_t devid_filter, uint_t verbose) 18614c06356bSdh142964 { 18624c06356bSdh142964 int idx, qidx, iqci, last_consumed; 18634c06356bSdh142964 uintptr_t ibqp; 18644c06356bSdh142964 uint32_t *qentryp = mdb_alloc(PMCS_QENTRY_SIZE, UM_SLEEP); 18654c06356bSdh142964 uint32_t *cip; 18664c06356bSdh142964 18674c06356bSdh142964 mdb_printf("\n"); 18684c06356bSdh142964 mdb_printf("Inbound Queues\n"); 18694c06356bSdh142964 mdb_printf("--------------\n"); 18704c06356bSdh142964 18714c06356bSdh142964 mdb_inc_indent(2); 18724c06356bSdh142964 18734c06356bSdh142964 for (qidx = 0; qidx < PMCS_NIQ; qidx++) { 18744c06356bSdh142964 ibqp = (uintptr_t)ss.iqp[qidx]; 18754c06356bSdh142964 18764c06356bSdh142964 if (ibqp == NULL) { 18774c06356bSdh142964 mdb_printf("No inbound queue ptr for queue #%d\n", 18784c06356bSdh142964 qidx); 18794c06356bSdh142964 continue; 18804c06356bSdh142964 } 18814c06356bSdh142964 18824c06356bSdh142964 mdb_printf("Inbound Queue #%d (Queue Type = %s)\n", qidx, 18834c06356bSdh142964 ibq_type(qidx)); 18844c06356bSdh142964 18854c06356bSdh142964 cip = (uint32_t *)((void *)ss.cip); 18864c06356bSdh142964 if (MDB_RD(&iqci, 4, cip + (qidx * 4)) == -1) { 18874c06356bSdh142964 mdb_warn("Couldn't read iqci\n"); 18884c06356bSdh142964 break; 18894c06356bSdh142964 } 18904c06356bSdh142964 iqci = LE_32(iqci); 18914c06356bSdh142964 18924c06356bSdh142964 mdb_printf("Producer index: %d Consumer index: %d\n\n", 18934c06356bSdh142964 ss.shadow_iqpi[qidx], iqci); 18944c06356bSdh142964 mdb_inc_indent(2); 18954c06356bSdh142964 18964c06356bSdh142964 if (iqci == 0) { 18974c06356bSdh142964 last_consumed = ss.ioq_depth - 1; 18984c06356bSdh142964 } else { 18994c06356bSdh142964 last_consumed = iqci - 1; 19004c06356bSdh142964 } 19014c06356bSdh142964 19024c06356bSdh142964 if (!verbose) { 19034c06356bSdh142964 mdb_printf("Last processed entry:\n"); 19044c06356bSdh142964 if (MDB_RD(qentryp, PMCS_QENTRY_SIZE, 19054c06356bSdh142964 (ibqp + (PMCS_QENTRY_SIZE * last_consumed))) 19064c06356bSdh142964 == -1) { 19074c06356bSdh142964 mdb_warn("Couldn't read queue entry at 0x%p\n", 19084c06356bSdh142964 (ibqp + (PMCS_QENTRY_SIZE * 19094c06356bSdh142964 last_consumed))); 19104c06356bSdh142964 break; 19114c06356bSdh142964 } 191265e70c04SDavid Hollister dump_one_qentry_inbound(qentryp, last_consumed, 191365e70c04SDavid Hollister devid_filter); 19144c06356bSdh142964 mdb_printf("\n"); 19154c06356bSdh142964 mdb_dec_indent(2); 19164c06356bSdh142964 continue; 19174c06356bSdh142964 } 19184c06356bSdh142964 19194c06356bSdh142964 for (idx = 0; idx < ss.ioq_depth; idx++) { 19204c06356bSdh142964 if (MDB_RD(qentryp, PMCS_QENTRY_SIZE, 19214c06356bSdh142964 (ibqp + (PMCS_QENTRY_SIZE * idx))) == -1) { 19224c06356bSdh142964 mdb_warn("Couldn't read queue entry at 0x%p\n", 19234c06356bSdh142964 (ibqp + (PMCS_QENTRY_SIZE * idx))); 19244c06356bSdh142964 break; 19254c06356bSdh142964 } 192665e70c04SDavid Hollister dump_one_qentry_inbound(qentryp, idx, devid_filter); 19274c06356bSdh142964 } 19284c06356bSdh142964 19294c06356bSdh142964 mdb_printf("\n"); 19304c06356bSdh142964 mdb_dec_indent(2); 19314c06356bSdh142964 } 19324c06356bSdh142964 19334c06356bSdh142964 mdb_dec_indent(2); 19344c06356bSdh142964 mdb_free(qentryp, PMCS_QENTRY_SIZE); 19354c06356bSdh142964 } 19364c06356bSdh142964 19379aed1621SDavid Hollister /* 19389aed1621SDavid Hollister * phy is our copy of the PHY structure. phyp is the pointer to the actual 19399aed1621SDavid Hollister * kernel PHY data structure 19409aed1621SDavid Hollister */ 19414c06356bSdh142964 static void 19429aed1621SDavid Hollister display_phy(struct pmcs_phy phy, struct pmcs_phy *phyp, int verbose, 19439aed1621SDavid Hollister int totals_only) 19444c06356bSdh142964 { 19454c06356bSdh142964 char *dtype, *speed; 19464c06356bSdh142964 char *yes = "Yes"; 19474c06356bSdh142964 char *no = "No"; 19484c06356bSdh142964 char *cfgd = no; 19494c06356bSdh142964 char *apend = no; 19504c06356bSdh142964 char *asent = no; 19514c06356bSdh142964 char *dead = no; 19524c06356bSdh142964 char *changed = no; 19539aed1621SDavid Hollister char route_attr, route_method; 19544c06356bSdh142964 19554c06356bSdh142964 switch (phy.dtype) { 19564c06356bSdh142964 case NOTHING: 19574c06356bSdh142964 dtype = "None"; 19584c06356bSdh142964 break; 19594c06356bSdh142964 case SATA: 19604c06356bSdh142964 dtype = "SATA"; 19614c06356bSdh142964 if (phy.configured) { 19624c06356bSdh142964 ++sata_phys; 19634c06356bSdh142964 } 19644c06356bSdh142964 break; 19654c06356bSdh142964 case SAS: 19664c06356bSdh142964 dtype = "SAS"; 19674c06356bSdh142964 if (phy.configured) { 19684c06356bSdh142964 ++sas_phys; 19694c06356bSdh142964 } 19704c06356bSdh142964 break; 19714c06356bSdh142964 case EXPANDER: 19724c06356bSdh142964 dtype = "EXP"; 19734c06356bSdh142964 if (phy.configured) { 19744c06356bSdh142964 ++exp_phys; 19754c06356bSdh142964 } 19764c06356bSdh142964 break; 19774c06356bSdh142964 } 19784c06356bSdh142964 19794c06356bSdh142964 if (phy.dtype == NOTHING) { 19804c06356bSdh142964 empty_phys++; 19814c06356bSdh142964 } else if ((phy.dtype == EXPANDER) && phy.configured) { 19824c06356bSdh142964 num_expanders++; 19834c06356bSdh142964 } 19844c06356bSdh142964 19854c06356bSdh142964 if (totals_only) { 19864c06356bSdh142964 return; 19874c06356bSdh142964 } 19884c06356bSdh142964 19894c06356bSdh142964 switch (phy.link_rate) { 19904c06356bSdh142964 case SAS_LINK_RATE_1_5GBIT: 19914c06356bSdh142964 speed = "1.5Gb/s"; 19924c06356bSdh142964 break; 19934c06356bSdh142964 case SAS_LINK_RATE_3GBIT: 19944c06356bSdh142964 speed = "3 Gb/s"; 19954c06356bSdh142964 break; 19964c06356bSdh142964 case SAS_LINK_RATE_6GBIT: 19974c06356bSdh142964 speed = "6 Gb/s"; 19984c06356bSdh142964 break; 19994c06356bSdh142964 default: 20004c06356bSdh142964 speed = "N/A"; 20014c06356bSdh142964 break; 20024c06356bSdh142964 } 20034c06356bSdh142964 20044c06356bSdh142964 if ((phy.dtype != NOTHING) || verbose) { 20054c06356bSdh142964 print_sas_address(&phy); 20064c06356bSdh142964 20074c06356bSdh142964 if (phy.device_id != PMCS_INVALID_DEVICE_ID) { 20084c06356bSdh142964 mdb_printf(" %3d %4d %6s %4s ", 20094c06356bSdh142964 phy.device_id, phy.phynum, speed, dtype); 20104c06356bSdh142964 } else { 20114c06356bSdh142964 mdb_printf(" N/A %4d %6s %4s ", 20124c06356bSdh142964 phy.phynum, speed, dtype); 20134c06356bSdh142964 } 20144c06356bSdh142964 20154c06356bSdh142964 if (verbose) { 20164c06356bSdh142964 if (phy.abort_sent) { 20174c06356bSdh142964 asent = yes; 20184c06356bSdh142964 } 20194c06356bSdh142964 if (phy.abort_pending) { 20204c06356bSdh142964 apend = yes; 20214c06356bSdh142964 } 20224c06356bSdh142964 if (phy.configured) { 20234c06356bSdh142964 cfgd = yes; 20244c06356bSdh142964 } 20254c06356bSdh142964 if (phy.dead) { 20264c06356bSdh142964 dead = yes; 20274c06356bSdh142964 } 20284c06356bSdh142964 if (phy.changed) { 20294c06356bSdh142964 changed = yes; 20304c06356bSdh142964 } 20314c06356bSdh142964 20329aed1621SDavid Hollister switch (phy.routing_attr) { 20339aed1621SDavid Hollister case SMP_ROUTING_DIRECT: 20349aed1621SDavid Hollister route_attr = 'D'; 20359aed1621SDavid Hollister break; 20369aed1621SDavid Hollister case SMP_ROUTING_SUBTRACTIVE: 20379aed1621SDavid Hollister route_attr = 'S'; 20389aed1621SDavid Hollister break; 20399aed1621SDavid Hollister case SMP_ROUTING_TABLE: 20409aed1621SDavid Hollister route_attr = 'T'; 20419aed1621SDavid Hollister break; 20429aed1621SDavid Hollister default: 20439aed1621SDavid Hollister route_attr = '?'; 20449aed1621SDavid Hollister break; 20459aed1621SDavid Hollister } 20469aed1621SDavid Hollister 20479aed1621SDavid Hollister switch (phy.routing_method) { 20489aed1621SDavid Hollister case SMP_ROUTING_DIRECT: 20499aed1621SDavid Hollister route_method = 'D'; 20509aed1621SDavid Hollister break; 20519aed1621SDavid Hollister case SMP_ROUTING_SUBTRACTIVE: 20529aed1621SDavid Hollister route_method = 'S'; 20539aed1621SDavid Hollister break; 20549aed1621SDavid Hollister case SMP_ROUTING_TABLE: 20559aed1621SDavid Hollister route_method = 'T'; 20569aed1621SDavid Hollister break; 20579aed1621SDavid Hollister default: 20589aed1621SDavid Hollister route_attr = '?'; 20599aed1621SDavid Hollister break; 20609aed1621SDavid Hollister } 20619aed1621SDavid Hollister 20629aed1621SDavid Hollister mdb_printf("%-4s %-4s %-4s %-4s %-4s %3d %3c/%1c %3d " 20639aed1621SDavid Hollister "%1d 0x%p ", cfgd, apend, asent, changed, dead, 20649aed1621SDavid Hollister phy.ref_count, route_attr, route_method, 20659aed1621SDavid Hollister phy.enum_attempts, phy.reenumerate, phy.phy_lock); 20664c06356bSdh142964 } 20674c06356bSdh142964 20684c06356bSdh142964 mdb_printf("Path: %s\n", phy.path); 20699aed1621SDavid Hollister 20709aed1621SDavid Hollister /* 20719aed1621SDavid Hollister * In verbose mode, on the next line print the drill down 20729aed1621SDavid Hollister * info to see either the DISCOVER response or the REPORT 20739aed1621SDavid Hollister * GENERAL response depending on the PHY's dtype 20749aed1621SDavid Hollister */ 20759aed1621SDavid Hollister if (verbose) { 20769aed1621SDavid Hollister uintptr_t tphyp = (uintptr_t)phyp; 20779aed1621SDavid Hollister 20789aed1621SDavid Hollister mdb_inc_indent(4); 20799aed1621SDavid Hollister switch (phy.dtype) { 20809aed1621SDavid Hollister case EXPANDER: 20819aed1621SDavid Hollister if (!phy.configured) { 20829aed1621SDavid Hollister break; 20839aed1621SDavid Hollister } 20849aed1621SDavid Hollister mdb_printf("REPORT GENERAL response: %p::" 20859aed1621SDavid Hollister "print smp_report_general_resp_t\n", 20869aed1621SDavid Hollister (tphyp + offsetof(struct pmcs_phy, 20879aed1621SDavid Hollister rg_resp))); 20889aed1621SDavid Hollister break; 20899aed1621SDavid Hollister case SAS: 20909aed1621SDavid Hollister case SATA: 20919aed1621SDavid Hollister mdb_printf("DISCOVER response: %p::" 20929aed1621SDavid Hollister "print smp_discover_resp_t\n", 20939aed1621SDavid Hollister (tphyp + offsetof(struct pmcs_phy, 20949aed1621SDavid Hollister disc_resp))); 20959aed1621SDavid Hollister break; 20969aed1621SDavid Hollister default: 20979aed1621SDavid Hollister break; 20989aed1621SDavid Hollister } 20999aed1621SDavid Hollister mdb_dec_indent(4); 21009aed1621SDavid Hollister } 21014c06356bSdh142964 } 21024c06356bSdh142964 } 21034c06356bSdh142964 21044c06356bSdh142964 static void 21054c06356bSdh142964 display_phys(struct pmcs_hw ss, int verbose, struct pmcs_phy *parent, int level, 21064c06356bSdh142964 int totals_only) 21074c06356bSdh142964 { 21084c06356bSdh142964 pmcs_phy_t phy; 21094c06356bSdh142964 pmcs_phy_t *pphy = parent; 21104c06356bSdh142964 21114c06356bSdh142964 mdb_inc_indent(3); 21124c06356bSdh142964 21134c06356bSdh142964 if (parent == NULL) { 21144c06356bSdh142964 pphy = (pmcs_phy_t *)ss.root_phys; 21154c06356bSdh142964 } else { 21164c06356bSdh142964 pphy = (pmcs_phy_t *)parent; 21174c06356bSdh142964 } 21184c06356bSdh142964 21194c06356bSdh142964 if (level == 0) { 21204c06356bSdh142964 sas_phys = 0; 21214c06356bSdh142964 sata_phys = 0; 21224c06356bSdh142964 exp_phys = 0; 21234c06356bSdh142964 num_expanders = 0; 21244c06356bSdh142964 empty_phys = 0; 21254c06356bSdh142964 } 21264c06356bSdh142964 21274c06356bSdh142964 if (!totals_only) { 21284c06356bSdh142964 if (level == 0) { 21294c06356bSdh142964 mdb_printf("PHY information\n"); 21304c06356bSdh142964 } 21314c06356bSdh142964 mdb_printf("--------\n"); 21324c06356bSdh142964 mdb_printf("Level %2d\n", level); 21334c06356bSdh142964 mdb_printf("--------\n"); 21344c06356bSdh142964 mdb_printf("SAS Address Hdl Phy# Speed Type "); 21354c06356bSdh142964 21364c06356bSdh142964 if (verbose) { 21379aed1621SDavid Hollister mdb_printf("Cfgd AbtP AbtS Chgd Dead Ref RtA/M Enm R " 21389aed1621SDavid Hollister "Lock\n"); 21394c06356bSdh142964 } else { 21404c06356bSdh142964 mdb_printf("\n"); 21414c06356bSdh142964 } 21424c06356bSdh142964 } 21434c06356bSdh142964 21444c06356bSdh142964 while (pphy) { 21454c06356bSdh142964 if (MDB_RD(&phy, sizeof (phy), (uintptr_t)pphy) == -1) { 21464c06356bSdh142964 NOREAD(pmcs_phy_t, phy); 21474c06356bSdh142964 break; 21484c06356bSdh142964 } 21494c06356bSdh142964 21509aed1621SDavid Hollister display_phy(phy, pphy, verbose, totals_only); 21514c06356bSdh142964 21524c06356bSdh142964 if (phy.children) { 21534c06356bSdh142964 display_phys(ss, verbose, phy.children, level + 1, 21544c06356bSdh142964 totals_only); 21554c06356bSdh142964 if (!totals_only) { 21564c06356bSdh142964 mdb_printf("\n"); 21574c06356bSdh142964 } 21584c06356bSdh142964 } 21594c06356bSdh142964 21604c06356bSdh142964 pphy = phy.sibling; 21614c06356bSdh142964 } 21624c06356bSdh142964 21634c06356bSdh142964 mdb_dec_indent(3); 21644c06356bSdh142964 21654c06356bSdh142964 if (level == 0) { 21664c06356bSdh142964 if (verbose) { 21674c06356bSdh142964 mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP) " 21684c06356bSdh142964 "(+%d subsidiary + %d empty)\n", "Occupied PHYs:", 21694c06356bSdh142964 (sas_phys + sata_phys + num_expanders), 21704c06356bSdh142964 sas_phys, sata_phys, num_expanders, 21714c06356bSdh142964 (exp_phys - num_expanders), empty_phys); 21724c06356bSdh142964 } else { 21734c06356bSdh142964 mdb_printf("%19s %d (%d SAS + %d SATA + %d SMP)\n", 21744c06356bSdh142964 "Occupied PHYs:", 21754c06356bSdh142964 (sas_phys + sata_phys + num_expanders), 21764c06356bSdh142964 sas_phys, sata_phys, num_expanders); 21774c06356bSdh142964 } 21784c06356bSdh142964 } 21794c06356bSdh142964 } 21804c06356bSdh142964 21814c06356bSdh142964 /* 2182c3bc407cSdh142964 * filter is used to indicate whether we are filtering log messages based 2183c3bc407cSdh142964 * on "instance". The other filtering (based on options) depends on the 2184c3bc407cSdh142964 * values that are passed in for "sas_addr" and "phy_path". 2185c3bc407cSdh142964 * 21864c06356bSdh142964 * MAX_INST_STRLEN is the largest string size from which we will attempt 21874c06356bSdh142964 * to convert to an instance number. The string will be formed up as 21884c06356bSdh142964 * "0t<inst>\0" so that mdb_strtoull can parse it properly. 21894c06356bSdh142964 */ 21904c06356bSdh142964 #define MAX_INST_STRLEN 8 21914c06356bSdh142964 21924c06356bSdh142964 static int 2193601c90f1SSrikanth, Ramana pmcs_dump_tracelog(boolean_t filter, int instance, uint64_t tail_lines, 21941f81b464SDavid Hollister const char *phy_path, uint64_t sas_address, uint64_t verbose) 21954c06356bSdh142964 { 21964c06356bSdh142964 pmcs_tbuf_t *tbuf_addr; 21974c06356bSdh142964 uint_t tbuf_idx; 21984c06356bSdh142964 pmcs_tbuf_t tbuf; 21994c06356bSdh142964 boolean_t wrap, elem_filtered; 22004c06356bSdh142964 uint_t start_idx, elems_to_print, idx, tbuf_num_elems; 22014c06356bSdh142964 char *bufp; 22024c06356bSdh142964 char elem_inst[MAX_INST_STRLEN], ei_idx; 2203c3bc407cSdh142964 uint64_t sas_addr; 2204c3bc407cSdh142964 uint8_t *sas_addressp; 22054c06356bSdh142964 22064c06356bSdh142964 /* Get the address of the first element */ 22074c06356bSdh142964 if (mdb_readvar(&tbuf_addr, "pmcs_tbuf") == -1) { 22084c06356bSdh142964 mdb_warn("can't read pmcs_tbuf"); 22094c06356bSdh142964 return (DCMD_ERR); 22104c06356bSdh142964 } 22114c06356bSdh142964 22124c06356bSdh142964 /* Get the total number */ 22134c06356bSdh142964 if (mdb_readvar(&tbuf_num_elems, "pmcs_tbuf_num_elems") == -1) { 22144c06356bSdh142964 mdb_warn("can't read pmcs_tbuf_num_elems"); 22154c06356bSdh142964 return (DCMD_ERR); 22164c06356bSdh142964 } 22174c06356bSdh142964 22184c06356bSdh142964 /* Get the current index */ 22194c06356bSdh142964 if (mdb_readvar(&tbuf_idx, "pmcs_tbuf_idx") == -1) { 22204c06356bSdh142964 mdb_warn("can't read pmcs_tbuf_idx"); 22214c06356bSdh142964 return (DCMD_ERR); 22224c06356bSdh142964 } 22234c06356bSdh142964 22244c06356bSdh142964 /* Indicator as to whether the buffer has wrapped */ 22254c06356bSdh142964 if (mdb_readvar(&wrap, "pmcs_tbuf_wrap") == -1) { 22264c06356bSdh142964 mdb_warn("can't read pmcs_tbuf_wrap"); 22274c06356bSdh142964 return (DCMD_ERR); 22284c06356bSdh142964 } 22294c06356bSdh142964 2230c3bc407cSdh142964 /* 2231c3bc407cSdh142964 * On little-endian systems, the SAS address passed in will be 2232c3bc407cSdh142964 * byte swapped. Take care of that here. 2233c3bc407cSdh142964 */ 2234c3bc407cSdh142964 #if defined(_LITTLE_ENDIAN) 2235c3bc407cSdh142964 sas_addr = ((sas_address << 56) | 2236c3bc407cSdh142964 ((sas_address << 40) & 0xff000000000000ULL) | 2237c3bc407cSdh142964 ((sas_address << 24) & 0xff0000000000ULL) | 2238c3bc407cSdh142964 ((sas_address << 8) & 0xff00000000ULL) | 2239c3bc407cSdh142964 ((sas_address >> 8) & 0xff000000ULL) | 2240c3bc407cSdh142964 ((sas_address >> 24) & 0xff0000ULL) | 2241c3bc407cSdh142964 ((sas_address >> 40) & 0xff00ULL) | 2242c3bc407cSdh142964 (sas_address >> 56)); 2243c3bc407cSdh142964 #else 2244c3bc407cSdh142964 sas_addr = sas_address; 2245c3bc407cSdh142964 #endif 2246c3bc407cSdh142964 sas_addressp = (uint8_t *)&sas_addr; 2247c3bc407cSdh142964 2248601c90f1SSrikanth, Ramana /* Ensure the tail number isn't greater than the size of the log */ 2249601c90f1SSrikanth, Ramana if (tail_lines > tbuf_num_elems) { 2250601c90f1SSrikanth, Ramana tail_lines = tbuf_num_elems; 2251601c90f1SSrikanth, Ramana } 2252601c90f1SSrikanth, Ramana 22534c06356bSdh142964 /* Figure out where we start and stop */ 22544c06356bSdh142964 if (wrap) { 2255601c90f1SSrikanth, Ramana if (tail_lines) { 2256601c90f1SSrikanth, Ramana /* Do we need to wrap backwards? */ 2257601c90f1SSrikanth, Ramana if (tail_lines > tbuf_idx) { 2258601c90f1SSrikanth, Ramana start_idx = tbuf_num_elems - (tail_lines - 2259601c90f1SSrikanth, Ramana tbuf_idx); 2260601c90f1SSrikanth, Ramana } else { 2261601c90f1SSrikanth, Ramana start_idx = tbuf_idx - tail_lines; 2262601c90f1SSrikanth, Ramana } 2263601c90f1SSrikanth, Ramana elems_to_print = tail_lines; 2264601c90f1SSrikanth, Ramana } else { 22654c06356bSdh142964 start_idx = tbuf_idx; 22664c06356bSdh142964 elems_to_print = tbuf_num_elems; 2267601c90f1SSrikanth, Ramana } 2268601c90f1SSrikanth, Ramana } else { 2269601c90f1SSrikanth, Ramana if (tail_lines > tbuf_idx) { 2270601c90f1SSrikanth, Ramana tail_lines = tbuf_idx; 2271601c90f1SSrikanth, Ramana } 2272601c90f1SSrikanth, Ramana if (tail_lines) { 2273601c90f1SSrikanth, Ramana start_idx = tbuf_idx - tail_lines; 2274601c90f1SSrikanth, Ramana elems_to_print = tail_lines; 22754c06356bSdh142964 } else { 22764c06356bSdh142964 start_idx = 0; 22774c06356bSdh142964 elems_to_print = tbuf_idx; 22784c06356bSdh142964 } 2279601c90f1SSrikanth, Ramana } 22804c06356bSdh142964 22814c06356bSdh142964 idx = start_idx; 22824c06356bSdh142964 22834c06356bSdh142964 /* Dump the buffer contents */ 22844c06356bSdh142964 while (elems_to_print != 0) { 22854c06356bSdh142964 if (MDB_RD(&tbuf, sizeof (pmcs_tbuf_t), (tbuf_addr + idx)) 22864c06356bSdh142964 == -1) { 22874c06356bSdh142964 NOREAD(tbuf, (tbuf_addr + idx)); 22884c06356bSdh142964 return (DCMD_ERR); 22894c06356bSdh142964 } 22904c06356bSdh142964 2291c3bc407cSdh142964 /* 2292c3bc407cSdh142964 * Check for filtering on HBA instance 2293c3bc407cSdh142964 */ 22944c06356bSdh142964 elem_filtered = B_FALSE; 22954c06356bSdh142964 22964c06356bSdh142964 if (filter) { 22974c06356bSdh142964 bufp = tbuf.buf; 22984c06356bSdh142964 /* Skip the driver name */ 22994c06356bSdh142964 while (*bufp < '0' || *bufp > '9') { 23004c06356bSdh142964 bufp++; 23014c06356bSdh142964 } 23024c06356bSdh142964 23034c06356bSdh142964 ei_idx = 0; 23044c06356bSdh142964 elem_inst[ei_idx++] = '0'; 23054c06356bSdh142964 elem_inst[ei_idx++] = 't'; 23064c06356bSdh142964 while (*bufp != ':' && ei_idx < (MAX_INST_STRLEN - 1)) { 23074c06356bSdh142964 elem_inst[ei_idx++] = *bufp; 23084c06356bSdh142964 bufp++; 23094c06356bSdh142964 } 23104c06356bSdh142964 elem_inst[ei_idx] = 0; 23114c06356bSdh142964 23124c06356bSdh142964 /* Get the instance */ 23134c06356bSdh142964 if ((int)mdb_strtoull(elem_inst) != instance) { 23144c06356bSdh142964 elem_filtered = B_TRUE; 23154c06356bSdh142964 } 23164c06356bSdh142964 } 23174c06356bSdh142964 2318c3bc407cSdh142964 if (!elem_filtered && (phy_path || sas_address)) { 2319c3bc407cSdh142964 /* 2320c3bc407cSdh142964 * This message is not being filtered by HBA instance. 2321c3bc407cSdh142964 * Now check to see if we're filtering based on 2322c3bc407cSdh142964 * PHY path or SAS address. 2323c3bc407cSdh142964 * Filtering is an "OR" operation. So, if any of the 2324c3bc407cSdh142964 * criteria matches, this message will be printed. 2325c3bc407cSdh142964 */ 2326c3bc407cSdh142964 elem_filtered = B_TRUE; 2327c3bc407cSdh142964 2328c3bc407cSdh142964 if (phy_path != NULL) { 2329c3bc407cSdh142964 if (strncmp(phy_path, tbuf.phy_path, 2330c3bc407cSdh142964 PMCS_TBUF_UA_MAX_SIZE) == 0) { 2331c3bc407cSdh142964 elem_filtered = B_FALSE; 2332c3bc407cSdh142964 } 2333c3bc407cSdh142964 } 2334c3bc407cSdh142964 if (sas_address != 0) { 2335c3bc407cSdh142964 if (memcmp(sas_addressp, tbuf.phy_sas_address, 2336c3bc407cSdh142964 8) == 0) { 2337c3bc407cSdh142964 elem_filtered = B_FALSE; 2338c3bc407cSdh142964 } 2339c3bc407cSdh142964 } 2340c3bc407cSdh142964 } 2341c3bc407cSdh142964 23424c06356bSdh142964 if (!elem_filtered) { 23431f81b464SDavid Hollister /* 23441f81b464SDavid Hollister * If the -v flag was given, print the firmware 23451f81b464SDavid Hollister * timestamp along with the clock time 23461f81b464SDavid Hollister */ 23471f81b464SDavid Hollister mdb_printf("%Y.%09ld ", tbuf.timestamp); 23481f81b464SDavid Hollister if (verbose) { 23491f81b464SDavid Hollister mdb_printf("(0x%" PRIx64 ") ", 23501f81b464SDavid Hollister tbuf.fw_timestamp); 23511f81b464SDavid Hollister } 23521f81b464SDavid Hollister mdb_printf("%s\n", tbuf.buf); 23534c06356bSdh142964 } 23544c06356bSdh142964 23554c06356bSdh142964 --elems_to_print; 23564c06356bSdh142964 if (++idx == tbuf_num_elems) { 23574c06356bSdh142964 idx = 0; 23584c06356bSdh142964 } 23594c06356bSdh142964 } 23604c06356bSdh142964 23614c06356bSdh142964 return (DCMD_OK); 23624c06356bSdh142964 } 23634c06356bSdh142964 23644c06356bSdh142964 /* 23654c06356bSdh142964 * Walkers 23664c06356bSdh142964 */ 23674c06356bSdh142964 static int 23684c06356bSdh142964 targets_walk_i(mdb_walk_state_t *wsp) 23694c06356bSdh142964 { 23704c06356bSdh142964 if (wsp->walk_addr == NULL) { 23714c06356bSdh142964 mdb_warn("Can not perform global walk\n"); 23724c06356bSdh142964 return (WALK_ERR); 23734c06356bSdh142964 } 23744c06356bSdh142964 23754c06356bSdh142964 /* 23764c06356bSdh142964 * Address provided belongs to HBA softstate. Get the targets pointer 23774c06356bSdh142964 * to begin the walk. 23784c06356bSdh142964 */ 23794c06356bSdh142964 if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) != 23804c06356bSdh142964 sizeof (pmcs_hw_t)) { 23814c06356bSdh142964 mdb_warn("Unable to read HBA softstate\n"); 23824c06356bSdh142964 return (WALK_ERR); 23834c06356bSdh142964 } 23844c06356bSdh142964 23854c06356bSdh142964 if (targets == NULL) { 23864c06356bSdh142964 targets = mdb_alloc(sizeof (targets) * ss.max_dev, UM_SLEEP); 23874c06356bSdh142964 } 23884c06356bSdh142964 23894c06356bSdh142964 if (MDB_RD(targets, sizeof (targets) * ss.max_dev, ss.targets) == -1) { 23904c06356bSdh142964 NOREAD(targets, ss.targets); 23914c06356bSdh142964 return (WALK_ERR); 23924c06356bSdh142964 } 23934c06356bSdh142964 23944c06356bSdh142964 target_idx = 0; 23954c06356bSdh142964 wsp->walk_addr = (uintptr_t)(targets[0]); 23964c06356bSdh142964 wsp->walk_data = mdb_alloc(sizeof (pmcs_xscsi_t), UM_SLEEP); 23974c06356bSdh142964 23984c06356bSdh142964 return (WALK_NEXT); 23994c06356bSdh142964 } 24004c06356bSdh142964 24014c06356bSdh142964 static int 24024c06356bSdh142964 targets_walk_s(mdb_walk_state_t *wsp) 24034c06356bSdh142964 { 24044c06356bSdh142964 int status; 24054c06356bSdh142964 24064c06356bSdh142964 if (target_idx == ss.max_dev) { 24074c06356bSdh142964 return (WALK_DONE); 24084c06356bSdh142964 } 24094c06356bSdh142964 24104c06356bSdh142964 if (mdb_vread(wsp->walk_data, sizeof (pmcs_xscsi_t), 24114c06356bSdh142964 wsp->walk_addr) == -1) { 24124c06356bSdh142964 mdb_warn("Failed to read target at %p", (void *)wsp->walk_addr); 24134c06356bSdh142964 return (WALK_DONE); 24144c06356bSdh142964 } 24154c06356bSdh142964 24164c06356bSdh142964 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 24174c06356bSdh142964 wsp->walk_cbdata); 24184c06356bSdh142964 24194c06356bSdh142964 do { 24204c06356bSdh142964 wsp->walk_addr = (uintptr_t)(targets[++target_idx]); 24214c06356bSdh142964 } while ((wsp->walk_addr == NULL) && (target_idx < ss.max_dev)); 24224c06356bSdh142964 24234c06356bSdh142964 if (target_idx == ss.max_dev) { 24244c06356bSdh142964 return (WALK_DONE); 24254c06356bSdh142964 } 24264c06356bSdh142964 24274c06356bSdh142964 return (status); 24284c06356bSdh142964 } 24294c06356bSdh142964 24304c06356bSdh142964 static void 24314c06356bSdh142964 targets_walk_f(mdb_walk_state_t *wsp) 24324c06356bSdh142964 { 24334c06356bSdh142964 mdb_free(wsp->walk_data, sizeof (pmcs_xscsi_t)); 24344c06356bSdh142964 } 24354c06356bSdh142964 24364c06356bSdh142964 24374c06356bSdh142964 static pmcs_phy_t * 24384c06356bSdh142964 pmcs_next_sibling(pmcs_phy_t *phyp) 24394c06356bSdh142964 { 24404c06356bSdh142964 pmcs_phy_t parent; 24414c06356bSdh142964 24424c06356bSdh142964 /* 24434c06356bSdh142964 * First, if this is a root PHY, there are no more siblings 24444c06356bSdh142964 */ 24454c06356bSdh142964 if (phyp->level == 0) { 24464c06356bSdh142964 return (NULL); 24474c06356bSdh142964 } 24484c06356bSdh142964 24494c06356bSdh142964 /* 24504c06356bSdh142964 * Otherwise, next sibling is the parent's sibling 24514c06356bSdh142964 */ 24524c06356bSdh142964 while (phyp->level > 0) { 24534c06356bSdh142964 if (mdb_vread(&parent, sizeof (pmcs_phy_t), 24544c06356bSdh142964 (uintptr_t)phyp->parent) == -1) { 24554c06356bSdh142964 mdb_warn("pmcs_next_sibling: Failed to read PHY at %p", 24564c06356bSdh142964 (void *)phyp->parent); 24574c06356bSdh142964 return (NULL); 24584c06356bSdh142964 } 24594c06356bSdh142964 24604c06356bSdh142964 if (parent.sibling != NULL) { 24614c06356bSdh142964 break; 24624c06356bSdh142964 } 24634c06356bSdh142964 2464e71c81d1SJesse Butler /* 2465e71c81d1SJesse Butler * If this PHY's sibling is NULL and it's a root phy, 2466e71c81d1SJesse Butler * we're done. 2467e71c81d1SJesse Butler */ 2468e71c81d1SJesse Butler if (parent.level == 0) { 2469e71c81d1SJesse Butler return (NULL); 2470e71c81d1SJesse Butler } 2471e71c81d1SJesse Butler 24724c06356bSdh142964 phyp = phyp->parent; 24734c06356bSdh142964 } 24744c06356bSdh142964 24754c06356bSdh142964 return (parent.sibling); 24764c06356bSdh142964 } 24774c06356bSdh142964 24784c06356bSdh142964 static int 24794c06356bSdh142964 phy_walk_i(mdb_walk_state_t *wsp) 24804c06356bSdh142964 { 24814c06356bSdh142964 if (wsp->walk_addr == NULL) { 24824c06356bSdh142964 mdb_warn("Can not perform global walk\n"); 24834c06356bSdh142964 return (WALK_ERR); 24844c06356bSdh142964 } 24854c06356bSdh142964 24864c06356bSdh142964 /* 24874c06356bSdh142964 * Address provided belongs to HBA softstate. Get the targets pointer 24884c06356bSdh142964 * to begin the walk. 24894c06356bSdh142964 */ 24904c06356bSdh142964 if (mdb_vread(&ss, sizeof (pmcs_hw_t), wsp->walk_addr) != 24914c06356bSdh142964 sizeof (pmcs_hw_t)) { 24924c06356bSdh142964 mdb_warn("Unable to read HBA softstate\n"); 24934c06356bSdh142964 return (WALK_ERR); 24944c06356bSdh142964 } 24954c06356bSdh142964 24964c06356bSdh142964 wsp->walk_addr = (uintptr_t)(ss.root_phys); 24974c06356bSdh142964 wsp->walk_data = mdb_alloc(sizeof (pmcs_phy_t), UM_SLEEP); 24984c06356bSdh142964 24994c06356bSdh142964 return (WALK_NEXT); 25004c06356bSdh142964 } 25014c06356bSdh142964 25024c06356bSdh142964 static int 25034c06356bSdh142964 phy_walk_s(mdb_walk_state_t *wsp) 25044c06356bSdh142964 { 25054c06356bSdh142964 pmcs_phy_t *phyp, *nphyp; 25064c06356bSdh142964 int status; 25074c06356bSdh142964 25084c06356bSdh142964 if (mdb_vread(wsp->walk_data, sizeof (pmcs_phy_t), 25094c06356bSdh142964 wsp->walk_addr) == -1) { 25104c06356bSdh142964 mdb_warn("phy_walk_s: Failed to read PHY at %p", 25114c06356bSdh142964 (void *)wsp->walk_addr); 25124c06356bSdh142964 return (WALK_DONE); 25134c06356bSdh142964 } 25144c06356bSdh142964 25154c06356bSdh142964 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 25164c06356bSdh142964 wsp->walk_cbdata); 25174c06356bSdh142964 25184c06356bSdh142964 phyp = (pmcs_phy_t *)wsp->walk_data; 25194c06356bSdh142964 if (phyp->children) { 25204c06356bSdh142964 wsp->walk_addr = (uintptr_t)(phyp->children); 25214c06356bSdh142964 } else { 25224c06356bSdh142964 wsp->walk_addr = (uintptr_t)(phyp->sibling); 25234c06356bSdh142964 } 25244c06356bSdh142964 25254c06356bSdh142964 if (wsp->walk_addr == NULL) { 25264c06356bSdh142964 /* 25274c06356bSdh142964 * We reached the end of this sibling list. Trudge back up 25284c06356bSdh142964 * to the parent and find the next sibling after the expander 25294c06356bSdh142964 * we just finished traversing, if there is one. 25304c06356bSdh142964 */ 25314c06356bSdh142964 nphyp = pmcs_next_sibling(phyp); 25324c06356bSdh142964 25334c06356bSdh142964 if (nphyp == NULL) { 25344c06356bSdh142964 return (WALK_DONE); 25354c06356bSdh142964 } 25364c06356bSdh142964 25374c06356bSdh142964 wsp->walk_addr = (uintptr_t)nphyp; 25384c06356bSdh142964 } 25394c06356bSdh142964 25404c06356bSdh142964 return (status); 25414c06356bSdh142964 } 25424c06356bSdh142964 25434c06356bSdh142964 static void 25444c06356bSdh142964 phy_walk_f(mdb_walk_state_t *wsp) 25454c06356bSdh142964 { 25464c06356bSdh142964 mdb_free(wsp->walk_data, sizeof (pmcs_phy_t)); 25474c06356bSdh142964 } 25484c06356bSdh142964 254914d6cf0aSdh142964 static void 255014d6cf0aSdh142964 display_matching_work(struct pmcs_hw ss, uintmax_t index, uintmax_t snum, 255114d6cf0aSdh142964 uintmax_t tag_type) 255214d6cf0aSdh142964 { 255314d6cf0aSdh142964 int idx; 255414d6cf0aSdh142964 pmcwork_t work, *wp = &work; 255514d6cf0aSdh142964 uintptr_t _wp; 255614d6cf0aSdh142964 boolean_t printed_header = B_FALSE; 255714d6cf0aSdh142964 uint32_t mask, mask_val, match_val; 255814d6cf0aSdh142964 char *match_type; 255914d6cf0aSdh142964 256014d6cf0aSdh142964 if (index != UINT_MAX) { 256114d6cf0aSdh142964 match_type = "index"; 256214d6cf0aSdh142964 mask = PMCS_TAG_INDEX_MASK; 256314d6cf0aSdh142964 mask_val = index << PMCS_TAG_INDEX_SHIFT; 256414d6cf0aSdh142964 match_val = index; 256514d6cf0aSdh142964 } else if (snum != UINT_MAX) { 256614d6cf0aSdh142964 match_type = "serial number"; 256714d6cf0aSdh142964 mask = PMCS_TAG_SERNO_MASK; 256814d6cf0aSdh142964 mask_val = snum << PMCS_TAG_SERNO_SHIFT; 256914d6cf0aSdh142964 match_val = snum; 257014d6cf0aSdh142964 } else { 257114d6cf0aSdh142964 switch (tag_type) { 257214d6cf0aSdh142964 case PMCS_TAG_TYPE_NONE: 257314d6cf0aSdh142964 match_type = "tag type NONE"; 257414d6cf0aSdh142964 break; 257514d6cf0aSdh142964 case PMCS_TAG_TYPE_CBACK: 257614d6cf0aSdh142964 match_type = "tag type CBACK"; 257714d6cf0aSdh142964 break; 257814d6cf0aSdh142964 case PMCS_TAG_TYPE_WAIT: 257914d6cf0aSdh142964 match_type = "tag type WAIT"; 258014d6cf0aSdh142964 break; 258114d6cf0aSdh142964 } 258214d6cf0aSdh142964 mask = PMCS_TAG_TYPE_MASK; 258314d6cf0aSdh142964 mask_val = tag_type << PMCS_TAG_TYPE_SHIFT; 258414d6cf0aSdh142964 match_val = tag_type; 258514d6cf0aSdh142964 } 258614d6cf0aSdh142964 258714d6cf0aSdh142964 _wp = (uintptr_t)ss.work; 258814d6cf0aSdh142964 258914d6cf0aSdh142964 for (idx = 0; idx < ss.max_cmd; idx++, _wp += sizeof (pmcwork_t)) { 259014d6cf0aSdh142964 if (MDB_RD(&work, sizeof (pmcwork_t), _wp) == -1) { 259114d6cf0aSdh142964 NOREAD(pmcwork_t, _wp); 259214d6cf0aSdh142964 continue; 259314d6cf0aSdh142964 } 259414d6cf0aSdh142964 259514d6cf0aSdh142964 if ((work.htag & mask) != mask_val) { 259614d6cf0aSdh142964 continue; 259714d6cf0aSdh142964 } 259814d6cf0aSdh142964 259914d6cf0aSdh142964 if (printed_header == B_FALSE) { 260014d6cf0aSdh142964 if (tag_type) { 260114d6cf0aSdh142964 mdb_printf("\nWork structures matching %s\n\n", 260214d6cf0aSdh142964 match_type, match_val); 260314d6cf0aSdh142964 } else { 260414d6cf0aSdh142964 mdb_printf("\nWork structures matching %s of " 260514d6cf0aSdh142964 "0x%x\n\n", match_type, match_val); 260614d6cf0aSdh142964 } 260714d6cf0aSdh142964 mdb_printf("%8s %10s %20s %8s %8s O D\n", 260814d6cf0aSdh142964 "HTag", "State", "Phy Path", "Target", "Timer"); 260914d6cf0aSdh142964 printed_header = B_TRUE; 261014d6cf0aSdh142964 } 261114d6cf0aSdh142964 261214d6cf0aSdh142964 display_one_work(wp, 0, 0); 261314d6cf0aSdh142964 } 261414d6cf0aSdh142964 261514d6cf0aSdh142964 if (!printed_header) { 261614d6cf0aSdh142964 mdb_printf("No work structure matches found\n"); 261714d6cf0aSdh142964 } 261814d6cf0aSdh142964 } 261914d6cf0aSdh142964 262014d6cf0aSdh142964 static int 262114d6cf0aSdh142964 pmcs_tag(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 262214d6cf0aSdh142964 { 262314d6cf0aSdh142964 struct pmcs_hw ss; 262414d6cf0aSdh142964 uintmax_t tag_type = UINT_MAX; 262514d6cf0aSdh142964 uintmax_t snum = UINT_MAX; 262614d6cf0aSdh142964 uintmax_t index = UINT_MAX; 262714d6cf0aSdh142964 int args = 0; 262814d6cf0aSdh142964 void *pmcs_state; 262914d6cf0aSdh142964 char *state_str; 263014d6cf0aSdh142964 struct dev_info dip; 263114d6cf0aSdh142964 263214d6cf0aSdh142964 if (!(flags & DCMD_ADDRSPEC)) { 263314d6cf0aSdh142964 pmcs_state = NULL; 263414d6cf0aSdh142964 if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) { 263514d6cf0aSdh142964 mdb_warn("can't read pmcs_softc_state"); 263614d6cf0aSdh142964 return (DCMD_ERR); 263714d6cf0aSdh142964 } 263814d6cf0aSdh142964 if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_tag", argc, 263914d6cf0aSdh142964 argv, (uintptr_t)pmcs_state) == -1) { 264014d6cf0aSdh142964 mdb_warn("mdb_pwalk_dcmd failed"); 264114d6cf0aSdh142964 return (DCMD_ERR); 264214d6cf0aSdh142964 } 264314d6cf0aSdh142964 return (DCMD_OK); 264414d6cf0aSdh142964 } 264514d6cf0aSdh142964 264614d6cf0aSdh142964 if (mdb_getopts(argc, argv, 264714d6cf0aSdh142964 'i', MDB_OPT_UINT64, &index, 264814d6cf0aSdh142964 's', MDB_OPT_UINT64, &snum, 264914d6cf0aSdh142964 't', MDB_OPT_UINT64, &tag_type) != argc) 265014d6cf0aSdh142964 return (DCMD_USAGE); 265114d6cf0aSdh142964 265214d6cf0aSdh142964 /* 265314d6cf0aSdh142964 * Count the number of supplied options and make sure they are 265414d6cf0aSdh142964 * within appropriate ranges. If they're set to UINT_MAX, that means 265514d6cf0aSdh142964 * they were not supplied, in which case reset them to 0. 265614d6cf0aSdh142964 */ 265714d6cf0aSdh142964 if (index != UINT_MAX) { 265814d6cf0aSdh142964 args++; 265914d6cf0aSdh142964 if (index > PMCS_TAG_INDEX_MASK) { 266014d6cf0aSdh142964 mdb_warn("Index is out of range\n"); 266114d6cf0aSdh142964 return (DCMD_USAGE); 266214d6cf0aSdh142964 } 266314d6cf0aSdh142964 } 266414d6cf0aSdh142964 266514d6cf0aSdh142964 if (tag_type != UINT_MAX) { 266614d6cf0aSdh142964 args++; 266714d6cf0aSdh142964 switch (tag_type) { 266814d6cf0aSdh142964 case PMCS_TAG_TYPE_NONE: 266914d6cf0aSdh142964 case PMCS_TAG_TYPE_CBACK: 267014d6cf0aSdh142964 case PMCS_TAG_TYPE_WAIT: 267114d6cf0aSdh142964 break; 267214d6cf0aSdh142964 default: 267314d6cf0aSdh142964 mdb_warn("Invalid tag type\n"); 267414d6cf0aSdh142964 return (DCMD_USAGE); 267514d6cf0aSdh142964 } 267614d6cf0aSdh142964 } 267714d6cf0aSdh142964 267814d6cf0aSdh142964 if (snum != UINT_MAX) { 267914d6cf0aSdh142964 args++; 268014d6cf0aSdh142964 if (snum > (PMCS_TAG_SERNO_MASK >> PMCS_TAG_SERNO_SHIFT)) { 268114d6cf0aSdh142964 mdb_warn("Serial number is out of range\n"); 268214d6cf0aSdh142964 return (DCMD_USAGE); 268314d6cf0aSdh142964 } 268414d6cf0aSdh142964 } 268514d6cf0aSdh142964 268614d6cf0aSdh142964 /* 268714d6cf0aSdh142964 * Make sure 1 and only 1 option is specified 268814d6cf0aSdh142964 */ 268914d6cf0aSdh142964 if ((args == 0) || (args > 1)) { 269014d6cf0aSdh142964 mdb_warn("Exactly one of -i, -s and -t must be specified\n"); 269114d6cf0aSdh142964 return (DCMD_USAGE); 269214d6cf0aSdh142964 } 269314d6cf0aSdh142964 269414d6cf0aSdh142964 if (MDB_RD(&ss, sizeof (ss), addr) == -1) { 269514d6cf0aSdh142964 NOREAD(pmcs_hw_t, addr); 269614d6cf0aSdh142964 return (DCMD_ERR); 269714d6cf0aSdh142964 } 269814d6cf0aSdh142964 269914d6cf0aSdh142964 if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) { 270014d6cf0aSdh142964 NOREAD(pmcs_hw_t, addr); 270114d6cf0aSdh142964 return (DCMD_ERR); 270214d6cf0aSdh142964 } 270314d6cf0aSdh142964 270414d6cf0aSdh142964 /* processing completed */ 270514d6cf0aSdh142964 270614d6cf0aSdh142964 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) || 270714d6cf0aSdh142964 (flags & DCMD_LOOPFIRST)) { 270814d6cf0aSdh142964 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST)) 270914d6cf0aSdh142964 mdb_printf("\n"); 271014d6cf0aSdh142964 mdb_printf("%16s %9s %4s B C WorkFlags wserno DbgMsk %16s\n", 271114d6cf0aSdh142964 "Address", "State", "Inst", "DIP"); 271214d6cf0aSdh142964 mdb_printf("=================================" 271314d6cf0aSdh142964 "============================================\n"); 271414d6cf0aSdh142964 } 271514d6cf0aSdh142964 271614d6cf0aSdh142964 switch (ss.state) { 271714d6cf0aSdh142964 case STATE_NIL: 271814d6cf0aSdh142964 state_str = "Invalid"; 271914d6cf0aSdh142964 break; 272014d6cf0aSdh142964 case STATE_PROBING: 272114d6cf0aSdh142964 state_str = "Probing"; 272214d6cf0aSdh142964 break; 272314d6cf0aSdh142964 case STATE_RUNNING: 272414d6cf0aSdh142964 state_str = "Running"; 272514d6cf0aSdh142964 break; 272614d6cf0aSdh142964 case STATE_UNPROBING: 272714d6cf0aSdh142964 state_str = "Unprobing"; 272814d6cf0aSdh142964 break; 272914d6cf0aSdh142964 case STATE_DEAD: 273014d6cf0aSdh142964 state_str = "Dead"; 273114d6cf0aSdh142964 break; 27325c45adf0SJesse Butler case STATE_IN_RESET: 27335c45adf0SJesse Butler state_str = "In Reset"; 27345c45adf0SJesse Butler break; 273514d6cf0aSdh142964 } 273614d6cf0aSdh142964 273714d6cf0aSdh142964 mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr, 273814d6cf0aSdh142964 state_str, dip.devi_instance, ss.blocked, ss.configuring, 273914d6cf0aSdh142964 ss.work_flags, ss.wserno, ss.debug_mask, ss.dip); 274014d6cf0aSdh142964 mdb_printf("\n"); 274114d6cf0aSdh142964 274214d6cf0aSdh142964 mdb_inc_indent(4); 274314d6cf0aSdh142964 display_matching_work(ss, index, snum, tag_type); 274414d6cf0aSdh142964 mdb_dec_indent(4); 274514d6cf0aSdh142964 mdb_printf("\n"); 274614d6cf0aSdh142964 274714d6cf0aSdh142964 return (DCMD_OK); 274814d6cf0aSdh142964 } 274914d6cf0aSdh142964 27509719310aSDavid Hollister #ifndef _KMDB 27519719310aSDavid Hollister static int 27529719310aSDavid Hollister pmcs_dump_fwlog(struct pmcs_hw *ss, int instance, const char *ofile) 27539719310aSDavid Hollister { 27549719310aSDavid Hollister uint8_t *fwlogp; 27559719310aSDavid Hollister int ofilefd = -1; 27569719310aSDavid Hollister char ofilename[MAXPATHLEN]; 27579719310aSDavid Hollister int rval = DCMD_OK; 27589719310aSDavid Hollister 27599719310aSDavid Hollister if (ss->fwlogp == NULL) { 27609719310aSDavid Hollister mdb_warn("Firmware event log disabled for instance %d", 27619719310aSDavid Hollister instance); 27629719310aSDavid Hollister return (DCMD_OK); 27639719310aSDavid Hollister } 27649719310aSDavid Hollister 27659719310aSDavid Hollister if (snprintf(ofilename, MAXPATHLEN, "%s%d", ofile, instance) > 27669719310aSDavid Hollister MAXPATHLEN) { 27679719310aSDavid Hollister mdb_warn("Output filename is too long for instance %d", 27689719310aSDavid Hollister instance); 27699719310aSDavid Hollister return (DCMD_ERR); 27709719310aSDavid Hollister } 27719719310aSDavid Hollister 27729719310aSDavid Hollister fwlogp = mdb_alloc(PMCS_FWLOG_SIZE, UM_SLEEP); 27739719310aSDavid Hollister 27749719310aSDavid Hollister if (MDB_RD(fwlogp, PMCS_FWLOG_SIZE, ss->fwlogp) == -1) { 27759719310aSDavid Hollister NOREAD(fwlogp, ss->fwlogp); 27769719310aSDavid Hollister rval = DCMD_ERR; 27779719310aSDavid Hollister goto cleanup; 27789719310aSDavid Hollister } 27799719310aSDavid Hollister 27809719310aSDavid Hollister ofilefd = open(ofilename, O_WRONLY | O_CREAT, 27819719310aSDavid Hollister S_IRUSR | S_IRGRP | S_IROTH); 27829719310aSDavid Hollister if (ofilefd < 0) { 27839719310aSDavid Hollister mdb_warn("Unable to open '%s' to dump instance %d event log", 27849719310aSDavid Hollister ofilename, instance); 27859719310aSDavid Hollister rval = DCMD_ERR; 27869719310aSDavid Hollister goto cleanup; 27879719310aSDavid Hollister } 27889719310aSDavid Hollister 27899719310aSDavid Hollister if (write(ofilefd, fwlogp, PMCS_FWLOG_SIZE) != PMCS_FWLOG_SIZE) { 27909719310aSDavid Hollister mdb_warn("Failed to write %d bytes to output file: instance %d", 27919719310aSDavid Hollister PMCS_FWLOG_SIZE, instance); 27929719310aSDavid Hollister rval = DCMD_ERR; 27939719310aSDavid Hollister goto cleanup; 27949719310aSDavid Hollister } 27959719310aSDavid Hollister 27969719310aSDavid Hollister mdb_printf("Event log for instance %d written to %s\n", instance, 27979719310aSDavid Hollister ofilename); 27989719310aSDavid Hollister 27999719310aSDavid Hollister cleanup: 28009719310aSDavid Hollister if (ofilefd >= 0) { 28019719310aSDavid Hollister close(ofilefd); 28029719310aSDavid Hollister } 28039719310aSDavid Hollister mdb_free(fwlogp, PMCS_FWLOG_SIZE); 28049719310aSDavid Hollister return (rval); 28059719310aSDavid Hollister } 28069719310aSDavid Hollister 28079719310aSDavid Hollister static int 28089719310aSDavid Hollister pmcs_fwlog(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 28099719310aSDavid Hollister { 28109719310aSDavid Hollister void *pmcs_state; 28119719310aSDavid Hollister const char *ofile = NULL; 28129719310aSDavid Hollister struct pmcs_hw ss; 28139719310aSDavid Hollister struct dev_info dip; 28149719310aSDavid Hollister 28159719310aSDavid Hollister if (mdb_getopts(argc, argv, 'o', MDB_OPT_STR, &ofile, NULL) != argc) { 28169719310aSDavid Hollister return (DCMD_USAGE); 28179719310aSDavid Hollister } 28189719310aSDavid Hollister 28199719310aSDavid Hollister if (ofile == NULL) { 28209719310aSDavid Hollister mdb_printf("No output file specified\n"); 28219719310aSDavid Hollister return (DCMD_USAGE); 28229719310aSDavid Hollister } 28239719310aSDavid Hollister 28249719310aSDavid Hollister if (!(flags & DCMD_ADDRSPEC)) { 28259719310aSDavid Hollister pmcs_state = NULL; 28269719310aSDavid Hollister if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) { 28279719310aSDavid Hollister mdb_warn("can't read pmcs_softc_state"); 28289719310aSDavid Hollister return (DCMD_ERR); 28299719310aSDavid Hollister } 28309719310aSDavid Hollister if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_fwlog", argc, 28319719310aSDavid Hollister argv, (uintptr_t)pmcs_state) == -1) { 28329719310aSDavid Hollister mdb_warn("mdb_pwalk_dcmd failed for pmcs_log"); 28339719310aSDavid Hollister return (DCMD_ERR); 28349719310aSDavid Hollister } 28359719310aSDavid Hollister return (DCMD_OK); 28369719310aSDavid Hollister } 28379719310aSDavid Hollister 28389719310aSDavid Hollister if (MDB_RD(&ss, sizeof (ss), addr) == -1) { 28399719310aSDavid Hollister NOREAD(pmcs_hw_t, addr); 28409719310aSDavid Hollister return (DCMD_ERR); 28419719310aSDavid Hollister } 28429719310aSDavid Hollister 28439719310aSDavid Hollister if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) { 28449719310aSDavid Hollister NOREAD(pmcs_hw_t, addr); 28459719310aSDavid Hollister return (DCMD_ERR); 28469719310aSDavid Hollister } 28479719310aSDavid Hollister 28489719310aSDavid Hollister return (pmcs_dump_fwlog(&ss, dip.devi_instance, ofile)); 28499719310aSDavid Hollister } 28509719310aSDavid Hollister #endif /* _KMDB */ 28519719310aSDavid Hollister 28524c06356bSdh142964 static int 2853c3bc407cSdh142964 pmcs_log(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2854c3bc407cSdh142964 { 2855c3bc407cSdh142964 void *pmcs_state; 2856c3bc407cSdh142964 struct pmcs_hw ss; 2857c3bc407cSdh142964 struct dev_info dip; 2858c3bc407cSdh142964 const char *match_phy_path = NULL; 2859601c90f1SSrikanth, Ramana uint64_t match_sas_address = 0, tail_lines = 0; 28601f81b464SDavid Hollister uint_t verbose = 0; 2861c3bc407cSdh142964 2862c3bc407cSdh142964 if (!(flags & DCMD_ADDRSPEC)) { 2863c3bc407cSdh142964 pmcs_state = NULL; 2864c3bc407cSdh142964 if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) { 2865c3bc407cSdh142964 mdb_warn("can't read pmcs_softc_state"); 2866c3bc407cSdh142964 return (DCMD_ERR); 2867c3bc407cSdh142964 } 2868c3bc407cSdh142964 if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs_log", argc, 2869c3bc407cSdh142964 argv, (uintptr_t)pmcs_state) == -1) { 2870c3bc407cSdh142964 mdb_warn("mdb_pwalk_dcmd failed for pmcs_log"); 2871c3bc407cSdh142964 return (DCMD_ERR); 2872c3bc407cSdh142964 } 2873c3bc407cSdh142964 return (DCMD_OK); 2874c3bc407cSdh142964 } 2875c3bc407cSdh142964 2876c3bc407cSdh142964 if (mdb_getopts(argc, argv, 2877601c90f1SSrikanth, Ramana 'l', MDB_OPT_UINT64, &tail_lines, 2878c3bc407cSdh142964 'p', MDB_OPT_STR, &match_phy_path, 2879c3bc407cSdh142964 's', MDB_OPT_UINT64, &match_sas_address, 28801f81b464SDavid Hollister 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2881c3bc407cSdh142964 NULL) != argc) { 2882c3bc407cSdh142964 return (DCMD_USAGE); 2883c3bc407cSdh142964 } 2884c3bc407cSdh142964 2885c3bc407cSdh142964 if (MDB_RD(&ss, sizeof (ss), addr) == -1) { 2886c3bc407cSdh142964 NOREAD(pmcs_hw_t, addr); 2887c3bc407cSdh142964 return (DCMD_ERR); 2888c3bc407cSdh142964 } 2889c3bc407cSdh142964 2890c3bc407cSdh142964 if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) { 2891c3bc407cSdh142964 NOREAD(pmcs_hw_t, addr); 2892c3bc407cSdh142964 return (DCMD_ERR); 2893c3bc407cSdh142964 } 2894c3bc407cSdh142964 2895c3bc407cSdh142964 if (!(flags & DCMD_LOOP)) { 2896c3bc407cSdh142964 return (pmcs_dump_tracelog(B_TRUE, dip.devi_instance, 28971f81b464SDavid Hollister tail_lines, match_phy_path, match_sas_address, verbose)); 2898c3bc407cSdh142964 } else if (flags & DCMD_LOOPFIRST) { 2899601c90f1SSrikanth, Ramana return (pmcs_dump_tracelog(B_FALSE, 0, tail_lines, 29001f81b464SDavid Hollister match_phy_path, match_sas_address, verbose)); 2901c3bc407cSdh142964 } else { 2902c3bc407cSdh142964 return (DCMD_OK); 2903c3bc407cSdh142964 } 2904c3bc407cSdh142964 } 2905c3bc407cSdh142964 2906c3bc407cSdh142964 static int 29074c06356bSdh142964 pmcs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 29084c06356bSdh142964 { 29094c06356bSdh142964 struct pmcs_hw ss; 29104c06356bSdh142964 uint_t verbose = FALSE; 29114c06356bSdh142964 uint_t phy_info = FALSE; 29124c06356bSdh142964 uint_t hw_info = FALSE; 29134c06356bSdh142964 uint_t target_info = FALSE; 29144c06356bSdh142964 uint_t work_info = FALSE; 29154c06356bSdh142964 uint_t ic_info = FALSE; 29164c06356bSdh142964 uint_t iport_info = FALSE; 29174c06356bSdh142964 uint_t waitqs_info = FALSE; 29184c06356bSdh142964 uint_t ibq = FALSE; 29194c06356bSdh142964 uint_t obq = FALSE; 29204c06356bSdh142964 uint_t tgt_phy_count = FALSE; 292114d6cf0aSdh142964 uint_t compq = FALSE; 2922c3bc407cSdh142964 uint_t unconfigured = FALSE; 2923f7aef0b0SReed uint_t damap_info = FALSE; 2924f7aef0b0SReed uint_t dtc_info = FALSE; 2925658280b6SDavid Hollister uint_t wserno = FALSE; 29261f81b464SDavid Hollister uint_t fwlog = FALSE; 292765e70c04SDavid Hollister boolean_t devid_filter = FALSE; 292865e70c04SDavid Hollister uintptr_t pdevid; 292965e70c04SDavid Hollister uint32_t devid; 29304c06356bSdh142964 int rv = DCMD_OK; 29314c06356bSdh142964 void *pmcs_state; 29324c06356bSdh142964 char *state_str; 29334c06356bSdh142964 struct dev_info dip; 2934f7aef0b0SReed per_iport_setting_t pis; 29354c06356bSdh142964 29364c06356bSdh142964 if (!(flags & DCMD_ADDRSPEC)) { 29374c06356bSdh142964 pmcs_state = NULL; 29384c06356bSdh142964 if (mdb_readvar(&pmcs_state, "pmcs_softc_state") == -1) { 29394c06356bSdh142964 mdb_warn("can't read pmcs_softc_state"); 29404c06356bSdh142964 return (DCMD_ERR); 29414c06356bSdh142964 } 29424c06356bSdh142964 if (mdb_pwalk_dcmd("genunix`softstate", "pmcs`pmcs", argc, argv, 29434c06356bSdh142964 (uintptr_t)pmcs_state) == -1) { 29444c06356bSdh142964 mdb_warn("mdb_pwalk_dcmd failed"); 29454c06356bSdh142964 return (DCMD_ERR); 29464c06356bSdh142964 } 29474c06356bSdh142964 return (DCMD_OK); 29484c06356bSdh142964 } 29494c06356bSdh142964 29504c06356bSdh142964 if (mdb_getopts(argc, argv, 295114d6cf0aSdh142964 'c', MDB_OPT_SETBITS, TRUE, &compq, 2952f7aef0b0SReed 'd', MDB_OPT_SETBITS, TRUE, &dtc_info, 295365e70c04SDavid Hollister 'D', MDB_OPT_UINTPTR_SET, &devid_filter, &pdevid, 29541f81b464SDavid Hollister 'e', MDB_OPT_SETBITS, TRUE, &fwlog, 29554c06356bSdh142964 'h', MDB_OPT_SETBITS, TRUE, &hw_info, 29564c06356bSdh142964 'i', MDB_OPT_SETBITS, TRUE, &ic_info, 29574c06356bSdh142964 'I', MDB_OPT_SETBITS, TRUE, &iport_info, 2958f7aef0b0SReed 'm', MDB_OPT_SETBITS, TRUE, &damap_info, 29594c06356bSdh142964 'p', MDB_OPT_SETBITS, TRUE, &phy_info, 29604c06356bSdh142964 'q', MDB_OPT_SETBITS, TRUE, &ibq, 29614c06356bSdh142964 'Q', MDB_OPT_SETBITS, TRUE, &obq, 2962658280b6SDavid Hollister 's', MDB_OPT_SETBITS, TRUE, &wserno, 29634c06356bSdh142964 't', MDB_OPT_SETBITS, TRUE, &target_info, 29644c06356bSdh142964 'T', MDB_OPT_SETBITS, TRUE, &tgt_phy_count, 2965c3bc407cSdh142964 'u', MDB_OPT_SETBITS, TRUE, &unconfigured, 29664c06356bSdh142964 'v', MDB_OPT_SETBITS, TRUE, &verbose, 29674c06356bSdh142964 'w', MDB_OPT_SETBITS, TRUE, &work_info, 29684c06356bSdh142964 'W', MDB_OPT_SETBITS, TRUE, &waitqs_info, 29694c06356bSdh142964 NULL) != argc) 29704c06356bSdh142964 return (DCMD_USAGE); 29714c06356bSdh142964 2972f7aef0b0SReed /* 2973f7aef0b0SReed * The 'd' and 'm' options implicitly enable the 'I' option 2974f7aef0b0SReed */ 2975f7aef0b0SReed pis.pis_damap_info = damap_info; 2976f7aef0b0SReed pis.pis_dtc_info = dtc_info; 2977f7aef0b0SReed if (damap_info || dtc_info) { 2978f7aef0b0SReed iport_info = TRUE; 2979f7aef0b0SReed } 2980f7aef0b0SReed 298165e70c04SDavid Hollister /* 298265e70c04SDavid Hollister * The -D option is meaningless without -q and/or -Q, and implies 298365e70c04SDavid Hollister * verbosity. 298465e70c04SDavid Hollister */ 298565e70c04SDavid Hollister if (devid_filter) { 298665e70c04SDavid Hollister devid = (uint64_t)pdevid & 0xffffffff; 298765e70c04SDavid Hollister if (!ibq && !obq) { 298865e70c04SDavid Hollister mdb_printf("-D requires either -q or -Q\n"); 298965e70c04SDavid Hollister return (DCMD_USAGE); 299065e70c04SDavid Hollister } 299165e70c04SDavid Hollister if (devid > PMCS_DEVICE_ID_MASK) { 299265e70c04SDavid Hollister mdb_printf("Device ID invalid\n"); 299365e70c04SDavid Hollister return (DCMD_USAGE); 299465e70c04SDavid Hollister } 299565e70c04SDavid Hollister verbose = TRUE; 299665e70c04SDavid Hollister } 299765e70c04SDavid Hollister 29984c06356bSdh142964 if (MDB_RD(&ss, sizeof (ss), addr) == -1) { 29994c06356bSdh142964 NOREAD(pmcs_hw_t, addr); 30004c06356bSdh142964 return (DCMD_ERR); 30014c06356bSdh142964 } 30024c06356bSdh142964 30034c06356bSdh142964 if (MDB_RD(&dip, sizeof (struct dev_info), ss.dip) == -1) { 30044c06356bSdh142964 NOREAD(pmcs_hw_t, addr); 30054c06356bSdh142964 return (DCMD_ERR); 30064c06356bSdh142964 } 30074c06356bSdh142964 30084c06356bSdh142964 /* processing completed */ 30094c06356bSdh142964 30104c06356bSdh142964 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) || 30114c06356bSdh142964 (flags & DCMD_LOOPFIRST) || phy_info || target_info || hw_info || 3012c3bc407cSdh142964 work_info || waitqs_info || ibq || obq || tgt_phy_count || compq || 30131f81b464SDavid Hollister unconfigured || fwlog) { 30144c06356bSdh142964 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST)) 30154c06356bSdh142964 mdb_printf("\n"); 30164c06356bSdh142964 mdb_printf("%16s %9s %4s B C WorkFlags wserno DbgMsk %16s\n", 30174c06356bSdh142964 "Address", "State", "Inst", "DIP"); 30184c06356bSdh142964 mdb_printf("=================================" 30194c06356bSdh142964 "============================================\n"); 30204c06356bSdh142964 } 30214c06356bSdh142964 30224c06356bSdh142964 switch (ss.state) { 30234c06356bSdh142964 case STATE_NIL: 30244c06356bSdh142964 state_str = "Invalid"; 30254c06356bSdh142964 break; 30264c06356bSdh142964 case STATE_PROBING: 30274c06356bSdh142964 state_str = "Probing"; 30284c06356bSdh142964 break; 30294c06356bSdh142964 case STATE_RUNNING: 30304c06356bSdh142964 state_str = "Running"; 30314c06356bSdh142964 break; 30324c06356bSdh142964 case STATE_UNPROBING: 30334c06356bSdh142964 state_str = "Unprobing"; 30344c06356bSdh142964 break; 30354c06356bSdh142964 case STATE_DEAD: 30364c06356bSdh142964 state_str = "Dead"; 30374c06356bSdh142964 break; 30385c45adf0SJesse Butler case STATE_IN_RESET: 30395c45adf0SJesse Butler state_str = "In Reset"; 30405c45adf0SJesse Butler break; 30414c06356bSdh142964 } 30424c06356bSdh142964 30434c06356bSdh142964 mdb_printf("%16p %9s %4d %1d %1d 0x%08x 0x%04x 0x%04x %16p\n", addr, 30444c06356bSdh142964 state_str, dip.devi_instance, ss.blocked, ss.configuring, 30454c06356bSdh142964 ss.work_flags, ss.wserno, ss.debug_mask, ss.dip); 30464c06356bSdh142964 mdb_printf("\n"); 30474c06356bSdh142964 30484c06356bSdh142964 mdb_inc_indent(4); 30494c06356bSdh142964 30504c06356bSdh142964 if (waitqs_info) 30514c06356bSdh142964 display_waitqs(ss, verbose); 30524c06356bSdh142964 30534c06356bSdh142964 if (hw_info) 30544c06356bSdh142964 display_hwinfo(ss, verbose); 30554c06356bSdh142964 30564c06356bSdh142964 if (phy_info || tgt_phy_count) 30574c06356bSdh142964 display_phys(ss, verbose, NULL, 0, tgt_phy_count); 30584c06356bSdh142964 30594c06356bSdh142964 if (target_info || tgt_phy_count) 30604c06356bSdh142964 display_targets(ss, verbose, tgt_phy_count); 30614c06356bSdh142964 3062658280b6SDavid Hollister if (work_info || wserno) 3063658280b6SDavid Hollister display_work(ss, verbose, wserno); 30644c06356bSdh142964 30654c06356bSdh142964 if (ic_info) 30664c06356bSdh142964 display_ic(ss, verbose); 30674c06356bSdh142964 30684c06356bSdh142964 if (ibq) 306965e70c04SDavid Hollister display_inbound_queues(ss, devid, verbose); 30704c06356bSdh142964 30714c06356bSdh142964 if (obq) 307265e70c04SDavid Hollister display_outbound_queues(ss, devid, verbose); 30734c06356bSdh142964 30744c06356bSdh142964 if (iport_info) 3075f7aef0b0SReed display_iport(ss, addr, verbose, &pis); 30764c06356bSdh142964 307714d6cf0aSdh142964 if (compq) 307814d6cf0aSdh142964 display_completion_queue(ss); 307914d6cf0aSdh142964 3080c3bc407cSdh142964 if (unconfigured) 3081c3bc407cSdh142964 display_unconfigured_targets(addr); 3082c3bc407cSdh142964 30831f81b464SDavid Hollister if (fwlog) 30841f81b464SDavid Hollister display_event_log(ss); 30851f81b464SDavid Hollister 30864c06356bSdh142964 mdb_dec_indent(4); 30874c06356bSdh142964 30884c06356bSdh142964 return (rv); 30894c06356bSdh142964 } 30904c06356bSdh142964 30914c06356bSdh142964 void 30924c06356bSdh142964 pmcs_help() 30934c06356bSdh142964 { 30944c06356bSdh142964 mdb_printf("Prints summary information about each pmcs instance.\n" 309514d6cf0aSdh142964 " -c: Dump the completion queue\n" 3096f7aef0b0SReed " -d: Print per-iport information about device tree children\n" 309765e70c04SDavid Hollister " -D <device ID>: With -q/-Q, filter by device handle\n" 30981f81b464SDavid Hollister " -e: Display the in-memory firmware event log\n" 30994c06356bSdh142964 " -h: Print more detailed hardware information\n" 31004c06356bSdh142964 " -i: Print interrupt coalescing information\n" 31014c06356bSdh142964 " -I: Print information about each iport\n" 3102f7aef0b0SReed " -m: Print per-iport information about DAM/damap state\n" 31034c06356bSdh142964 " -p: Print information about each attached PHY\n" 31044c06356bSdh142964 " -q: Dump inbound queues\n" 31054c06356bSdh142964 " -Q: Dump outbound queues\n" 3106658280b6SDavid Hollister " -s: Dump all work structures sorted by serial number\n" 3107c3bc407cSdh142964 " -t: Print information about each configured target\n" 31084c06356bSdh142964 " -T: Print target and PHY count summary\n" 3109c3bc407cSdh142964 " -u: Show SAS address of all unconfigured targets\n" 31104c06356bSdh142964 " -w: Dump work structures\n" 31114c06356bSdh142964 " -W: List pmcs cmds waiting on various queues\n" 31124c06356bSdh142964 " -v: Add verbosity to the above options\n"); 31134c06356bSdh142964 } 31144c06356bSdh142964 311514d6cf0aSdh142964 void 3116c3bc407cSdh142964 pmcs_log_help() 3117c3bc407cSdh142964 { 3118c3bc407cSdh142964 mdb_printf("Dump the pmcs log buffer, possibly with filtering.\n" 3119601c90f1SSrikanth, Ramana " -l TAIL_LINES: Dump the last TAIL_LINES messages\n" 3120c3bc407cSdh142964 " -p PHY_PATH: Dump messages matching PHY_PATH\n" 3121c3bc407cSdh142964 " -s SAS_ADDRESS: Dump messages matching SAS_ADDRESS\n\n" 3122c3bc407cSdh142964 "Where: PHY_PATH can be found with ::pmcs -p (e.g. pp04.18.18.01)\n" 3123c3bc407cSdh142964 " SAS_ADDRESS can be found with ::pmcs -t " 3124c3bc407cSdh142964 "(e.g. 5000c5000358c221)\n"); 3125c3bc407cSdh142964 } 3126c3bc407cSdh142964 void 312714d6cf0aSdh142964 pmcs_tag_help() 312814d6cf0aSdh142964 { 312914d6cf0aSdh142964 mdb_printf("Print all work structures by matching the tag.\n" 313014d6cf0aSdh142964 " -i index: Match tag index (0x000 - 0xfff)\n" 313114d6cf0aSdh142964 " -s serialnumber: Match serial number (0x0000 - 0xffff)\n" 313214d6cf0aSdh142964 " -t tagtype: Match tag type [NONE(1), CBACK(2), " 313314d6cf0aSdh142964 "WAIT(3)]\n"); 313414d6cf0aSdh142964 } 313514d6cf0aSdh142964 31364c06356bSdh142964 static const mdb_dcmd_t dcmds[] = { 313765e70c04SDavid Hollister { "pmcs", "?[-cdehiImpQqtTuwWv] [-D <device ID>]", 313865e70c04SDavid Hollister "print pmcs information", pmcs_dcmd, pmcs_help 31394c06356bSdh142964 }, 3140c3bc407cSdh142964 { "pmcs_log", 31411f81b464SDavid Hollister "?[-v] [-p PHY_PATH | -s SAS_ADDRESS | -l TAIL_LINES]", 3142c3bc407cSdh142964 "dump pmcs log file", pmcs_log, pmcs_log_help 3143c3bc407cSdh142964 }, 314414d6cf0aSdh142964 { "pmcs_tag", "?[-t tagtype|-s serialnum|-i index]", 314514d6cf0aSdh142964 "Find work structures by tag type, serial number or index", 314614d6cf0aSdh142964 pmcs_tag, pmcs_tag_help 314714d6cf0aSdh142964 }, 31489719310aSDavid Hollister #ifndef _KMDB 31499719310aSDavid Hollister { "pmcs_fwlog", 31509719310aSDavid Hollister "?-o output_file", 31519719310aSDavid Hollister "dump pmcs firmware event log to output_file", pmcs_fwlog, NULL 31529719310aSDavid Hollister }, 31539719310aSDavid Hollister #endif /* _KMDB */ 31544c06356bSdh142964 { NULL } 31554c06356bSdh142964 }; 31564c06356bSdh142964 31574c06356bSdh142964 static const mdb_walker_t walkers[] = { 31584c06356bSdh142964 { "pmcs_targets", "walk target structures", 31594c06356bSdh142964 targets_walk_i, targets_walk_s, targets_walk_f }, 31604c06356bSdh142964 { "pmcs_phys", "walk PHY structures", 31614c06356bSdh142964 phy_walk_i, phy_walk_s, phy_walk_f }, 31624c06356bSdh142964 { NULL } 31634c06356bSdh142964 }; 31644c06356bSdh142964 31654c06356bSdh142964 static const mdb_modinfo_t modinfo = { 31664c06356bSdh142964 MDB_API_VERSION, dcmds, walkers 31674c06356bSdh142964 }; 31684c06356bSdh142964 31694c06356bSdh142964 const mdb_modinfo_t * 31704c06356bSdh142964 _mdb_init(void) 31714c06356bSdh142964 { 31724c06356bSdh142964 return (&modinfo); 31734c06356bSdh142964 } 3174