cmds.c revision 1.5 1 /* $NetBSD: cmds.c,v 1.5 2002/04/07 20:20:31 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*-
40 * Copyright (c) 1999 Michael Smith
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * from FreeBSD: command.c,v 1.2 2000/04/11 23:04:17 msmith Exp
65 */
66
67 #ifndef lint
68 #include <sys/cdefs.h>
69 __RCSID("$NetBSD: cmds.c,v 1.5 2002/04/07 20:20:31 ad Exp $");
70 #endif /* not lint */
71
72 #include <sys/types.h>
73 #include <sys/ioctl.h>
74 #include <sys/queue.h>
75 #include <sys/endian.h>
76
77 #include <dev/ic/mlxreg.h>
78 #include <dev/ic/mlxio.h>
79
80 #include <err.h>
81 #include <fcntl.h>
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <string.h>
85 #include <ctype.h>
86 #include <unistd.h>
87 #include <getopt.h>
88
89 #include "extern.h"
90
91 static void cmd_status0(struct mlx_disk *);
92 static void cmd_check0(struct mlx_disk *);
93 static void cmd_detach0(struct mlx_disk *);
94
95 static struct mlx_rebuild_status rs;
96 static int rstatus;
97
98 struct {
99 int hwid;
100 const char *name;
101 } static const mlx_ctlr_names[] = {
102 { 0x01, "960P/PD" },
103 { 0x02, "960PL" },
104 { 0x10, "960PG" },
105 { 0x11, "960PJ" },
106 { 0x12, "960PR" },
107 { 0x13, "960PT" },
108 { 0x14, "960PTL0" },
109 { 0x15, "960PRL" } ,
110 { 0x16, "960PTL1" },
111 { 0x20, "1100PVX" },
112 { -1, NULL },
113 };
114
115 /*
116 * Status output
117 */
118 static void
119 cmd_status0(struct mlx_disk *md)
120 {
121 int result;
122
123 result = md->hwunit;
124 if (ioctl(mlxfd, MLXD_STATUS, &result) < 0)
125 err(EXIT_FAILURE, "ioctl(MLXD_STATUS)");
126
127 switch(result) {
128 case MLX_SYSD_ONLINE:
129 printf("%s: online\n", md->name);
130 break;
131
132 case MLX_SYSD_CRITICAL:
133 printf("%s: critical\n", md->name);
134 if (!rstatus)
135 rstatus = 1;
136 break;
137
138 case MLX_SYSD_OFFLINE:
139 printf("%s: offline\n", md->name);
140 rstatus = 2;
141 break;
142
143 default:
144 printf("%s: unknown status 0x%02x\n", md->name, result);
145 break;
146 }
147
148 /* Rebuild/check in progress on this drive? */
149 if (rs.rs_drive == md->hwunit &&
150 rs.rs_code != MLX_REBUILDSTAT_IDLE) {
151 switch(rs.rs_code) {
152 case MLX_REBUILDSTAT_REBUILDCHECK:
153 printf(" [consistency check");
154 break;
155
156 case MLX_REBUILDSTAT_ADDCAPACITY:
157 printf(" [add capacity");
158 break;
159
160 case MLX_REBUILDSTAT_ADDCAPACITYINIT:
161 printf(" [add capacity init");
162 break;
163
164 default:
165 printf(" [unknown operation");
166 break;
167 }
168
169 printf(": %d/%d, %d%% complete]\n", rs.rs_remaining, rs.rs_size,
170 ((rs.rs_size - rs.rs_remaining) / (rs.rs_size / 100)));
171 }
172 }
173
174 int
175 cmd_status(char **argv)
176 {
177
178 if (ioctl(mlxfd, MLX_REBUILDSTAT, &rs) < 0)
179 err(EXIT_FAILURE, "ioctl(MLX_REBUILDSTAT)");
180
181 mlx_disk_iterate(cmd_status0);
182 return (rstatus);
183 }
184
185 /*
186 * Display controller status.
187 */
188 int
189 cmd_cstatus(char **argv)
190 {
191 struct mlx_enquiry2 enq;
192 struct mlx_phys_drv pd;
193 static char buf[80];
194 const char *model;
195 int i, channel, target;
196
197 mlx_enquiry(&enq);
198
199 for (i = 0; i < sizeof(mlx_ctlr_names) / sizeof(mlx_ctlr_names[0]); i++)
200 if (enq.me_hardware_id[0] == mlx_ctlr_names[i].hwid) {
201 model = mlx_ctlr_names[i].name;
202 break;
203 }
204
205 if (i == sizeof(mlx_ctlr_names) / sizeof(mlx_ctlr_names[0])) {
206 sprintf(buf, " model 0x%x", enq.me_hardware_id[0]);
207 model = buf;
208 }
209
210 printf("DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
211 model, enq.me_actual_channels,
212 enq.me_actual_channels > 1 ? "s" : "",
213 enq.me_firmware_id[0], enq.me_firmware_id[1],
214 enq.me_firmware_id[3], enq.me_firmware_id[2],
215 le32toh(enq.me_mem_size) / (1024 * 1024));
216
217 if (verbosity > 0) {
218 printf(" Hardware ID\t\t\t0x%08x\n",
219 le32toh(*(u_int32_t *)enq.me_hardware_id));
220 printf(" Firmware ID\t\t\t0x%08x\n",
221 le32toh(*(u_int32_t *)enq.me_firmware_id));
222 printf(" Configured/Actual channels\t%d/%d\n",
223 enq.me_configured_channels, enq.me_actual_channels);
224 printf(" Max Targets\t\t\t%d\n", enq.me_max_targets);
225 printf(" Max Tags\t\t\t%d\n", enq.me_max_tags);
226 printf(" Max System Drives\t\t%d\n", enq.me_max_sys_drives);
227 printf(" Max Arms\t\t\t%d\n", enq.me_max_arms);
228 printf(" Max Spans\t\t\t%d\n", enq.me_max_spans);
229 printf(" DRAM/cache/flash/NVRAM size\t%d/%d/%d/%d\n",
230 le32toh(enq.me_mem_size), le32toh(enq.me_cache_size),
231 le32toh(enq.me_flash_size), le32toh(enq.me_nvram_size));
232 printf(" DRAM type\t\t\t%d\n", le16toh(enq.me_mem_type));
233 printf(" Clock Speed\t\t\t%dns\n",
234 le16toh(enq.me_clock_speed));
235 printf(" Hardware Speed\t\t%dns\n",
236 le16toh(enq.me_hardware_speed));
237 printf(" Max Commands\t\t\t%d\n",
238 le16toh(enq.me_max_commands));
239 printf(" Max SG Entries\t\t%d\n", le16toh(enq.me_max_sg));
240 printf(" Max DP\t\t\t%d\n", le16toh(enq.me_max_dp));
241 printf(" Max IOD\t\t\t%d\n", le16toh(enq.me_max_iod));
242 printf(" Max Comb\t\t\t%d\n", le16toh(enq.me_max_comb));
243 printf(" Latency\t\t\t%ds\n", enq.me_latency);
244 printf(" SCSI Timeout\t\t\t%ds\n", enq.me_scsi_timeout);
245 printf(" Min Free Lines\t\t%d\n",
246 le16toh(enq.me_min_freelines));
247 printf(" Rate Constant\t\t\t%d\n", enq.me_rate_const);
248 printf(" MAXBLK\t\t\t%d\n", le16toh(enq.me_maxblk));
249 printf(" Blocking Factor\t\t%d sectors\n",
250 le16toh(enq.me_blocking_factor));
251 printf(" Cache Line Size\t\t%d blocks\n",
252 le16toh(enq.me_cacheline));
253 printf(" SCSI Capability\t\t%s%dMHz, %d bit\n",
254 enq.me_scsi_cap & (1<<4) ? "differential " : "",
255 (1 << ((enq.me_scsi_cap >> 2) & 3)) * 10,
256 8 << (enq.me_scsi_cap & 0x3));
257 printf(" Firmware Build Number\t\t%d\n",
258 le16toh(enq.me_firmware_build));
259 printf(" Fault Management Type\t\t%d\n",
260 enq.me_fault_mgmt_type);
261 #if 0
262 printf(" Features\t\t\t%b\n", enq.me_firmware_features,
263 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
264 #endif
265 }
266
267 fflush(stdout);
268
269 /*
270 * Fetch and print physical drive data.
271 */
272 for (channel = 0; channel < enq.me_configured_channels; channel++) {
273 for (target = 0; target < enq.me_max_targets; target++)
274 if (mlx_get_device_state(channel, target, &pd) == 0 &&
275 (pd.pd_flags1 & MLX_PHYS_DRV_PRESENT) != 0)
276 mlx_print_phys_drv(&pd, channel, target, " ");
277 }
278
279 return (0);
280 }
281
282 /*
283 * Recscan for new or changed system drives.
284 */
285 int
286 cmd_rescan(char **argv)
287 {
288
289 if (ioctl(mlxfd, MLX_RESCAN_DRIVES) < 0)
290 err(EXIT_FAILURE, "rescan failed");
291 return (0);
292 }
293
294 /*
295 * Detach one or more system drives from a controller.
296 */
297 static void
298 cmd_detach0(struct mlx_disk *md)
299 {
300
301 if (ioctl(mlxfd, MLXD_DETACH, &md->hwunit) < 0)
302 warn("can't detach %s", md->name);
303 }
304
305 int
306 cmd_detach(char **argv)
307 {
308
309 mlx_disk_iterate(cmd_detach0);
310 return (0);
311 }
312
313 /*
314 * Initiate a consistency check on a system drive.
315 */
316 static void
317 cmd_check0(struct mlx_disk *md)
318 {
319 int result;
320
321 if (ioctl(mlxfd, MLXD_CHECKASYNC, &result) == 0)
322 return;
323
324 switch (result) {
325 case 0x0002:
326 warnx("one or more of the SCSI disks on which %s", md->name);
327 warnx("depends is DEAD.");
328 break;
329
330 case 0x0105:
331 warnx("drive %s is invalid, or not a drive which ", md->name);
332 warnx("can be checked.");
333 break;
334
335 case 0x0106:
336 warnx("drive rebuild or consistency check is already ");
337 warnx("in progress on this controller.");
338 break;
339
340 default:
341 err(EXIT_FAILURE, "ioctl(MLXD_CHECKASYNC)");
342 /* NOTREACHED */
343 }
344 }
345
346 int
347 cmd_check(char **argv)
348 {
349
350 mlx_disk_iterate(cmd_check0);
351 return (0);
352 }
353
354 /*
355 * Initiate a physical drive rebuild.
356 */
357 int
358 cmd_rebuild(char **argv)
359 {
360 struct mlx_rebuild_request rb;
361 char *p;
362
363 if (argv[0] == NULL || argv[1] != NULL)
364 usage();
365
366 rb.rr_channel = (int)strtol(*argv, &p, 0);
367 if (p[0] != ':' || p[1] == '\0')
368 usage();
369
370 rb.rr_target = (int)strtol(*argv, &p, 0);
371 if (p[0] != '\0')
372 usage();
373
374 if (ioctl(mlxfd, MLX_REBUILDASYNC, &rb) == 0)
375 return (0);
376
377 switch (rb.rr_status) {
378 case 0x0002:
379 warnx("the drive at %d:%d is already ONLINE", rb.rr_channel,
380 rb.rr_target);
381 break;
382
383 case 0x0004:
384 warnx("drive failed during rebuild");
385 break;
386
387 case 0x0105:
388 warnx("there is no drive at %d:%d", rb.rr_channel,
389 rb.rr_target);
390 break;
391
392 case 0x0106:
393 warnx("drive rebuild or consistency check is already in ");
394 warnx("progress on this controller");
395 break;
396
397 default:
398 err(EXIT_FAILURE, "ioctl(MLXD_CHECKASYNC)");
399 /* NOTREACHED */
400 }
401
402 return(0);
403 }
404