15febcb4aSScott Carter, SD IOSW /*
25febcb4aSScott Carter, SD IOSW  * CDDL HEADER START
35febcb4aSScott Carter, SD IOSW  *
45febcb4aSScott Carter, SD IOSW  * The contents of this file are subject to the terms of the
55febcb4aSScott Carter, SD IOSW  * Common Development and Distribution License (the "License").
65febcb4aSScott Carter, SD IOSW  * You may not use this file except in compliance with the License.
75febcb4aSScott Carter, SD IOSW  *
85febcb4aSScott Carter, SD IOSW  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95febcb4aSScott Carter, SD IOSW  * or http://www.opensolaris.org/os/licensing.
105febcb4aSScott Carter, SD IOSW  * See the License for the specific language governing permissions
115febcb4aSScott Carter, SD IOSW  * and limitations under the License.
125febcb4aSScott Carter, SD IOSW  *
135febcb4aSScott Carter, SD IOSW  * When distributing Covered Code, include this CDDL HEADER in each
145febcb4aSScott Carter, SD IOSW  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155febcb4aSScott Carter, SD IOSW  * If applicable, add the following below this CDDL HEADER, with the
165febcb4aSScott Carter, SD IOSW  * fields enclosed by brackets "[]" replaced with your own identifying
175febcb4aSScott Carter, SD IOSW  * information: Portions Copyright [yyyy] [name of copyright owner]
185febcb4aSScott Carter, SD IOSW  *
195febcb4aSScott Carter, SD IOSW  * CDDL HEADER END
205febcb4aSScott Carter, SD IOSW  */
215febcb4aSScott Carter, SD IOSW /*
22b285fe30SScott M. Carter  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
235febcb4aSScott Carter, SD IOSW  */
245febcb4aSScott Carter, SD IOSW 
255febcb4aSScott Carter, SD IOSW #include <sys/mdb_modapi.h>
265febcb4aSScott Carter, SD IOSW #include <sys/proc.h>
275febcb4aSScott Carter, SD IOSW #include <sys/types.h>
285febcb4aSScott Carter, SD IOSW #include <sys/sunddi.h>
295febcb4aSScott Carter, SD IOSW #include <sys/ddi_intr.h>
305febcb4aSScott Carter, SD IOSW #include <sys/ddi_intr_impl.h>
315febcb4aSScott Carter, SD IOSW #include <stddef.h>
325febcb4aSScott Carter, SD IOSW 
335febcb4aSScott Carter, SD IOSW #include "list.h"
345febcb4aSScott Carter, SD IOSW 
355febcb4aSScott Carter, SD IOSW extern int	mdb_devinfo2driver(uintptr_t, char *, size_t);
365febcb4aSScott Carter, SD IOSW 
375febcb4aSScott Carter, SD IOSW static char *
irm_get_type(int type)385febcb4aSScott Carter, SD IOSW irm_get_type(int type)
395febcb4aSScott Carter, SD IOSW {
405febcb4aSScott Carter, SD IOSW 	if (type == (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX))
415febcb4aSScott Carter, SD IOSW 		return ("MSI/X");
425febcb4aSScott Carter, SD IOSW 
435febcb4aSScott Carter, SD IOSW 	switch (type) {
445febcb4aSScott Carter, SD IOSW 	case DDI_INTR_TYPE_FIXED:
455febcb4aSScott Carter, SD IOSW 		return ("Fixed");
465febcb4aSScott Carter, SD IOSW 	case DDI_INTR_TYPE_MSI:
475febcb4aSScott Carter, SD IOSW 		return ("MSI");
485febcb4aSScott Carter, SD IOSW 	case DDI_INTR_TYPE_MSIX:
495febcb4aSScott Carter, SD IOSW 		return ("MSI-X");
505febcb4aSScott Carter, SD IOSW 	default:
515febcb4aSScott Carter, SD IOSW 		return ("Unknown");
525febcb4aSScott Carter, SD IOSW 	}
535febcb4aSScott Carter, SD IOSW }
545febcb4aSScott Carter, SD IOSW 
55b285fe30SScott M. Carter static int
check_irm_enabled(void)56b285fe30SScott M. Carter check_irm_enabled(void)
57b285fe30SScott M. Carter {
58b285fe30SScott M. Carter 	GElf_Sym	sym;
59b285fe30SScott M. Carter 	uintptr_t	addr;
60b285fe30SScott M. Carter 	int		value;
61b285fe30SScott M. Carter 
62b285fe30SScott M. Carter 	if (mdb_lookup_by_name("irm_enable", &sym) == -1) {
63b285fe30SScott M. Carter 		mdb_warn("couldn't find irm_enable");
64b285fe30SScott M. Carter 		return (0);
65b285fe30SScott M. Carter 	}
66b285fe30SScott M. Carter 
67b285fe30SScott M. Carter 	addr = (uintptr_t)sym.st_value;
68b285fe30SScott M. Carter 
69b285fe30SScott M. Carter 	if (mdb_vread(&value, sizeof (value), addr) != sizeof (value)) {
70b285fe30SScott M. Carter 		mdb_warn("couldn't read irm_enable at %p", addr);
71b285fe30SScott M. Carter 		return (0);
72b285fe30SScott M. Carter 	}
73b285fe30SScott M. Carter 
74b285fe30SScott M. Carter 	return (value);
75b285fe30SScott M. Carter }
76b285fe30SScott M. Carter 
775febcb4aSScott Carter, SD IOSW int
irmpools_walk_init(mdb_walk_state_t * wsp)785febcb4aSScott Carter, SD IOSW irmpools_walk_init(mdb_walk_state_t *wsp)
795febcb4aSScott Carter, SD IOSW {
805febcb4aSScott Carter, SD IOSW 	GElf_Sym sym;
815febcb4aSScott Carter, SD IOSW 
825febcb4aSScott Carter, SD IOSW 	if (mdb_lookup_by_name("irm_pools_list", &sym) == -1) {
835febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't find irm_pools_list");
845febcb4aSScott Carter, SD IOSW 		return (WALK_ERR);
855febcb4aSScott Carter, SD IOSW 	}
865febcb4aSScott Carter, SD IOSW 
875febcb4aSScott Carter, SD IOSW 	wsp->walk_addr = (uintptr_t)sym.st_value;
885febcb4aSScott Carter, SD IOSW 
895febcb4aSScott Carter, SD IOSW 	return (list_walk_init_named(wsp, "interrupt pools", "pool"));
905febcb4aSScott Carter, SD IOSW }
915febcb4aSScott Carter, SD IOSW 
925febcb4aSScott Carter, SD IOSW int
irmreqs_walk_init(mdb_walk_state_t * wsp)935febcb4aSScott Carter, SD IOSW irmreqs_walk_init(mdb_walk_state_t *wsp)
945febcb4aSScott Carter, SD IOSW {
955febcb4aSScott Carter, SD IOSW 	wsp->walk_addr = (uintptr_t)(wsp->walk_addr +
965febcb4aSScott Carter, SD IOSW 	    offsetof(ddi_irm_pool_t, ipool_req_list));
975febcb4aSScott Carter, SD IOSW 
985febcb4aSScott Carter, SD IOSW 	return (list_walk_init_named(wsp, "interrupt requests", "request"));
995febcb4aSScott Carter, SD IOSW }
1005febcb4aSScott Carter, SD IOSW 
1015febcb4aSScott Carter, SD IOSW int
irmpools_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1025febcb4aSScott Carter, SD IOSW irmpools_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1035febcb4aSScott Carter, SD IOSW {
1045febcb4aSScott Carter, SD IOSW 	ddi_irm_pool_t	pool;
1055febcb4aSScott Carter, SD IOSW 	struct dev_info	dev;
1065febcb4aSScott Carter, SD IOSW 	char		driver[MODMAXNAMELEN + 1] = "";
1075febcb4aSScott Carter, SD IOSW 	char		devname[MODMAXNAMELEN + 1] = "";
1085febcb4aSScott Carter, SD IOSW 
1095febcb4aSScott Carter, SD IOSW 	if (argc != 0)
1105febcb4aSScott Carter, SD IOSW 		return (DCMD_USAGE);
1115febcb4aSScott Carter, SD IOSW 
112b285fe30SScott M. Carter 	if (check_irm_enabled() == 0) {
113b285fe30SScott M. Carter 		mdb_warn("IRM is not enabled");
114b285fe30SScott M. Carter 		return (DCMD_ERR);
115b285fe30SScott M. Carter 	}
116b285fe30SScott M. Carter 
1175febcb4aSScott Carter, SD IOSW 	if (!(flags & DCMD_ADDRSPEC)) {
1185febcb4aSScott Carter, SD IOSW 		if (mdb_walk_dcmd("irmpools", "irmpools", argc, argv) == -1) {
1195febcb4aSScott Carter, SD IOSW 			mdb_warn("can't walk interrupt pools");
1205febcb4aSScott Carter, SD IOSW 			return (DCMD_ERR);
1215febcb4aSScott Carter, SD IOSW 		}
1225febcb4aSScott Carter, SD IOSW 		return (DCMD_OK);
1235febcb4aSScott Carter, SD IOSW 	}
1245febcb4aSScott Carter, SD IOSW 
1255febcb4aSScott Carter, SD IOSW 	if (DCMD_HDRSPEC(flags)) {
1265febcb4aSScott Carter, SD IOSW 		mdb_printf("%<u>%?s  %-18s  %-8s  %-6s  %-9s  %-8s%</u>\n",
1275febcb4aSScott Carter, SD IOSW 		    "ADDR", "OWNER", "TYPE", "SIZE", "REQUESTED", "RESERVED");
1285febcb4aSScott Carter, SD IOSW 	}
1295febcb4aSScott Carter, SD IOSW 
1305febcb4aSScott Carter, SD IOSW 	if (mdb_vread(&pool, sizeof (pool), addr) != sizeof (pool)) {
1315febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't read interrupt pool at %p", addr);
1325febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
1335febcb4aSScott Carter, SD IOSW 	}
1345febcb4aSScott Carter, SD IOSW 
1355febcb4aSScott Carter, SD IOSW 	if (mdb_vread(&dev, sizeof (dev),
1365febcb4aSScott Carter, SD IOSW 	    (uintptr_t)pool.ipool_owner) != sizeof (dev)) {
1375febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't read dev_info at %p", pool.ipool_owner);
1385febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
1395febcb4aSScott Carter, SD IOSW 	}
1405febcb4aSScott Carter, SD IOSW 
1415febcb4aSScott Carter, SD IOSW 	mdb_devinfo2driver((uintptr_t)pool.ipool_owner, driver,
1425febcb4aSScott Carter, SD IOSW 	    sizeof (driver));
143*7ff178cdSJimmy Vetayases 	/*
144*7ff178cdSJimmy Vetayases 	 * Include driver instance number only if the node has an
145*7ff178cdSJimmy Vetayases 	 * instance number assigned (i.e. instance != -1) to it.
146*7ff178cdSJimmy Vetayases 	 * This will cover cases like rootnex driver which doesn't
147*7ff178cdSJimmy Vetayases 	 * have instance number assigned to it.
148*7ff178cdSJimmy Vetayases 	 */
149*7ff178cdSJimmy Vetayases 	if (dev.devi_instance != -1)
1505febcb4aSScott Carter, SD IOSW 		mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
1515febcb4aSScott Carter, SD IOSW 		    dev.devi_instance);
152*7ff178cdSJimmy Vetayases 	else
153*7ff178cdSJimmy Vetayases 		mdb_snprintf(devname, sizeof (devname), "%s", driver);
1545febcb4aSScott Carter, SD IOSW 
1555febcb4aSScott Carter, SD IOSW 	mdb_printf("%0?p  %-18s  %-8s  %-6d  %-9d  %-8d\n", addr, devname,
1565febcb4aSScott Carter, SD IOSW 	    irm_get_type(pool.ipool_types), pool.ipool_totsz,
1575febcb4aSScott Carter, SD IOSW 	    pool.ipool_reqno, pool.ipool_resno);
1585febcb4aSScott Carter, SD IOSW 
1595febcb4aSScott Carter, SD IOSW 	return (DCMD_OK);
1605febcb4aSScott Carter, SD IOSW }
1615febcb4aSScott Carter, SD IOSW 
1625febcb4aSScott Carter, SD IOSW int
irmreqs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1635febcb4aSScott Carter, SD IOSW irmreqs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1645febcb4aSScott Carter, SD IOSW {
1655febcb4aSScott Carter, SD IOSW 	if (argc != 0)
1665febcb4aSScott Carter, SD IOSW 		return (DCMD_USAGE);
1675febcb4aSScott Carter, SD IOSW 
168b285fe30SScott M. Carter 	if (check_irm_enabled() == 0) {
169b285fe30SScott M. Carter 		mdb_warn("IRM is not enabled");
170b285fe30SScott M. Carter 		return (DCMD_ERR);
171b285fe30SScott M. Carter 	}
172b285fe30SScott M. Carter 
1735febcb4aSScott Carter, SD IOSW 	if (!(flags & DCMD_ADDRSPEC)) {
1745febcb4aSScott Carter, SD IOSW 		mdb_warn("can't perform global interrupt request walk");
1755febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
1765febcb4aSScott Carter, SD IOSW 	}
1775febcb4aSScott Carter, SD IOSW 
1785febcb4aSScott Carter, SD IOSW 	if (mdb_pwalk_dcmd("irmreqs", "irmreq", argc, argv, addr) == -1) {
1795febcb4aSScott Carter, SD IOSW 		mdb_warn("can't walk interrupt requests");
1805febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
1815febcb4aSScott Carter, SD IOSW 	}
1825febcb4aSScott Carter, SD IOSW 
1835febcb4aSScott Carter, SD IOSW 	return (DCMD_OK);
1845febcb4aSScott Carter, SD IOSW }
1855febcb4aSScott Carter, SD IOSW 
1865febcb4aSScott Carter, SD IOSW /*ARGSUSED*/
1875febcb4aSScott Carter, SD IOSW int
irmreq_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1885febcb4aSScott Carter, SD IOSW irmreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1895febcb4aSScott Carter, SD IOSW {
1905febcb4aSScott Carter, SD IOSW 	ddi_irm_req_t		req;
1915febcb4aSScott Carter, SD IOSW 	struct dev_info		dev;
1925febcb4aSScott Carter, SD IOSW 	struct devinfo_intr	intr;
1935febcb4aSScott Carter, SD IOSW 	char			driver[MODMAXNAMELEN + 1] = "";
1945febcb4aSScott Carter, SD IOSW 	char			devname[MODMAXNAMELEN + 1] = "";
1955febcb4aSScott Carter, SD IOSW 
1965febcb4aSScott Carter, SD IOSW 	if (argc != 0)
1975febcb4aSScott Carter, SD IOSW 		return (DCMD_USAGE);
1985febcb4aSScott Carter, SD IOSW 
1995febcb4aSScott Carter, SD IOSW 	if (!(flags & DCMD_ADDRSPEC)) {
2005febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
2015febcb4aSScott Carter, SD IOSW 	}
2025febcb4aSScott Carter, SD IOSW 
2035febcb4aSScott Carter, SD IOSW 	if (DCMD_HDRSPEC(flags)) {
2045febcb4aSScott Carter, SD IOSW 		mdb_printf("%<u>%?s  %-18s  %-8s  %-8s  %-6s  %-4s  "
2055febcb4aSScott Carter, SD IOSW 		    "%-6s%</u>\n", "ADDR", "OWNER", "TYPE", "CALLBACK",
2065febcb4aSScott Carter, SD IOSW 		    "NINTRS", "NREQ", "NAVAIL");
2075febcb4aSScott Carter, SD IOSW 	}
2085febcb4aSScott Carter, SD IOSW 
2095febcb4aSScott Carter, SD IOSW 	if (mdb_vread(&req, sizeof (req), addr) != sizeof (req)) {
2105febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't read interrupt request at %p", addr);
2115febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
2125febcb4aSScott Carter, SD IOSW 	}
2135febcb4aSScott Carter, SD IOSW 
2145febcb4aSScott Carter, SD IOSW 	if (mdb_vread(&dev, sizeof (dev),
2155febcb4aSScott Carter, SD IOSW 	    (uintptr_t)req.ireq_dip) != sizeof (dev)) {
2165febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't read dev_info at %p", req.ireq_dip);
2175febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
2185febcb4aSScott Carter, SD IOSW 	}
2195febcb4aSScott Carter, SD IOSW 
2205febcb4aSScott Carter, SD IOSW 	if (mdb_vread(&intr, sizeof (intr),
2215febcb4aSScott Carter, SD IOSW 	    (uintptr_t)dev.devi_intr_p) != sizeof (intr)) {
2225febcb4aSScott Carter, SD IOSW 		mdb_warn("couldn't read devinfo_intr at %p", dev.devi_intr_p);
2235febcb4aSScott Carter, SD IOSW 		return (DCMD_ERR);
2245febcb4aSScott Carter, SD IOSW 	}
2255febcb4aSScott Carter, SD IOSW 
2265febcb4aSScott Carter, SD IOSW 	mdb_devinfo2driver((uintptr_t)req.ireq_dip, driver, sizeof (driver));
2275febcb4aSScott Carter, SD IOSW 	mdb_snprintf(devname, sizeof (devname), "%s#%d", driver,
2285febcb4aSScott Carter, SD IOSW 	    dev.devi_instance);
2295febcb4aSScott Carter, SD IOSW 
2305febcb4aSScott Carter, SD IOSW 	mdb_printf("%0?p  %-18s  %-8s  %-8s  %-6d  %-4d  %-6d\n",
2315febcb4aSScott Carter, SD IOSW 	    addr, devname, irm_get_type(req.ireq_type),
2325febcb4aSScott Carter, SD IOSW 	    (req.ireq_flags & DDI_IRM_FLAG_CALLBACK) ? "Yes" : "No",
2335febcb4aSScott Carter, SD IOSW 	    intr.devi_intr_sup_nintrs, req.ireq_nreq, req.ireq_navail);
2345febcb4aSScott Carter, SD IOSW 
2355febcb4aSScott Carter, SD IOSW 	return (DCMD_OK);
2365febcb4aSScott Carter, SD IOSW }
237