126947304SEvan Yan /*
226947304SEvan Yan * CDDL HEADER START
326947304SEvan Yan *
426947304SEvan Yan * The contents of this file are subject to the terms of the
526947304SEvan Yan * Common Development and Distribution License (the "License").
626947304SEvan Yan * You may not use this file except in compliance with the License.
726947304SEvan Yan *
826947304SEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
926947304SEvan Yan * or http://www.opensolaris.org/os/licensing.
1026947304SEvan Yan * See the License for the specific language governing permissions
1126947304SEvan Yan * and limitations under the License.
1226947304SEvan Yan *
1326947304SEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
1426947304SEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1526947304SEvan Yan * If applicable, add the following below this CDDL HEADER, with the
1626947304SEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
1726947304SEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
1826947304SEvan Yan *
1926947304SEvan Yan * CDDL HEADER END
2026947304SEvan Yan */
2126947304SEvan Yan /*
2226947304SEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2326947304SEvan Yan * Use is subject to license terms.
24*e386d4ddSRobert Mustacchi * Copyright 2019, Joyent, Inc.
2526947304SEvan Yan */
2626947304SEvan Yan
2726947304SEvan Yan #include <sys/mdb_modapi.h>
2826947304SEvan Yan #include <sys/proc.h>
2926947304SEvan Yan #include <sys/types.h>
3026947304SEvan Yan #include <sys/sunddi.h>
3126947304SEvan Yan #include <sys/ddi_hp.h>
3226947304SEvan Yan #include "devinfo.h"
3326947304SEvan Yan
3426947304SEvan Yan static char *
ddihp_get_cn_state(ddi_hp_cn_state_t state)3526947304SEvan Yan ddihp_get_cn_state(ddi_hp_cn_state_t state)
3626947304SEvan Yan {
3726947304SEvan Yan switch (state) {
3826947304SEvan Yan case DDI_HP_CN_STATE_EMPTY:
3926947304SEvan Yan return ("Empty");
4026947304SEvan Yan case DDI_HP_CN_STATE_PRESENT:
4126947304SEvan Yan return ("Present");
4226947304SEvan Yan case DDI_HP_CN_STATE_POWERED:
4326947304SEvan Yan return ("Powered");
4426947304SEvan Yan case DDI_HP_CN_STATE_ENABLED:
4526947304SEvan Yan return ("Enabled");
4626947304SEvan Yan case DDI_HP_CN_STATE_PORT_EMPTY:
4726947304SEvan Yan return ("Port_Empty");
4826947304SEvan Yan case DDI_HP_CN_STATE_PORT_PRESENT:
4926947304SEvan Yan return ("Port_Present");
5026947304SEvan Yan case DDI_HP_CN_STATE_OFFLINE:
5126947304SEvan Yan return ("Offline");
5226947304SEvan Yan case DDI_HP_CN_STATE_ATTACHED:
5326947304SEvan Yan return ("Attached");
5426947304SEvan Yan case DDI_HP_CN_STATE_MAINTENANCE:
5526947304SEvan Yan return ("Maintenance");
5626947304SEvan Yan case DDI_HP_CN_STATE_ONLINE:
5726947304SEvan Yan return ("Online");
5826947304SEvan Yan default:
5926947304SEvan Yan return ("Unknown");
6026947304SEvan Yan }
6126947304SEvan Yan }
6226947304SEvan Yan
6326947304SEvan Yan /*ARGSUSED*/
6426947304SEvan Yan static int
hotplug_print(uintptr_t addr,struct dev_info * dev,devinfo_cb_data_t * data)6526947304SEvan Yan hotplug_print(uintptr_t addr, struct dev_info *dev, devinfo_cb_data_t *data)
6626947304SEvan Yan {
6726947304SEvan Yan ddi_hp_cn_handle_t hdl;
6826947304SEvan Yan uintptr_t hdlp = (uintptr_t)dev->devi_hp_hdlp;
6926947304SEvan Yan char cn_type[15];
7026947304SEvan Yan char cn_name[15];
7126947304SEvan Yan
7226947304SEvan Yan while (hdlp) {
7326947304SEvan Yan if (mdb_vread(&hdl, sizeof (ddi_hp_cn_handle_t), hdlp) == -1) {
7426947304SEvan Yan mdb_warn("Failed to read hdlp!\n");
7526947304SEvan Yan return (DCMD_ERR);
7626947304SEvan Yan }
7726947304SEvan Yan
7826947304SEvan Yan if (!(data->di_flags & DEVINFO_HP_PHYSICAL) ||
7926947304SEvan Yan hdl.cn_info.cn_type != DDI_HP_CN_TYPE_VIRTUAL_PORT) {
8026947304SEvan Yan if (mdb_readstr(cn_type, sizeof (cn_type),
8126947304SEvan Yan (uintptr_t)hdl.cn_info.cn_type_str) == -1) {
8226947304SEvan Yan mdb_warn("Failed to read cn_type!\n");
8326947304SEvan Yan return (DCMD_ERR);
8426947304SEvan Yan }
8526947304SEvan Yan if (mdb_readstr(cn_name, sizeof (cn_name),
8626947304SEvan Yan (uintptr_t)hdl.cn_info.cn_name) == -1) {
8726947304SEvan Yan mdb_warn("Failed to read cn_name!\n");
8826947304SEvan Yan return (DCMD_ERR);
8926947304SEvan Yan }
9026947304SEvan Yan mdb_printf("%?p %?p %-12s %-15s %-15s\n", hdl.cn_dip,
9126947304SEvan Yan hdlp, ddihp_get_cn_state(hdl.cn_info.cn_state),
9226947304SEvan Yan cn_type, cn_name);
9326947304SEvan Yan }
9426947304SEvan Yan hdlp = (uintptr_t)hdl.next;
9526947304SEvan Yan };
9626947304SEvan Yan
9726947304SEvan Yan return (WALK_NEXT);
9826947304SEvan Yan }
9926947304SEvan Yan
10026947304SEvan Yan void
hotplug_help(void)10126947304SEvan Yan hotplug_help(void)
10226947304SEvan Yan {
10326947304SEvan Yan mdb_printf("Switches:\n"
10426947304SEvan Yan " -p only print the physical hotplug connectors\n");
10526947304SEvan Yan }
10626947304SEvan Yan
10726947304SEvan Yan int
hotplug(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)10826947304SEvan Yan hotplug(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
10926947304SEvan Yan {
11026947304SEvan Yan devinfo_cb_data_t data;
11126947304SEvan Yan uintptr_t devinfo_root; /* Address of root of devinfo tree */
11226947304SEvan Yan ddi_hp_cn_handle_t hdl;
11326947304SEvan Yan char cn_type[15];
11426947304SEvan Yan char cn_name[15];
11526947304SEvan Yan int status;
11626947304SEvan Yan
11726947304SEvan Yan data.di_flags = 0;
11820c06695SRobert Mustacchi data.di_filter = NULL;
119*e386d4ddSRobert Mustacchi data.di_instance = UINT64_MAX;
12026947304SEvan Yan if (mdb_getopts(argc, argv,
12126947304SEvan Yan 'p', MDB_OPT_SETBITS, DEVINFO_HP_PHYSICAL, &data.di_flags, NULL)
12226947304SEvan Yan != argc)
12326947304SEvan Yan return (DCMD_USAGE);
12426947304SEvan Yan
12526947304SEvan Yan if (DCMD_HDRSPEC(flags)) {
12626947304SEvan Yan mdb_printf("%<u>%?s %?s %-12s %-15s %-15s%</u>\n",
12726947304SEvan Yan "PARENT_DEVINFO", "HANDLE", "STATE", "TYPE", "CN_NAME");
12826947304SEvan Yan }
12926947304SEvan Yan
13026947304SEvan Yan if ((flags & DCMD_ADDRSPEC) == 0) {
13126947304SEvan Yan data.di_flags |= DEVINFO_PARENT | DEVINFO_CHILD;
13226947304SEvan Yan
13326947304SEvan Yan if (mdb_readvar(&devinfo_root, "top_devinfo") == -1) {
13426947304SEvan Yan mdb_warn("failed to read 'top_devinfo'");
135892ad162SToomas Soome return (0);
13626947304SEvan Yan }
13726947304SEvan Yan
13826947304SEvan Yan data.di_base = devinfo_root;
13926947304SEvan Yan status = mdb_pwalk("devinfo", (mdb_walk_cb_t)hotplug_print,
14026947304SEvan Yan &data, devinfo_root);
14126947304SEvan Yan if (status == -1) {
14226947304SEvan Yan mdb_warn("couldn't walk devinfo tree");
14326947304SEvan Yan return (DCMD_ERR);
14426947304SEvan Yan }
14526947304SEvan Yan return (DCMD_OK);
14626947304SEvan Yan }
14726947304SEvan Yan
14826947304SEvan Yan if (mdb_vread(&hdl, sizeof (ddi_hp_cn_handle_t), (uintptr_t)addr)
14926947304SEvan Yan == -1) {
15026947304SEvan Yan mdb_warn("Failed to read hdlp!\n");
15126947304SEvan Yan return (DCMD_ERR);
15226947304SEvan Yan }
15326947304SEvan Yan if (mdb_readstr(cn_type, sizeof (cn_type),
15426947304SEvan Yan (uintptr_t)hdl.cn_info.cn_type_str) == -1) {
15526947304SEvan Yan mdb_warn("Failed to read cn_type!\n");
15626947304SEvan Yan return (DCMD_ERR);
15726947304SEvan Yan }
15826947304SEvan Yan if (mdb_readstr(cn_name, sizeof (cn_name),
15926947304SEvan Yan (uintptr_t)hdl.cn_info.cn_name) == -1) {
16026947304SEvan Yan mdb_warn("Failed to read cn_name!\n");
16126947304SEvan Yan return (DCMD_ERR);
16226947304SEvan Yan }
16326947304SEvan Yan mdb_printf("%?p %?p %-12s %-15s %-15s\n", hdl.cn_dip, addr,
16426947304SEvan Yan ddihp_get_cn_state(hdl.cn_info.cn_state), cn_type, cn_name);
16526947304SEvan Yan
16626947304SEvan Yan return (DCMD_OK);
16726947304SEvan Yan }
168