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