17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7f000930Syw161884 * Common Development and Distribution License (the "License"). 6*7f000930Syw161884 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 223a4e43d3Ssafa * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <ctype.h> 297c478bd9Sstevel@tonic-gate #include <dirent.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <langinfo.h> 337c478bd9Sstevel@tonic-gate #include <libintl.h> 347c478bd9Sstevel@tonic-gate #include <limits.h> 357c478bd9Sstevel@tonic-gate #include <locale.h> 367c478bd9Sstevel@tonic-gate #include <stdarg.h> 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <string.h> 407c478bd9Sstevel@tonic-gate #include <strings.h> 417c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 427c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi.h> 437c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi_ioc.h> 447c478bd9Sstevel@tonic-gate #include <sys/stat.h> 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate #include <sys/pci.h> 477c478bd9Sstevel@tonic-gate #include <unistd.h> 487c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 497c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 507c478bd9Sstevel@tonic-gate #include <config_admin.h> 517c478bd9Sstevel@tonic-gate #include <sys/param.h> 527c478bd9Sstevel@tonic-gate #include <sys/raidioctl.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * list of controllers to list 567c478bd9Sstevel@tonic-gate * setup like this: 577c478bd9Sstevel@tonic-gate * [ctrl_num] [status] 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * where status is: 607c478bd9Sstevel@tonic-gate * RAID Found, 617c478bd9Sstevel@tonic-gate * No RAID Found 627c478bd9Sstevel@tonic-gate * RAID not supported on this controller 637c478bd9Sstevel@tonic-gate * Invalid Controller 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate typedef enum { 677c478bd9Sstevel@tonic-gate RAID_FOUND = 0x0, 687c478bd9Sstevel@tonic-gate RAID_NOT_FOUND, 697c478bd9Sstevel@tonic-gate RAID_NOT_SUPPORTED, 707c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL, 717c478bd9Sstevel@tonic-gate RAID_DONT_USE 727c478bd9Sstevel@tonic-gate } raidctl_errno_t; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* For no-mixup indexing of info_ctrl */ 757c478bd9Sstevel@tonic-gate #define INFO_CTRL 0 767c478bd9Sstevel@tonic-gate #define INFO_STATUS 1 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static int **info_ctrl = NULL; 797c478bd9Sstevel@tonic-gate /* Length of conrollers list */ 807c478bd9Sstevel@tonic-gate static int ctrl_nums = 0; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #define DEVDIR "/dev/rdsk" 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define DO_HW_RAID_NOP -1 867c478bd9Sstevel@tonic-gate #define DO_HW_RAID_INFO 0 877c478bd9Sstevel@tonic-gate #define DO_HW_RAID_CREATE 1 887c478bd9Sstevel@tonic-gate #define DO_HW_RAID_DELETE 2 897c478bd9Sstevel@tonic-gate #define DO_HW_RAID_FLASH 3 907c478bd9Sstevel@tonic-gate 916fec3791Sjesseb /* values to use for raid level in raidctl */ 926fec3791Sjesseb #define RAID_STRIPE 0 936fec3791Sjesseb #define RAID_MIRROR 1 946fec3791Sjesseb 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * Error return codes 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate #define SUCCESS 0 997c478bd9Sstevel@tonic-gate #define INVALID_ARG 1 1007c478bd9Sstevel@tonic-gate #define FAILURE 2 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * FW Update Stuff 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* signature and initial offset for PCI expansion rom images */ 1077c478bd9Sstevel@tonic-gate #define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */ 1087c478bd9Sstevel@tonic-gate #define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* offsets in PCI data structure header */ 1117c478bd9Sstevel@tonic-gate #define PCIR_DEVID 0x6 /* PCI device id */ 1127c478bd9Sstevel@tonic-gate #define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */ 1137c478bd9Sstevel@tonic-gate #define PCIR_INDICATOR 0x15 /* "last image" indicator */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* flags for image types */ 1167c478bd9Sstevel@tonic-gate #define BIOS_IMAGE 0x1 1177c478bd9Sstevel@tonic-gate #define FCODE_IMAGE 0x2 1187c478bd9Sstevel@tonic-gate #define UNKNOWN_IMAGE 0x3 1197c478bd9Sstevel@tonic-gate #define LAST_IMAGE 0x80 1207c478bd9Sstevel@tonic-gate #define NOT_LAST_IMAGE 0 1217c478bd9Sstevel@tonic-gate #define PCI_IMAGE_UNIT_SIZE 512 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* ID's and offsets for MPT Firmware images */ 1247c478bd9Sstevel@tonic-gate #define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */ 1257c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */ 1267c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ 1277c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ 1287c478bd9Sstevel@tonic-gate 1296fec3791Sjesseb /* ID's for supported chips */ 1306fec3791Sjesseb #define LSI_1030 0x30 1316fec3791Sjesseb #define LSI_1064 0x50 1326fec3791Sjesseb #define LSI_1064E 0x56 1336fec3791Sjesseb #define LSI_1068E 0x58 1346fec3791Sjesseb 1357c478bd9Sstevel@tonic-gate /* Key to search for when looking for fcode version */ 1367c478bd9Sstevel@tonic-gate #define FCODE_VERS_KEY1 0x12 1377c478bd9Sstevel@tonic-gate #define FCODE_VERS_KEY2 0x7 138*7f000930Syw161884 #define BIOS_STR "LSI SCSI Host Adapter BIOS Driver: " 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* get a word from a buffer (works with non-word aligned offsets) */ 1417c478bd9Sstevel@tonic-gate #define gw(x) (((x)[0]) + (((x)[1]) << 8)) 1427c478bd9Sstevel@tonic-gate 1436fec3791Sjesseb /* Number of disks currently supported, per RAID volume */ 1446fec3791Sjesseb #define N_DISKS 8 1456fec3791Sjesseb 1466fec3791Sjesseb /* Maximum number of RAID volumes currently supported per HBA */ 1476fec3791Sjesseb #define N_RAIDVOLS 2 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * Function and strings to properly localize our prompt. 1517c478bd9Sstevel@tonic-gate * So for example in german it would ask (ja/nein) or (yes/no) in 1527c478bd9Sstevel@tonic-gate * english. 1537c478bd9Sstevel@tonic-gate */ 1546fec3791Sjesseb static int yes(void); 1557c478bd9Sstevel@tonic-gate static char yeschr[SCHAR_MAX + 2]; 1567c478bd9Sstevel@tonic-gate static char nochr[SCHAR_MAX +2]; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate typedef struct raidlist { 1596fec3791Sjesseb raid_config_t raid_config[N_RAIDVOLS]; 1607c478bd9Sstevel@tonic-gate int controller; 1617c478bd9Sstevel@tonic-gate char devctl[MAXPATHLEN]; 1627c478bd9Sstevel@tonic-gate struct raidlist *next; 1637c478bd9Sstevel@tonic-gate } raidlist_t; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate static raidlist_t *raids; 1667c478bd9Sstevel@tonic-gate 1676fec3791Sjesseb /* 1686fec3791Sjesseb * usage: raidctl 1696fec3791Sjesseb * usage: raidctl [-f] -c primary secondary 1706fec3791Sjesseb * usage: raidctl [-f] -c -r 1 primary secondary 1716fec3791Sjesseb * usage: raidctl [-f] -c -r 0 disk1 disk2 [disk3] ... 1726fec3791Sjesseb * usage: raidctl [-f] -d volume 1736fec3791Sjesseb * usage: raidctl [-f] -F image_file controller 1746fec3791Sjesseb * usage: raidctl -l [controller...] 1756fec3791Sjesseb * example: 1766fec3791Sjesseb * raidctl -c c1t1d0 c1t2d0 1776fec3791Sjesseb * raidctl -c -r 0 c1t1d0 c1t2d0 c1t3d0 c1t4d0 1786fec3791Sjesseb * raidctl -d c1t1d0 1796fec3791Sjesseb * raidctl -F image 1 1806fec3791Sjesseb */ 1817c478bd9Sstevel@tonic-gate static void 1827c478bd9Sstevel@tonic-gate usage(char *prog_name) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s\n"), prog_name); 1857c478bd9Sstevel@tonic-gate 1866fec3791Sjesseb (void) fprintf(stderr, gettext("usage: %s [-f] -c primary secondary\n"), 1877c478bd9Sstevel@tonic-gate prog_name); 1886fec3791Sjesseb 1896fec3791Sjesseb (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 1 primary " 1906fec3791Sjesseb "secondary\n"), prog_name); 1916fec3791Sjesseb 1926fec3791Sjesseb (void) fprintf(stderr, gettext("usage: %s [-f] -c -r 0 disk1 disk2 " 1936fec3791Sjesseb "[disk3] ...\n"), prog_name); 1946fec3791Sjesseb 1956fec3791Sjesseb (void) fprintf(stderr, gettext("usage: %s [-f] -d volume\n"), 1966fec3791Sjesseb prog_name); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1997c478bd9Sstevel@tonic-gate gettext("usage: %s [-f] -F image_file controller \n"), 2007c478bd9Sstevel@tonic-gate prog_name); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"), 2037c478bd9Sstevel@tonic-gate prog_name); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("example:\n")); 2067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); 2076fec3791Sjesseb (void) fprintf(stderr, "%s -c -r 0 c1t1d0 c1t2d0 " 2086fec3791Sjesseb "c1t3d0 c1t4d0\n", prog_name); 2097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); 2107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -F image 1\n", prog_name); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate exit(1); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* Make errno message more "user friendly" */ 2167c478bd9Sstevel@tonic-gate static void 2177c478bd9Sstevel@tonic-gate raidctl_error(char *str) 2187c478bd9Sstevel@tonic-gate { 2197c478bd9Sstevel@tonic-gate switch (errno) { 2203a4e43d3Ssafa case EINVAL: 2213a4e43d3Ssafa (void) fprintf(stderr, gettext("Error: " 2223a4e43d3Ssafa "invalid argument would be returned\n")); 2233a4e43d3Ssafa break; 2247c478bd9Sstevel@tonic-gate case EIO: 2257c478bd9Sstevel@tonic-gate case EFAULT: 2267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2277c478bd9Sstevel@tonic-gate gettext("Error: Device inaccessible.\n")); 2287c478bd9Sstevel@tonic-gate break; 2297c478bd9Sstevel@tonic-gate case ENOTTY: 2307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error: " 2317c478bd9Sstevel@tonic-gate "Device does not support requested action.\n")); 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate default: 2347c478bd9Sstevel@tonic-gate perror(str); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate static int 2397c478bd9Sstevel@tonic-gate get_link_path(const char *thing, char *buf) 2407c478bd9Sstevel@tonic-gate { 2417c478bd9Sstevel@tonic-gate if (readlink(thing, buf, MAXPATHLEN) < 0) 2427c478bd9Sstevel@tonic-gate return (1); 2437c478bd9Sstevel@tonic-gate return (0); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate static int 2477c478bd9Sstevel@tonic-gate get_ctrl_devctl(char *ctrl, char *b) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2507c478bd9Sstevel@tonic-gate char *colon; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate colon = strrchr(devctl_buf, ':'); 2557c478bd9Sstevel@tonic-gate if (colon == NULL) 2567c478bd9Sstevel@tonic-gate return (1); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate *colon = 0; 2597c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf); 2607c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 2617c478bd9Sstevel@tonic-gate return (0); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate static int 2657c478bd9Sstevel@tonic-gate get_devctl(char *disk, char *b) 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 2687c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2697c478bd9Sstevel@tonic-gate char *slash; 2707c478bd9Sstevel@tonic-gate char devname[32]; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (get_link_path(disk, buf1)) 2737c478bd9Sstevel@tonic-gate return (1); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, buf1, MAXPATHLEN); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2787c478bd9Sstevel@tonic-gate if (slash == NULL) 2797c478bd9Sstevel@tonic-gate return (1); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate *slash = 0; 2827c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2837c478bd9Sstevel@tonic-gate (void) strlcpy(devname, slash, 32); 2847c478bd9Sstevel@tonic-gate *slash = 0; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", 2877c478bd9Sstevel@tonic-gate devctl_buf, devname); 2886fec3791Sjesseb 2897c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 2906fec3791Sjesseb 2917c478bd9Sstevel@tonic-gate return (0); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate static int 2957c478bd9Sstevel@tonic-gate already_there(int controller) 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate while (curr != NULL) { 3007c478bd9Sstevel@tonic-gate if (curr->controller == controller) 3017c478bd9Sstevel@tonic-gate return (1); 3026fec3791Sjesseb 3037c478bd9Sstevel@tonic-gate curr = curr->next; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate return (0); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * Display those controllers where RAID volumes were not found 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate static void 3137c478bd9Sstevel@tonic-gate print_no_raids() 3147c478bd9Sstevel@tonic-gate { 3157c478bd9Sstevel@tonic-gate int i, space = 0; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 3187c478bd9Sstevel@tonic-gate return; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 3217c478bd9Sstevel@tonic-gate /* Status of '0' means RAID exists at that controller */ 3227c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_FOUND || 3237c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 3247c478bd9Sstevel@tonic-gate continue; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (!space && raids != NULL) { 3277c478bd9Sstevel@tonic-gate (void) printf("\n"); 3287c478bd9Sstevel@tonic-gate space = 1; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* switch statement used to enable gettext()'ing of text */ 3327c478bd9Sstevel@tonic-gate switch (info_ctrl[i][INFO_STATUS]) { 3337c478bd9Sstevel@tonic-gate case RAID_INVALID_CTRL: 3347c478bd9Sstevel@tonic-gate (void) printf(gettext("Invalid controller '%d'\n"), 3357c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 3367c478bd9Sstevel@tonic-gate break; 3377c478bd9Sstevel@tonic-gate case RAID_NOT_SUPPORTED: 3387c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID supported " 3397c478bd9Sstevel@tonic-gate "on controller '%d'\n"), 3407c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate break; 3437c478bd9Sstevel@tonic-gate default: 3447c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found on " 3457c478bd9Sstevel@tonic-gate "controller '%d'\n"), info_ctrl[i][INFO_CTRL]); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate static void 3517c478bd9Sstevel@tonic-gate add_raid_to_raidlist(char *ctrl_name, int controller) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate raidlist_t *curr; 3547c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 3557c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 3566fec3791Sjesseb int nvols; 3578ba1bcfcSdduvall int fd; 3588ba1bcfcSdduvall int i; 3596fec3791Sjesseb int n; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if (readlink(ctrl_name, buf, sizeof (buf)) < 0) 3627c478bd9Sstevel@tonic-gate return; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if (get_ctrl_devctl(buf, buf1)) 3657c478bd9Sstevel@tonic-gate return; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* 3687c478bd9Sstevel@tonic-gate * If "-l" was specified, then only look at those controllers 3697c478bd9Sstevel@tonic-gate * listed as part of the command line input. 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 3727c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 3737c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 3747c478bd9Sstevel@tonic-gate continue; 3756fec3791Sjesseb if (controller == info_ctrl[i][INFO_CTRL]) 3767c478bd9Sstevel@tonic-gate break; 3777c478bd9Sstevel@tonic-gate } 3786fec3791Sjesseb /* return if we didn't find a controller */ 3796fec3791Sjesseb if (i == ctrl_nums) 3807c478bd9Sstevel@tonic-gate return; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate fd = open(buf1, O_RDONLY); 3847c478bd9Sstevel@tonic-gate if (fd == -1) { 3857c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3867c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL; 3877c478bd9Sstevel@tonic-gate return; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3906fec3791Sjesseb /* 3916fec3791Sjesseb * query the HBA driver for volume capacity 3926fec3791Sjesseb */ 3936fec3791Sjesseb if (ioctl(fd, RAID_NUMVOLUMES, &nvols) < 0) { 3946fec3791Sjesseb if (info_ctrl != NULL) 3956fec3791Sjesseb info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 3966fec3791Sjesseb (void) close(fd); 3976fec3791Sjesseb return; 3986fec3791Sjesseb } 3996fec3791Sjesseb 4006fec3791Sjesseb /* 4016fec3791Sjesseb * now iterate through nvols configurations 4026fec3791Sjesseb */ 4036fec3791Sjesseb for (n = 0; n < nvols; n++) { 4046fec3791Sjesseb raid_config_t config; 4056fec3791Sjesseb 4066fec3791Sjesseb /* use unitid to retrieve this volume */ 4076fec3791Sjesseb config.unitid = n; 4087c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 4097c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 4107c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 4117c478bd9Sstevel@tonic-gate (void) close(fd); 4127c478bd9Sstevel@tonic-gate return; 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 4156fec3791Sjesseb /* if ndisks is 0, this volume is not configured */ 4166fec3791Sjesseb if (config.ndisks == 0) 4176fec3791Sjesseb continue; 4186fec3791Sjesseb 4196fec3791Sjesseb /* otherwise, we have a raid volume */ 4207c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 4217c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_FOUND; 4227c478bd9Sstevel@tonic-gate 4236fec3791Sjesseb /* 4246fec3791Sjesseb * if raids has not been initialized, do it. 4256fec3791Sjesseb * otherwise, see if this controller is in 4266fec3791Sjesseb * raids. 4276fec3791Sjesseb */ 4287c478bd9Sstevel@tonic-gate if (raids == NULL) { 4297c478bd9Sstevel@tonic-gate raids = (raidlist_t *)malloc(sizeof (raidlist_t)); 4307c478bd9Sstevel@tonic-gate curr = raids; 4317c478bd9Sstevel@tonic-gate } else { 4327c478bd9Sstevel@tonic-gate curr = raids; 4336fec3791Sjesseb if (already_there(controller)) 4346fec3791Sjesseb goto already_there; 4356fec3791Sjesseb 4366fec3791Sjesseb /* add this controller to raids */ 4377c478bd9Sstevel@tonic-gate while (curr->next != NULL) 4387c478bd9Sstevel@tonic-gate curr = curr->next; 4397c478bd9Sstevel@tonic-gate curr->next = (raidlist_t *)malloc(sizeof (raidlist_t)); 4407c478bd9Sstevel@tonic-gate curr = curr->next; 4417c478bd9Sstevel@tonic-gate } 4426fec3791Sjesseb 4436fec3791Sjesseb already_there: 4447c478bd9Sstevel@tonic-gate curr->next = NULL; 4457c478bd9Sstevel@tonic-gate curr->controller = controller; 4467c478bd9Sstevel@tonic-gate (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); 4477c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4486fec3791Sjesseb (void) memcpy(&curr->raid_config[n], &config, 4496fec3791Sjesseb (sizeof (raid_config_t))); 4506fec3791Sjesseb } 4516fec3791Sjesseb 4526fec3791Sjesseb if (info_ctrl != NULL && info_ctrl[i][INFO_STATUS] != RAID_FOUND) 4536fec3791Sjesseb info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate static void 4577c478bd9Sstevel@tonic-gate print_header() 4587c478bd9Sstevel@tonic-gate { 4596fec3791Sjesseb (void) printf(gettext("RAID\tVolume\tRAID\t\tRAID\t\tDisk")); 4607c478bd9Sstevel@tonic-gate (void) printf("\n"); 4616fec3791Sjesseb (void) printf(gettext("Volume\tType\tStatus\t\tDisk\t\tStatus")); 4627c478bd9Sstevel@tonic-gate (void) printf("\n"); 4637c478bd9Sstevel@tonic-gate (void) printf("------------------------------------------------------"); 4647c478bd9Sstevel@tonic-gate (void) printf("\n"); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate static void 4687c478bd9Sstevel@tonic-gate print_raidconfig(int c, raid_config_t config) 4697c478bd9Sstevel@tonic-gate { 4707c478bd9Sstevel@tonic-gate int i; 4716fec3791Sjesseb char voltype[8]; 4727c478bd9Sstevel@tonic-gate 4736fec3791Sjesseb /* print RAID volume target ID and volume type */ 4746fec3791Sjesseb if (config.raid_level == RAID_STRIPE) { 4756fec3791Sjesseb (void) snprintf(voltype, sizeof (voltype), "IS"); 4766fec3791Sjesseb } else if (config.raid_level == RAID_MIRROR) { 4776fec3791Sjesseb (void) snprintf(voltype, sizeof (voltype), "IM"); 4786fec3791Sjesseb } 4796fec3791Sjesseb 4806fec3791Sjesseb (void) printf("c%dt%dd0\t%s\t", c, config.targetid, voltype); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* Get RAID Info */ 4837c478bd9Sstevel@tonic-gate if (config.flags & RAID_FLAG_RESYNCING && 4847c478bd9Sstevel@tonic-gate config.state == RAID_STATE_DEGRADED) { 4857c478bd9Sstevel@tonic-gate (void) printf(gettext("RESYNCING\t")); 4867c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_DEGRADED) { 4877c478bd9Sstevel@tonic-gate (void) printf(gettext("DEGRADED\t")); 4887c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_OPTIMAL) { 4897c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\t\t")); 4907c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_FAILED) { 4917c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\t\t")); 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate (void) printf(gettext("ERROR\t\t")); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* Get RAID Disks */ 4977c478bd9Sstevel@tonic-gate (void) printf("c%dt%dd0\t\t", c, config.disk[0]); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* Get RAID Disk's Status */ 5007c478bd9Sstevel@tonic-gate if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) { 5017c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 5027c478bd9Sstevel@tonic-gate } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) { 5037c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 5047c478bd9Sstevel@tonic-gate } else { 5057c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate for (i = 1; i < config.ndisks; i++) { 5097c478bd9Sstevel@tonic-gate (void) printf("\t\t\t\tc%dt%dd0\t\t", c, config.disk[i]); 5107c478bd9Sstevel@tonic-gate if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) { 5117c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 5127c478bd9Sstevel@tonic-gate } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) { 5137c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 5147c478bd9Sstevel@tonic-gate } else { 5157c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate static void 5217c478bd9Sstevel@tonic-gate print_disklist() 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 5246fec3791Sjesseb int i; 5256fec3791Sjesseb 5267c478bd9Sstevel@tonic-gate while (curr != NULL) { 5276fec3791Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 5286fec3791Sjesseb if (curr->raid_config[i].ndisks != 0) { 5296fec3791Sjesseb print_raidconfig(curr->controller, 5306fec3791Sjesseb curr->raid_config[i]); 5316fec3791Sjesseb } 5326fec3791Sjesseb } 5337c478bd9Sstevel@tonic-gate curr = curr->next; 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate static void 5387c478bd9Sstevel@tonic-gate free_disklist() 5397c478bd9Sstevel@tonic-gate { 5407c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate while (curr != NULL) { 5437c478bd9Sstevel@tonic-gate raidlist_t *temp; 5447c478bd9Sstevel@tonic-gate temp = curr; 5457c478bd9Sstevel@tonic-gate curr = curr->next; 5467c478bd9Sstevel@tonic-gate free(temp); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate static void 5517c478bd9Sstevel@tonic-gate do_search() 5527c478bd9Sstevel@tonic-gate { 5537c478bd9Sstevel@tonic-gate DIR *dir; 5547c478bd9Sstevel@tonic-gate struct dirent *dp; 5557c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 5567c478bd9Sstevel@tonic-gate int c; 5577c478bd9Sstevel@tonic-gate int i, j; 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * In case repeated numbers were found, assign the repititions as 5617c478bd9Sstevel@tonic-gate * RAID_DONT_USE 5627c478bd9Sstevel@tonic-gate */ 5637c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 5647c478bd9Sstevel@tonic-gate int first_one = 1; 5657c478bd9Sstevel@tonic-gate for (j = 0; j < ctrl_nums; j++) { 5667c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_CTRL] == 5677c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_CTRL]) { 5687c478bd9Sstevel@tonic-gate if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE) 5697c478bd9Sstevel@tonic-gate continue; 5707c478bd9Sstevel@tonic-gate if (first_one) { 5717c478bd9Sstevel@tonic-gate first_one = 0; 5727c478bd9Sstevel@tonic-gate } else { 5737c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_STATUS] = 5747c478bd9Sstevel@tonic-gate RAID_DONT_USE; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate if ((dir = opendir("/dev/cfg")) == NULL) { 5817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5827c478bd9Sstevel@tonic-gate gettext("Cannot open /dev/cfg: %s\n"), strerror(errno)); 5837c478bd9Sstevel@tonic-gate return; 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate while ((dp = readdir(dir)) != NULL) { 5867c478bd9Sstevel@tonic-gate if (strcmp(dp->d_name, ".") == 0 || 5877c478bd9Sstevel@tonic-gate strcmp(dp->d_name, "..") == 0) 5887c478bd9Sstevel@tonic-gate continue; 5897c478bd9Sstevel@tonic-gate if (sscanf(dp->d_name, "c%d", &c) != 1) 5907c478bd9Sstevel@tonic-gate continue; 5917c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name); 5927c478bd9Sstevel@tonic-gate add_raid_to_raidlist(buf, c); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate (void) closedir(dir); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * do_info() will do the following: 5997c478bd9Sstevel@tonic-gate * - create a list of disks' devctls 6007c478bd9Sstevel@tonic-gate * - try to talk to each of the devctls found 6017c478bd9Sstevel@tonic-gate * - if raid configuration is found, display it. 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate static void 6047c478bd9Sstevel@tonic-gate do_info() 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate int i; 6077c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate do_search(); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (raids == NULL) { 6127c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 6137c478bd9Sstevel@tonic-gate print_no_raids(); 6147c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 6157c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 6167c478bd9Sstevel@tonic-gate free(info_ctrl); 6177c478bd9Sstevel@tonic-gate } else { 6187c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found\n")); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate return; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate print_header(); 6247c478bd9Sstevel@tonic-gate print_disklist(); 6257c478bd9Sstevel@tonic-gate print_no_raids(); 6267c478bd9Sstevel@tonic-gate free_disklist(); 6277c478bd9Sstevel@tonic-gate if (info_ctrl) { 6287c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 6297c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 6307c478bd9Sstevel@tonic-gate free(info_ctrl); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate static int 6356fec3791Sjesseb disk_in_raid(int c, int t) 6366fec3791Sjesseb { 6376fec3791Sjesseb raidlist_t *curr; 6386fec3791Sjesseb raid_config_t raid; 6396fec3791Sjesseb int i, j, n; 6406fec3791Sjesseb 6416fec3791Sjesseb do_search(); 6426fec3791Sjesseb curr = raids; 6436fec3791Sjesseb 6446fec3791Sjesseb while (curr != NULL) { 6456fec3791Sjesseb if (curr->controller == c) { 6466fec3791Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 6476fec3791Sjesseb raid = curr->raid_config[i]; 6486fec3791Sjesseb if ((n = raid.ndisks) != 0) { 6496fec3791Sjesseb for (j = 0; j < n; j++) { 6506fec3791Sjesseb if (raid.disk[j] == t) { 6516fec3791Sjesseb return (1); 6526fec3791Sjesseb } 6536fec3791Sjesseb } 6546fec3791Sjesseb } 6556fec3791Sjesseb } 6566fec3791Sjesseb } 6576fec3791Sjesseb curr = curr->next; 6586fec3791Sjesseb } 6596fec3791Sjesseb return (0); 6606fec3791Sjesseb } 6616fec3791Sjesseb 6626fec3791Sjesseb static int 6637c478bd9Sstevel@tonic-gate disk_there(int c, int t) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate char disk[100]; 6667c478bd9Sstevel@tonic-gate int fd; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate fd = open(disk, O_RDWR | O_NDELAY); 6717c478bd9Sstevel@tonic-gate if (fd == -1) { 6727c478bd9Sstevel@tonic-gate return (-1); 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate (void) close(fd); 6767c478bd9Sstevel@tonic-gate return (0); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate static int 6807c478bd9Sstevel@tonic-gate get_controller(char *dev) 6817c478bd9Sstevel@tonic-gate { 6827c478bd9Sstevel@tonic-gate raidlist_t *curr; 6837c478bd9Sstevel@tonic-gate int c; 6847c478bd9Sstevel@tonic-gate do_search(); 6857c478bd9Sstevel@tonic-gate curr = raids; 6867c478bd9Sstevel@tonic-gate while (curr != NULL) { 6877c478bd9Sstevel@tonic-gate if (strcmp(curr->devctl, dev) == 0) { 6887c478bd9Sstevel@tonic-gate c = curr->controller; 6897c478bd9Sstevel@tonic-gate break; 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate curr = curr->next; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate free_disklist(); 6957c478bd9Sstevel@tonic-gate return (c); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate static int 6997c478bd9Sstevel@tonic-gate disk_mounted(char *d) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate struct mnttab mt; 7027c478bd9Sstevel@tonic-gate FILE *f = fopen("/etc/mnttab", "r"); 7037c478bd9Sstevel@tonic-gate 7048ba1bcfcSdduvall while (getmntent(f, &mt) != EOF) 7057c478bd9Sstevel@tonic-gate if (strstr(mt.mnt_special, d) != NULL) 7067c478bd9Sstevel@tonic-gate return (1); 7076fec3791Sjesseb 7087c478bd9Sstevel@tonic-gate return (0); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate static int 7127c478bd9Sstevel@tonic-gate disk_big_enough(char **d, diskaddr_t *cap, int *errcond) 7137c478bd9Sstevel@tonic-gate { 7147c478bd9Sstevel@tonic-gate struct dk_minfo minfo; 7157c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN]; 7166fec3791Sjesseb uint_t disk_lbsize[N_DISKS]; 7177c478bd9Sstevel@tonic-gate diskaddr_t disk_capacity[N_DISKS]; 7187c478bd9Sstevel@tonic-gate int i, fd; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 7216fec3791Sjesseb if (d[i] == NULL) 7226fec3791Sjesseb break; 7236fec3791Sjesseb 7247c478bd9Sstevel@tonic-gate (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 7257c478bd9Sstevel@tonic-gate fd = open(disk[i], O_RDWR | O_NDELAY); 7266fec3791Sjesseb if (fd == -1) 7277c478bd9Sstevel@tonic-gate return (FAILURE); 7287c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { 7297c478bd9Sstevel@tonic-gate (void) close(fd); 7307c478bd9Sstevel@tonic-gate return (FAILURE); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate disk_lbsize[i] = minfo.dki_lbsize; 7347c478bd9Sstevel@tonic-gate disk_capacity[i] = minfo.dki_capacity; 7357c478bd9Sstevel@tonic-gate 7366fec3791Sjesseb /* lbsize must be the same on all disks */ 7376fec3791Sjesseb if (disk_lbsize[0] != disk_lbsize[i]) { 7387c478bd9Sstevel@tonic-gate *errcond = 2; 7397c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7426fec3791Sjesseb /* ensure drive capacity is greater than or equal to first */ 7436fec3791Sjesseb if (disk_capacity[0] > disk_capacity[i]) { 7447c478bd9Sstevel@tonic-gate *errcond = 1; 7457c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7467c478bd9Sstevel@tonic-gate } 7476fec3791Sjesseb (void) close(fd); 7486fec3791Sjesseb } 7497c478bd9Sstevel@tonic-gate 7506fec3791Sjesseb /* 7516fec3791Sjesseb * setting capacity as the dk_minfo.dki_capacity of d[0] 7526fec3791Sjesseb * this is the number of dki_lbsize blocks on disk 7536fec3791Sjesseb */ 7547c478bd9Sstevel@tonic-gate *cap = disk_capacity[0]; 7557c478bd9Sstevel@tonic-gate return (SUCCESS); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate static int 7597c478bd9Sstevel@tonic-gate do_config_change_state(cfga_cmd_t cmd, int d, int c) 7607c478bd9Sstevel@tonic-gate { 7617c478bd9Sstevel@tonic-gate cfga_err_t cfga_err; 7627c478bd9Sstevel@tonic-gate char *ap_id; 7637c478bd9Sstevel@tonic-gate int rv = SUCCESS; 7647c478bd9Sstevel@tonic-gate int count = 0; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate ap_id = (char *)malloc(100); 7677c478bd9Sstevel@tonic-gate if (ap_id == NULL) 7687c478bd9Sstevel@tonic-gate return (FAILURE); 7697c478bd9Sstevel@tonic-gate 7707c478bd9Sstevel@tonic-gate (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d); 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * If the config_change_state() funcation fails, we want to 7747c478bd9Sstevel@tonic-gate * retry. If the retry fails, then we return failure to fail. 7757c478bd9Sstevel@tonic-gate * 7767c478bd9Sstevel@tonic-gate * If we fail: 7777c478bd9Sstevel@tonic-gate * 7787c478bd9Sstevel@tonic-gate * If we were called from create, then we fail the raid 7797c478bd9Sstevel@tonic-gate * creation. 7807c478bd9Sstevel@tonic-gate * 7817c478bd9Sstevel@tonic-gate * If we were called from delete, then the disk will not 7827c478bd9Sstevel@tonic-gate * be re-configured by raidctl. 7837c478bd9Sstevel@tonic-gate */ 7847c478bd9Sstevel@tonic-gate do { 7857c478bd9Sstevel@tonic-gate cfga_err = config_change_state(cmd, 1, &ap_id, NULL, 7867c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 7877c478bd9Sstevel@tonic-gate count++; 7887c478bd9Sstevel@tonic-gate } while (cfga_err != CFGA_OK && count < 2); 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate if (cfga_err != CFGA_OK) 7917c478bd9Sstevel@tonic-gate rv = FAILURE; 7927c478bd9Sstevel@tonic-gate 7937c478bd9Sstevel@tonic-gate free(ap_id); 7947c478bd9Sstevel@tonic-gate return (rv); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate static int 7986fec3791Sjesseb do_create(char **d, int rlevel, int force) 7997c478bd9Sstevel@tonic-gate { 8008ba1bcfcSdduvall raid_config_t config; 8016fec3791Sjesseb raid_config_t newvol; 8027c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN] = {0}; 8036fec3791Sjesseb int map[N_DISKS]; 8047c478bd9Sstevel@tonic-gate char channel1[MAXPATHLEN]; 8057c478bd9Sstevel@tonic-gate char channel2[MAXPATHLEN]; 8067c478bd9Sstevel@tonic-gate diskaddr_t capacity; 8076fec3791Sjesseb int fd, fd2, size, errcond; 8087c478bd9Sstevel@tonic-gate int c[N_DISKS]; 8097c478bd9Sstevel@tonic-gate int t[N_DISKS]; 8107c478bd9Sstevel@tonic-gate char *tmp; 8116fec3791Sjesseb int loc, i, devid, n, ndisks = 0; 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 8147c478bd9Sstevel@tonic-gate 8156fec3791Sjesseb /* initialize target map */ 8166fec3791Sjesseb for (i = 0; i < N_DISKS; i++) 8176fec3791Sjesseb map[i] = -1; 8186fec3791Sjesseb 8197c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 8206fec3791Sjesseb if (d[i] == NULL) 8216fec3791Sjesseb break; 8226fec3791Sjesseb 8237c478bd9Sstevel@tonic-gate if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || 8247c478bd9Sstevel@tonic-gate t[i] < 0) { 8257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8267c478bd9Sstevel@tonic-gate gettext("Invalid disk format.\n")); 8277c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 8306fec3791Sjesseb /* ensure that all disks are on the same controller, */ 8316fec3791Sjesseb if (c[i] != c[0]) { 8326fec3791Sjesseb (void) fprintf(stderr, gettext("Disks must be " 8336fec3791Sjesseb "on the same controller.\n")); 8347c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8376fec3791Sjesseb /* that all disks are online, */ 8386fec3791Sjesseb if (disk_there(c[0], t[i])) { 8396fec3791Sjesseb (void) printf(gettext("Disk 'c%dt%dd0' is not " 8406fec3791Sjesseb "present.\n"), c[0], t[i]); 8417c478bd9Sstevel@tonic-gate (void) printf(gettext("Cannot create RAID volume.\n")); 8427c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8456fec3791Sjesseb /* that there are no duplicate disks, */ 8466fec3791Sjesseb loc = t[i]; 8476fec3791Sjesseb if (map[loc] == -1) { 8486fec3791Sjesseb map[loc] = t[i]; 8496fec3791Sjesseb } else { 8506fec3791Sjesseb (void) fprintf(stderr, 8516fec3791Sjesseb gettext("Disks must be different.\n")); 8526fec3791Sjesseb return (INVALID_ARG); 8536fec3791Sjesseb } 8546fec3791Sjesseb 8556fec3791Sjesseb /* that no disk is already in use by another volume, */ 8566fec3791Sjesseb if (disk_in_raid(c[0], t[i])) { 8576fec3791Sjesseb (void) fprintf(stderr, gettext("Disk %s is already in " 8586fec3791Sjesseb "a RAID volume.\n"), d[i]); 8596fec3791Sjesseb return (INVALID_ARG); 8606fec3791Sjesseb } 8616fec3791Sjesseb 8626fec3791Sjesseb /* that no target's id is lower than the raidtarg, */ 8636fec3791Sjesseb if (t[0] > t[i]) { 8646fec3791Sjesseb (void) fprintf(stderr, gettext("First target ID must " 8656fec3791Sjesseb "be less than other member target IDs.\n")); 8666fec3791Sjesseb return (INVALID_ARG); 8676fec3791Sjesseb } 8686fec3791Sjesseb 8696fec3791Sjesseb (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 8706fec3791Sjesseb ndisks++; 8716fec3791Sjesseb } 8726fec3791Sjesseb 8736fec3791Sjesseb /* confirm minimum number of disks */ 8746fec3791Sjesseb if (ndisks < 2) { 8756fec3791Sjesseb (void) fprintf(stderr, gettext("At least two disks are required" 8766fec3791Sjesseb " for RAID creation.\n")); 8776fec3791Sjesseb return (INVALID_ARG); 8786fec3791Sjesseb } 8796fec3791Sjesseb 8806fec3791Sjesseb /* validate the drive capacities */ 8817c478bd9Sstevel@tonic-gate switch (disk_big_enough(d, &capacity, &errcond)) { 8827c478bd9Sstevel@tonic-gate case FAILURE: 8837c478bd9Sstevel@tonic-gate return (FAILURE); 8847c478bd9Sstevel@tonic-gate case INVALID_ARG: 8857c478bd9Sstevel@tonic-gate switch (errcond) { 8867c478bd9Sstevel@tonic-gate case 1: 8877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 8887c478bd9Sstevel@tonic-gate "primary disk is larger than secondary disk.\n")); 8897c478bd9Sstevel@tonic-gate break; 8907c478bd9Sstevel@tonic-gate case 2: 8917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 8927c478bd9Sstevel@tonic-gate "disk block sizes differ.\n")); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8976fec3791Sjesseb /* 8986fec3791Sjesseb * capacity is now set to the number of blocks on a disk, which is 8996fec3791Sjesseb * the total capacity of a mirror. the capacity of a stripe is the 9006fec3791Sjesseb * cumulative amount of blocks on all disks 9016fec3791Sjesseb */ 9026fec3791Sjesseb if (rlevel == RAID_STRIPE) 9036fec3791Sjesseb capacity *= ndisks; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (get_devctl(disk[0], channel1)) 9067c478bd9Sstevel@tonic-gate return (FAILURE); 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate fd = open(channel1, O_RDONLY); 9097c478bd9Sstevel@tonic-gate if (fd == -1) { 9107c478bd9Sstevel@tonic-gate perror(channel1); 9117c478bd9Sstevel@tonic-gate return (FAILURE); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 9146fec3791Sjesseb /* 9156fec3791Sjesseb * query the HBA driver for volume capacity 9166fec3791Sjesseb */ 9176fec3791Sjesseb if (ioctl(fd, RAID_NUMVOLUMES, &n) < 0) { 9186fec3791Sjesseb raidctl_error("RAID_NUMVOLUMES"); 9196fec3791Sjesseb goto fail; 9206fec3791Sjesseb } 9216fec3791Sjesseb 9226fec3791Sjesseb /* 9236fec3791Sjesseb * current support for both LSI1030 and LSI1064/1068 HBAs 9246fec3791Sjesseb */ 9256fec3791Sjesseb if (ioctl(fd, RAID_GETDEVID, &devid) < 0) { 9266fec3791Sjesseb raidctl_error("RAID_GETDEVID"); 9276fec3791Sjesseb goto fail; 9286fec3791Sjesseb } 9296fec3791Sjesseb 9306fec3791Sjesseb if ((devid == LSI_1064) || (devid == LSI_1064E) || (devid == 9316fec3791Sjesseb LSI_1068E)) { 9326fec3791Sjesseb /* 9336fec3791Sjesseb * no secondary channel, just check to make 9346fec3791Sjesseb * sure we can fit a new volume 9356fec3791Sjesseb */ 9366fec3791Sjesseb for (i = 0; i < n; i++) { 9376fec3791Sjesseb config.unitid = i; 9387c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 9397c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 9406fec3791Sjesseb goto fail; 9416fec3791Sjesseb } 9426fec3791Sjesseb 9436fec3791Sjesseb if (config.ndisks == 0) 9446fec3791Sjesseb break; 9456fec3791Sjesseb } 9466fec3791Sjesseb 9476fec3791Sjesseb if (i == n) { 9486fec3791Sjesseb (void) printf(gettext("HBA supports a maximum of %d " 9496fec3791Sjesseb "RAID Volumes, HBA is full\n"), n); 9506fec3791Sjesseb goto fail; 9516fec3791Sjesseb } 9526fec3791Sjesseb 9536fec3791Sjesseb /* 9546fec3791Sjesseb * we have the capacity to add a volume, now confirm the 9556fec3791Sjesseb * creation. the 1064 uses a much larger metadata region 9566fec3791Sjesseb * than the 1030 (64MB, as opposed to 16KB). this larger 9576fec3791Sjesseb * reservation is enough to alter the disk label. therefore, 9586fec3791Sjesseb * once the volume is created, it must be relabeled. 9596fec3791Sjesseb * first, confirm that no file systems are mounted, as 9606fec3791Sjesseb * we will be pulling the disk out from under them 9616fec3791Sjesseb */ 9626fec3791Sjesseb for (i = 0; i < ndisks; i++) { 9636fec3791Sjesseb if (disk_mounted(d[i])) { 9646fec3791Sjesseb (void) fprintf(stderr, gettext("Cannot create " 9656fec3791Sjesseb "RAID volume, disk \"%s\" is mounted " 9666fec3791Sjesseb ".\n"), d[i]); 9676fec3791Sjesseb return (INVALID_ARG); 9686fec3791Sjesseb } 9696fec3791Sjesseb } 9706fec3791Sjesseb 9716fec3791Sjesseb /* 9726fec3791Sjesseb * will not support data migration or disk relabeling with 9736fec3791Sjesseb * this utility, and so next we must confirm the creation as 9746fec3791Sjesseb * all data on member disks will be lost. 9756fec3791Sjesseb */ 9766fec3791Sjesseb if (!force) { 9776fec3791Sjesseb (void) fprintf(stderr, gettext("Creating RAID volume " 9786fec3791Sjesseb "c%dt%dd0 will destroy all data on member disks, " 9796fec3791Sjesseb "proceed (%s/%s)? "), c[0], t[0], yeschr, nochr); 9806fec3791Sjesseb if (!yes()) { 9816fec3791Sjesseb (void) fprintf(stderr, gettext("RAID volume " 9826fec3791Sjesseb "c%dt%dd0 not created.\n\n"), c[0], t[0]); 9836fec3791Sjesseb (void) close(fd); 9846fec3791Sjesseb return (SUCCESS); 9856fec3791Sjesseb } 9866fec3791Sjesseb } 9876fec3791Sjesseb 9886fec3791Sjesseb /* 9896fec3791Sjesseb * we are ready to move onto the creation 9906fec3791Sjesseb */ 9916fec3791Sjesseb goto no_secondary_channel; 9926fec3791Sjesseb } 9936fec3791Sjesseb 9946fec3791Sjesseb /* 9956fec3791Sjesseb * LSI1030, support for single IM volume 9966fec3791Sjesseb */ 9976fec3791Sjesseb if (rlevel != RAID_MIRROR) { 9986fec3791Sjesseb (void) printf(gettext("HBA only supports RAID " 9996fec3791Sjesseb "level 1 (mirrored) volumes\n")); 10006fec3791Sjesseb goto fail; 10016fec3791Sjesseb } 10026fec3791Sjesseb /* 10036fec3791Sjesseb * look up the volume configuration 10046fec3791Sjesseb */ 10056fec3791Sjesseb config.unitid = n; 10066fec3791Sjesseb if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 10076fec3791Sjesseb raidctl_error("RAID_GETCONFIG"); 10086fec3791Sjesseb goto fail; 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10118ba1bcfcSdduvall if (config.ndisks != 0) { 10126fec3791Sjesseb (void) printf(gettext("RAID Volume already exists " 10136fec3791Sjesseb "on this controller 'c%dt%dd0'\n"), 10146fec3791Sjesseb c[0], config.targetid); 10156fec3791Sjesseb goto fail; 101605411564Sjesseb } 101705411564Sjesseb 101805411564Sjesseb /* 10197c478bd9Sstevel@tonic-gate * Make sure there isn't a raid created on this controller's 10206fec3791Sjesseb * other channel, if it has multiple channels 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate (void) strlcpy(channel2, channel1, sizeof (channel2)); 10237c478bd9Sstevel@tonic-gate tmp = strrchr(channel2, ':'); 10247c478bd9Sstevel@tonic-gate tmp[0] = 0; 10257c478bd9Sstevel@tonic-gate size = strlen(channel2); 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate /* 10286fec3791Sjesseb * Make sure that the secondary disk is not mounted 10296fec3791Sjesseb */ 10306fec3791Sjesseb if (disk_mounted(disk[1])) { 10316fec3791Sjesseb (void) fprintf(stderr, gettext("Cannot create RAID volume when " 10326fec3791Sjesseb "secondary disk \"%s\" is mounted.\n"), disk[1]); 10336fec3791Sjesseb return (INVALID_ARG); 10346fec3791Sjesseb } 10356fec3791Sjesseb 10366fec3791Sjesseb /* 10377c478bd9Sstevel@tonic-gate * Format the channel string for the other channel so we can 10386fec3791Sjesseb * see if a raid exists on it. In this case if we are being 10396fec3791Sjesseb * asked to create a raid on channel 2 (indicated by the 1,1 10406fec3791Sjesseb * at the end of the string) we want to check channel 1), 10416fec3791Sjesseb * otherwise we will check channel 2. 10427c478bd9Sstevel@tonic-gate */ 10437c478bd9Sstevel@tonic-gate if (channel2[size - 2] == ',') { 10447c478bd9Sstevel@tonic-gate channel2[size - 1] = 0; 10457c478bd9Sstevel@tonic-gate channel2[size - 2] = 0; 10466fec3791Sjesseb (void) snprintf(channel2, sizeof (channel2), 10476fec3791Sjesseb "%s:devctl", channel2); 10487c478bd9Sstevel@tonic-gate } else { 10496fec3791Sjesseb (void) snprintf(channel2, sizeof (channel2), 10506fec3791Sjesseb "%s,1:devctl", channel2); 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate fd2 = open(channel2, O_RDONLY); 10547c478bd9Sstevel@tonic-gate if (fd2 == -1) { 10557c478bd9Sstevel@tonic-gate if (errno == ENOENT) 10567c478bd9Sstevel@tonic-gate goto no_secondary_channel; 10577c478bd9Sstevel@tonic-gate perror(channel2); 10586fec3791Sjesseb goto fail; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { 10626fec3791Sjesseb goto fail; 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10658ba1bcfcSdduvall if (config.ndisks != 0) { 10667c478bd9Sstevel@tonic-gate int cx; 10677c478bd9Sstevel@tonic-gate cx = get_controller(channel2); 10686fec3791Sjesseb (void) printf(gettext("RAID Volume already exists " 10696fec3791Sjesseb "on this controller 'c%dt%dd0'\n"), cx, 10706fec3791Sjesseb config.targetid); 10716fec3791Sjesseb goto fail; 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate no_secondary_channel: 10757c478bd9Sstevel@tonic-gate 10766fec3791Sjesseb /* all checks complete, fill in the config */ 10776fec3791Sjesseb newvol.targetid = t[0]; 10786fec3791Sjesseb newvol.disk[0] = t[0]; 10796fec3791Sjesseb newvol.raid_level = rlevel; 10806fec3791Sjesseb newvol.ndisks = ndisks; 10816fec3791Sjesseb newvol.raid_capacity = capacity; 10827c478bd9Sstevel@tonic-gate 10836fec3791Sjesseb /* populate config.disk, and unconfigure all disks, except targetid */ 10846fec3791Sjesseb for (i = 1; i < ndisks; i++) { 10857c478bd9Sstevel@tonic-gate if (do_config_change_state(CFGA_CMD_UNCONFIGURE, 10866fec3791Sjesseb t[i], c[0])) { 10877c478bd9Sstevel@tonic-gate perror("config_change_state"); 10886fec3791Sjesseb goto fail; 10896fec3791Sjesseb } 10906fec3791Sjesseb newvol.disk[i] = t[i]; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10936fec3791Sjesseb if (ioctl(fd, RAID_CREATE, &newvol)) { 10946fec3791Sjesseb /* reconfigure all disks, except targetid */ 10956fec3791Sjesseb for (i = 1; i < ndisks; i++) { 10967c478bd9Sstevel@tonic-gate (void) do_config_change_state(CFGA_CMD_CONFIGURE, 10976fec3791Sjesseb newvol.disk[i], c[0]); 10986fec3791Sjesseb } 10997c478bd9Sstevel@tonic-gate raidctl_error("RAID_CREATE"); 11006fec3791Sjesseb goto fail; 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); 11047c478bd9Sstevel@tonic-gate (void) close(fd); 11057c478bd9Sstevel@tonic-gate (void) close(fd2); 11067c478bd9Sstevel@tonic-gate return (SUCCESS); 11077c478bd9Sstevel@tonic-gate 11086fec3791Sjesseb fail: 11098ba1bcfcSdduvall (void) close(fd); 11106fec3791Sjesseb (void) close(fd2); 11117c478bd9Sstevel@tonic-gate return (FAILURE); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate static int 11156fec3791Sjesseb do_delete(char *d, int force) 11167c478bd9Sstevel@tonic-gate { 11178ba1bcfcSdduvall raid_config_t config; 11187c478bd9Sstevel@tonic-gate char disk1[MAXPATHLEN]; 11197c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 11207c478bd9Sstevel@tonic-gate int fd; 11217c478bd9Sstevel@tonic-gate int target; 11227c478bd9Sstevel@tonic-gate int ctrl; 11236fec3791Sjesseb int i, j; 11246fec3791Sjesseb int wrong_targ = 0; 11256fec3791Sjesseb int nvols; 11267c478bd9Sstevel@tonic-gate uint8_t t; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) { 11317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Invalid disk format.\n")); 11327c478bd9Sstevel@tonic-gate return (INVALID_ARG); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate t = (uint8_t)target; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate if (get_devctl(disk1, buf) != 0) { 11396fec3791Sjesseb (void) fprintf(stderr, gettext("Not a volume '%s'\n"), d); 11407c478bd9Sstevel@tonic-gate return (FAILURE); 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate fd = open(buf, O_RDONLY); 11447c478bd9Sstevel@tonic-gate if (fd == -1) { 11457c478bd9Sstevel@tonic-gate perror(buf); 11467c478bd9Sstevel@tonic-gate return (FAILURE); 11477c478bd9Sstevel@tonic-gate } 11487c478bd9Sstevel@tonic-gate 11496fec3791Sjesseb if (ioctl(fd, RAID_NUMVOLUMES, &nvols)) { 11506fec3791Sjesseb raidctl_error("RAID_NUMVOLUMES"); 11516fec3791Sjesseb goto fail; 11526fec3791Sjesseb } 11536fec3791Sjesseb 11546fec3791Sjesseb for (i = 0; i < nvols; i++) { 11556fec3791Sjesseb config.unitid = i; 11567c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config)) { 11577c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 11587c478bd9Sstevel@tonic-gate goto fail; 11597c478bd9Sstevel@tonic-gate } 11606fec3791Sjesseb if (config.ndisks != 0) { 11616fec3791Sjesseb /* there is a RAID volume in this slot */ 11626fec3791Sjesseb if (config.targetid != t) { 11636fec3791Sjesseb wrong_targ++; 11646fec3791Sjesseb continue; 11656fec3791Sjesseb } 11666fec3791Sjesseb /* and it's our target */ 11676fec3791Sjesseb break; 11686fec3791Sjesseb } 11696fec3791Sjesseb } 11707c478bd9Sstevel@tonic-gate 11716fec3791Sjesseb if (i == nvols) { 11726fec3791Sjesseb /* we found no RAID volumes */ 11736fec3791Sjesseb (void) fprintf(stderr, gettext("No RAID volumes exist on " 11747c478bd9Sstevel@tonic-gate "controller '%d'\n"), ctrl); 11757c478bd9Sstevel@tonic-gate goto fail; 11767c478bd9Sstevel@tonic-gate } 11777c478bd9Sstevel@tonic-gate 11786fec3791Sjesseb if (wrong_targ == nvols) { 11796fec3791Sjesseb /* we found RAID volumes, but none matched */ 11807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11817c478bd9Sstevel@tonic-gate gettext("RAID volume 'c%dt%dd0' does not exist\n"), 11827c478bd9Sstevel@tonic-gate ctrl, t); 11837c478bd9Sstevel@tonic-gate goto fail; 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate 11866fec3791Sjesseb /* if this volume is a stripe, all data will be lost */ 11876fec3791Sjesseb if (config.raid_level == RAID_STRIPE) { 11886fec3791Sjesseb if (disk_mounted(d)) { 11896fec3791Sjesseb (void) fprintf(stderr, gettext("Cannot delete " 11906fec3791Sjesseb "RAID0 volume, \"%s\" is mounted.\n"), d); 11916fec3791Sjesseb return (INVALID_ARG); 11926fec3791Sjesseb } 11936fec3791Sjesseb 11946fec3791Sjesseb if (!force) { 11956fec3791Sjesseb (void) fprintf(stderr, gettext("Deleting volume " 11966fec3791Sjesseb "c%dt%dd0 will destroy all data it contains, " 11976fec3791Sjesseb "proceed (%s/%s)? "), ctrl, t, yeschr, nochr); 11986fec3791Sjesseb if (!yes()) { 11996fec3791Sjesseb (void) fprintf(stderr, gettext("RAID volume " 12006fec3791Sjesseb "c%dt%dd0 not deleted.\n\n"), ctrl, t); 12016fec3791Sjesseb (void) close(fd); 12026fec3791Sjesseb return (SUCCESS); 12036fec3791Sjesseb } 12046fec3791Sjesseb } 12056fec3791Sjesseb } 12066fec3791Sjesseb 12077c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_DELETE, &t)) { 12087c478bd9Sstevel@tonic-gate perror("RAID_DELETE"); 12097c478bd9Sstevel@tonic-gate goto fail; 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12126fec3791Sjesseb /* reconfigure all disks, except targetid */ 12136fec3791Sjesseb for (j = 1; j < config.ndisks; j++) { 12146fec3791Sjesseb (void) do_config_change_state(CFGA_CMD_CONFIGURE, 12156fec3791Sjesseb config.disk[j], ctrl); 12166fec3791Sjesseb } 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), 12197c478bd9Sstevel@tonic-gate ctrl, target); 12207c478bd9Sstevel@tonic-gate (void) close(fd); 12217c478bd9Sstevel@tonic-gate return (SUCCESS); 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate fail: 12247c478bd9Sstevel@tonic-gate (void) close(fd); 12257c478bd9Sstevel@tonic-gate return (FAILURE); 12267c478bd9Sstevel@tonic-gate } 12277c478bd9Sstevel@tonic-gate 1228*7f000930Syw161884 static void 1229*7f000930Syw161884 getimagetype(uint8_t *rombuf, int *imagetype) 1230*7f000930Syw161884 { 1231*7f000930Syw161884 uint8_t type = rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE]; 1232*7f000930Syw161884 if (type == 0) { 1233*7f000930Syw161884 *imagetype = BIOS_IMAGE; 1234*7f000930Syw161884 return; 1235*7f000930Syw161884 } 1236*7f000930Syw161884 if (type == 1) { 1237*7f000930Syw161884 *imagetype = FCODE_IMAGE; 1238*7f000930Syw161884 return; 1239*7f000930Syw161884 } 1240*7f000930Syw161884 } 1241*7f000930Syw161884 12427c478bd9Sstevel@tonic-gate static int 12437c478bd9Sstevel@tonic-gate getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion) 12447c478bd9Sstevel@tonic-gate { 12457c478bd9Sstevel@tonic-gate int x, y, size; 12467c478bd9Sstevel@tonic-gate int found_1 = 0, found_2 = 0; 12477c478bd9Sstevel@tonic-gate int image_length = 0; 12487c478bd9Sstevel@tonic-gate int no_of_images = 0; 12497c478bd9Sstevel@tonic-gate uint8_t *rombuf_1 = NULL; 12507c478bd9Sstevel@tonic-gate uint16_t image_units = 0; 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate /* 12537c478bd9Sstevel@tonic-gate * Single Image - Open firmware image 12547c478bd9Sstevel@tonic-gate */ 12557c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) { 12567c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR; 12577c478bd9Sstevel@tonic-gate no_of_images = 1; 12587c478bd9Sstevel@tonic-gate goto process_image; 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate /* 12627c478bd9Sstevel@tonic-gate * Combined Image - First Image - x86/PC-AT Bios image 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) { 12657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 12667c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 12677c478bd9Sstevel@tonic-gate return (1); 12687c478bd9Sstevel@tonic-gate } 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate /* 12717c478bd9Sstevel@tonic-gate * Seek to 2nd Image 12727c478bd9Sstevel@tonic-gate */ 12737c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR); 12747c478bd9Sstevel@tonic-gate image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH); 12757c478bd9Sstevel@tonic-gate image_length = image_units * PCI_IMAGE_UNIT_SIZE; 12767c478bd9Sstevel@tonic-gate rombuf_1 += image_length; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate /* 12797c478bd9Sstevel@tonic-gate * Combined Image - Second Image - Open Firmware image 12807c478bd9Sstevel@tonic-gate */ 12817c478bd9Sstevel@tonic-gate if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) { 12827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 12837c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 12847c478bd9Sstevel@tonic-gate return (1); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate rombuf_1 += PCI_PDS_INDICATOR; 12877c478bd9Sstevel@tonic-gate no_of_images = 2; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate process_image: 12907c478bd9Sstevel@tonic-gate /* 12917c478bd9Sstevel@tonic-gate * This should be the last image 12927c478bd9Sstevel@tonic-gate */ 12937c478bd9Sstevel@tonic-gate if (*rombuf_1 != LAST_IMAGE) { 12947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is not a valid " 12957c478bd9Sstevel@tonic-gate "Bios/Fcode image file\n")); 12967c478bd9Sstevel@tonic-gate return (1); 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate /* 1300*7f000930Syw161884 * Scan through the bios/fcode file to get the fcode version 13017c478bd9Sstevel@tonic-gate * 0x12 and 0x7 indicate the start of the fcode version string 13027c478bd9Sstevel@tonic-gate */ 13037c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 8); x++) { 13047c478bd9Sstevel@tonic-gate if ((rombuf[x] == FCODE_VERS_KEY1) && 13057c478bd9Sstevel@tonic-gate (rombuf[x+1] == FCODE_VERS_KEY2) && 13067c478bd9Sstevel@tonic-gate (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') && 13077c478bd9Sstevel@tonic-gate (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') && 13087c478bd9Sstevel@tonic-gate (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') && 13097c478bd9Sstevel@tonic-gate (rombuf[x+8] == 'n')) { 13107c478bd9Sstevel@tonic-gate found_1 = 1; 13117c478bd9Sstevel@tonic-gate break; 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate } 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate /* 13167c478bd9Sstevel@tonic-gate * Store the version string if we have found the beginning of it 13177c478bd9Sstevel@tonic-gate */ 13187c478bd9Sstevel@tonic-gate if (found_1) { 13197c478bd9Sstevel@tonic-gate while (x > 0) { 13207c478bd9Sstevel@tonic-gate if (rombuf[--x] == FCODE_VERS_KEY1) { 13217c478bd9Sstevel@tonic-gate if (rombuf[x-1] != FCODE_VERS_KEY1) { 13227c478bd9Sstevel@tonic-gate x++; 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate break; 13257c478bd9Sstevel@tonic-gate } 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate if (x > 0) { 13287c478bd9Sstevel@tonic-gate *fcodeversion = (char *)malloc(rombuf[x] + 1); 13297c478bd9Sstevel@tonic-gate for (y = 0; y < rombuf[x]; y++) { 13307c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = rombuf[x+y+1]; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 13337c478bd9Sstevel@tonic-gate } else { 13347c478bd9Sstevel@tonic-gate found_1 = 0; 13357c478bd9Sstevel@tonic-gate } 13367c478bd9Sstevel@tonic-gate } 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate /* 1339*7f000930Syw161884 * Scan through the bios/fcode file to get the Bios version 13407c478bd9Sstevel@tonic-gate * "@(#)" string indicates the start of the Bios version string 13417c478bd9Sstevel@tonic-gate * Append this version string, after already existing fcode version. 13427c478bd9Sstevel@tonic-gate */ 13437c478bd9Sstevel@tonic-gate if (no_of_images == 2) { 13447c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 4); x++) { 13457c478bd9Sstevel@tonic-gate if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 13467c478bd9Sstevel@tonic-gate (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 13477c478bd9Sstevel@tonic-gate found_2 = 1; 13487c478bd9Sstevel@tonic-gate break; 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate if (found_2) { 13537c478bd9Sstevel@tonic-gate x += 4; 13547c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\n'; 13557c478bd9Sstevel@tonic-gate size = y + strlen((char *)(rombuf + x)) + 13567c478bd9Sstevel@tonic-gate strlen(BIOS_STR) + 2; 13577c478bd9Sstevel@tonic-gate *fcodeversion = (char *)realloc((*fcodeversion), size); 13587c478bd9Sstevel@tonic-gate y++; 13597c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 13607c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, BIOS_STR, size); 13617c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, (char *)(rombuf + x), 13627c478bd9Sstevel@tonic-gate size); 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate 13667c478bd9Sstevel@tonic-gate return ((found_1 || found_2) ? 0 : 1); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate static void 13707c478bd9Sstevel@tonic-gate getfwver(uint8_t *rombuf, char *fwversion) 13717c478bd9Sstevel@tonic-gate { 13727c478bd9Sstevel@tonic-gate (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d", 13737c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 3], 13747c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 2], 13757c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 1], 13767c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 0]); 13777c478bd9Sstevel@tonic-gate } 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate static int 1380*7f000930Syw161884 getbioscodever(uint8_t *rombuf, uint32_t nbytes, char **biosversion) 1381*7f000930Syw161884 { 1382*7f000930Syw161884 int x, size; 1383*7f000930Syw161884 int found = 0; 1384*7f000930Syw161884 1385*7f000930Syw161884 for (x = 0; x < (nbytes - 4); x++) { 1386*7f000930Syw161884 if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 1387*7f000930Syw161884 (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 1388*7f000930Syw161884 found = 1; 1389*7f000930Syw161884 break; 1390*7f000930Syw161884 } 1391*7f000930Syw161884 } 1392*7f000930Syw161884 1393*7f000930Syw161884 if (found) { 1394*7f000930Syw161884 x += 4; 1395*7f000930Syw161884 size = strlen((char *)(rombuf + x)) + strlen(BIOS_STR) + 1; 1396*7f000930Syw161884 *biosversion = (char *)realloc((*biosversion), size); 1397*7f000930Syw161884 bcopy((char *)(rombuf + x), *biosversion, size - 1); 1398*7f000930Syw161884 (*biosversion)[size - 1] = '\0'; 1399*7f000930Syw161884 } 1400*7f000930Syw161884 1401*7f000930Syw161884 return (found); 1402*7f000930Syw161884 1403*7f000930Syw161884 } 1404*7f000930Syw161884 1405*7f000930Syw161884 static int 14067c478bd9Sstevel@tonic-gate checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype) 14077c478bd9Sstevel@tonic-gate { 14087c478bd9Sstevel@tonic-gate char *imageversion = NULL; 1409*7f000930Syw161884 char *biosversion = NULL; 14107c478bd9Sstevel@tonic-gate char *fwversion; 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate fwversion = (char *)malloc(8); 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate if (gw(&rombuf[0]) == PCIROM_SIG) { 1415*7f000930Syw161884 14167c478bd9Sstevel@tonic-gate *imagetype = UNKNOWN_IMAGE; 1417*7f000930Syw161884 getimagetype(rombuf, imagetype); 1418*7f000930Syw161884 1419*7f000930Syw161884 if (*imagetype == FCODE_IMAGE) { 1420*7f000930Syw161884 if (getfcodever(rombuf, nbytes, &imageversion) == 0 && 1421*7f000930Syw161884 imageversion != NULL) { 1422*7f000930Syw161884 (void) printf(gettext("Image file contains " 1423*7f000930Syw161884 "fcode version \t%s\n"), imageversion); 14247c478bd9Sstevel@tonic-gate free(imageversion); 1425*7f000930Syw161884 } 1426*7f000930Syw161884 } else if (*imagetype == BIOS_IMAGE) { 1427*7f000930Syw161884 if (getbioscodever(rombuf, nbytes, &biosversion) == 1 && 1428*7f000930Syw161884 biosversion != NULL) { 1429*7f000930Syw161884 (void) printf(gettext("Image file contains " 1430*7f000930Syw161884 "BIOS version \t%s\n"), biosversion); 1431*7f000930Syw161884 free(biosversion); 1432*7f000930Syw161884 } 14337c478bd9Sstevel@tonic-gate } else { 1434*7f000930Syw161884 /* When imagetype equals to UNKNOWN_IMAGE */ 14357c478bd9Sstevel@tonic-gate return (-1); 14367c478bd9Sstevel@tonic-gate } 1437*7f000930Syw161884 14387c478bd9Sstevel@tonic-gate } else if (gw(&rombuf[3]) == FW_ROM_ID) { 14397c478bd9Sstevel@tonic-gate if (chksum != 0) { 14407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14417c478bd9Sstevel@tonic-gate gettext("The ROM checksum appears bad " 14427c478bd9Sstevel@tonic-gate "(%d)\n"), chksum); 14437c478bd9Sstevel@tonic-gate return (-1); 14447c478bd9Sstevel@tonic-gate } 14457c478bd9Sstevel@tonic-gate getfwver(rombuf, fwversion); 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) & 14487c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_MASK) == 14497c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_IM_SCSI) { 14507c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 14517c478bd9Sstevel@tonic-gate "MPT firmware version %s " 14527c478bd9Sstevel@tonic-gate "(w/Integrated Mirroring)\n"), 14537c478bd9Sstevel@tonic-gate fwversion); 14547c478bd9Sstevel@tonic-gate } else { 14557c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 14567c478bd9Sstevel@tonic-gate "MPT firmware ""version %s\n"), 14577c478bd9Sstevel@tonic-gate fwversion); 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate free(fwversion); 14607c478bd9Sstevel@tonic-gate } else { 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate #ifdef DEBUG 14637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0])); 14647c478bd9Sstevel@tonic-gate #else 14657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Not valid FCODE image\n")); 14667c478bd9Sstevel@tonic-gate #endif 14677c478bd9Sstevel@tonic-gate return (-1); 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate return (0); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate static int 14737c478bd9Sstevel@tonic-gate updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl) 14747c478bd9Sstevel@tonic-gate { 14757c478bd9Sstevel@tonic-gate int fd = 0; 14767c478bd9Sstevel@tonic-gate update_flash_t flashdata; 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate fd = open(devctl, O_RDONLY); 14797c478bd9Sstevel@tonic-gate if (fd == -1) { 14807c478bd9Sstevel@tonic-gate perror(devctl); 14817c478bd9Sstevel@tonic-gate return (-1); 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate (void) memset(&flashdata, 0, sizeof (flashdata)); 14847c478bd9Sstevel@tonic-gate flashdata.ptrbuffer = (caddr_t)rombuf; 14857c478bd9Sstevel@tonic-gate flashdata.size = nbytes; 14867c478bd9Sstevel@tonic-gate if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) { 14877c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_FCODE; 14887c478bd9Sstevel@tonic-gate } else { 14897c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_UCODE; 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_UPDATEFW, &flashdata)) { 14937c478bd9Sstevel@tonic-gate raidctl_error("RAID_UPDATEFW"); 14947c478bd9Sstevel@tonic-gate (void) close(fd); 14957c478bd9Sstevel@tonic-gate return (-1); 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate (void) close(fd); 14997c478bd9Sstevel@tonic-gate return (0); 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate static int 15037c478bd9Sstevel@tonic-gate readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum) 15047c478bd9Sstevel@tonic-gate { 15057c478bd9Sstevel@tonic-gate struct stat statbuf; 15067c478bd9Sstevel@tonic-gate uint32_t count; 15077c478bd9Sstevel@tonic-gate uint32_t checksum = 0; 15087c478bd9Sstevel@tonic-gate int fd, i; 15097c478bd9Sstevel@tonic-gate uint8_t *filebuf; 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) { 15137c478bd9Sstevel@tonic-gate perror(filespec); 15147c478bd9Sstevel@tonic-gate return (-1); 15157c478bd9Sstevel@tonic-gate } 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (fstat(fd, &statbuf) != 0) { 15187c478bd9Sstevel@tonic-gate perror("fstat"); 15197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15207c478bd9Sstevel@tonic-gate gettext("Error getting stats on file\n")); 15217c478bd9Sstevel@tonic-gate (void) close(fd); 15227c478bd9Sstevel@tonic-gate return (-1); 15237c478bd9Sstevel@tonic-gate } 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate #ifdef DEBUG 15267c478bd9Sstevel@tonic-gate (void) printf("Filesize = %ld\n", statbuf.st_size); 15277c478bd9Sstevel@tonic-gate #endif 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes); 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate count = read(fd, filebuf + *nbytes, statbuf.st_size); 15327c478bd9Sstevel@tonic-gate (void) close(fd); 15337c478bd9Sstevel@tonic-gate if (count != statbuf.st_size) { 15347c478bd9Sstevel@tonic-gate perror("size check"); 15357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("File is corrupt\n")); 15367c478bd9Sstevel@tonic-gate return (-1); 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate for (i = 0; i < *nbytes; i++) 15407c478bd9Sstevel@tonic-gate checksum += filebuf[i] << (8 * (i & 3)); 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate *rombuf = filebuf; 15437c478bd9Sstevel@tonic-gate *nbytes = *nbytes + count; 15447c478bd9Sstevel@tonic-gate *chksum = checksum; 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate return (0); 15477c478bd9Sstevel@tonic-gate } 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate static int 15506fec3791Sjesseb yes(void) 15517c478bd9Sstevel@tonic-gate { 15527c478bd9Sstevel@tonic-gate int i, b; 15537c478bd9Sstevel@tonic-gate char ans[SCHAR_MAX + 1]; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 15567c478bd9Sstevel@tonic-gate b = getchar(); 15577c478bd9Sstevel@tonic-gate if (b == '\n' || b == '\0' || b == EOF) { 15587c478bd9Sstevel@tonic-gate ans[i] = 0; 15597c478bd9Sstevel@tonic-gate break; 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate if (i < SCHAR_MAX) 15627c478bd9Sstevel@tonic-gate ans[i] = b; 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate if (i >= SCHAR_MAX) { 15657c478bd9Sstevel@tonic-gate i = SCHAR_MAX; 15667c478bd9Sstevel@tonic-gate ans[SCHAR_MAX] = 0; 15677c478bd9Sstevel@tonic-gate } 15686fec3791Sjesseb if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0)) 15697c478bd9Sstevel@tonic-gate return (1); 15706fec3791Sjesseb 15717c478bd9Sstevel@tonic-gate return (0); 15727c478bd9Sstevel@tonic-gate } 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate static int 15757c478bd9Sstevel@tonic-gate do_flash(int c, char *fpath, int force) 15767c478bd9Sstevel@tonic-gate { 15777c478bd9Sstevel@tonic-gate char devctl[MAXPATHLEN] = {0}; 15787c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 15797c478bd9Sstevel@tonic-gate int rv = 0; 15807c478bd9Sstevel@tonic-gate int imagetype; 15817c478bd9Sstevel@tonic-gate uint32_t nbytes = 0; 15827c478bd9Sstevel@tonic-gate uint32_t chksum; 15837c478bd9Sstevel@tonic-gate uint8_t *rombuf = NULL; 15847c478bd9Sstevel@tonic-gate char cwd[MAXPATHLEN]; 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate /* 15877c478bd9Sstevel@tonic-gate * Read fw file 15887c478bd9Sstevel@tonic-gate */ 15897c478bd9Sstevel@tonic-gate rv = readfile(fpath, &rombuf, &nbytes, &chksum); 15907c478bd9Sstevel@tonic-gate if (rv != 0) { 15917c478bd9Sstevel@tonic-gate return (FAILURE); 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate (void) getcwd(cwd, sizeof (cwd)); 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate /* Get link from "/dev/cfg" */ 15997c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c); 16007c478bd9Sstevel@tonic-gate if (get_link_path(buf, devctl) != 0) { 16017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16027c478bd9Sstevel@tonic-gate gettext("Invalid controller '%d'\n"), c); 16037c478bd9Sstevel@tonic-gate return (INVALID_ARG); 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate /* Check File */ 16077c478bd9Sstevel@tonic-gate rv = checkfile(rombuf, nbytes, chksum, &imagetype); 16087c478bd9Sstevel@tonic-gate if (rv != 0) { 16097c478bd9Sstevel@tonic-gate return (FAILURE); 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate /* Confirm */ 16137c478bd9Sstevel@tonic-gate if (!force) { 16147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Update flash image on " 16157c478bd9Sstevel@tonic-gate "controller %d (%s/%s)? "), c, yeschr, nochr); 16166fec3791Sjesseb if (!yes()) { 16176fec3791Sjesseb (void) fprintf(stderr, gettext("Controller %d not " 16186fec3791Sjesseb "flashed.\n\n"), c); 16197c478bd9Sstevel@tonic-gate return (SUCCESS); 16207c478bd9Sstevel@tonic-gate } 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate /* Do Flash */ 16247c478bd9Sstevel@tonic-gate if (updateflash(rombuf, nbytes, devctl)) { 16257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Flash not updated on " 16267c478bd9Sstevel@tonic-gate "Controller %d.\n\n"), c); 16277c478bd9Sstevel@tonic-gate return (INVALID_ARG); 16287c478bd9Sstevel@tonic-gate } 16297c478bd9Sstevel@tonic-gate (void) printf(gettext("Flash updated successfully.\n\n")); 16307c478bd9Sstevel@tonic-gate return (SUCCESS); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate static int 16347c478bd9Sstevel@tonic-gate fully_numeric(char *str) 16357c478bd9Sstevel@tonic-gate { 16367c478bd9Sstevel@tonic-gate int size = strlen(str); 16377c478bd9Sstevel@tonic-gate int i; 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 16407c478bd9Sstevel@tonic-gate if (i == 0 && str[i] == '-' && size != 1) 16417c478bd9Sstevel@tonic-gate continue; 16427c478bd9Sstevel@tonic-gate if (!isdigit(str[i])) 16437c478bd9Sstevel@tonic-gate return (0); 16447c478bd9Sstevel@tonic-gate } 16457c478bd9Sstevel@tonic-gate return (1); 16467c478bd9Sstevel@tonic-gate } 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate /* 16497c478bd9Sstevel@tonic-gate * Useful parsing macros 16507c478bd9Sstevel@tonic-gate */ 16517c478bd9Sstevel@tonic-gate #define must_be(s, c) if (*s++ != c) return (0) 16527c478bd9Sstevel@tonic-gate #define skip_digits(s) while (isdigit(*s)) s++ 16537c478bd9Sstevel@tonic-gate 16547c478bd9Sstevel@tonic-gate /* 16557c478bd9Sstevel@tonic-gate * Return true if a name is in the internal canonical form 16567c478bd9Sstevel@tonic-gate */ 16577c478bd9Sstevel@tonic-gate static int 16587c478bd9Sstevel@tonic-gate canonical_name(char *name) 16597c478bd9Sstevel@tonic-gate { 16607c478bd9Sstevel@tonic-gate must_be(name, 'c'); 16617c478bd9Sstevel@tonic-gate skip_digits(name); 16627c478bd9Sstevel@tonic-gate if (*name == 't') { 16637c478bd9Sstevel@tonic-gate name++; 16647c478bd9Sstevel@tonic-gate skip_digits(name); 16657c478bd9Sstevel@tonic-gate } 16667c478bd9Sstevel@tonic-gate must_be(name, 'd'); 16677c478bd9Sstevel@tonic-gate skip_digits(name); 16687c478bd9Sstevel@tonic-gate return (*name == 0); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate 16717c478bd9Sstevel@tonic-gate int 16727c478bd9Sstevel@tonic-gate main(int argc, char **argv) 16737c478bd9Sstevel@tonic-gate { 16747c478bd9Sstevel@tonic-gate int rv = SUCCESS; 16757c478bd9Sstevel@tonic-gate int i, c; 16767c478bd9Sstevel@tonic-gate int findex = DO_HW_RAID_INFO; 16777c478bd9Sstevel@tonic-gate int controller; 16786fec3791Sjesseb char *disks[N_DISKS] = {0}; 16797c478bd9Sstevel@tonic-gate char *darg; 16807c478bd9Sstevel@tonic-gate char *farg; 16816fec3791Sjesseb char *rarg; 16827c478bd9Sstevel@tonic-gate char *progname; 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate int l_flag = 0; 16857c478bd9Sstevel@tonic-gate int c_flag = 0; 16867c478bd9Sstevel@tonic-gate int d_flag = 0; 16877c478bd9Sstevel@tonic-gate int f_flag = 0; 16887c478bd9Sstevel@tonic-gate int F_flag = 0; 16896fec3791Sjesseb int r_flag = 0; 16907c478bd9Sstevel@tonic-gate int no_flags = 1; 16916fec3791Sjesseb int r = RAID_MIRROR; /* default raid level is 1 */ 16927c478bd9Sstevel@tonic-gate char *current_dir; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 16957c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 16987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Must be root.\n")); 16997c478bd9Sstevel@tonic-gate exit(1); 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) == NULL) 17037c478bd9Sstevel@tonic-gate progname = argv[0]; 17047c478bd9Sstevel@tonic-gate else 17057c478bd9Sstevel@tonic-gate progname++; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate raids = NULL; 17087c478bd9Sstevel@tonic-gate 17097c478bd9Sstevel@tonic-gate (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); 17107c478bd9Sstevel@tonic-gate (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); 17117c478bd9Sstevel@tonic-gate 17126fec3791Sjesseb while ((c = getopt(argc, argv, "cr:lfd:F:")) != EOF) { 17137c478bd9Sstevel@tonic-gate switch (c) { 17147c478bd9Sstevel@tonic-gate case 'c': 17156fec3791Sjesseb if (argc < 4) 17167c478bd9Sstevel@tonic-gate usage(progname); 17177c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_CREATE; 17187c478bd9Sstevel@tonic-gate c_flag = 1; 17197c478bd9Sstevel@tonic-gate no_flags = 0; 17207c478bd9Sstevel@tonic-gate break; 17216fec3791Sjesseb case 'r': 17226fec3791Sjesseb rarg = optarg; 17236fec3791Sjesseb r = atoi(rarg); 17246fec3791Sjesseb if ((r != RAID_STRIPE) && (r != RAID_MIRROR)) 17256fec3791Sjesseb usage(progname); 17266fec3791Sjesseb r_flag = 1; 17276fec3791Sjesseb break; 17287c478bd9Sstevel@tonic-gate case 'd': 17297c478bd9Sstevel@tonic-gate darg = optarg; 17307c478bd9Sstevel@tonic-gate d_flag = 1; 17317c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_DELETE; 17327c478bd9Sstevel@tonic-gate no_flags = 0; 17337c478bd9Sstevel@tonic-gate break; 17347c478bd9Sstevel@tonic-gate case 'l': 17357c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_INFO; 17367c478bd9Sstevel@tonic-gate l_flag = 1; 17377c478bd9Sstevel@tonic-gate no_flags = 0; 17387c478bd9Sstevel@tonic-gate break; 17397c478bd9Sstevel@tonic-gate case 'F': 17407c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_FLASH; 17417c478bd9Sstevel@tonic-gate farg = optarg; 17427c478bd9Sstevel@tonic-gate F_flag = 1; 17437c478bd9Sstevel@tonic-gate no_flags = 0; 17447c478bd9Sstevel@tonic-gate break; 17457c478bd9Sstevel@tonic-gate case 'f': 17467c478bd9Sstevel@tonic-gate f_flag = 1; 17477c478bd9Sstevel@tonic-gate no_flags = 0; 17487c478bd9Sstevel@tonic-gate break; 17496fec3791Sjesseb case '?': 17506fec3791Sjesseb default: 17517c478bd9Sstevel@tonic-gate usage(progname); 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate if (no_flags && argc > 1) 17567c478bd9Sstevel@tonic-gate usage(progname); 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate /* compatibility rules */ 17597c478bd9Sstevel@tonic-gate if (c_flag && d_flag) 17607c478bd9Sstevel@tonic-gate usage(progname); 17616fec3791Sjesseb if (l_flag && (d_flag || c_flag || f_flag || F_flag || r_flag)) 17627c478bd9Sstevel@tonic-gate usage(progname); 17636fec3791Sjesseb if (F_flag && (d_flag || c_flag || l_flag || r_flag)) 17647c478bd9Sstevel@tonic-gate usage(progname); 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate switch (findex) { 17677c478bd9Sstevel@tonic-gate case DO_HW_RAID_INFO: 17687c478bd9Sstevel@tonic-gate if (l_flag) { 17697c478bd9Sstevel@tonic-gate /* 17707c478bd9Sstevel@tonic-gate * "raidctl" makes argc == 1 17717c478bd9Sstevel@tonic-gate * "-l" makes argc == 2 17727c478bd9Sstevel@tonic-gate */ 17737c478bd9Sstevel@tonic-gate ctrl_nums = argc - 2; 17747c478bd9Sstevel@tonic-gate if (ctrl_nums != 0) { 17757c478bd9Sstevel@tonic-gate info_ctrl = (int **) 17767c478bd9Sstevel@tonic-gate malloc(ctrl_nums * sizeof (int)); 17777c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 17787c478bd9Sstevel@tonic-gate return (FAILURE); 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 17817c478bd9Sstevel@tonic-gate char *tmp = argv[i + 2]; 17827c478bd9Sstevel@tonic-gate 17837c478bd9Sstevel@tonic-gate info_ctrl[i] = (int *)malloc(2 * sizeof (int)); 17847c478bd9Sstevel@tonic-gate if (info_ctrl[i] == NULL) { 17857c478bd9Sstevel@tonic-gate free(info_ctrl); 17867c478bd9Sstevel@tonic-gate return (FAILURE); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 17897c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", 17907c478bd9Sstevel@tonic-gate &info_ctrl[i][INFO_CTRL]); 17917c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 17927c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL; 17937c478bd9Sstevel@tonic-gate } else { 17947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17957c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 17967c478bd9Sstevel@tonic-gate tmp); 17977c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 17987c478bd9Sstevel@tonic-gate RAID_DONT_USE; 17997c478bd9Sstevel@tonic-gate } 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate } else if (argc > 1) { 18027c478bd9Sstevel@tonic-gate usage(progname); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate do_info(); 18067c478bd9Sstevel@tonic-gate break; 18077c478bd9Sstevel@tonic-gate case DO_HW_RAID_CREATE: 18087c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 18096fec3791Sjesseb int p = 2 + (r_flag * 2) + f_flag + i; 18106fec3791Sjesseb 18116fec3791Sjesseb if (p == argc) 18126fec3791Sjesseb break; 18136fec3791Sjesseb 18146fec3791Sjesseb disks[i] = argv[p]; 18156fec3791Sjesseb 18167c478bd9Sstevel@tonic-gate if (!canonical_name(disks[i])) 18177c478bd9Sstevel@tonic-gate usage(progname); 18186fec3791Sjesseb 18196fec3791Sjesseb /* no more than 2 disks for raid level 1 */ 18206fec3791Sjesseb if ((r == RAID_MIRROR) && (i > 1)) 18216fec3791Sjesseb usage(progname); 18227c478bd9Sstevel@tonic-gate } 18236fec3791Sjesseb 18246fec3791Sjesseb rv = do_create(disks, r, f_flag); 18257c478bd9Sstevel@tonic-gate break; 18267c478bd9Sstevel@tonic-gate case DO_HW_RAID_DELETE: 18277c478bd9Sstevel@tonic-gate if (!canonical_name(darg)) 18287c478bd9Sstevel@tonic-gate usage(progname); 18297c478bd9Sstevel@tonic-gate 18306fec3791Sjesseb rv = do_delete(darg, f_flag); 18317c478bd9Sstevel@tonic-gate break; 18327c478bd9Sstevel@tonic-gate case DO_HW_RAID_FLASH: 18337c478bd9Sstevel@tonic-gate ctrl_nums = argc - f_flag - 3; 18347c478bd9Sstevel@tonic-gate if (ctrl_nums == 0) 18357c478bd9Sstevel@tonic-gate usage(progname); 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate current_dir = getcwd(NULL, MAXPATHLEN); 18387c478bd9Sstevel@tonic-gate 18397c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 18407c478bd9Sstevel@tonic-gate char *tmp = argv[i + 3 + f_flag]; 18417c478bd9Sstevel@tonic-gate (void) chdir(current_dir); 18427c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 18437c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", &controller); 18447c478bd9Sstevel@tonic-gate rv = do_flash(controller, farg, f_flag); 18457c478bd9Sstevel@tonic-gate if (rv == FAILURE) 18467c478bd9Sstevel@tonic-gate break; 18477c478bd9Sstevel@tonic-gate } else { 18487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18497c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 18507c478bd9Sstevel@tonic-gate tmp); 18517c478bd9Sstevel@tonic-gate } 18527c478bd9Sstevel@tonic-gate } 18537c478bd9Sstevel@tonic-gate free(current_dir); 18547c478bd9Sstevel@tonic-gate break; 18557c478bd9Sstevel@tonic-gate default: 18567c478bd9Sstevel@tonic-gate usage(progname); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate return (rv); 18597c478bd9Sstevel@tonic-gate } 1860