1*909Segillett /* 2*909Segillett * CDDL HEADER START 3*909Segillett * 4*909Segillett * The contents of this file are subject to the terms of the 5*909Segillett * Common Development and Distribution License, Version 1.0 only 6*909Segillett * (the "License"). You may not use this file except in compliance 7*909Segillett * with the License. 8*909Segillett * 9*909Segillett * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*909Segillett * or http://www.opensolaris.org/os/licensing. 11*909Segillett * See the License for the specific language governing permissions 12*909Segillett * and limitations under the License. 13*909Segillett * 14*909Segillett * When distributing Covered Code, include this CDDL HEADER in each 15*909Segillett * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*909Segillett * If applicable, add the following below this CDDL HEADER, with the 17*909Segillett * fields enclosed by brackets "[]" replaced with your own identifying 18*909Segillett * information: Portions Copyright [yyyy] [name of copyright owner] 19*909Segillett * 20*909Segillett * CDDL HEADER END 21*909Segillett */ 22*909Segillett /* 23*909Segillett * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*909Segillett * Use is subject to license terms. 25*909Segillett */ 26*909Segillett 27*909Segillett #pragma ident "%Z%%M% %I% %E% SMI" 28*909Segillett 29*909Segillett #include <sys/mdb_modapi.h> 30*909Segillett #include <mdb/mdb_ks.h> 31*909Segillett #include <sys/async.h> /* ecc_flt for pci_ecc.h */ 32*909Segillett #include <sys/ddi_subrdefs.h> 33*909Segillett #include <sys/pci/pci_obj.h> 34*909Segillett #include "px_obj.h" 35*909Segillett 36*909Segillett static int intr_pci_walk_step(mdb_walk_state_t *); 37*909Segillett static int intr_px_walk_step(mdb_walk_state_t *); 38*909Segillett static void intr_pci_print_items(mdb_walk_state_t *); 39*909Segillett static void intr_px_print_items(mdb_walk_state_t *); 40*909Segillett static char *intr_get_intr_type(msiq_rec_type_t); 41*909Segillett static void intr_print_line(int); 42*909Segillett static void intr_print_banner(void); 43*909Segillett 44*909Segillett typedef struct intr_info { 45*909Segillett uint32_t cpuid; 46*909Segillett uint32_t inum; 47*909Segillett uint32_t num; 48*909Segillett uint32_t pil; 49*909Segillett uint16_t mondo; 50*909Segillett uint8_t ino_ino; 51*909Segillett uint_t intr_state; 52*909Segillett int instance; 53*909Segillett int shared; 54*909Segillett msiq_rec_type_t intr_type; 55*909Segillett char driver_name[12]; 56*909Segillett char pathname[MAXNAMELEN]; 57*909Segillett } 58*909Segillett intr_info_t; 59*909Segillett 60*909Segillett static void intr_print_elements(intr_info_t); 61*909Segillett static int detailed = 0; /* Print detailed view */ 62*909Segillett 63*909Segillett 64*909Segillett static int 65*909Segillett intr_walk_init(mdb_walk_state_t *wsp) 66*909Segillett { 67*909Segillett wsp->walk_addr = NULL; 68*909Segillett 69*909Segillett return (WALK_NEXT); 70*909Segillett } 71*909Segillett 72*909Segillett static int 73*909Segillett intr_walk_step(mdb_walk_state_t *wsp) 74*909Segillett { 75*909Segillett pci_t *pci_per_p; 76*909Segillett px_t *px_state_p; 77*909Segillett 78*909Segillett /* read globally declared structures in the pci driver */ 79*909Segillett if (mdb_readvar(&pci_per_p, "per_pci_state") != -1) { 80*909Segillett wsp->walk_addr = (uintptr_t)pci_per_p; 81*909Segillett intr_pci_walk_step(wsp); 82*909Segillett } 83*909Segillett 84*909Segillett /* read globally declared structures in the px driver */ 85*909Segillett if (mdb_readvar(&px_state_p, "px_state_p") != -1) { 86*909Segillett wsp->walk_addr = (uintptr_t)px_state_p; 87*909Segillett intr_px_walk_step(wsp); 88*909Segillett } 89*909Segillett 90*909Segillett return (WALK_DONE); 91*909Segillett } 92*909Segillett 93*909Segillett static int 94*909Segillett intr_pci_walk_step(mdb_walk_state_t *wsp) 95*909Segillett { 96*909Segillett pci_t *pci_per_p; 97*909Segillett pci_t pci_per; 98*909Segillett uintptr_t start_addr; 99*909Segillett 100*909Segillett /* Read start of state structure array */ 101*909Segillett if (mdb_vread(&pci_per_p, sizeof (uintptr_t), 102*909Segillett (uintptr_t)wsp->walk_addr) == -1) { 103*909Segillett mdb_warn("intr: failed to read the initial pci_per_p " 104*909Segillett "structure\n"); 105*909Segillett return (WALK_ERR); 106*909Segillett } 107*909Segillett 108*909Segillett /* Figure out how many items are here */ 109*909Segillett start_addr = (uintptr_t)pci_per_p; 110*909Segillett 111*909Segillett while (mdb_vread(&pci_per_p, sizeof (uintptr_t), 112*909Segillett (uintptr_t)start_addr) != -1) { 113*909Segillett /* Read until nothing is left */ 114*909Segillett if (mdb_vread(&pci_per, sizeof (pci_t), 115*909Segillett (uintptr_t)pci_per_p) == -1) { 116*909Segillett return (WALK_DONE); 117*909Segillett } 118*909Segillett 119*909Segillett wsp->walk_addr = (uintptr_t)pci_per.pci_ib_p; 120*909Segillett intr_pci_print_items(wsp); 121*909Segillett 122*909Segillett start_addr += sizeof (uintptr_t); 123*909Segillett } 124*909Segillett 125*909Segillett return (WALK_DONE); 126*909Segillett } 127*909Segillett 128*909Segillett static int 129*909Segillett intr_px_walk_step(mdb_walk_state_t *wsp) 130*909Segillett { 131*909Segillett px_t *px_state_p; 132*909Segillett px_t px_state; 133*909Segillett uintptr_t start_addr; 134*909Segillett 135*909Segillett /* Read start of state structure array */ 136*909Segillett if (mdb_vread(&px_state_p, sizeof (uintptr_t), 137*909Segillett (uintptr_t)wsp->walk_addr) == -1) { 138*909Segillett mdb_warn("intr: failed to read the initial px_per_p " 139*909Segillett "structure\n"); 140*909Segillett return (WALK_ERR); 141*909Segillett } 142*909Segillett 143*909Segillett /* Figure out how many items are here */ 144*909Segillett start_addr = (uintptr_t)px_state_p; 145*909Segillett 146*909Segillett while (mdb_vread(&px_state_p, sizeof (uintptr_t), 147*909Segillett (uintptr_t)start_addr) != -1) { 148*909Segillett /* Read until nothing is left */ 149*909Segillett if (mdb_vread(&px_state, sizeof (px_t), 150*909Segillett (uintptr_t)px_state_p) == -1) { 151*909Segillett return (WALK_DONE); 152*909Segillett } 153*909Segillett 154*909Segillett wsp->walk_addr = (uintptr_t)px_state.px_ib_p; 155*909Segillett intr_px_print_items(wsp); 156*909Segillett 157*909Segillett start_addr += sizeof (uintptr_t); 158*909Segillett } 159*909Segillett 160*909Segillett return (WALK_DONE); 161*909Segillett } 162*909Segillett 163*909Segillett static void 164*909Segillett intr_pci_print_items(mdb_walk_state_t *wsp) 165*909Segillett { 166*909Segillett ib_t pci_ib; 167*909Segillett ib_ino_info_t *ib_ino_lst; 168*909Segillett ib_ino_info_t list; 169*909Segillett ih_t ih; 170*909Segillett int count; 171*909Segillett char name[MODMAXNAMELEN + 1]; 172*909Segillett struct dev_info devinfo; 173*909Segillett intr_info_t info; 174*909Segillett 175*909Segillett if (mdb_vread(&pci_ib, sizeof (ib_t), 176*909Segillett (uintptr_t)wsp->walk_addr) == -1) { 177*909Segillett mdb_warn("intr: failed to read pci interrupt block " 178*909Segillett "structure\n"); 179*909Segillett return; 180*909Segillett } 181*909Segillett 182*909Segillett /* Read in ib_ino_info_t structure at address */ 183*909Segillett ib_ino_lst = pci_ib.ib_ino_lst; 184*909Segillett if (mdb_vread(&list, sizeof (ib_ino_info_t), 185*909Segillett (uintptr_t)ib_ino_lst) == -1) { 186*909Segillett /* Nothing here to read from */ 187*909Segillett return; 188*909Segillett } 189*909Segillett 190*909Segillett intr_print_line(77); 191*909Segillett intr_print_banner(); 192*909Segillett intr_print_line(77); 193*909Segillett 194*909Segillett do { 195*909Segillett if (mdb_vread(&ih, sizeof (ih_t), 196*909Segillett (uintptr_t)list.ino_ih_start) == -1) { 197*909Segillett mdb_warn("intr: failed to read pci interrupt entry " 198*909Segillett "structure\n"); 199*909Segillett return; 200*909Segillett } 201*909Segillett 202*909Segillett count = 0; 203*909Segillett 204*909Segillett do { 205*909Segillett bzero((void *)&info, sizeof (intr_info_t)); 206*909Segillett 207*909Segillett if (list.ino_ih_size > 1) { 208*909Segillett info.shared = 1; 209*909Segillett } 210*909Segillett 211*909Segillett (void) mdb_devinfo2driver((uintptr_t)ih.ih_dip, 212*909Segillett name, sizeof (name)); 213*909Segillett 214*909Segillett (void) mdb_ddi_pathname((uintptr_t)ih.ih_dip, 215*909Segillett info.pathname, sizeof (info.pathname)); 216*909Segillett 217*909Segillett /* Get instance */ 218*909Segillett if (mdb_vread(&devinfo, sizeof (struct dev_info), 219*909Segillett (uintptr_t)ih.ih_dip) == -1) { 220*909Segillett mdb_warn("intr: failed to read DIP " 221*909Segillett "structure\n"); 222*909Segillett return; 223*909Segillett } 224*909Segillett 225*909Segillett /* Make sure the name doesn't over run */ 226*909Segillett (void) mdb_snprintf(info.driver_name, 227*909Segillett sizeof (info.driver_name), "%s", name); 228*909Segillett 229*909Segillett info.instance = devinfo.devi_instance; 230*909Segillett info.inum = ih.ih_inum; 231*909Segillett info.intr_type = INTX_REC; 232*909Segillett info.num = 0; 233*909Segillett info.intr_state = ih.ih_intr_state; 234*909Segillett info.ino_ino = list.ino_ino; 235*909Segillett info.mondo = list.ino_mondo; 236*909Segillett info.pil = list.ino_pil; 237*909Segillett info.cpuid = list.ino_cpuid; 238*909Segillett 239*909Segillett intr_print_elements(info); 240*909Segillett count++; 241*909Segillett 242*909Segillett (void) mdb_vread(&ih, sizeof (ih_t), 243*909Segillett (uintptr_t)ih.ih_next); 244*909Segillett 245*909Segillett } while (count < list.ino_ih_size); 246*909Segillett 247*909Segillett } while (mdb_vread(&list, sizeof (ib_ino_info_t), 248*909Segillett (uintptr_t)list.ino_next) != -1); 249*909Segillett 250*909Segillett intr_print_line(77); 251*909Segillett } 252*909Segillett 253*909Segillett static void 254*909Segillett intr_px_print_items(mdb_walk_state_t *wsp) 255*909Segillett { 256*909Segillett px_ib_t px_ib; 257*909Segillett px_ib_ino_info_t *px_ib_ino_lst; 258*909Segillett px_ib_ino_info_t px_list; 259*909Segillett px_ih_t px_ih; 260*909Segillett int count; 261*909Segillett char name[MODMAXNAMELEN + 1]; 262*909Segillett struct dev_info devinfo; 263*909Segillett intr_info_t info; 264*909Segillett 265*909Segillett if (mdb_vread(&px_ib, sizeof (px_ib_t), wsp->walk_addr) == -1) { 266*909Segillett mdb_warn("intr: failed to read px interrupt block " 267*909Segillett "structure\n"); 268*909Segillett return; 269*909Segillett } 270*909Segillett 271*909Segillett /* Read in px_ib_ino_info_t structure at address */ 272*909Segillett px_ib_ino_lst = px_ib.ib_ino_lst; 273*909Segillett if (mdb_vread(&px_list, sizeof (px_ib_ino_info_t), 274*909Segillett (uintptr_t)px_ib_ino_lst) == -1) { 275*909Segillett /* Nothing here to read from */ 276*909Segillett return; 277*909Segillett } 278*909Segillett 279*909Segillett intr_print_line(77); 280*909Segillett intr_print_banner(); 281*909Segillett intr_print_line(77); 282*909Segillett 283*909Segillett do { 284*909Segillett if (mdb_vread(&px_ih, sizeof (px_ih_t), 285*909Segillett (uintptr_t)px_list.ino_ih_start) == -1) { 286*909Segillett mdb_warn("intr: failed to read px interrupt entry " 287*909Segillett "structure\n"); 288*909Segillett return; 289*909Segillett } 290*909Segillett 291*909Segillett count = 0; 292*909Segillett 293*909Segillett do { 294*909Segillett bzero((void *)&info, sizeof (intr_info_t)); 295*909Segillett 296*909Segillett if (px_list.ino_ih_size > 1) { 297*909Segillett info.shared = 1; 298*909Segillett } 299*909Segillett 300*909Segillett (void) mdb_devinfo2driver((uintptr_t)px_ih.ih_dip, 301*909Segillett name, sizeof (name)); 302*909Segillett 303*909Segillett (void) mdb_ddi_pathname((uintptr_t)px_ih.ih_dip, 304*909Segillett info.pathname, sizeof (info.pathname)); 305*909Segillett 306*909Segillett /* Get instance */ 307*909Segillett if (mdb_vread(&devinfo, sizeof (struct dev_info), 308*909Segillett (uintptr_t)px_ih.ih_dip) == -1) { 309*909Segillett mdb_warn("intr: failed to read DIP " 310*909Segillett "structure\n"); 311*909Segillett return; 312*909Segillett } 313*909Segillett 314*909Segillett /* Make sure the name doesn't over run */ 315*909Segillett (void) mdb_snprintf(info.driver_name, 316*909Segillett sizeof (info.driver_name), "%s", name); 317*909Segillett 318*909Segillett info.instance = devinfo.devi_instance; 319*909Segillett info.inum = px_ih.ih_inum; 320*909Segillett info.intr_type = px_ih.ih_rec_type; 321*909Segillett info.num = px_ih.ih_msg_code; 322*909Segillett info.intr_state = px_ih.ih_intr_state; 323*909Segillett info.ino_ino = px_list.ino_ino; 324*909Segillett info.mondo = px_list.ino_sysino; 325*909Segillett info.pil = px_list.ino_pil; 326*909Segillett info.cpuid = px_list.ino_cpuid; 327*909Segillett 328*909Segillett intr_print_elements(info); 329*909Segillett count++; 330*909Segillett 331*909Segillett (void) mdb_vread(&px_ih, sizeof (ih_t), 332*909Segillett (uintptr_t)px_ih.ih_next); 333*909Segillett 334*909Segillett } while (count < px_list.ino_ih_size); 335*909Segillett 336*909Segillett } while (mdb_vread(&px_list, sizeof (px_ib_ino_info_t), 337*909Segillett (uintptr_t)px_list.ino_next) != -1); 338*909Segillett 339*909Segillett intr_print_line(77); 340*909Segillett } 341*909Segillett 342*909Segillett static char * 343*909Segillett intr_get_intr_type(msiq_rec_type_t rec_type) 344*909Segillett { 345*909Segillett switch (rec_type) { 346*909Segillett case MSG_REC: 347*909Segillett return ("PCIe"); 348*909Segillett case MSI32_REC: 349*909Segillett case MSI64_REC: 350*909Segillett return ("MSI"); 351*909Segillett case INTX_REC: 352*909Segillett default: 353*909Segillett return ("Fixed"); 354*909Segillett } 355*909Segillett } 356*909Segillett 357*909Segillett static void 358*909Segillett intr_print_line(int cnt) 359*909Segillett { 360*909Segillett int x; 361*909Segillett 362*909Segillett if (!detailed) { 363*909Segillett mdb_printf("+"); 364*909Segillett for (x = 0; x < cnt; x++) { 365*909Segillett mdb_printf("-"); 366*909Segillett } 367*909Segillett mdb_printf("+\n"); 368*909Segillett } 369*909Segillett } 370*909Segillett 371*909Segillett static void 372*909Segillett intr_print_banner(void) 373*909Segillett { 374*909Segillett if (!detailed) { 375*909Segillett mdb_printf("| Device\t" 376*909Segillett "| Shard\t" 377*909Segillett "| Type\t" 378*909Segillett "| MSG #\t" 379*909Segillett "| State " 380*909Segillett "| INO\t" 381*909Segillett "| Mondo\t" 382*909Segillett "| Pil\t" 383*909Segillett "| CPU " 384*909Segillett "|\n"); 385*909Segillett } 386*909Segillett } 387*909Segillett 388*909Segillett static void 389*909Segillett intr_print_elements(intr_info_t info) 390*909Segillett { 391*909Segillett if (!detailed) { 392*909Segillett mdb_printf("| %11s#%d\t", info.driver_name, info.instance); 393*909Segillett mdb_printf("| %s\t", 394*909Segillett info.shared ? "yes" : "no"); 395*909Segillett mdb_printf("| %s\t", intr_get_intr_type(info.intr_type)); 396*909Segillett if (strcmp("Fixed", intr_get_intr_type(info.intr_type)) == 0) { 397*909Segillett mdb_printf("| --- \t"); 398*909Segillett } else { 399*909Segillett mdb_printf("| %4d\t", info.num); 400*909Segillett } 401*909Segillett 402*909Segillett mdb_printf("| %2s\t", 403*909Segillett info.intr_state ? "enbl" : "disbl"); 404*909Segillett mdb_printf("| 0x%x\t", info.ino_ino); 405*909Segillett mdb_printf("| 0x%x", info.mondo); 406*909Segillett if (!(info.mondo & 0xF000)) { /* Don't overrun table width */ 407*909Segillett mdb_printf("\t"); 408*909Segillett } 409*909Segillett mdb_printf("| %4d\t", info.pil); 410*909Segillett mdb_printf("| %3d |\n", info.cpuid); 411*909Segillett } else { 412*909Segillett mdb_printf("\n-------------------------------------------\n"); 413*909Segillett mdb_printf("Device:\t\t%s\n", info.driver_name); 414*909Segillett mdb_printf("Instance:\t%d\n", info.instance); 415*909Segillett mdb_printf("Path:\t\t%s\n", info.pathname); 416*909Segillett mdb_printf("Inum:\t\t%d\n", info.inum); 417*909Segillett mdb_printf("Interrupt Type:\t%s\n", 418*909Segillett intr_get_intr_type(info.intr_type)); 419*909Segillett if (strcmp("MSI", intr_get_intr_type(info.intr_type)) == 0) 420*909Segillett mdb_printf("MSI/X Number:\t%s\n", info.num); 421*909Segillett 422*909Segillett mdb_printf("Shared Intr:\t%s\n", 423*909Segillett info.shared ? "yes" : "no"); 424*909Segillett mdb_printf("State:\t\t%d (%s)\n", info.intr_state, 425*909Segillett info.intr_state ? "Enabled" : "Disabled"); 426*909Segillett mdb_printf("INO:\t\t0x%x\n", info.ino_ino); 427*909Segillett mdb_printf("Mondo:\t\t0x%x\n", info.mondo); 428*909Segillett mdb_printf("Pil:\t\t%d\n", info.pil); 429*909Segillett mdb_printf("CPU:\t\t%d\n", info.cpuid); 430*909Segillett } 431*909Segillett } 432*909Segillett 433*909Segillett /*ARGSUSED*/ 434*909Segillett static void 435*909Segillett intr_walk_fini(mdb_walk_state_t *wsp) 436*909Segillett { 437*909Segillett /* Nothing to do here */ 438*909Segillett } 439*909Segillett 440*909Segillett /*ARGSUSED*/ 441*909Segillett static int 442*909Segillett intr_intr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 443*909Segillett { 444*909Segillett detailed = 0; 445*909Segillett 446*909Segillett if (mdb_getopts(argc, argv, 'd', MDB_OPT_SETBITS, TRUE, &detailed, 447*909Segillett NULL) != argc) 448*909Segillett return (DCMD_USAGE); 449*909Segillett 450*909Segillett if (!(flags & DCMD_ADDRSPEC)) { 451*909Segillett if (mdb_walk_dcmd("interrupts", "interrupts", argc, argv) 452*909Segillett == -1) { 453*909Segillett mdb_warn("can't walk pci/px buffer entries\n"); 454*909Segillett return (DCMD_ERR); 455*909Segillett } 456*909Segillett return (DCMD_OK); 457*909Segillett } 458*909Segillett 459*909Segillett return (DCMD_OK); 460*909Segillett } 461*909Segillett 462*909Segillett /* 463*909Segillett * MDB module linkage information: 464*909Segillett */ 465*909Segillett 466*909Segillett static const mdb_dcmd_t dcmds[] = { 467*909Segillett { "interrupts", "[-d]", "display the interrupt info registered with " 468*909Segillett "the PCI/PX nexus drivers", intr_intr }, 469*909Segillett { NULL } 470*909Segillett }; 471*909Segillett 472*909Segillett static const mdb_walker_t walkers[] = { 473*909Segillett { "interrupts", "walk PCI/PX interrupt structures", 474*909Segillett intr_walk_init, intr_walk_step, intr_walk_fini }, 475*909Segillett { NULL } 476*909Segillett }; 477*909Segillett 478*909Segillett static const mdb_modinfo_t modinfo = { 479*909Segillett MDB_API_VERSION, dcmds, walkers 480*909Segillett }; 481*909Segillett 482*909Segillett const mdb_modinfo_t * 483*909Segillett _mdb_init(void) 484*909Segillett { 485*909Segillett return (&modinfo); 486*909Segillett } 487