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 /*
27  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28  */
29 
30 #include <limits.h>
31 #include <sys/mdb_modapi.h>
32 #include <sys/sysinfo.h>
33 #include <sys/sunmdi.h>
34 #include <sys/scsi/scsi.h>
35 #include "mr_sas.h"
36 
37 int
construct_path(uintptr_t addr,char * result)38 construct_path(uintptr_t addr, char *result)
39 {
40 	struct	dev_info	d;
41 	char	devi_node[PATH_MAX];
42 	char	devi_addr[PATH_MAX];
43 
44 	if (mdb_vread(&d, sizeof (d), addr) == -1) {
45 		mdb_warn("couldn't read dev_info");
46 		return (DCMD_ERR);
47 	}
48 
49 	if (d.devi_parent) {
50 		construct_path((uintptr_t)d.devi_parent, result);
51 		mdb_readstr(devi_node, sizeof (devi_node),
52 		    (uintptr_t)d.devi_node_name);
53 		mdb_readstr(devi_addr, sizeof (devi_addr),
54 		    (uintptr_t)d.devi_addr);
55 		mdb_snprintf(result+strlen(result),
56 		    PATH_MAX-strlen(result),
57 		    "/%s%s%s", devi_node, (*devi_addr ? "@" : ""),
58 		    devi_addr);
59 	}
60 	return (DCMD_OK);
61 }
62 
63 void
display_targets(struct mrsas_instance * m,int verbose)64 display_targets(struct mrsas_instance *m, int verbose)
65 {
66 	int	tgt;
67 	struct mrsas_ld mr_ldp[MRDRV_MAX_LD];
68 	struct mrsas_tbolt_pd mr_pdp[MRSAS_TBOLT_PD_TGT_MAX];
69 	char	device_path[PATH_MAX];
70 
71 	if (verbose) {
72 		*device_path = 0;
73 		if (construct_path((uintptr_t)m->dip, device_path) != DCMD_OK) {
74 			strcpy(device_path, "couldn't determine device path");
75 		}
76 	}
77 
78 	mdb_printf("\n");
79 	if (verbose)
80 		mdb_printf("%s\n", device_path);
81 	mdb_printf("Physical/Logical Target\n");
82 	mdb_printf("-----------------------\n");
83 
84 	if (mdb_vread(&mr_ldp, sizeof (mr_ldp), (uintptr_t)m->mr_ld_list)
85 	    == -1 ||
86 	    mdb_vread(&mr_pdp, sizeof (mr_pdp), (uintptr_t)m->mr_tbolt_pd_list)
87 	    == -1) {
88 		mdb_warn("can't read list of disks");
89 		return;
90 	}
91 
92 	for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) {
93 		if (mr_ldp[tgt].dip != NULL &&
94 		    mr_ldp[tgt].lun_type == MRSAS_LD_LUN) {
95 			mdb_printf("Logical          sd %d\n", tgt);
96 		}
97 	}
98 	for (tgt = 0; tgt < MRSAS_TBOLT_PD_TGT_MAX; tgt++) {
99 		if (mr_pdp[tgt].dip != NULL &&
100 		    mr_pdp[tgt].lun_type == MRSAS_TBOLT_PD_LUN) {
101 			mdb_printf("Physical         sd %d\n", tgt);
102 		}
103 	}
104 	mdb_printf("\n");
105 }
106 
107 void
display_deviceinfo(struct mrsas_instance * m)108 display_deviceinfo(struct mrsas_instance *m)
109 {
110 	uint16_t vid, did, svid, sid;
111 
112 	vid = m->vendor_id;
113 	did = m->device_id;
114 	svid = m->subsysvid;
115 	sid = m->subsysid;
116 
117 	mdb_printf("\n");
118 	mdb_printf("vendor_id device_id subsysvid subsysid");
119 	mdb_printf("\n");
120 	mdb_printf("--------------------------------------");
121 	mdb_printf("\n");
122 	mdb_printf("    0x%x   0x%x    0x%x    0x%x",
123 	    vid, did, svid, sid);
124 	mdb_printf("\n");
125 }
126 
127 static int
mr_sas_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)128 mr_sas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
129 {
130 	struct mrsas_instance m;
131 
132 	int	instance;
133 	uint16_t ncmds;
134 	uint_t	verbose = FALSE;
135 	uint_t	device_info = FALSE;
136 	uint_t	target_info = FALSE;
137 	int	rv = DCMD_OK;
138 	void	*mrsas_state;
139 
140 	if (!(flags & DCMD_ADDRSPEC)) {
141 		mrsas_state = NULL;
142 		if (mdb_readvar(&mrsas_state, "mrsas_state") == -1) {
143 			mdb_warn("can't read mrsas_state");
144 			return (DCMD_ERR);
145 		}
146 		if (mdb_pwalk_dcmd("genunix`softstate", "mr_sas`mr_sas",
147 		    argc, argv, (uintptr_t)mrsas_state) == -1) {
148 			mdb_warn("mdb_pwalk_dcmd failed");
149 			return (DCMD_ERR);
150 		}
151 		return (DCMD_OK);
152 	}
153 
154 	if (mdb_getopts(argc, argv,
155 	    'd', MDB_OPT_SETBITS, TRUE, &device_info,
156 	    't', MDB_OPT_SETBITS, TRUE, &target_info,
157 	    'v', MDB_OPT_SETBITS, TRUE, &verbose,
158 	    NULL) != argc)
159 		return (DCMD_USAGE);
160 
161 	if (mdb_vread(&m, sizeof (m), addr) == -1) {
162 		mdb_warn("couldn't read mrsas_instance struct at 0x%p", addr);
163 		return (DCMD_ERR);
164 	}
165 	instance = m.instance;
166 
167 	/* cmd slot info */
168 	ncmds = m.max_fw_cmds;
169 
170 	/* processing completed */
171 	if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
172 	    (flags & DCMD_LOOPFIRST)) {
173 		if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
174 			mdb_printf("\n");
175 		mdb_printf("         mrsas_t inst max_fw_cmds intr_type");
176 		mdb_printf("\n");
177 		mdb_printf("===========================================");
178 		mdb_printf("\n");
179 	}
180 
181 	mdb_printf("%16p %4d      %4d    ", addr, instance, ncmds);
182 	switch (m.intr_type) {
183 		case DDI_INTR_TYPE_MSIX:
184 			mdb_printf("MSI-X");
185 			break;
186 		case DDI_INTR_TYPE_MSI:
187 			mdb_printf("MSI");
188 			break;
189 		case DDI_INTR_TYPE_FIXED:
190 			mdb_printf("FIXED");
191 			break;
192 		default:
193 			mdb_printf("INVALD");
194 	}
195 	mdb_printf("\n");
196 
197 	if (target_info)
198 		display_targets(&m, verbose);
199 
200 	if (device_info)
201 		display_deviceinfo(&m);
202 
203 	return (rv);
204 }
205 
206 void
mr_sas_help(void)207 mr_sas_help(void)
208 {
209 	mdb_printf("Prints summary information about each mr_sas instance, "
210 	    "Without the address of a \"struct mrsas_instance\", prints every "
211 	    "instance.\n\n"
212 	    "Switches:\n"
213 	    "  -t   includes information about targets\n"
214 	    "  -d   includes information about the hardware\n"
215 	    "  -v   displays extra information for some options\n");
216 }
217 
218 static const mdb_dcmd_t dcmds[] = {
219 	{ "mr_sas", "?[-tdv]", "print mr_sas information", mr_sas_dcmd,
220 	    mr_sas_help },
221 	{ NULL }
222 };
223 
224 static const mdb_modinfo_t modinfo = {
225 	MDB_API_VERSION, dcmds, NULL
226 };
227 
228 const mdb_modinfo_t *
_mdb_init(void)229 _mdb_init(void)
230 {
231 	return (&modinfo);
232 }
233