1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2019, Joyent, Inc. 25 */ 26 27 #include <sys/mdb_modapi.h> 28 #include <sys/proc.h> 29 #include <sys/types.h> 30 #include <sys/sunddi.h> 31 #include <sys/ddi_hp.h> 32 #include "devinfo.h" 33 34 static char * 35 ddihp_get_cn_state(ddi_hp_cn_state_t state) 36 { 37 switch (state) { 38 case DDI_HP_CN_STATE_EMPTY: 39 return ("Empty"); 40 case DDI_HP_CN_STATE_PRESENT: 41 return ("Present"); 42 case DDI_HP_CN_STATE_POWERED: 43 return ("Powered"); 44 case DDI_HP_CN_STATE_ENABLED: 45 return ("Enabled"); 46 case DDI_HP_CN_STATE_PORT_EMPTY: 47 return ("Port_Empty"); 48 case DDI_HP_CN_STATE_PORT_PRESENT: 49 return ("Port_Present"); 50 case DDI_HP_CN_STATE_OFFLINE: 51 return ("Offline"); 52 case DDI_HP_CN_STATE_ATTACHED: 53 return ("Attached"); 54 case DDI_HP_CN_STATE_MAINTENANCE: 55 return ("Maintenance"); 56 case DDI_HP_CN_STATE_ONLINE: 57 return ("Online"); 58 default: 59 return ("Unknown"); 60 } 61 } 62 63 /*ARGSUSED*/ 64 static int 65 hotplug_print(uintptr_t addr, struct dev_info *dev, devinfo_cb_data_t *data) 66 { 67 ddi_hp_cn_handle_t hdl; 68 uintptr_t hdlp = (uintptr_t)dev->devi_hp_hdlp; 69 char cn_type[15]; 70 char cn_name[15]; 71 72 while (hdlp) { 73 if (mdb_vread(&hdl, sizeof (ddi_hp_cn_handle_t), hdlp) == -1) { 74 mdb_warn("Failed to read hdlp!\n"); 75 return (DCMD_ERR); 76 } 77 78 if (!(data->di_flags & DEVINFO_HP_PHYSICAL) || 79 hdl.cn_info.cn_type != DDI_HP_CN_TYPE_VIRTUAL_PORT) { 80 if (mdb_readstr(cn_type, sizeof (cn_type), 81 (uintptr_t)hdl.cn_info.cn_type_str) == -1) { 82 mdb_warn("Failed to read cn_type!\n"); 83 return (DCMD_ERR); 84 } 85 if (mdb_readstr(cn_name, sizeof (cn_name), 86 (uintptr_t)hdl.cn_info.cn_name) == -1) { 87 mdb_warn("Failed to read cn_name!\n"); 88 return (DCMD_ERR); 89 } 90 mdb_printf("%?p %?p %-12s %-15s %-15s\n", hdl.cn_dip, 91 hdlp, ddihp_get_cn_state(hdl.cn_info.cn_state), 92 cn_type, cn_name); 93 } 94 hdlp = (uintptr_t)hdl.next; 95 }; 96 97 return (WALK_NEXT); 98 } 99 100 void 101 hotplug_help(void) 102 { 103 mdb_printf("Switches:\n" 104 " -p only print the physical hotplug connectors\n"); 105 } 106 107 int 108 hotplug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 109 { 110 devinfo_cb_data_t data; 111 uintptr_t devinfo_root; /* Address of root of devinfo tree */ 112 ddi_hp_cn_handle_t hdl; 113 char cn_type[15]; 114 char cn_name[15]; 115 int status; 116 117 data.di_flags = 0; 118 data.di_filter = NULL; 119 data.di_instance = UINT64_MAX; 120 if (mdb_getopts(argc, argv, 121 'p', MDB_OPT_SETBITS, DEVINFO_HP_PHYSICAL, &data.di_flags, NULL) 122 != argc) 123 return (DCMD_USAGE); 124 125 if (DCMD_HDRSPEC(flags)) { 126 mdb_printf("%<u>%?s %?s %-12s %-15s %-15s%</u>\n", 127 "PARENT_DEVINFO", "HANDLE", "STATE", "TYPE", "CN_NAME"); 128 } 129 130 if ((flags & DCMD_ADDRSPEC) == 0) { 131 data.di_flags |= DEVINFO_PARENT | DEVINFO_CHILD; 132 133 if (mdb_readvar(&devinfo_root, "top_devinfo") == -1) { 134 mdb_warn("failed to read 'top_devinfo'"); 135 return (0); 136 } 137 138 data.di_base = devinfo_root; 139 status = mdb_pwalk("devinfo", (mdb_walk_cb_t)hotplug_print, 140 &data, devinfo_root); 141 if (status == -1) { 142 mdb_warn("couldn't walk devinfo tree"); 143 return (DCMD_ERR); 144 } 145 return (DCMD_OK); 146 } 147 148 if (mdb_vread(&hdl, sizeof (ddi_hp_cn_handle_t), (uintptr_t)addr) 149 == -1) { 150 mdb_warn("Failed to read hdlp!\n"); 151 return (DCMD_ERR); 152 } 153 if (mdb_readstr(cn_type, sizeof (cn_type), 154 (uintptr_t)hdl.cn_info.cn_type_str) == -1) { 155 mdb_warn("Failed to read cn_type!\n"); 156 return (DCMD_ERR); 157 } 158 if (mdb_readstr(cn_name, sizeof (cn_name), 159 (uintptr_t)hdl.cn_info.cn_name) == -1) { 160 mdb_warn("Failed to read cn_name!\n"); 161 return (DCMD_ERR); 162 } 163 mdb_printf("%?p %?p %-12s %-15s %-15s\n", hdl.cn_dip, addr, 164 ddihp_get_cn_state(hdl.cn_info.cn_state), cn_type, cn_name); 165 166 return (DCMD_OK); 167 } 168