xref: /onnv-gate/usr/src/cmd/mdb/sparc/modules/intr/intr.c (revision 11513:b68f438a1f7f)
1909Segillett /*
2909Segillett  * CDDL HEADER START
3909Segillett  *
4909Segillett  * The contents of this file are subject to the terms of the
51725Segillett  * Common Development and Distribution License (the "License").
61725Segillett  * You may not use this file except in compliance with the License.
7909Segillett  *
8909Segillett  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9909Segillett  * or http://www.opensolaris.org/os/licensing.
10909Segillett  * See the License for the specific language governing permissions
11909Segillett  * and limitations under the License.
12909Segillett  *
13909Segillett  * When distributing Covered Code, include this CDDL HEADER in each
14909Segillett  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15909Segillett  * If applicable, add the following below this CDDL HEADER, with the
16909Segillett  * fields enclosed by brackets "[]" replaced with your own identifying
17909Segillett  * information: Portions Copyright [yyyy] [name of copyright owner]
18909Segillett  *
19909Segillett  * CDDL HEADER END
20909Segillett  */
21909Segillett /*
22*11513SAlan.Adamson@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23909Segillett  * Use is subject to license terms.
24909Segillett  */
25909Segillett 
26909Segillett #include <sys/mdb_modapi.h>
27909Segillett #include <mdb/mdb_ks.h>
28909Segillett #include <sys/async.h>		/* ecc_flt for pci_ecc.h */
29909Segillett #include <sys/ddi_subrdefs.h>
30909Segillett #include <sys/pci/pci_obj.h>
31*11513SAlan.Adamson@Sun.COM #include "niumx_var.h"
32909Segillett #include "px_obj.h"
33909Segillett 
34909Segillett static int intr_pci_walk_step(mdb_walk_state_t *);
35909Segillett static int intr_px_walk_step(mdb_walk_state_t *);
36*11513SAlan.Adamson@Sun.COM static int intr_niumx_walk_step(mdb_walk_state_t *);
37909Segillett static void intr_pci_print_items(mdb_walk_state_t *);
38909Segillett static void intr_px_print_items(mdb_walk_state_t *);
391725Segillett static char *intr_get_intr_type(uint16_t type);
40909Segillett static void intr_print_banner(void);
41909Segillett 
42909Segillett typedef struct intr_info {
43909Segillett 	uint32_t	cpuid;
44909Segillett 	uint32_t	inum;
45909Segillett 	uint32_t	num;
46909Segillett 	uint32_t	pil;
471725Segillett 	uint16_t	intr_type;
48909Segillett 	uint16_t	mondo;
49909Segillett 	uint8_t		ino_ino;
50909Segillett 	uint_t		intr_state;
51909Segillett 	int		instance;
52909Segillett 	int		shared;
53909Segillett 	char		driver_name[12];
54909Segillett 	char		pathname[MAXNAMELEN];
55909Segillett }
56909Segillett intr_info_t;
57909Segillett 
583830Segillett #define	PX_MAX_ENTRIES		32
593830Segillett 
60909Segillett static void intr_print_elements(intr_info_t);
61909Segillett static int detailed = 0; /* Print detailed view */
62909Segillett 
63909Segillett 
64909Segillett static int
intr_walk_init(mdb_walk_state_t * wsp)65909Segillett intr_walk_init(mdb_walk_state_t *wsp)
66909Segillett {
67909Segillett 	wsp->walk_addr = NULL;
68909Segillett 
69909Segillett 	return (WALK_NEXT);
70909Segillett }
71909Segillett 
72909Segillett static int
intr_walk_step(mdb_walk_state_t * wsp)73909Segillett intr_walk_step(mdb_walk_state_t *wsp)
74909Segillett {
75909Segillett 	pci_t		*pci_per_p;
76909Segillett 	px_t		*px_state_p;
77*11513SAlan.Adamson@Sun.COM 	niumx_devstate_t *niumx_state_p;
78909Segillett 
79909Segillett 	/* read globally declared structures in the pci driver */
80909Segillett 	if (mdb_readvar(&pci_per_p, "per_pci_state") != -1) {
81909Segillett 		wsp->walk_addr = (uintptr_t)pci_per_p;
82909Segillett 		intr_pci_walk_step(wsp);
83909Segillett 	}
84909Segillett 
85909Segillett 	/* read globally declared structures in the px driver */
86909Segillett 	if (mdb_readvar(&px_state_p, "px_state_p") != -1) {
87909Segillett 		wsp->walk_addr = (uintptr_t)px_state_p;
88909Segillett 		intr_px_walk_step(wsp);
89909Segillett 	}
90909Segillett 
91*11513SAlan.Adamson@Sun.COM 	/* read globally declared structures in the niumx driver */
92*11513SAlan.Adamson@Sun.COM 	if (mdb_readvar(&niumx_state_p, "niumx_state") != -1) {
93*11513SAlan.Adamson@Sun.COM 		wsp->walk_addr = (uintptr_t)niumx_state_p;
94*11513SAlan.Adamson@Sun.COM 		intr_niumx_walk_step(wsp);
95*11513SAlan.Adamson@Sun.COM 	}
96*11513SAlan.Adamson@Sun.COM 
97909Segillett 	return (WALK_DONE);
98909Segillett }
99909Segillett 
100909Segillett static int
intr_pci_walk_step(mdb_walk_state_t * wsp)101909Segillett intr_pci_walk_step(mdb_walk_state_t *wsp)
102909Segillett {
103909Segillett 	pci_t		*pci_per_p;
104909Segillett 	pci_t		pci_per;
105909Segillett 	uintptr_t	start_addr;
106909Segillett 
107909Segillett 	/* Read start of state structure array */
108909Segillett 	if (mdb_vread(&pci_per_p, sizeof (uintptr_t),
109909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
110909Segillett 		mdb_warn("intr: failed to read the initial pci_per_p "
111909Segillett 		    "structure\n");
112909Segillett 		return (WALK_ERR);
113909Segillett 	}
114909Segillett 
115909Segillett 	/* Figure out how many items are here */
116909Segillett 	start_addr = (uintptr_t)pci_per_p;
117909Segillett 
118965Sgovinda 	intr_print_banner();
119965Sgovinda 
120909Segillett 	while (mdb_vread(&pci_per_p, sizeof (uintptr_t),
121909Segillett 	    (uintptr_t)start_addr) != -1) {
122909Segillett 		/* Read until nothing is left */
123909Segillett 		if (mdb_vread(&pci_per, sizeof (pci_t),
124909Segillett 		    (uintptr_t)pci_per_p) == -1) {
125909Segillett 			return (WALK_DONE);
126909Segillett 		}
127909Segillett 
128909Segillett 		wsp->walk_addr = (uintptr_t)pci_per.pci_ib_p;
129909Segillett 		intr_pci_print_items(wsp);
130909Segillett 
131909Segillett 		start_addr += sizeof (uintptr_t);
132909Segillett 	}
133909Segillett 
134909Segillett 	return (WALK_DONE);
135909Segillett }
136909Segillett 
137909Segillett static int
intr_px_walk_step(mdb_walk_state_t * wsp)138909Segillett intr_px_walk_step(mdb_walk_state_t *wsp)
139909Segillett {
140909Segillett 	px_t		*px_state_p;
141909Segillett 	px_t		px_state;
142909Segillett 	uintptr_t	start_addr;
1433830Segillett 	int		x;
144909Segillett 
145909Segillett 	/* Read start of state structure array */
146909Segillett 	if (mdb_vread(&px_state_p, sizeof (uintptr_t),
147909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
148909Segillett 		mdb_warn("intr: failed to read the initial px_per_p "
149909Segillett 		    "structure\n");
150909Segillett 		return (WALK_ERR);
151909Segillett 	}
152909Segillett 
153909Segillett 	/* Figure out how many items are here */
154909Segillett 	start_addr = (uintptr_t)px_state_p;
155909Segillett 
156965Sgovinda 	intr_print_banner();
157965Sgovinda 
1583830Segillett 	for (x = 0; x < PX_MAX_ENTRIES; x++) {
1593830Segillett 		(void) mdb_vread(&px_state_p, sizeof (uintptr_t),
1603830Segillett 		    (uintptr_t)start_addr);
1613830Segillett 
1623830Segillett 		start_addr += sizeof (uintptr_t);
1633830Segillett 
1643830Segillett 		/* Read if anything is there */
165909Segillett 		if (mdb_vread(&px_state, sizeof (px_t),
166909Segillett 		    (uintptr_t)px_state_p) == -1) {
1673830Segillett 			continue;
168909Segillett 		}
169909Segillett 
170909Segillett 		wsp->walk_addr = (uintptr_t)px_state.px_ib_p;
171909Segillett 		intr_px_print_items(wsp);
172909Segillett 	}
173909Segillett 
174909Segillett 	return (WALK_DONE);
175909Segillett }
176909Segillett 
177*11513SAlan.Adamson@Sun.COM static int
intr_niumx_walk_step(mdb_walk_state_t * wsp)178*11513SAlan.Adamson@Sun.COM intr_niumx_walk_step(mdb_walk_state_t *wsp)
179*11513SAlan.Adamson@Sun.COM {
180*11513SAlan.Adamson@Sun.COM 	niumx_devstate_t *niumx_state_p;
181*11513SAlan.Adamson@Sun.COM 	niumx_devstate_t niumx_state;
182*11513SAlan.Adamson@Sun.COM 	uintptr_t	start_addr;
183*11513SAlan.Adamson@Sun.COM 	char		name[MODMAXNAMELEN + 1];
184*11513SAlan.Adamson@Sun.COM 	struct dev_info	dev;
185*11513SAlan.Adamson@Sun.COM 	intr_info_t	info;
186*11513SAlan.Adamson@Sun.COM 	int		i;
187*11513SAlan.Adamson@Sun.COM 
188*11513SAlan.Adamson@Sun.COM 	/* Read start of state structure array */
189*11513SAlan.Adamson@Sun.COM 	if (mdb_vread(&niumx_state_p, sizeof (uintptr_t),
190*11513SAlan.Adamson@Sun.COM 	    (uintptr_t)wsp->walk_addr) == -1) {
191*11513SAlan.Adamson@Sun.COM 		mdb_warn("intr: failed to read the initial niumx_state_p "
192*11513SAlan.Adamson@Sun.COM 		    "structure\n");
193*11513SAlan.Adamson@Sun.COM 		return (WALK_ERR);
194*11513SAlan.Adamson@Sun.COM 	}
195*11513SAlan.Adamson@Sun.COM 
196*11513SAlan.Adamson@Sun.COM 	/* Figure out how many items are here */
197*11513SAlan.Adamson@Sun.COM 	start_addr = (uintptr_t)niumx_state_p;
198*11513SAlan.Adamson@Sun.COM 
199*11513SAlan.Adamson@Sun.COM 	while (mdb_vread(&niumx_state_p, sizeof (uintptr_t),
200*11513SAlan.Adamson@Sun.COM 	    (uintptr_t)start_addr) >= 0) {
201*11513SAlan.Adamson@Sun.COM 
202*11513SAlan.Adamson@Sun.COM 		start_addr += sizeof (uintptr_t);
203*11513SAlan.Adamson@Sun.COM 
204*11513SAlan.Adamson@Sun.COM 		/* Read if anything is there */
205*11513SAlan.Adamson@Sun.COM 		if (mdb_vread(&niumx_state, sizeof (niumx_devstate_t),
206*11513SAlan.Adamson@Sun.COM 		    (uintptr_t)niumx_state_p) == -1) {
207*11513SAlan.Adamson@Sun.COM 			return (WALK_DONE);
208*11513SAlan.Adamson@Sun.COM 		}
209*11513SAlan.Adamson@Sun.COM 
210*11513SAlan.Adamson@Sun.COM 		for (i = 0; i < NIUMX_MAX_INTRS; i++) {
211*11513SAlan.Adamson@Sun.COM 			if (niumx_state.niumx_ihtable[i].ih_sysino == 0)
212*11513SAlan.Adamson@Sun.COM 				continue;
213*11513SAlan.Adamson@Sun.COM 
214*11513SAlan.Adamson@Sun.COM 			if (niumx_state.niumx_ihtable[i].ih_dip == 0)
215*11513SAlan.Adamson@Sun.COM 				continue;
216*11513SAlan.Adamson@Sun.COM 
217*11513SAlan.Adamson@Sun.COM 			bzero((void *)&info, sizeof (intr_info_t));
218*11513SAlan.Adamson@Sun.COM 
219*11513SAlan.Adamson@Sun.COM 			info.shared = 0;
220*11513SAlan.Adamson@Sun.COM 
221*11513SAlan.Adamson@Sun.COM 			(void) mdb_devinfo2driver(
222*11513SAlan.Adamson@Sun.COM 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip,
223*11513SAlan.Adamson@Sun.COM 			    name, sizeof (name));
224*11513SAlan.Adamson@Sun.COM 
225*11513SAlan.Adamson@Sun.COM 			(void) mdb_ddi_pathname(
226*11513SAlan.Adamson@Sun.COM 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip,
227*11513SAlan.Adamson@Sun.COM 			    info.pathname, sizeof (info.pathname));
228*11513SAlan.Adamson@Sun.COM 
229*11513SAlan.Adamson@Sun.COM 			/* Get instance */
230*11513SAlan.Adamson@Sun.COM 			if (mdb_vread(&dev, sizeof (struct dev_info),
231*11513SAlan.Adamson@Sun.COM 			    (uintptr_t)niumx_state.niumx_ihtable[i].ih_dip) ==
232*11513SAlan.Adamson@Sun.COM 			    -1) {
233*11513SAlan.Adamson@Sun.COM 				mdb_warn("intr: failed to read DIP "
234*11513SAlan.Adamson@Sun.COM 				    "structure\n");
235*11513SAlan.Adamson@Sun.COM 
236*11513SAlan.Adamson@Sun.COM 				return (WALK_DONE);
237*11513SAlan.Adamson@Sun.COM 			}
238*11513SAlan.Adamson@Sun.COM 
239*11513SAlan.Adamson@Sun.COM 			/* Make sure the name doesn't over run */
240*11513SAlan.Adamson@Sun.COM 			(void) mdb_snprintf(info.driver_name,
241*11513SAlan.Adamson@Sun.COM 			    sizeof (info.driver_name), "%s", name);
242*11513SAlan.Adamson@Sun.COM 
243*11513SAlan.Adamson@Sun.COM 			info.instance = dev.devi_instance;
244*11513SAlan.Adamson@Sun.COM 			info.inum = niumx_state.niumx_ihtable[i].ih_inum;
245*11513SAlan.Adamson@Sun.COM 			info.intr_type = DDI_INTR_TYPE_FIXED;
246*11513SAlan.Adamson@Sun.COM 			info.num = 0;
247*11513SAlan.Adamson@Sun.COM 			info.intr_state = niumx_state.niumx_ihtable[i].ih_state;
248*11513SAlan.Adamson@Sun.COM 			info.ino_ino = i;
249*11513SAlan.Adamson@Sun.COM 			info.mondo = niumx_state.niumx_ihtable[i].ih_sysino;
250*11513SAlan.Adamson@Sun.COM 			info.pil = niumx_state.niumx_ihtable[i].ih_pri;
251*11513SAlan.Adamson@Sun.COM 			info.cpuid = niumx_state.niumx_ihtable[i].ih_cpuid;
252*11513SAlan.Adamson@Sun.COM 
253*11513SAlan.Adamson@Sun.COM 			intr_print_elements(info);
254*11513SAlan.Adamson@Sun.COM 		}
255*11513SAlan.Adamson@Sun.COM 	}
256*11513SAlan.Adamson@Sun.COM 
257*11513SAlan.Adamson@Sun.COM 	return (WALK_DONE);
258*11513SAlan.Adamson@Sun.COM }
259*11513SAlan.Adamson@Sun.COM 
260909Segillett static void
intr_pci_print_items(mdb_walk_state_t * wsp)261909Segillett intr_pci_print_items(mdb_walk_state_t *wsp)
262909Segillett {
2632973Sgovinda 	ib_t			ib;
2642973Sgovinda 	ib_ino_info_t		ino;
2652973Sgovinda 	ib_ino_pil_t		ipil;
266909Segillett 	ih_t			ih;
267909Segillett 	int			count;
268909Segillett 	char			name[MODMAXNAMELEN + 1];
2692973Sgovinda 	struct dev_info		dev;
270909Segillett 	intr_info_t		info;
271909Segillett 
2722973Sgovinda 	if (mdb_vread(&ib, sizeof (ib_t),
273909Segillett 	    (uintptr_t)wsp->walk_addr) == -1) {
274909Segillett 		mdb_warn("intr: failed to read pci interrupt block "
275909Segillett 		    "structure\n");
276909Segillett 		return;
277909Segillett 	}
278909Segillett 
279909Segillett 	/* Read in ib_ino_info_t structure at address */
2802973Sgovinda 	if (mdb_vread(&ino, sizeof (ib_ino_info_t),
2812973Sgovinda 	    (uintptr_t)ib.ib_ino_lst) == -1) {
282909Segillett 		/* Nothing here to read from */
283909Segillett 		return;
284909Segillett 	}
285909Segillett 
286909Segillett 	do {
2872973Sgovinda 		if (mdb_vread(&ipil, sizeof (ib_ino_pil_t),
2882973Sgovinda 		    (uintptr_t)ino.ino_ipil_p) == -1) {
2892973Sgovinda 			mdb_warn("intr: failed to read pci interrupt "
2902973Sgovinda 			    "ib_ino_pil_t structure\n");
291909Segillett 			return;
292909Segillett 		}
293909Segillett 
294909Segillett 		do {
2952973Sgovinda 			if (mdb_vread(&ih, sizeof (ih_t),
2962973Sgovinda 			    (uintptr_t)ipil.ipil_ih_start) == -1) {
2972973Sgovinda 				mdb_warn("intr: failed to read pci interrupt "
2982973Sgovinda 				    "ih_t structure\n");
299909Segillett 				return;
300909Segillett 			}
301909Segillett 
3022973Sgovinda 			count = 0;
3032973Sgovinda 
3042973Sgovinda 			do {
3052973Sgovinda 				bzero((void *)&info, sizeof (intr_info_t));
3062973Sgovinda 
3072973Sgovinda 				if ((ino.ino_ipil_size > 1) ||
3082973Sgovinda 				    (ipil.ipil_ih_size > 1)) {
3092973Sgovinda 					info.shared = 1;
3102973Sgovinda 				}
3112973Sgovinda 
3122973Sgovinda 				(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
3132973Sgovinda 				    name, sizeof (name));
3142973Sgovinda 
3152973Sgovinda 				(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
3162973Sgovinda 				    info.pathname, sizeof (info.pathname));
3172973Sgovinda 
3182973Sgovinda 				/* Get instance */
3192973Sgovinda 				if (mdb_vread(&dev, sizeof (struct dev_info),
3202973Sgovinda 				    (uintptr_t)ih.ih_dip) == -1) {
3212973Sgovinda 					mdb_warn("intr: failed to read DIP "
3222973Sgovinda 					    "structure\n");
3232973Sgovinda 					return;
3242973Sgovinda 				}
325909Segillett 
3262973Sgovinda 				/* Make sure the name doesn't over run */
3272973Sgovinda 				(void) mdb_snprintf(info.driver_name,
3282973Sgovinda 				    sizeof (info.driver_name), "%s", name);
3292973Sgovinda 
3302973Sgovinda 				info.instance = dev.devi_instance;
3312973Sgovinda 				info.inum = ih.ih_inum;
3322973Sgovinda 				info.intr_type = DDI_INTR_TYPE_FIXED;
3332973Sgovinda 				info.num = 0;
3342973Sgovinda 				info.intr_state = ih.ih_intr_state;
3352973Sgovinda 				info.ino_ino = ino.ino_ino;
3362973Sgovinda 				info.mondo = ino.ino_mondo;
3372973Sgovinda 				info.pil = ipil.ipil_pil;
3382973Sgovinda 				info.cpuid = ino.ino_cpuid;
339909Segillett 
3402973Sgovinda 				intr_print_elements(info);
3412973Sgovinda 				count++;
3422973Sgovinda 
3432973Sgovinda 				(void) mdb_vread(&ih, sizeof (ih_t),
3442973Sgovinda 				    (uintptr_t)ih.ih_next);
345909Segillett 
3462973Sgovinda 			} while (count < ipil.ipil_ih_size);
347909Segillett 
3482973Sgovinda 		} while (mdb_vread(&ipil, sizeof (ib_ino_pil_t),
3492973Sgovinda 		    (uintptr_t)ipil.ipil_next_p) != -1);
350909Segillett 
3512973Sgovinda 	} while (mdb_vread(&ino, sizeof (ib_ino_info_t),
3522973Sgovinda 	    (uintptr_t)ino.ino_next_p) != -1);
353909Segillett }
354909Segillett 
355909Segillett static void
intr_px_print_items(mdb_walk_state_t * wsp)356909Segillett intr_px_print_items(mdb_walk_state_t *wsp)
357909Segillett {
3582973Sgovinda 	px_ib_t		ib;
3592973Sgovinda 	px_ino_t	ino;
3602973Sgovinda 	px_ino_pil_t	ipil;
3612973Sgovinda 	px_ih_t		ih;
3622973Sgovinda 	int		count;
3632973Sgovinda 	char		name[MODMAXNAMELEN + 1];
3642973Sgovinda 	struct dev_info	dev;
3652973Sgovinda 	intr_info_t	info;
3662973Sgovinda 	devinfo_intr_t	intr_p;
367909Segillett 
3682973Sgovinda 	if (mdb_vread(&ib, sizeof (px_ib_t), wsp->walk_addr) == -1) {
369909Segillett 		return;
370909Segillett 	}
371909Segillett 
3722973Sgovinda 	/* Read in px_ino_t structure at address */
3732973Sgovinda 	if (mdb_vread(&ino, sizeof (px_ino_t),
3742973Sgovinda 	    (uintptr_t)ib.ib_ino_lst) == -1) {
375909Segillett 		/* Nothing here to read from */
376909Segillett 		return;
377909Segillett 	}
378909Segillett 
3793830Segillett 	do { /* ino_next_p loop */
3802973Sgovinda 		if (mdb_vread(&ipil, sizeof (px_ino_pil_t),
3812973Sgovinda 		    (uintptr_t)ino.ino_ipil_p) == -1) {
38210053SEvan.Yan@Sun.COM 			continue;
383909Segillett 		}
384909Segillett 
3853830Segillett 		do { /* ipil_next_p loop */
3862973Sgovinda 			if (mdb_vread(&ih, sizeof (px_ih_t),
3872973Sgovinda 			    (uintptr_t)ipil.ipil_ih_start) == -1) {
38810053SEvan.Yan@Sun.COM 				continue;
389909Segillett 			}
390909Segillett 
3912973Sgovinda 			count = 0;
3922973Sgovinda 
3933830Segillett 			do { /* ipil_ih_size loop */
3942973Sgovinda 				bzero((void *)&info, sizeof (intr_info_t));
395909Segillett 
3962973Sgovinda 				(void) mdb_devinfo2driver((uintptr_t)ih.ih_dip,
3972973Sgovinda 				    name, sizeof (name));
3982973Sgovinda 
3992973Sgovinda 				(void) mdb_ddi_pathname((uintptr_t)ih.ih_dip,
4002973Sgovinda 				    info.pathname, sizeof (info.pathname));
4011725Segillett 
4022973Sgovinda 				/* Get instance */
4032973Sgovinda 				if (mdb_vread(&dev, sizeof (struct dev_info),
4042973Sgovinda 				    (uintptr_t)ih.ih_dip) == -1) {
4052973Sgovinda 					mdb_warn("intr: failed to read DIP "
4062973Sgovinda 					    "structure\n");
4072973Sgovinda 					return;
4082973Sgovinda 				}
4092973Sgovinda 
4102973Sgovinda 				/* Make sure the name doesn't over run */
4112973Sgovinda 				(void) mdb_snprintf(info.driver_name,
4122973Sgovinda 				    sizeof (info.driver_name), "%s", name);
4132973Sgovinda 
4142973Sgovinda 				info.instance = dev.devi_instance;
4152973Sgovinda 				info.inum = ih.ih_inum;
4161725Segillett 
4172973Sgovinda 				/*
4182973Sgovinda 				 * Read the type used, keep PCIe messages
4192973Sgovinda 				 * separate.
4202973Sgovinda 				 */
4212973Sgovinda 				(void) mdb_vread(&intr_p,
4222973Sgovinda 				    sizeof (devinfo_intr_t),
4232973Sgovinda 				    (uintptr_t)dev.devi_intr_p);
4242973Sgovinda 
4252973Sgovinda 				if (ih.ih_rec_type != MSG_REC) {
4262973Sgovinda 					info.intr_type =
4272973Sgovinda 					    intr_p.devi_intr_curr_type;
4282973Sgovinda 				}
4292973Sgovinda 
43010597SDaniel.Ice@Sun.COM 				if ((ino.ino_ipil_size > 1) ||
43110597SDaniel.Ice@Sun.COM 				    (ipil.ipil_ih_size > 1)) {
4322973Sgovinda 					info.shared = 1;
4332973Sgovinda 				}
434909Segillett 
4352973Sgovinda 				info.num = ih.ih_msg_code;
4362973Sgovinda 				info.intr_state = ih.ih_intr_state;
4372973Sgovinda 				info.ino_ino = ino.ino_ino;
4382973Sgovinda 				info.mondo = ino.ino_sysino;
4392973Sgovinda 				info.pil = ipil.ipil_pil;
4402973Sgovinda 				info.cpuid = ino.ino_cpuid;
4412973Sgovinda 
4422973Sgovinda 				intr_print_elements(info);
4432973Sgovinda 				count++;
444909Segillett 
4452973Sgovinda 				(void) mdb_vread(&ih, sizeof (px_ih_t),
4462973Sgovinda 				    (uintptr_t)ih.ih_next);
4472973Sgovinda 
4482973Sgovinda 			} while (count < ipil.ipil_ih_size);
449909Segillett 
45010053SEvan.Yan@Sun.COM 		} while ((ipil.ipil_next_p != NULL) &&
45110053SEvan.Yan@Sun.COM 		    (mdb_vread(&ipil, sizeof (px_ino_pil_t),
45210053SEvan.Yan@Sun.COM 		    (uintptr_t)ipil.ipil_next_p) != -1));
453909Segillett 
45410053SEvan.Yan@Sun.COM 	} while ((ino.ino_next_p != NULL) && (mdb_vread(&ino, sizeof (px_ino_t),
45510053SEvan.Yan@Sun.COM 	    (uintptr_t)ino.ino_next_p) != -1));
456909Segillett }
457909Segillett 
458909Segillett static char *
intr_get_intr_type(uint16_t type)4591725Segillett intr_get_intr_type(uint16_t type)
460909Segillett {
4611725Segillett 	switch (type) {
4621725Segillett 		case	DDI_INTR_TYPE_FIXED:
4631725Segillett 			return ("Fixed");
4641725Segillett 		case	DDI_INTR_TYPE_MSI:
4651725Segillett 			return ("MSI");
4661725Segillett 		case	DDI_INTR_TYPE_MSIX:
4671725Segillett 			return ("MSI-X");
4681725Segillett 		default:
469909Segillett 			return ("PCIe");
470909Segillett 	}
471909Segillett }
472909Segillett 
473909Segillett static void
intr_print_banner(void)474909Segillett intr_print_banner(void)
475909Segillett {
476909Segillett 	if (!detailed) {
477965Sgovinda 		mdb_printf("\n%<u>\tDevice\t"
478965Sgovinda 		    " Type\t"
479965Sgovinda 		    " MSG #\t"
480965Sgovinda 		    " State\t"
481965Sgovinda 		    " INO\t"
482965Sgovinda 		    " Mondo\t"
48310597SDaniel.Ice@Sun.COM 		    " Shared\t"
484965Sgovinda 		    "  Pil\t"
485965Sgovinda 		    " CPU   %</u>"
486965Sgovinda 		    "\n");
487909Segillett 	}
488909Segillett }
489909Segillett 
490909Segillett static void
intr_print_elements(intr_info_t info)491909Segillett intr_print_elements(intr_info_t info)
492909Segillett {
493909Segillett 	if (!detailed) {
494965Sgovinda 		mdb_printf(" %11s#%d\t", info.driver_name, info.instance);
495965Sgovinda 		mdb_printf(" %s\t", intr_get_intr_type(info.intr_type));
4961725Segillett 		if (info.intr_type == DDI_INTR_TYPE_FIXED) {
497965Sgovinda 			mdb_printf("  --- \t");
498909Segillett 		} else {
499965Sgovinda 			mdb_printf(" %4d\t", info.num);
500909Segillett 		}
501965Sgovinda 		mdb_printf(" %2s\t",
502909Segillett 		    info.intr_state ? "enbl" : "disbl");
503965Sgovinda 		mdb_printf(" 0x%x\t", info.ino_ino);
504965Sgovinda 		mdb_printf(" 0x%x\t", info.mondo);
50510597SDaniel.Ice@Sun.COM 		mdb_printf(" %5s\t",
50610597SDaniel.Ice@Sun.COM 		    info.shared ? "yes" : "no");
507965Sgovinda 		mdb_printf(" %4d\t", info.pil);
508965Sgovinda 		mdb_printf(" %3d \n", info.cpuid);
509909Segillett 	} else {
510909Segillett 		mdb_printf("\n-------------------------------------------\n");
511909Segillett 		mdb_printf("Device:\t\t%s\n", info.driver_name);
512909Segillett 		mdb_printf("Instance:\t%d\n", info.instance);
513909Segillett 		mdb_printf("Path:\t\t%s\n", info.pathname);
514909Segillett 		mdb_printf("Inum:\t\t%d\n", info.inum);
515909Segillett 		mdb_printf("Interrupt Type:\t%s\n",
516909Segillett 		    intr_get_intr_type(info.intr_type));
5171725Segillett 		if (info.intr_type == DDI_INTR_TYPE_MSI) {
5181725Segillett 			mdb_printf("MSI Number:\t%d\n", info.num);
5191725Segillett 		} else if (info.intr_type == DDI_INTR_TYPE_MSIX) {
5201725Segillett 			mdb_printf("MSI-X Number:\t%d\n", info.num);
5211725Segillett 		} else if (!info.intr_type) {
5221725Segillett 			mdb_printf("PCIe Message #:\t%d\n", info.num);
5231725Segillett 		}
524909Segillett 
525909Segillett 		mdb_printf("Shared Intr:\t%s\n",
526909Segillett 		    info.shared ? "yes" : "no");
527909Segillett 		mdb_printf("State:\t\t%d (%s)\n", info.intr_state,
528909Segillett 		    info.intr_state ? "Enabled" : "Disabled");
529909Segillett 		mdb_printf("INO:\t\t0x%x\n", info.ino_ino);
530909Segillett 		mdb_printf("Mondo:\t\t0x%x\n", info.mondo);
531909Segillett 		mdb_printf("Pil:\t\t%d\n", info.pil);
532909Segillett 		mdb_printf("CPU:\t\t%d\n", info.cpuid);
533909Segillett 	}
534909Segillett }
535909Segillett 
536909Segillett /*ARGSUSED*/
537909Segillett static void
intr_walk_fini(mdb_walk_state_t * wsp)538909Segillett intr_walk_fini(mdb_walk_state_t *wsp)
539909Segillett {
540909Segillett 	/* Nothing to do here */
541909Segillett }
542909Segillett 
543909Segillett /*ARGSUSED*/
544909Segillett static int
intr_intr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)545909Segillett intr_intr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
546909Segillett {
547909Segillett 	detailed = 0;
548909Segillett 
549909Segillett 	if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &detailed,
550909Segillett 	    NULL) != argc)
551909Segillett 		return (DCMD_USAGE);
552909Segillett 
553909Segillett 	if (!(flags & DCMD_ADDRSPEC)) {
554909Segillett 		if (mdb_walk_dcmd("interrupts", "interrupts", argc, argv)
555909Segillett 		    == -1) {
556909Segillett 			mdb_warn("can't walk pci/px buffer entries\n");
557909Segillett 			return (DCMD_ERR);
558909Segillett 		}
559909Segillett 		return (DCMD_OK);
560909Segillett 	}
561909Segillett 
562909Segillett 	return (DCMD_OK);
563909Segillett }
564909Segillett 
565909Segillett /*
566909Segillett  * MDB module linkage information:
567909Segillett  */
568909Segillett 
569909Segillett static const mdb_dcmd_t dcmds[] = {
570909Segillett 	{ "interrupts", "[-d]", "display the interrupt info registered with "
571909Segillett 	    "the PCI/PX nexus drivers", intr_intr },
572909Segillett 	{ NULL }
573909Segillett };
574909Segillett 
575909Segillett static const mdb_walker_t walkers[] = {
576909Segillett 	{ "interrupts", "walk PCI/PX interrupt structures",
577909Segillett 		intr_walk_init, intr_walk_step, intr_walk_fini },
578909Segillett 	{ NULL }
579909Segillett };
580909Segillett 
581909Segillett static const mdb_modinfo_t modinfo = {
582909Segillett 	MDB_API_VERSION, dcmds, walkers
583909Segillett };
584909Segillett 
585909Segillett const mdb_modinfo_t *
_mdb_init(void)586909Segillett _mdb_init(void)
587909Segillett {
588909Segillett 	return (&modinfo);
589909Segillett }
590