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