xref: /titanic_52/usr/src/cmd/mdb/sparc/modules/intr/intr.c (revision 500b1e787b108592a37e3d54dc9b5e676de5386d)
136fe4a92Segillett /*
236fe4a92Segillett  * CDDL HEADER START
336fe4a92Segillett  *
436fe4a92Segillett  * The contents of this file are subject to the terms of the
520036fe5Segillett  * Common Development and Distribution License (the "License").
620036fe5Segillett  * You may not use this file except in compliance with the License.
736fe4a92Segillett  *
836fe4a92Segillett  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
936fe4a92Segillett  * or http://www.opensolaris.org/os/licensing.
1036fe4a92Segillett  * See the License for the specific language governing permissions
1136fe4a92Segillett  * and limitations under the License.
1236fe4a92Segillett  *
1336fe4a92Segillett  * When distributing Covered Code, include this CDDL HEADER in each
1436fe4a92Segillett  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1536fe4a92Segillett  * If applicable, add the following below this CDDL HEADER, with the
1636fe4a92Segillett  * fields enclosed by brackets "[]" replaced with your own identifying
1736fe4a92Segillett  * information: Portions Copyright [yyyy] [name of copyright owner]
1836fe4a92Segillett  *
1936fe4a92Segillett  * CDDL HEADER END
2036fe4a92Segillett  */
2136fe4a92Segillett /*
22*500b1e78SAlan Adamson, SD OSSD  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2336fe4a92Segillett  * Use is subject to license terms.
2436fe4a92Segillett  */
2536fe4a92Segillett 
2636fe4a92Segillett #include <sys/mdb_modapi.h>
2736fe4a92Segillett #include <mdb/mdb_ks.h>
2836fe4a92Segillett #include <sys/async.h>		/* ecc_flt for pci_ecc.h */
2936fe4a92Segillett #include <sys/ddi_subrdefs.h>
3036fe4a92Segillett #include <sys/pci/pci_obj.h>
31*500b1e78SAlan Adamson, SD OSSD #include "niumx_var.h"
3236fe4a92Segillett #include "px_obj.h"
3336fe4a92Segillett 
3436fe4a92Segillett static int intr_pci_walk_step(mdb_walk_state_t *);
3536fe4a92Segillett static int intr_px_walk_step(mdb_walk_state_t *);
36*500b1e78SAlan Adamson, SD OSSD static int intr_niumx_walk_step(mdb_walk_state_t *);
3736fe4a92Segillett static void intr_pci_print_items(mdb_walk_state_t *);
3836fe4a92Segillett static void intr_px_print_items(mdb_walk_state_t *);
3920036fe5Segillett static char *intr_get_intr_type(uint16_t type);
4036fe4a92Segillett static void intr_print_banner(void);
4136fe4a92Segillett 
4236fe4a92Segillett typedef struct intr_info {
4336fe4a92Segillett 	uint32_t	cpuid;
4436fe4a92Segillett 	uint32_t	inum;
4536fe4a92Segillett 	uint32_t	num;
4636fe4a92Segillett 	uint32_t	pil;
4720036fe5Segillett 	uint16_t	intr_type;
4836fe4a92Segillett 	uint16_t	mondo;
4936fe4a92Segillett 	uint8_t		ino_ino;
5036fe4a92Segillett 	uint_t		intr_state;
5136fe4a92Segillett 	int		instance;
5236fe4a92Segillett 	int		shared;
5336fe4a92Segillett 	char		driver_name[12];
5436fe4a92Segillett 	char		pathname[MAXNAMELEN];
5536fe4a92Segillett }
5636fe4a92Segillett intr_info_t;
5736fe4a92Segillett 
582419d3ccSegillett #define	PX_MAX_ENTRIES		32
592419d3ccSegillett 
6036fe4a92Segillett static void intr_print_elements(intr_info_t);
6136fe4a92Segillett static int detailed = 0; /* Print detailed view */
6236fe4a92Segillett 
6336fe4a92Segillett 
6436fe4a92Segillett static int
6536fe4a92Segillett intr_walk_init(mdb_walk_state_t *wsp)
6636fe4a92Segillett {
6736fe4a92Segillett 	wsp->walk_addr = NULL;
6836fe4a92Segillett 
6936fe4a92Segillett 	return (WALK_NEXT);
7036fe4a92Segillett }
7136fe4a92Segillett 
7236fe4a92Segillett static int
7336fe4a92Segillett intr_walk_step(mdb_walk_state_t *wsp)
7436fe4a92Segillett {
7536fe4a92Segillett 	pci_t		*pci_per_p;
7636fe4a92Segillett 	px_t		*px_state_p;
77*500b1e78SAlan Adamson, SD OSSD 	niumx_devstate_t *niumx_state_p;
7836fe4a92Segillett 
7936fe4a92Segillett 	/* read globally declared structures in the pci driver */
8036fe4a92Segillett 	if (mdb_readvar(&pci_per_p, "per_pci_state") != -1) {
8136fe4a92Segillett 		wsp->walk_addr = (uintptr_t)pci_per_p;
8236fe4a92Segillett 		intr_pci_walk_step(wsp);
8336fe4a92Segillett 	}
8436fe4a92Segillett 
8536fe4a92Segillett 	/* read globally declared structures in the px driver */
8636fe4a92Segillett 	if (mdb_readvar(&px_state_p, "px_state_p") != -1) {
8736fe4a92Segillett 		wsp->walk_addr = (uintptr_t)px_state_p;
8836fe4a92Segillett 		intr_px_walk_step(wsp);
8936fe4a92Segillett 	}
9036fe4a92Segillett 
91*500b1e78SAlan Adamson, SD OSSD 	/* read globally declared structures in the niumx driver */
92*500b1e78SAlan Adamson, SD OSSD 	if (mdb_readvar(&niumx_state_p, "niumx_state") != -1) {
93*500b1e78SAlan Adamson, SD OSSD 		wsp->walk_addr = (uintptr_t)niumx_state_p;
94*500b1e78SAlan Adamson, SD OSSD 		intr_niumx_walk_step(wsp);
95*500b1e78SAlan Adamson, SD OSSD 	}
96*500b1e78SAlan Adamson, SD OSSD 
9736fe4a92Segillett 	return (WALK_DONE);
9836fe4a92Segillett }
9936fe4a92Segillett 
10036fe4a92Segillett static int
10136fe4a92Segillett intr_pci_walk_step(mdb_walk_state_t *wsp)
10236fe4a92Segillett {
10336fe4a92Segillett 	pci_t		*pci_per_p;
10436fe4a92Segillett 	pci_t		pci_per;
10536fe4a92Segillett 	uintptr_t	start_addr;
10636fe4a92Segillett 
10736fe4a92Segillett 	/* Read start of state structure array */
10836fe4a92Segillett 	if (mdb_vread(&pci_per_p, sizeof (uintptr_t),
10936fe4a92Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
11036fe4a92Segillett 		mdb_warn("intr: failed to read the initial pci_per_p "
11136fe4a92Segillett 		    "structure\n");
11236fe4a92Segillett 		return (WALK_ERR);
11336fe4a92Segillett 	}
11436fe4a92Segillett 
11536fe4a92Segillett 	/* Figure out how many items are here */
11636fe4a92Segillett 	start_addr = (uintptr_t)pci_per_p;
11736fe4a92Segillett 
1189c75c6bfSgovinda 	intr_print_banner();
1199c75c6bfSgovinda 
12036fe4a92Segillett 	while (mdb_vread(&pci_per_p, sizeof (uintptr_t),
12136fe4a92Segillett 	    (uintptr_t)start_addr) != -1) {
12236fe4a92Segillett 		/* Read until nothing is left */
12336fe4a92Segillett 		if (mdb_vread(&pci_per, sizeof (pci_t),
12436fe4a92Segillett 		    (uintptr_t)pci_per_p) == -1) {
12536fe4a92Segillett 			return (WALK_DONE);
12636fe4a92Segillett 		}
12736fe4a92Segillett 
12836fe4a92Segillett 		wsp->walk_addr = (uintptr_t)pci_per.pci_ib_p;
12936fe4a92Segillett 		intr_pci_print_items(wsp);
13036fe4a92Segillett 
13136fe4a92Segillett 		start_addr += sizeof (uintptr_t);
13236fe4a92Segillett 	}
13336fe4a92Segillett 
13436fe4a92Segillett 	return (WALK_DONE);
13536fe4a92Segillett }
13636fe4a92Segillett 
13736fe4a92Segillett static int
13836fe4a92Segillett intr_px_walk_step(mdb_walk_state_t *wsp)
13936fe4a92Segillett {
14036fe4a92Segillett 	px_t		*px_state_p;
14136fe4a92Segillett 	px_t		px_state;
14236fe4a92Segillett 	uintptr_t	start_addr;
1432419d3ccSegillett 	int		x;
14436fe4a92Segillett 
14536fe4a92Segillett 	/* Read start of state structure array */
14636fe4a92Segillett 	if (mdb_vread(&px_state_p, sizeof (uintptr_t),
14736fe4a92Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
14836fe4a92Segillett 		mdb_warn("intr: failed to read the initial px_per_p "
14936fe4a92Segillett 		    "structure\n");
15036fe4a92Segillett 		return (WALK_ERR);
15136fe4a92Segillett 	}
15236fe4a92Segillett 
15336fe4a92Segillett 	/* Figure out how many items are here */
15436fe4a92Segillett 	start_addr = (uintptr_t)px_state_p;
15536fe4a92Segillett 
1569c75c6bfSgovinda 	intr_print_banner();
1579c75c6bfSgovinda 
1582419d3ccSegillett 	for (x = 0; x < PX_MAX_ENTRIES; x++) {
1592419d3ccSegillett 		(void) mdb_vread(&px_state_p, sizeof (uintptr_t),
1602419d3ccSegillett 		    (uintptr_t)start_addr);
1612419d3ccSegillett 
1622419d3ccSegillett 		start_addr += sizeof (uintptr_t);
1632419d3ccSegillett 
1642419d3ccSegillett 		/* Read if anything is there */
16536fe4a92Segillett 		if (mdb_vread(&px_state, sizeof (px_t),
16636fe4a92Segillett 		    (uintptr_t)px_state_p) == -1) {
1672419d3ccSegillett 			continue;
16836fe4a92Segillett 		}
16936fe4a92Segillett 
17036fe4a92Segillett 		wsp->walk_addr = (uintptr_t)px_state.px_ib_p;
17136fe4a92Segillett 		intr_px_print_items(wsp);
17236fe4a92Segillett 	}
17336fe4a92Segillett 
17436fe4a92Segillett 	return (WALK_DONE);
17536fe4a92Segillett }
17636fe4a92Segillett 
177*500b1e78SAlan Adamson, SD OSSD static int
178*500b1e78SAlan Adamson, SD OSSD intr_niumx_walk_step(mdb_walk_state_t *wsp)
179*500b1e78SAlan Adamson, SD OSSD {
180*500b1e78SAlan Adamson, SD OSSD 	niumx_devstate_t *niumx_state_p;
181*500b1e78SAlan Adamson, SD OSSD 	niumx_devstate_t niumx_state;
182*500b1e78SAlan Adamson, SD OSSD 	uintptr_t	start_addr;
183*500b1e78SAlan Adamson, SD OSSD 	char		name[MODMAXNAMELEN + 1];
184*500b1e78SAlan Adamson, SD OSSD 	struct dev_info	dev;
185*500b1e78SAlan Adamson, SD OSSD 	intr_info_t	info;
186*500b1e78SAlan Adamson, SD OSSD 	int		i;
187*500b1e78SAlan Adamson, SD OSSD 
188*500b1e78SAlan Adamson, SD OSSD 	/* Read start of state structure array */
189*500b1e78SAlan Adamson, SD OSSD 	if (mdb_vread(&niumx_state_p, sizeof (uintptr_t),
190*500b1e78SAlan Adamson, SD OSSD 	    (uintptr_t)wsp->walk_addr) == -1) {
191*500b1e78SAlan Adamson, SD OSSD 		mdb_warn("intr: failed to read the initial niumx_state_p "
192*500b1e78SAlan Adamson, SD OSSD 		    "structure\n");
193*500b1e78SAlan Adamson, SD OSSD 		return (WALK_ERR);
194*500b1e78SAlan Adamson, SD OSSD 	}
195*500b1e78SAlan Adamson, SD OSSD 
196*500b1e78SAlan Adamson, SD OSSD 	/* Figure out how many items are here */
197*500b1e78SAlan Adamson, SD OSSD 	start_addr = (uintptr_t)niumx_state_p;
198*500b1e78SAlan Adamson, SD OSSD 
199*500b1e78SAlan Adamson, SD OSSD 	while (mdb_vread(&niumx_state_p, sizeof (uintptr_t),
200*500b1e78SAlan Adamson, SD OSSD 	    (uintptr_t)start_addr) >= 0) {
201*500b1e78SAlan Adamson, SD OSSD 
202*500b1e78SAlan Adamson, SD OSSD 		start_addr += sizeof (uintptr_t);
203*500b1e78SAlan Adamson, SD OSSD 
204*500b1e78SAlan Adamson, SD OSSD 		/* Read if anything is there */
205*500b1e78SAlan Adamson, SD OSSD 		if (mdb_vread(&niumx_state, sizeof (niumx_devstate_t),
206*500b1e78SAlan Adamson, SD OSSD 		    (uintptr_t)niumx_state_p) == -1) {
207*500b1e78SAlan Adamson, SD OSSD 			return (WALK_DONE);
208*500b1e78SAlan Adamson, SD OSSD 		}
209*500b1e78SAlan Adamson, SD OSSD 
210*500b1e78SAlan Adamson, SD OSSD 		for (i = 0; i < NIUMX_MAX_INTRS; i++) {
211*500b1e78SAlan Adamson, SD OSSD 			if (niumx_state.niumx_ihtable[i].ih_sysino == 0)
212*500b1e78SAlan Adamson, SD OSSD 				continue;
213*500b1e78SAlan Adamson, SD OSSD 
214*500b1e78SAlan Adamson, SD OSSD 			if (niumx_state.niumx_ihtable[i].ih_dip == 0)
215*500b1e78SAlan Adamson, SD OSSD 				continue;
216*500b1e78SAlan Adamson, SD OSSD 
217*500b1e78SAlan Adamson, SD OSSD 			bzero((void *)&info, sizeof (intr_info_t));
218*500b1e78SAlan Adamson, SD OSSD 
219*500b1e78SAlan Adamson, SD OSSD 			info.shared = 0;
220*500b1e78SAlan Adamson, SD OSSD 
221*500b1e78SAlan Adamson, SD OSSD 			(void) mdb_devinfo2driver(
222*500b1e78SAlan Adamson, SD OSSD 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip,
223*500b1e78SAlan Adamson, SD OSSD 			    name, sizeof (name));
224*500b1e78SAlan Adamson, SD OSSD 
225*500b1e78SAlan Adamson, SD OSSD 			(void) mdb_ddi_pathname(
226*500b1e78SAlan Adamson, SD OSSD 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip,
227*500b1e78SAlan Adamson, SD OSSD 			    info.pathname, sizeof (info.pathname));
228*500b1e78SAlan Adamson, SD OSSD 
229*500b1e78SAlan Adamson, SD OSSD 			/* Get instance */
230*500b1e78SAlan Adamson, SD OSSD 			if (mdb_vread(&dev, sizeof (struct dev_info),
231*500b1e78SAlan Adamson, SD OSSD 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip) ==
232*500b1e78SAlan Adamson, SD OSSD 			    -1) {
233*500b1e78SAlan Adamson, SD OSSD 				mdb_warn("intr: failed to read DIP "
234*500b1e78SAlan Adamson, SD OSSD 				    "structure\n");
235*500b1e78SAlan Adamson, SD OSSD 
236*500b1e78SAlan Adamson, SD OSSD 				return (WALK_DONE);
237*500b1e78SAlan Adamson, SD OSSD 			}
238*500b1e78SAlan Adamson, SD OSSD 
239*500b1e78SAlan Adamson, SD OSSD 			/* Make sure the name doesn't over run */
240*500b1e78SAlan Adamson, SD OSSD 			(void) mdb_snprintf(info.driver_name,
241*500b1e78SAlan Adamson, SD OSSD 			    sizeof (info.driver_name), "%s", name);
242*500b1e78SAlan Adamson, SD OSSD 
243*500b1e78SAlan Adamson, SD OSSD 			info.instance = dev.devi_instance;
244*500b1e78SAlan Adamson, SD OSSD 			info.inum = niumx_state.niumx_ihtable[i].ih_inum;
245*500b1e78SAlan Adamson, SD OSSD 			info.intr_type = DDI_INTR_TYPE_FIXED;
246*500b1e78SAlan Adamson, SD OSSD 			info.num = 0;
247*500b1e78SAlan Adamson, SD OSSD 			info.intr_state = niumx_state.niumx_ihtable[i].ih_state;
248*500b1e78SAlan Adamson, SD OSSD 			info.ino_ino = i;
249*500b1e78SAlan Adamson, SD OSSD 			info.mondo = niumx_state.niumx_ihtable[i].ih_sysino;
250*500b1e78SAlan Adamson, SD OSSD 			info.pil = niumx_state.niumx_ihtable[i].ih_pri;
251*500b1e78SAlan Adamson, SD OSSD 			info.cpuid = niumx_state.niumx_ihtable[i].ih_cpuid;
252*500b1e78SAlan Adamson, SD OSSD 
253*500b1e78SAlan Adamson, SD OSSD 			intr_print_elements(info);
254*500b1e78SAlan Adamson, SD OSSD 		}
255*500b1e78SAlan Adamson, SD OSSD 	}
256*500b1e78SAlan Adamson, SD OSSD 
257*500b1e78SAlan Adamson, SD OSSD 	return (WALK_DONE);
258*500b1e78SAlan Adamson, SD OSSD }
259*500b1e78SAlan Adamson, SD OSSD 
26036fe4a92Segillett static void
26136fe4a92Segillett intr_pci_print_items(mdb_walk_state_t *wsp)
26236fe4a92Segillett {
263b0fc0e77Sgovinda 	ib_t			ib;
264b0fc0e77Sgovinda 	ib_ino_info_t		ino;
265b0fc0e77Sgovinda 	ib_ino_pil_t		ipil;
26636fe4a92Segillett 	ih_t			ih;
26736fe4a92Segillett 	int			count;
26836fe4a92Segillett 	char			name[MODMAXNAMELEN + 1];
269b0fc0e77Sgovinda 	struct dev_info		dev;
27036fe4a92Segillett 	intr_info_t		info;
27136fe4a92Segillett 
272b0fc0e77Sgovinda 	if (mdb_vread(&ib, sizeof (ib_t),
27336fe4a92Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
27436fe4a92Segillett 		mdb_warn("intr: failed to read pci interrupt block "
27536fe4a92Segillett 		    "structure\n");
27636fe4a92Segillett 		return;
27736fe4a92Segillett 	}
27836fe4a92Segillett 
27936fe4a92Segillett 	/* Read in ib_ino_info_t structure at address */
280b0fc0e77Sgovinda 	if (mdb_vread(&ino, sizeof (ib_ino_info_t),
281b0fc0e77Sgovinda 	    (uintptr_t)ib.ib_ino_lst) == -1) {
28236fe4a92Segillett 		/* Nothing here to read from */
28336fe4a92Segillett 		return;
28436fe4a92Segillett 	}
28536fe4a92Segillett 
28636fe4a92Segillett 	do {
287b0fc0e77Sgovinda 		if (mdb_vread(&ipil, sizeof (ib_ino_pil_t),
288b0fc0e77Sgovinda 		    (uintptr_t)ino.ino_ipil_p) == -1) {
289b0fc0e77Sgovinda 			mdb_warn("intr: failed to read pci interrupt "
290b0fc0e77Sgovinda 			    "ib_ino_pil_t structure\n");
291b0fc0e77Sgovinda 			return;
292b0fc0e77Sgovinda 		}
293b0fc0e77Sgovinda 
294b0fc0e77Sgovinda 		do {
29536fe4a92Segillett 			if (mdb_vread(&ih, sizeof (ih_t),
296b0fc0e77Sgovinda 			    (uintptr_t)ipil.ipil_ih_start) == -1) {
297b0fc0e77Sgovinda 				mdb_warn("intr: failed to read pci interrupt "
298b0fc0e77Sgovinda 				    "ih_t structure\n");
29936fe4a92Segillett 				return;
30036fe4a92Segillett 			}
30136fe4a92Segillett 
30236fe4a92Segillett 			count = 0;
30336fe4a92Segillett 
30436fe4a92Segillett 			do {
30536fe4a92Segillett 				bzero((void *)&info, sizeof (intr_info_t));
30636fe4a92Segillett 
307b0fc0e77Sgovinda 				if ((ino.ino_ipil_size > 1) ||
308b0fc0e77Sgovinda 				    (ipil.ipil_ih_size > 1)) {
30936fe4a92Segillett 					info.shared = 1;
31036fe4a92Segillett 				}
31136fe4a92Segillett 
31236fe4a92Segillett 				(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
31336fe4a92Segillett 				    name, sizeof (name));
31436fe4a92Segillett 
31536fe4a92Segillett 				(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
31636fe4a92Segillett 				    info.pathname, sizeof (info.pathname));
31736fe4a92Segillett 
31836fe4a92Segillett 				/* Get instance */
319b0fc0e77Sgovinda 				if (mdb_vread(&dev, sizeof (struct dev_info),
32036fe4a92Segillett 				    (uintptr_t)ih.ih_dip) == -1) {
32136fe4a92Segillett 					mdb_warn("intr: failed to read DIP "
32236fe4a92Segillett 					    "structure\n");
32336fe4a92Segillett 					return;
32436fe4a92Segillett 				}
32536fe4a92Segillett 
32636fe4a92Segillett 				/* Make sure the name doesn't over run */
32736fe4a92Segillett 				(void) mdb_snprintf(info.driver_name,
32836fe4a92Segillett 				    sizeof (info.driver_name), "%s", name);
32936fe4a92Segillett 
330b0fc0e77Sgovinda 				info.instance = dev.devi_instance;
33136fe4a92Segillett 				info.inum = ih.ih_inum;
33220036fe5Segillett 				info.intr_type = DDI_INTR_TYPE_FIXED;
33336fe4a92Segillett 				info.num = 0;
33436fe4a92Segillett 				info.intr_state = ih.ih_intr_state;
335b0fc0e77Sgovinda 				info.ino_ino = ino.ino_ino;
336b0fc0e77Sgovinda 				info.mondo = ino.ino_mondo;
337b0fc0e77Sgovinda 				info.pil = ipil.ipil_pil;
338b0fc0e77Sgovinda 				info.cpuid = ino.ino_cpuid;
33936fe4a92Segillett 
34036fe4a92Segillett 				intr_print_elements(info);
34136fe4a92Segillett 				count++;
34236fe4a92Segillett 
34336fe4a92Segillett 				(void) mdb_vread(&ih, sizeof (ih_t),
34436fe4a92Segillett 				    (uintptr_t)ih.ih_next);
34536fe4a92Segillett 
346b0fc0e77Sgovinda 			} while (count < ipil.ipil_ih_size);
34736fe4a92Segillett 
348b0fc0e77Sgovinda 		} while (mdb_vread(&ipil, sizeof (ib_ino_pil_t),
349b0fc0e77Sgovinda 		    (uintptr_t)ipil.ipil_next_p) != -1);
350b0fc0e77Sgovinda 
351b0fc0e77Sgovinda 	} while (mdb_vread(&ino, sizeof (ib_ino_info_t),
352b0fc0e77Sgovinda 	    (uintptr_t)ino.ino_next_p) != -1);
35336fe4a92Segillett }
35436fe4a92Segillett 
35536fe4a92Segillett static void
35636fe4a92Segillett intr_px_print_items(mdb_walk_state_t *wsp)
35736fe4a92Segillett {
358b0fc0e77Sgovinda 	px_ib_t		ib;
359b0fc0e77Sgovinda 	px_ino_t	ino;
360b0fc0e77Sgovinda 	px_ino_pil_t	ipil;
361b0fc0e77Sgovinda 	px_ih_t		ih;
36236fe4a92Segillett 	int		count;
36336fe4a92Segillett 	char		name[MODMAXNAMELEN + 1];
364b0fc0e77Sgovinda 	struct dev_info	dev;
36536fe4a92Segillett 	intr_info_t	info;
36620036fe5Segillett 	devinfo_intr_t	intr_p;
36736fe4a92Segillett 
368b0fc0e77Sgovinda 	if (mdb_vread(&ib, sizeof (px_ib_t), wsp->walk_addr) == -1) {
36936fe4a92Segillett 		return;
37036fe4a92Segillett 	}
37136fe4a92Segillett 
372b0fc0e77Sgovinda 	/* Read in px_ino_t structure at address */
373b0fc0e77Sgovinda 	if (mdb_vread(&ino, sizeof (px_ino_t),
374b0fc0e77Sgovinda 	    (uintptr_t)ib.ib_ino_lst) == -1) {
37536fe4a92Segillett 		/* Nothing here to read from */
37636fe4a92Segillett 		return;
37736fe4a92Segillett 	}
37836fe4a92Segillett 
3792419d3ccSegillett 	do { /* ino_next_p loop */
380b0fc0e77Sgovinda 		if (mdb_vread(&ipil, sizeof (px_ino_pil_t),
381b0fc0e77Sgovinda 		    (uintptr_t)ino.ino_ipil_p) == -1) {
38209b1eac2SEvan Yan 			continue;
383b0fc0e77Sgovinda 		}
384b0fc0e77Sgovinda 
3852419d3ccSegillett 		do { /* ipil_next_p loop */
386b0fc0e77Sgovinda 			if (mdb_vread(&ih, sizeof (px_ih_t),
387b0fc0e77Sgovinda 			    (uintptr_t)ipil.ipil_ih_start) == -1) {
38809b1eac2SEvan Yan 				continue;
38936fe4a92Segillett 			}
39036fe4a92Segillett 
39136fe4a92Segillett 			count = 0;
39236fe4a92Segillett 
3932419d3ccSegillett 			do { /* ipil_ih_size loop */
39436fe4a92Segillett 				bzero((void *)&info, sizeof (intr_info_t));
39536fe4a92Segillett 
396b0fc0e77Sgovinda 				(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
39736fe4a92Segillett 				    name, sizeof (name));
39836fe4a92Segillett 
399b0fc0e77Sgovinda 				(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
40036fe4a92Segillett 				    info.pathname, sizeof (info.pathname));
40136fe4a92Segillett 
40236fe4a92Segillett 				/* Get instance */
403b0fc0e77Sgovinda 				if (mdb_vread(&dev, sizeof (struct dev_info),
404b0fc0e77Sgovinda 				    (uintptr_t)ih.ih_dip) == -1) {
40536fe4a92Segillett 					mdb_warn("intr: failed to read DIP "
40636fe4a92Segillett 					    "structure\n");
40736fe4a92Segillett 					return;
40836fe4a92Segillett 				}
40936fe4a92Segillett 
41036fe4a92Segillett 				/* Make sure the name doesn't over run */
41136fe4a92Segillett 				(void) mdb_snprintf(info.driver_name,
41236fe4a92Segillett 				    sizeof (info.driver_name), "%s", name);
41336fe4a92Segillett 
414b0fc0e77Sgovinda 				info.instance = dev.devi_instance;
415b0fc0e77Sgovinda 				info.inum = ih.ih_inum;
41620036fe5Segillett 
417b0fc0e77Sgovinda 				/*
418b0fc0e77Sgovinda 				 * Read the type used, keep PCIe messages
419b0fc0e77Sgovinda 				 * separate.
420b0fc0e77Sgovinda 				 */
421b0fc0e77Sgovinda 				(void) mdb_vread(&intr_p,
422b0fc0e77Sgovinda 				    sizeof (devinfo_intr_t),
423b0fc0e77Sgovinda 				    (uintptr_t)dev.devi_intr_p);
424b0fc0e77Sgovinda 
425b0fc0e77Sgovinda 				if (ih.ih_rec_type != MSG_REC) {
426b0fc0e77Sgovinda 					info.intr_type =
427b0fc0e77Sgovinda 					    intr_p.devi_intr_curr_type;
42820036fe5Segillett 				}
42920036fe5Segillett 
43022edf370SDaniel Ice 				if ((ino.ino_ipil_size > 1) ||
43122edf370SDaniel Ice 				    (ipil.ipil_ih_size > 1)) {
432b0fc0e77Sgovinda 					info.shared = 1;
433b0fc0e77Sgovinda 				}
434b0fc0e77Sgovinda 
435b0fc0e77Sgovinda 				info.num = ih.ih_msg_code;
436b0fc0e77Sgovinda 				info.intr_state = ih.ih_intr_state;
437b0fc0e77Sgovinda 				info.ino_ino = ino.ino_ino;
438b0fc0e77Sgovinda 				info.mondo = ino.ino_sysino;
439b0fc0e77Sgovinda 				info.pil = ipil.ipil_pil;
440b0fc0e77Sgovinda 				info.cpuid = ino.ino_cpuid;
44136fe4a92Segillett 
44236fe4a92Segillett 				intr_print_elements(info);
44336fe4a92Segillett 				count++;
44436fe4a92Segillett 
445b0fc0e77Sgovinda 				(void) mdb_vread(&ih, sizeof (px_ih_t),
446b0fc0e77Sgovinda 				    (uintptr_t)ih.ih_next);
44736fe4a92Segillett 
448b0fc0e77Sgovinda 			} while (count < ipil.ipil_ih_size);
44936fe4a92Segillett 
45009b1eac2SEvan Yan 		} while ((ipil.ipil_next_p != NULL) &&
45109b1eac2SEvan Yan 		    (mdb_vread(&ipil, sizeof (px_ino_pil_t),
45209b1eac2SEvan Yan 		    (uintptr_t)ipil.ipil_next_p) != -1));
453b0fc0e77Sgovinda 
45409b1eac2SEvan Yan 	} while ((ino.ino_next_p != NULL) && (mdb_vread(&ino, sizeof (px_ino_t),
45509b1eac2SEvan Yan 	    (uintptr_t)ino.ino_next_p) != -1));
45636fe4a92Segillett }
45736fe4a92Segillett 
45836fe4a92Segillett static char *
45920036fe5Segillett intr_get_intr_type(uint16_t type)
46036fe4a92Segillett {
46120036fe5Segillett 	switch (type) {
46220036fe5Segillett 		case	DDI_INTR_TYPE_FIXED:
46336fe4a92Segillett 			return ("Fixed");
46420036fe5Segillett 		case	DDI_INTR_TYPE_MSI:
46520036fe5Segillett 			return ("MSI");
46620036fe5Segillett 		case	DDI_INTR_TYPE_MSIX:
46720036fe5Segillett 			return ("MSI-X");
46820036fe5Segillett 		default:
46920036fe5Segillett 			return ("PCIe");
47036fe4a92Segillett 	}
47136fe4a92Segillett }
47236fe4a92Segillett 
47336fe4a92Segillett static void
47436fe4a92Segillett intr_print_banner(void)
47536fe4a92Segillett {
47636fe4a92Segillett 	if (!detailed) {
4779c75c6bfSgovinda 		mdb_printf("\n%<u>\tDevice\t"
4789c75c6bfSgovinda 		    " Type\t"
4799c75c6bfSgovinda 		    " MSG #\t"
4809c75c6bfSgovinda 		    " State\t"
4819c75c6bfSgovinda 		    " INO\t"
4829c75c6bfSgovinda 		    " Mondo\t"
48322edf370SDaniel Ice 		    " Shared\t"
4849c75c6bfSgovinda 		    "  Pil\t"
4859c75c6bfSgovinda 		    " CPU   %</u>"
4869c75c6bfSgovinda 		    "\n");
48736fe4a92Segillett 	}
48836fe4a92Segillett }
48936fe4a92Segillett 
49036fe4a92Segillett static void
49136fe4a92Segillett intr_print_elements(intr_info_t info)
49236fe4a92Segillett {
49336fe4a92Segillett 	if (!detailed) {
4949c75c6bfSgovinda 		mdb_printf(" %11s#%d\t", info.driver_name, info.instance);
4959c75c6bfSgovinda 		mdb_printf(" %s\t", intr_get_intr_type(info.intr_type));
49620036fe5Segillett 		if (info.intr_type == DDI_INTR_TYPE_FIXED) {
4979c75c6bfSgovinda 			mdb_printf("  --- \t");
49836fe4a92Segillett 		} else {
4999c75c6bfSgovinda 			mdb_printf(" %4d\t", info.num);
50036fe4a92Segillett 		}
5019c75c6bfSgovinda 		mdb_printf(" %2s\t",
50236fe4a92Segillett 		    info.intr_state ? "enbl" : "disbl");
5039c75c6bfSgovinda 		mdb_printf(" 0x%x\t", info.ino_ino);
5049c75c6bfSgovinda 		mdb_printf(" 0x%x\t", info.mondo);
50522edf370SDaniel Ice 		mdb_printf(" %5s\t",
50622edf370SDaniel Ice 		    info.shared ? "yes" : "no");
5079c75c6bfSgovinda 		mdb_printf(" %4d\t", info.pil);
5089c75c6bfSgovinda 		mdb_printf(" %3d \n", info.cpuid);
50936fe4a92Segillett 	} else {
51036fe4a92Segillett 		mdb_printf("\n-------------------------------------------\n");
51136fe4a92Segillett 		mdb_printf("Device:\t\t%s\n", info.driver_name);
51236fe4a92Segillett 		mdb_printf("Instance:\t%d\n", info.instance);
51336fe4a92Segillett 		mdb_printf("Path:\t\t%s\n", info.pathname);
51436fe4a92Segillett 		mdb_printf("Inum:\t\t%d\n", info.inum);
51536fe4a92Segillett 		mdb_printf("Interrupt Type:\t%s\n",
51636fe4a92Segillett 		    intr_get_intr_type(info.intr_type));
51720036fe5Segillett 		if (info.intr_type == DDI_INTR_TYPE_MSI) {
51820036fe5Segillett 			mdb_printf("MSI Number:\t%d\n", info.num);
51920036fe5Segillett 		} else if (info.intr_type == DDI_INTR_TYPE_MSIX) {
52020036fe5Segillett 			mdb_printf("MSI-X Number:\t%d\n", info.num);
52120036fe5Segillett 		} else if (!info.intr_type) {
52220036fe5Segillett 			mdb_printf("PCIe Message #:\t%d\n", info.num);
52320036fe5Segillett 		}
52436fe4a92Segillett 
52536fe4a92Segillett 		mdb_printf("Shared Intr:\t%s\n",
52636fe4a92Segillett 		    info.shared ? "yes" : "no");
52736fe4a92Segillett 		mdb_printf("State:\t\t%d (%s)\n", info.intr_state,
52836fe4a92Segillett 		    info.intr_state ? "Enabled" : "Disabled");
52936fe4a92Segillett 		mdb_printf("INO:\t\t0x%x\n", info.ino_ino);
53036fe4a92Segillett 		mdb_printf("Mondo:\t\t0x%x\n", info.mondo);
53136fe4a92Segillett 		mdb_printf("Pil:\t\t%d\n", info.pil);
53236fe4a92Segillett 		mdb_printf("CPU:\t\t%d\n", info.cpuid);
53336fe4a92Segillett 	}
53436fe4a92Segillett }
53536fe4a92Segillett 
53636fe4a92Segillett /*ARGSUSED*/
53736fe4a92Segillett static void
53836fe4a92Segillett intr_walk_fini(mdb_walk_state_t *wsp)
53936fe4a92Segillett {
54036fe4a92Segillett 	/* Nothing to do here */
54136fe4a92Segillett }
54236fe4a92Segillett 
54336fe4a92Segillett /*ARGSUSED*/
54436fe4a92Segillett static int
54536fe4a92Segillett intr_intr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
54636fe4a92Segillett {
54736fe4a92Segillett 	detailed = 0;
54836fe4a92Segillett 
54936fe4a92Segillett 	if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &detailed,
55036fe4a92Segillett 	    NULL) != argc)
55136fe4a92Segillett 		return (DCMD_USAGE);
55236fe4a92Segillett 
55336fe4a92Segillett 	if (!(flags & DCMD_ADDRSPEC)) {
55436fe4a92Segillett 		if (mdb_walk_dcmd("interrupts", "interrupts", argc, argv)
55536fe4a92Segillett 		    == -1) {
55636fe4a92Segillett 			mdb_warn("can't walk pci/px buffer entries\n");
55736fe4a92Segillett 			return (DCMD_ERR);
55836fe4a92Segillett 		}
55936fe4a92Segillett 		return (DCMD_OK);
56036fe4a92Segillett 	}
56136fe4a92Segillett 
56236fe4a92Segillett 	return (DCMD_OK);
56336fe4a92Segillett }
56436fe4a92Segillett 
56536fe4a92Segillett /*
56636fe4a92Segillett  * MDB module linkage information:
56736fe4a92Segillett  */
56836fe4a92Segillett 
56936fe4a92Segillett static const mdb_dcmd_t dcmds[] = {
57036fe4a92Segillett 	{ "interrupts", "[-d]", "display the interrupt info registered with "
57136fe4a92Segillett 	    "the PCI/PX nexus drivers", intr_intr },
57236fe4a92Segillett 	{ NULL }
57336fe4a92Segillett };
57436fe4a92Segillett 
57536fe4a92Segillett static const mdb_walker_t walkers[] = {
57636fe4a92Segillett 	{ "interrupts", "walk PCI/PX interrupt structures",
57736fe4a92Segillett 		intr_walk_init, intr_walk_step, intr_walk_fini },
57836fe4a92Segillett 	{ NULL }
57936fe4a92Segillett };
58036fe4a92Segillett 
58136fe4a92Segillett static const mdb_modinfo_t modinfo = {
58236fe4a92Segillett 	MDB_API_VERSION, dcmds, walkers
58336fe4a92Segillett };
58436fe4a92Segillett 
58536fe4a92Segillett const mdb_modinfo_t *
58636fe4a92Segillett _mdb_init(void)
58736fe4a92Segillett {
58836fe4a92Segillett 	return (&modinfo);
58936fe4a92Segillett }
590