1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <limits.h> 27 #include <sys/mdb_modapi.h> 28 #include <sys/sysinfo.h> 29 #include <sys/sunmdi.h> 30 #include <sys/scsi/scsi.h> 31 #include "mr_sas.h" 32 33 int 34 construct_path(uintptr_t addr, char *result) 35 { 36 struct dev_info d; 37 char devi_node[PATH_MAX]; 38 char devi_addr[PATH_MAX]; 39 40 if (mdb_vread(&d, sizeof (d), addr) == -1) { 41 mdb_warn("couldn't read dev_info"); 42 return (DCMD_ERR); 43 } 44 45 if (d.devi_parent) { 46 construct_path((uintptr_t)d.devi_parent, result); 47 mdb_readstr(devi_node, sizeof (devi_node), 48 (uintptr_t)d.devi_node_name); 49 mdb_readstr(devi_addr, sizeof (devi_addr), 50 (uintptr_t)d.devi_addr); 51 mdb_snprintf(result+strlen(result), 52 PATH_MAX-strlen(result), 53 "/%s%s%s", devi_node, (*devi_addr ? "@" : ""), 54 devi_addr); 55 } 56 return (DCMD_OK); 57 } 58 59 void 60 display_targets(struct mrsas_instance m, int verbose) 61 { 62 int tgt; 63 struct mrsas_ld *mr_ldp; 64 char device_path[PATH_MAX]; 65 66 if (verbose) { 67 *device_path = 0; 68 if (construct_path((uintptr_t)m.dip, device_path) != DCMD_OK) { 69 strcpy(device_path, "couldn't determine device path"); 70 } 71 } 72 73 mdb_printf("\n"); 74 if (verbose) 75 mdb_printf("%s\n", device_path); 76 mdb_printf("dev_type target\n"); 77 mdb_printf("----------"); 78 mdb_printf("\n"); 79 for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) { 80 mr_ldp = (struct mrsas_ld *)&m.mr_ld_list[tgt]; 81 if ((mr_ldp != NULL) && (mr_ldp->dip != NULL) && 82 (mr_ldp->lun_type == MRSAS_LD_LUN)) { 83 mdb_printf("sd %d", tgt); 84 mdb_printf("\n"); 85 } 86 } 87 mdb_printf("\n"); 88 } 89 90 void 91 display_deviceinfo(struct mrsas_instance m) 92 { 93 uint16_t vid, did, svid, sid; 94 95 vid = m.vendor_id; 96 did = m.device_id; 97 svid = m.subsysvid; 98 sid = m.subsysid; 99 100 mdb_printf("\n"); 101 mdb_printf("vendor_id device_id subsysvid subsysid"); 102 mdb_printf("\n"); 103 mdb_printf("--------------------------------------"); 104 mdb_printf("\n"); 105 mdb_printf(" 0x%x 0x%x 0x%x 0x%x", 106 vid, did, svid, sid); 107 mdb_printf("\n"); 108 } 109 110 static int 111 mr_sas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 112 { 113 struct mrsas_instance m; 114 115 int instance; 116 uint16_t ncmds; 117 uint_t verbose = FALSE; 118 uint_t device_info = FALSE; 119 uint_t target_info = FALSE; 120 int rv = DCMD_OK; 121 void *mrsas_state; 122 123 if (!(flags & DCMD_ADDRSPEC)) { 124 mrsas_state = NULL; 125 if (mdb_readvar(&mrsas_state, "mrsas_state") == -1) { 126 mdb_warn("can't read mrsas_state"); 127 return (DCMD_ERR); 128 } 129 if (mdb_pwalk_dcmd("genunix`softstate", "mr_sas`mr_sas", 130 argc, argv, (uintptr_t)mrsas_state) == -1) { 131 mdb_warn("mdb_pwalk_dcmd failed"); 132 return (DCMD_ERR); 133 } 134 return (DCMD_OK); 135 } 136 137 if (mdb_getopts(argc, argv, 138 'd', MDB_OPT_SETBITS, TRUE, &device_info, 139 't', MDB_OPT_SETBITS, TRUE, &target_info, 140 'v', MDB_OPT_SETBITS, TRUE, &verbose, 141 NULL) != argc) 142 return (DCMD_USAGE); 143 144 if (mdb_vread(&m, sizeof (m), addr) == -1) { 145 mdb_warn("couldn't read mrsas_instance struct at 0x%p", addr); 146 return (DCMD_ERR); 147 } 148 instance = m.instance; 149 150 /* cmd slot info */ 151 ncmds = m.max_fw_cmds; 152 153 /* processing completed */ 154 if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) || 155 (flags & DCMD_LOOPFIRST)) { 156 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST)) 157 mdb_printf("\n"); 158 mdb_printf(" mrsas_t inst max_fw_cmds intr_type"); 159 mdb_printf("\n"); 160 mdb_printf("==========================================="); 161 mdb_printf("\n"); 162 } 163 164 mdb_printf("%16p %4d %4d ", addr, instance, ncmds); 165 switch (m.intr_type) { 166 case DDI_INTR_TYPE_MSIX: 167 mdb_printf("MSI-X"); 168 break; 169 case DDI_INTR_TYPE_MSI: 170 mdb_printf("MSI"); 171 break; 172 case DDI_INTR_TYPE_FIXED: 173 mdb_printf("FIXED"); 174 break; 175 default: 176 mdb_printf("INVALD"); 177 } 178 mdb_printf("\n"); 179 180 if (target_info) 181 display_targets(m, verbose); 182 183 if (device_info) 184 display_deviceinfo(m); 185 186 return (rv); 187 } 188 189 void 190 mr_sas_help(void) 191 { 192 mdb_printf("Prints summary information about each mr_sas instance, " 193 "Without the address of a \"struct mrsas_instance\", prints every " 194 "instance.\n\n" 195 "Switches:\n" 196 " -t includes information about targets\n" 197 " -d includes information about the hardware\n" 198 " -v displays extra information for some options\n"); 199 } 200 201 static const mdb_dcmd_t dcmds[] = { 202 { "mr_sas", "?[-tdv]", "print mr_sas information", mr_sas_dcmd, 203 mr_sas_help }, 204 { NULL } 205 }; 206 207 static const mdb_modinfo_t modinfo = { 208 MDB_API_VERSION, dcmds, NULL 209 }; 210 211 const mdb_modinfo_t * 212 _mdb_init(void) 213 { 214 return (&modinfo); 215 } 216