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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 233a4e43d3Ssafa * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 29*8ba1bcfcSdduvall 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <dirent.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <langinfo.h> 357c478bd9Sstevel@tonic-gate #include <libintl.h> 367c478bd9Sstevel@tonic-gate #include <limits.h> 377c478bd9Sstevel@tonic-gate #include <locale.h> 387c478bd9Sstevel@tonic-gate #include <stdarg.h> 397c478bd9Sstevel@tonic-gate #include <stdio.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <string.h> 427c478bd9Sstevel@tonic-gate #include <strings.h> 437c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 447c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi.h> 457c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi_ioc.h> 467c478bd9Sstevel@tonic-gate #include <sys/stat.h> 477c478bd9Sstevel@tonic-gate #include <sys/types.h> 487c478bd9Sstevel@tonic-gate #include <sys/pci.h> 497c478bd9Sstevel@tonic-gate #include <unistd.h> 507c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 517c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 527c478bd9Sstevel@tonic-gate #include <config_admin.h> 537c478bd9Sstevel@tonic-gate #include <sys/param.h> 547c478bd9Sstevel@tonic-gate #include <sys/raidioctl.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * list of controllers to list 587c478bd9Sstevel@tonic-gate * setup like this: 597c478bd9Sstevel@tonic-gate * [ctrl_num] [status] 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * where status is: 627c478bd9Sstevel@tonic-gate * RAID Found, 637c478bd9Sstevel@tonic-gate * No RAID Found 647c478bd9Sstevel@tonic-gate * RAID not supported on this controller 657c478bd9Sstevel@tonic-gate * Invalid Controller 667c478bd9Sstevel@tonic-gate */ 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate typedef enum { 697c478bd9Sstevel@tonic-gate RAID_FOUND = 0x0, 707c478bd9Sstevel@tonic-gate RAID_NOT_FOUND, 717c478bd9Sstevel@tonic-gate RAID_NOT_SUPPORTED, 727c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL, 737c478bd9Sstevel@tonic-gate RAID_DONT_USE 747c478bd9Sstevel@tonic-gate } raidctl_errno_t; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* For no-mixup indexing of info_ctrl */ 777c478bd9Sstevel@tonic-gate #define INFO_CTRL 0 787c478bd9Sstevel@tonic-gate #define INFO_STATUS 1 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate static int **info_ctrl = NULL; 817c478bd9Sstevel@tonic-gate /* Length of conrollers list */ 827c478bd9Sstevel@tonic-gate static int ctrl_nums = 0; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define DEVDIR "/dev/rdsk" 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate #define DO_HW_RAID_NOP -1 887c478bd9Sstevel@tonic-gate #define DO_HW_RAID_INFO 0 897c478bd9Sstevel@tonic-gate #define DO_HW_RAID_CREATE 1 907c478bd9Sstevel@tonic-gate #define DO_HW_RAID_DELETE 2 917c478bd9Sstevel@tonic-gate #define DO_HW_RAID_FLASH 3 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Error return codes 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate #define SUCCESS 0 977c478bd9Sstevel@tonic-gate #define INVALID_ARG 1 987c478bd9Sstevel@tonic-gate #define FAILURE 2 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * FW Update Stuff 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* signature and initial offset for PCI expansion rom images */ 1057c478bd9Sstevel@tonic-gate #define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */ 1067c478bd9Sstevel@tonic-gate #define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */ 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate /* offsets in PCI data structure header */ 1097c478bd9Sstevel@tonic-gate #define PCIR_DEVID 0x6 /* PCI device id */ 1107c478bd9Sstevel@tonic-gate #define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */ 1117c478bd9Sstevel@tonic-gate #define PCIR_INDICATOR 0x15 /* "last image" indicator */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* flags for image types */ 1147c478bd9Sstevel@tonic-gate #define BIOS_IMAGE 0x1 1157c478bd9Sstevel@tonic-gate #define FCODE_IMAGE 0x2 1167c478bd9Sstevel@tonic-gate #define UNKNOWN_IMAGE 0x3 1177c478bd9Sstevel@tonic-gate #define LAST_IMAGE 0x80 1187c478bd9Sstevel@tonic-gate #define NOT_LAST_IMAGE 0 1197c478bd9Sstevel@tonic-gate #define PCI_IMAGE_UNIT_SIZE 512 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* ID's and offsets for MPT Firmware images */ 1227c478bd9Sstevel@tonic-gate #define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */ 1237c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */ 1247c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ 1257c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* Key to search for when looking for fcode version */ 1287c478bd9Sstevel@tonic-gate #define FCODE_VERS_KEY1 0x12 1297c478bd9Sstevel@tonic-gate #define FCODE_VERS_KEY2 0x7 1307c478bd9Sstevel@tonic-gate #define BIOS_STR "LSI1030 SCSI Host Adapter BIOS Driver: " 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* get a word from a buffer (works with non-word aligned offsets) */ 1337c478bd9Sstevel@tonic-gate #define gw(x) (((x)[0]) + (((x)[1]) << 8)) 1347c478bd9Sstevel@tonic-gate 135*8ba1bcfcSdduvall /* Number of disks currently supported */ 136*8ba1bcfcSdduvall #define N_DISKS 2 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Function and strings to properly localize our prompt. 1407c478bd9Sstevel@tonic-gate * So for example in german it would ask (ja/nein) or (yes/no) in 1417c478bd9Sstevel@tonic-gate * english. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate static int yes(int c); 1447c478bd9Sstevel@tonic-gate static char yeschr[SCHAR_MAX + 2]; 1457c478bd9Sstevel@tonic-gate static char nochr[SCHAR_MAX +2]; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate typedef struct raidlist { 148*8ba1bcfcSdduvall raid_config_t raid_config; 1497c478bd9Sstevel@tonic-gate int controller; 1507c478bd9Sstevel@tonic-gate char devctl[MAXPATHLEN]; 1517c478bd9Sstevel@tonic-gate struct raidlist *next; 1527c478bd9Sstevel@tonic-gate } raidlist_t; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate static raidlist_t *raids; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate static void 1577c478bd9Sstevel@tonic-gate usage(char *prog_name) 1587c478bd9Sstevel@tonic-gate { 1597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s\n"), prog_name); 1607c478bd9Sstevel@tonic-gate 161*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("usage: %s -c disk1 disk2\n"), 1627c478bd9Sstevel@tonic-gate prog_name); 163*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("usage: %s -d disk1\n"), prog_name); 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1667c478bd9Sstevel@tonic-gate gettext("usage: %s [-f] -F image_file controller \n"), 1677c478bd9Sstevel@tonic-gate prog_name); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"), 1707c478bd9Sstevel@tonic-gate prog_name); 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("example:\n")); 1737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); 1747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); 1757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -F image 1\n", prog_name); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate exit(1); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* Make errno message more "user friendly" */ 1817c478bd9Sstevel@tonic-gate static void 1827c478bd9Sstevel@tonic-gate raidctl_error(char *str) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate switch (errno) { 1853a4e43d3Ssafa case EINVAL: 1863a4e43d3Ssafa (void) fprintf(stderr, gettext("Error: " 1873a4e43d3Ssafa "invalid argument would be returned\n")); 1883a4e43d3Ssafa break; 1897c478bd9Sstevel@tonic-gate case EIO: 1907c478bd9Sstevel@tonic-gate case EFAULT: 1917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1927c478bd9Sstevel@tonic-gate gettext("Error: Device inaccessible.\n")); 1937c478bd9Sstevel@tonic-gate break; 1947c478bd9Sstevel@tonic-gate case ENOTTY: 1957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error: " 1967c478bd9Sstevel@tonic-gate "Device does not support requested action.\n")); 1977c478bd9Sstevel@tonic-gate break; 1987c478bd9Sstevel@tonic-gate default: 1997c478bd9Sstevel@tonic-gate perror(str); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static int 2047c478bd9Sstevel@tonic-gate get_link_path(const char *thing, char *buf) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate if (readlink(thing, buf, MAXPATHLEN) < 0) 2077c478bd9Sstevel@tonic-gate return (1); 2087c478bd9Sstevel@tonic-gate return (0); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static int 2127c478bd9Sstevel@tonic-gate get_ctrl_devctl(char *ctrl, char *b) 2137c478bd9Sstevel@tonic-gate { 2147c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2157c478bd9Sstevel@tonic-gate char *colon; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate colon = strrchr(devctl_buf, ':'); 2207c478bd9Sstevel@tonic-gate if (colon == NULL) 2217c478bd9Sstevel@tonic-gate return (1); 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate *colon = 0; 2247c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf); 2257c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 2267c478bd9Sstevel@tonic-gate return (0); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate static int 2307c478bd9Sstevel@tonic-gate get_devctl(char *disk, char *b) 2317c478bd9Sstevel@tonic-gate { 2327c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 2337c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2347c478bd9Sstevel@tonic-gate char *slash; 2357c478bd9Sstevel@tonic-gate char devname[32]; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate if (get_link_path(disk, buf1)) 2387c478bd9Sstevel@tonic-gate return (1); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, buf1, MAXPATHLEN); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2437c478bd9Sstevel@tonic-gate if (slash == NULL) 2447c478bd9Sstevel@tonic-gate return (1); 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate *slash = 0; 2477c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2487c478bd9Sstevel@tonic-gate (void) strlcpy(devname, slash, 32); 2497c478bd9Sstevel@tonic-gate *slash = 0; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", 2527c478bd9Sstevel@tonic-gate devctl_buf, devname); 2537c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 2547c478bd9Sstevel@tonic-gate return (0); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate static int 2587c478bd9Sstevel@tonic-gate already_there(int controller) 2597c478bd9Sstevel@tonic-gate { 2607c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate while (curr != NULL) { 2637c478bd9Sstevel@tonic-gate if (curr->controller == controller) 2647c478bd9Sstevel@tonic-gate return (1); 2657c478bd9Sstevel@tonic-gate curr = curr->next; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate return (0); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * Display those controllers where RAID volumes were not found 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate static void 2757c478bd9Sstevel@tonic-gate print_no_raids() 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate int i, space = 0; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 2807c478bd9Sstevel@tonic-gate return; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 2837c478bd9Sstevel@tonic-gate /* Status of '0' means RAID exists at that controller */ 2847c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_FOUND || 2857c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 2867c478bd9Sstevel@tonic-gate continue; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate if (!space && raids != NULL) { 2897c478bd9Sstevel@tonic-gate (void) printf("\n"); 2907c478bd9Sstevel@tonic-gate space = 1; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* switch statement used to enable gettext()'ing of text */ 2947c478bd9Sstevel@tonic-gate switch (info_ctrl[i][INFO_STATUS]) { 2957c478bd9Sstevel@tonic-gate case RAID_INVALID_CTRL: 2967c478bd9Sstevel@tonic-gate (void) printf(gettext("Invalid controller '%d'\n"), 2977c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 2987c478bd9Sstevel@tonic-gate break; 2997c478bd9Sstevel@tonic-gate case RAID_NOT_SUPPORTED: 3007c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID supported " 3017c478bd9Sstevel@tonic-gate "on controller '%d'\n"), 3027c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate break; 3057c478bd9Sstevel@tonic-gate default: 3067c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found on " 3077c478bd9Sstevel@tonic-gate "controller '%d'\n"), info_ctrl[i][INFO_CTRL]); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate static void 3137c478bd9Sstevel@tonic-gate add_raid_to_raidlist(char *ctrl_name, int controller) 3147c478bd9Sstevel@tonic-gate { 315*8ba1bcfcSdduvall raid_config_t config; 3167c478bd9Sstevel@tonic-gate raidlist_t *curr; 3177c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 3187c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 319*8ba1bcfcSdduvall int fd; 320*8ba1bcfcSdduvall int i; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate if (readlink(ctrl_name, buf, sizeof (buf)) < 0) 3237c478bd9Sstevel@tonic-gate return; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if (get_ctrl_devctl(buf, buf1)) 3267c478bd9Sstevel@tonic-gate return; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* 3297c478bd9Sstevel@tonic-gate * If "-l" was specified, then only look at those controllers 3307c478bd9Sstevel@tonic-gate * listed as part of the command line input. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 333*8ba1bcfcSdduvall int found = 0; 3347c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 3357c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 3367c478bd9Sstevel@tonic-gate continue; 337*8ba1bcfcSdduvall if (controller == info_ctrl[i][INFO_CTRL]) { 338*8ba1bcfcSdduvall found = 1; 3397c478bd9Sstevel@tonic-gate break; 3407c478bd9Sstevel@tonic-gate } 341*8ba1bcfcSdduvall } 342*8ba1bcfcSdduvall if (!found) 3437c478bd9Sstevel@tonic-gate return; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate fd = open(buf1, O_RDONLY); 3477c478bd9Sstevel@tonic-gate if (fd == -1) { 3487c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3497c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL; 3507c478bd9Sstevel@tonic-gate return; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 3547c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3557c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 3567c478bd9Sstevel@tonic-gate (void) close(fd); 3577c478bd9Sstevel@tonic-gate /* Fail silently */ 3587c478bd9Sstevel@tonic-gate return; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate (void) close(fd); 3617c478bd9Sstevel@tonic-gate 362*8ba1bcfcSdduvall if (config.ndisks == 0) { 3637c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3647c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; 3657c478bd9Sstevel@tonic-gate return; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3697c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_FOUND; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate if (raids == NULL) { 3727c478bd9Sstevel@tonic-gate raids = (raidlist_t *)malloc(sizeof (raidlist_t)); 3737c478bd9Sstevel@tonic-gate curr = raids; 3747c478bd9Sstevel@tonic-gate } else { 3757c478bd9Sstevel@tonic-gate if (already_there(controller)) { 3767c478bd9Sstevel@tonic-gate return; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate curr = raids; 3807c478bd9Sstevel@tonic-gate /* Seek to the end */ 3817c478bd9Sstevel@tonic-gate while (curr->next != NULL) 3827c478bd9Sstevel@tonic-gate curr = curr->next; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate curr->next = (raidlist_t *)malloc(sizeof (raidlist_t)); 3857c478bd9Sstevel@tonic-gate curr = curr->next; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate curr->next = NULL; 3887c478bd9Sstevel@tonic-gate curr->controller = controller; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); 3917c478bd9Sstevel@tonic-gate (void) fflush(stdout); 392*8ba1bcfcSdduvall (void) memcpy(&curr->raid_config, &config, sizeof (raid_config_t)); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate static void 3967c478bd9Sstevel@tonic-gate print_header() 3977c478bd9Sstevel@tonic-gate { 398*8ba1bcfcSdduvall (void) printf(gettext("RAID\t\tRAID\t\tRAID\t\tDisk")); 3997c478bd9Sstevel@tonic-gate (void) printf("\n"); 400*8ba1bcfcSdduvall (void) printf(gettext("Volume\t\tStatus\t\tDisk\t\tStatus")); 4017c478bd9Sstevel@tonic-gate (void) printf("\n"); 4027c478bd9Sstevel@tonic-gate (void) printf("------------------------------------------------------"); 4037c478bd9Sstevel@tonic-gate (void) printf("\n"); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate static void 4077c478bd9Sstevel@tonic-gate print_raidconfig(int c, raid_config_t config) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate int i; 4107c478bd9Sstevel@tonic-gate 411*8ba1bcfcSdduvall /* Get RAID Volume */ 412*8ba1bcfcSdduvall (void) printf("c%dt%dd0\t\t", c, config.targetid); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* Get RAID Info */ 4157c478bd9Sstevel@tonic-gate if (config.flags & RAID_FLAG_RESYNCING && 4167c478bd9Sstevel@tonic-gate config.state == RAID_STATE_DEGRADED) { 4177c478bd9Sstevel@tonic-gate (void) printf(gettext("RESYNCING\t")); 4187c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_DEGRADED) { 4197c478bd9Sstevel@tonic-gate (void) printf(gettext("DEGRADED\t")); 4207c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_OPTIMAL) { 4217c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\t\t")); 4227c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_FAILED) { 4237c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\t\t")); 4247c478bd9Sstevel@tonic-gate } else { 4257c478bd9Sstevel@tonic-gate (void) printf(gettext("ERROR\t\t")); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /* Get RAID Disks */ 4297c478bd9Sstevel@tonic-gate (void) printf("c%dt%dd0\t\t", c, config.disk[0]); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* Get RAID Disk's Status */ 4327c478bd9Sstevel@tonic-gate if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) { 4337c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 4347c478bd9Sstevel@tonic-gate } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) { 4357c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 4367c478bd9Sstevel@tonic-gate } else { 4377c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate for (i = 1; i < config.ndisks; i++) { 4417c478bd9Sstevel@tonic-gate (void) printf("\t\t\t\tc%dt%dd0\t\t", c, config.disk[i]); 4427c478bd9Sstevel@tonic-gate if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) { 4437c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 4447c478bd9Sstevel@tonic-gate } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) { 4457c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 4467c478bd9Sstevel@tonic-gate } else { 4477c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate } 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate static void 4537c478bd9Sstevel@tonic-gate print_disklist() 4547c478bd9Sstevel@tonic-gate { 4557c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 4567c478bd9Sstevel@tonic-gate while (curr != NULL) { 457*8ba1bcfcSdduvall print_raidconfig(curr->controller, curr->raid_config); 4587c478bd9Sstevel@tonic-gate curr = curr->next; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate static void 4637c478bd9Sstevel@tonic-gate free_disklist() 4647c478bd9Sstevel@tonic-gate { 4657c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate while (curr != NULL) { 4687c478bd9Sstevel@tonic-gate raidlist_t *temp; 4697c478bd9Sstevel@tonic-gate temp = curr; 4707c478bd9Sstevel@tonic-gate curr = curr->next; 4717c478bd9Sstevel@tonic-gate free(temp); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate static void 4767c478bd9Sstevel@tonic-gate do_search() 4777c478bd9Sstevel@tonic-gate { 4787c478bd9Sstevel@tonic-gate DIR *dir; 4797c478bd9Sstevel@tonic-gate struct dirent *dp; 4807c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 4817c478bd9Sstevel@tonic-gate int c; 4827c478bd9Sstevel@tonic-gate int i, j; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * In case repeated numbers were found, assign the repititions as 4867c478bd9Sstevel@tonic-gate * RAID_DONT_USE 4877c478bd9Sstevel@tonic-gate */ 4887c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 4897c478bd9Sstevel@tonic-gate int first_one = 1; 4907c478bd9Sstevel@tonic-gate for (j = 0; j < ctrl_nums; j++) { 4917c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_CTRL] == 4927c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_CTRL]) { 4937c478bd9Sstevel@tonic-gate if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE) 4947c478bd9Sstevel@tonic-gate continue; 4957c478bd9Sstevel@tonic-gate if (first_one) { 4967c478bd9Sstevel@tonic-gate first_one = 0; 4977c478bd9Sstevel@tonic-gate } else { 4987c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_STATUS] = 4997c478bd9Sstevel@tonic-gate RAID_DONT_USE; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate if ((dir = opendir("/dev/cfg")) == NULL) { 5067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5077c478bd9Sstevel@tonic-gate gettext("Cannot open /dev/cfg: %s\n"), strerror(errno)); 5087c478bd9Sstevel@tonic-gate return; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate while ((dp = readdir(dir)) != NULL) { 5117c478bd9Sstevel@tonic-gate if (strcmp(dp->d_name, ".") == 0 || 5127c478bd9Sstevel@tonic-gate strcmp(dp->d_name, "..") == 0) 5137c478bd9Sstevel@tonic-gate continue; 5147c478bd9Sstevel@tonic-gate if (sscanf(dp->d_name, "c%d", &c) != 1) 5157c478bd9Sstevel@tonic-gate continue; 5167c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name); 5177c478bd9Sstevel@tonic-gate add_raid_to_raidlist(buf, c); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate (void) closedir(dir); 5207c478bd9Sstevel@tonic-gate } 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * do_info() will do the following: 5247c478bd9Sstevel@tonic-gate * - create a list of disks' devctls 5257c478bd9Sstevel@tonic-gate * - try to talk to each of the devctls found 5267c478bd9Sstevel@tonic-gate * - if raid configuration is found, display it. 5277c478bd9Sstevel@tonic-gate */ 5287c478bd9Sstevel@tonic-gate static void 5297c478bd9Sstevel@tonic-gate do_info() 5307c478bd9Sstevel@tonic-gate { 5317c478bd9Sstevel@tonic-gate int i; 5327c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate do_search(); 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate if (raids == NULL) { 5377c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 5387c478bd9Sstevel@tonic-gate print_no_raids(); 5397c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 5407c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 5417c478bd9Sstevel@tonic-gate free(info_ctrl); 5427c478bd9Sstevel@tonic-gate } else { 5437c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found\n")); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate return; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate print_header(); 5497c478bd9Sstevel@tonic-gate print_disklist(); 5507c478bd9Sstevel@tonic-gate print_no_raids(); 5517c478bd9Sstevel@tonic-gate free_disklist(); 5527c478bd9Sstevel@tonic-gate if (info_ctrl) { 5537c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 5547c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 5557c478bd9Sstevel@tonic-gate free(info_ctrl); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate static int 5607c478bd9Sstevel@tonic-gate disk_there(int c, int t) 5617c478bd9Sstevel@tonic-gate { 5627c478bd9Sstevel@tonic-gate char disk[100]; 5637c478bd9Sstevel@tonic-gate int fd; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate fd = open(disk, O_RDWR | O_NDELAY); 5687c478bd9Sstevel@tonic-gate if (fd == -1) { 5697c478bd9Sstevel@tonic-gate return (-1); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate (void) close(fd); 5737c478bd9Sstevel@tonic-gate return (0); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate static int 5777c478bd9Sstevel@tonic-gate get_controller(char *dev) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate raidlist_t *curr; 5807c478bd9Sstevel@tonic-gate int c; 5817c478bd9Sstevel@tonic-gate do_search(); 5827c478bd9Sstevel@tonic-gate curr = raids; 5837c478bd9Sstevel@tonic-gate while (curr != NULL) { 5847c478bd9Sstevel@tonic-gate if (strcmp(curr->devctl, dev) == 0) { 5857c478bd9Sstevel@tonic-gate c = curr->controller; 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate curr = curr->next; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate free_disklist(); 5927c478bd9Sstevel@tonic-gate return (c); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate static int 5967c478bd9Sstevel@tonic-gate disk_mounted(char *d) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate struct mnttab mt; 5997c478bd9Sstevel@tonic-gate FILE *f = fopen("/etc/mnttab", "r"); 6007c478bd9Sstevel@tonic-gate 601*8ba1bcfcSdduvall while (getmntent(f, &mt) != EOF) 6027c478bd9Sstevel@tonic-gate if (strstr(mt.mnt_special, d) != NULL) 6037c478bd9Sstevel@tonic-gate return (1); 6047c478bd9Sstevel@tonic-gate return (0); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate static int 6087c478bd9Sstevel@tonic-gate disk_big_enough(char **d, diskaddr_t *cap, int *errcond) 6097c478bd9Sstevel@tonic-gate { 6107c478bd9Sstevel@tonic-gate struct dk_minfo minfo; 6117c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN]; 612*8ba1bcfcSdduvall diskaddr_t disk_lbsize[N_DISKS]; 6137c478bd9Sstevel@tonic-gate diskaddr_t disk_capacity[N_DISKS]; 6147c478bd9Sstevel@tonic-gate int i, fd; 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 6177c478bd9Sstevel@tonic-gate (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 6187c478bd9Sstevel@tonic-gate fd = open(disk[i], O_RDWR | O_NDELAY); 619*8ba1bcfcSdduvall if (fd == -1) { 6207c478bd9Sstevel@tonic-gate return (FAILURE); 621*8ba1bcfcSdduvall } 622*8ba1bcfcSdduvall 6237c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { 6247c478bd9Sstevel@tonic-gate (void) close(fd); 6257c478bd9Sstevel@tonic-gate return (FAILURE); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate disk_lbsize[i] = minfo.dki_lbsize; 6297c478bd9Sstevel@tonic-gate disk_capacity[i] = minfo.dki_capacity; 630*8ba1bcfcSdduvall (void) close(fd); 631*8ba1bcfcSdduvall } 6327c478bd9Sstevel@tonic-gate 633*8ba1bcfcSdduvall /* lbsize must be the same on both disks */ 634*8ba1bcfcSdduvall if (disk_lbsize[0] != disk_lbsize[1]) { 6357c478bd9Sstevel@tonic-gate *errcond = 2; 6367c478bd9Sstevel@tonic-gate return (INVALID_ARG); 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 639*8ba1bcfcSdduvall /* secondary size is not greater than or equal to primary size */ 640*8ba1bcfcSdduvall if (disk_capacity[0] > disk_capacity[1]) { 6417c478bd9Sstevel@tonic-gate *errcond = 1; 6427c478bd9Sstevel@tonic-gate return (INVALID_ARG); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 645*8ba1bcfcSdduvall /* Secondary disk is big enough */ 6467c478bd9Sstevel@tonic-gate *cap = disk_capacity[0]; 6477c478bd9Sstevel@tonic-gate return (SUCCESS); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate static int 6517c478bd9Sstevel@tonic-gate do_config_change_state(cfga_cmd_t cmd, int d, int c) 6527c478bd9Sstevel@tonic-gate { 6537c478bd9Sstevel@tonic-gate cfga_err_t cfga_err; 6547c478bd9Sstevel@tonic-gate char *ap_id; 6557c478bd9Sstevel@tonic-gate int rv = SUCCESS; 6567c478bd9Sstevel@tonic-gate int count = 0; 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate ap_id = (char *)malloc(100); 6597c478bd9Sstevel@tonic-gate if (ap_id == NULL) 6607c478bd9Sstevel@tonic-gate return (FAILURE); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate /* 6657c478bd9Sstevel@tonic-gate * If the config_change_state() funcation fails, we want to 6667c478bd9Sstevel@tonic-gate * retry. If the retry fails, then we return failure to fail. 6677c478bd9Sstevel@tonic-gate * 6687c478bd9Sstevel@tonic-gate * If we fail: 6697c478bd9Sstevel@tonic-gate * 6707c478bd9Sstevel@tonic-gate * If we were called from create, then we fail the raid 6717c478bd9Sstevel@tonic-gate * creation. 6727c478bd9Sstevel@tonic-gate * 6737c478bd9Sstevel@tonic-gate * If we were called from delete, then the disk will not 6747c478bd9Sstevel@tonic-gate * be re-configured by raidctl. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate do { 6777c478bd9Sstevel@tonic-gate cfga_err = config_change_state(cmd, 1, &ap_id, NULL, 6787c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 6797c478bd9Sstevel@tonic-gate count++; 6807c478bd9Sstevel@tonic-gate } while (cfga_err != CFGA_OK && count < 2); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if (cfga_err != CFGA_OK) 6837c478bd9Sstevel@tonic-gate rv = FAILURE; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate free(ap_id); 6867c478bd9Sstevel@tonic-gate return (rv); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate static int 690*8ba1bcfcSdduvall do_create(char **d) 6917c478bd9Sstevel@tonic-gate { 692*8ba1bcfcSdduvall raid_config_t config; 6937c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN] = {0}; 6947c478bd9Sstevel@tonic-gate char channel1[MAXPATHLEN]; 6957c478bd9Sstevel@tonic-gate char channel2[MAXPATHLEN]; 6967c478bd9Sstevel@tonic-gate diskaddr_t capacity; 697*8ba1bcfcSdduvall int fd, fd2, size, errcond, disk_here = 1; 6987c478bd9Sstevel@tonic-gate int c[N_DISKS]; 6997c478bd9Sstevel@tonic-gate int t[N_DISKS]; 7007c478bd9Sstevel@tonic-gate char *tmp; 701*8ba1bcfcSdduvall int i; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 7067c478bd9Sstevel@tonic-gate if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || 7077c478bd9Sstevel@tonic-gate t[i] < 0) { 7087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7097c478bd9Sstevel@tonic-gate gettext("Invalid disk format.\n")); 7107c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7117c478bd9Sstevel@tonic-gate } 712*8ba1bcfcSdduvall (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 713*8ba1bcfcSdduvall } 7147c478bd9Sstevel@tonic-gate 715*8ba1bcfcSdduvall /* Must be on same controller */ 716*8ba1bcfcSdduvall if (c[0] != c[1]) { 717*8ba1bcfcSdduvall (void) fprintf(stderr, 718*8ba1bcfcSdduvall gettext("Disks must be on the same controller.\n")); 7197c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 722*8ba1bcfcSdduvall /* primary disk target must be lower than secondary disk target */ 723*8ba1bcfcSdduvall if (t[0] > t[1]) { 724*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("Primary target ID " 725*8ba1bcfcSdduvall "must be less than secondary target ID.\n")); 726*8ba1bcfcSdduvall return (INVALID_ARG); 727*8ba1bcfcSdduvall } 728*8ba1bcfcSdduvall 729*8ba1bcfcSdduvall /* disks must not be the same */ 730*8ba1bcfcSdduvall if (t[0] == t[1]) { 731*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("Disks must be different.\n")); 732*8ba1bcfcSdduvall return (INVALID_ARG); 733*8ba1bcfcSdduvall } 734*8ba1bcfcSdduvall 735*8ba1bcfcSdduvall /* disks must be present */ 736*8ba1bcfcSdduvall if (disk_there(c[0], t[0])) { 737*8ba1bcfcSdduvall (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), 738*8ba1bcfcSdduvall c[0], t[0]); 739*8ba1bcfcSdduvall disk_here = 0; 740*8ba1bcfcSdduvall } 741*8ba1bcfcSdduvall if (disk_there(c[1], t[1])) { 742*8ba1bcfcSdduvall (void) printf(gettext("Disk 'c%dt%dd0' is not present.\n"), 743*8ba1bcfcSdduvall c[0], t[1]); 744*8ba1bcfcSdduvall disk_here = 0; 745*8ba1bcfcSdduvall } 746*8ba1bcfcSdduvall 747*8ba1bcfcSdduvall if (!disk_here) { 7487c478bd9Sstevel@tonic-gate (void) printf(gettext("Cannot create RAID volume.\n")); 7497c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 752*8ba1bcfcSdduvall /* secondary disk's size must be greater or equal to primary disk's */ 7537c478bd9Sstevel@tonic-gate switch (disk_big_enough(d, &capacity, &errcond)) { 7547c478bd9Sstevel@tonic-gate case FAILURE: 7557c478bd9Sstevel@tonic-gate return (FAILURE); 7567c478bd9Sstevel@tonic-gate case INVALID_ARG: 7577c478bd9Sstevel@tonic-gate switch (errcond) { 7587c478bd9Sstevel@tonic-gate case 1: 7597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 7607c478bd9Sstevel@tonic-gate "primary disk is larger than secondary disk.\n")); 7617c478bd9Sstevel@tonic-gate break; 7627c478bd9Sstevel@tonic-gate case 2: 7637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 7647c478bd9Sstevel@tonic-gate "disk block sizes differ.\n")); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 769*8ba1bcfcSdduvall /* secondary disk must not be mounted */ 770*8ba1bcfcSdduvall if (disk_mounted(d[1])) { 771*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("Cannot create RAID volume when " 772*8ba1bcfcSdduvall "secondary disk \"%s\" is mounted.\n"), d[1]); 773*8ba1bcfcSdduvall return (INVALID_ARG); 774*8ba1bcfcSdduvall } 7757c478bd9Sstevel@tonic-gate 776*8ba1bcfcSdduvall /* Only one RAID can exist per controller */ 7777c478bd9Sstevel@tonic-gate if (get_devctl(disk[0], channel1)) 7787c478bd9Sstevel@tonic-gate return (FAILURE); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate fd = open(channel1, O_RDONLY); 7817c478bd9Sstevel@tonic-gate if (fd == -1) { 7827c478bd9Sstevel@tonic-gate perror(channel1); 7837c478bd9Sstevel@tonic-gate return (FAILURE); 7847c478bd9Sstevel@tonic-gate } 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 7877c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 788*8ba1bcfcSdduvall goto fail1; 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate 791*8ba1bcfcSdduvall if (config.ndisks != 0) { 792*8ba1bcfcSdduvall (void) printf(gettext("RAID Volume already exists on this " 793*8ba1bcfcSdduvall "controller 'c%dt%dd0'\n"), c[0], config.targetid); 794*8ba1bcfcSdduvall goto fail1; 79505411564Sjesseb } 79605411564Sjesseb 79705411564Sjesseb /* 7987c478bd9Sstevel@tonic-gate * Make sure there isn't a raid created on this controller's 799*8ba1bcfcSdduvall * other channel 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate (void) strlcpy(channel2, channel1, sizeof (channel2)); 8027c478bd9Sstevel@tonic-gate tmp = strrchr(channel2, ':'); 8037c478bd9Sstevel@tonic-gate tmp[0] = 0; 8047c478bd9Sstevel@tonic-gate size = strlen(channel2); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate /* 8077c478bd9Sstevel@tonic-gate * Format the channel string for the other channel so we can 808*8ba1bcfcSdduvall * see if a raid exists on it. In this case if we are being asked 809*8ba1bcfcSdduvall * to create a raid on channel 2 (indicated by the 1,1 at the end 810*8ba1bcfcSdduvall * of the string) we want to check channel 1) otherwise we will 811*8ba1bcfcSdduvall * check channel 2. 8127c478bd9Sstevel@tonic-gate */ 8137c478bd9Sstevel@tonic-gate if (channel2[size - 2] == ',') { 8147c478bd9Sstevel@tonic-gate channel2[size - 1] = 0; 8157c478bd9Sstevel@tonic-gate channel2[size - 2] = 0; 816*8ba1bcfcSdduvall (void) snprintf(channel2, sizeof (channel2), "%s:devctl", 817*8ba1bcfcSdduvall channel2); 8187c478bd9Sstevel@tonic-gate } else { 819*8ba1bcfcSdduvall (void) snprintf(channel2, sizeof (channel2), "%s,1:devctl", 820*8ba1bcfcSdduvall channel2); 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate fd2 = open(channel2, O_RDONLY); 8247c478bd9Sstevel@tonic-gate if (fd2 == -1) { 8257c478bd9Sstevel@tonic-gate if (errno == ENOENT) 8267c478bd9Sstevel@tonic-gate goto no_secondary_channel; 8277c478bd9Sstevel@tonic-gate perror(channel2); 828*8ba1bcfcSdduvall goto fail1; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { 832*8ba1bcfcSdduvall goto fail2; 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 835*8ba1bcfcSdduvall if (config.ndisks != 0) { 8367c478bd9Sstevel@tonic-gate int cx; 8377c478bd9Sstevel@tonic-gate cx = get_controller(channel2); 838*8ba1bcfcSdduvall (void) printf(gettext("RAID Volume already exists on this " 839*8ba1bcfcSdduvall "controller 'c%dt%dd0'\n"), cx, config.targetid); 840*8ba1bcfcSdduvall goto fail2; 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate no_secondary_channel: 8447c478bd9Sstevel@tonic-gate 845*8ba1bcfcSdduvall /* No other RAID volumes exist, so we may continue */ 846*8ba1bcfcSdduvall config.raid_capacity = capacity; 847*8ba1bcfcSdduvall config.raid_level = 1; /* RAID 1: Mirror */ 848*8ba1bcfcSdduvall config.targetid = t[0]; /* Assume identity of first disk */ 849*8ba1bcfcSdduvall config.disk[0] = t[0]; /* Primary Disk */ 850*8ba1bcfcSdduvall config.disk[1] = t[1]; /* Secondary Disk */ 8517c478bd9Sstevel@tonic-gate 852*8ba1bcfcSdduvall /* Make secondary disk inaccessible to the system */ 8537c478bd9Sstevel@tonic-gate if (do_config_change_state(CFGA_CMD_UNCONFIGURE, 854*8ba1bcfcSdduvall config.disk[1], c[0])) { 8557c478bd9Sstevel@tonic-gate perror("config_change_state"); 856*8ba1bcfcSdduvall goto fail2; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate 859*8ba1bcfcSdduvall if (ioctl(fd, RAID_CREATE, &config)) { 8607c478bd9Sstevel@tonic-gate (void) do_config_change_state(CFGA_CMD_CONFIGURE, 861*8ba1bcfcSdduvall config.disk[1], c[0]); 8627c478bd9Sstevel@tonic-gate raidctl_error("RAID_CREATE"); 863*8ba1bcfcSdduvall goto fail2; 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); 8677c478bd9Sstevel@tonic-gate (void) close(fd); 8687c478bd9Sstevel@tonic-gate (void) close(fd2); 8697c478bd9Sstevel@tonic-gate return (SUCCESS); 8707c478bd9Sstevel@tonic-gate 871*8ba1bcfcSdduvall fail2: 87205411564Sjesseb (void) close(fd2); 873*8ba1bcfcSdduvall fail1: 874*8ba1bcfcSdduvall (void) close(fd); 8757c478bd9Sstevel@tonic-gate return (FAILURE); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate static int 8797c478bd9Sstevel@tonic-gate do_delete(char *d) 8807c478bd9Sstevel@tonic-gate { 881*8ba1bcfcSdduvall raid_config_t config; 8827c478bd9Sstevel@tonic-gate char disk1[MAXPATHLEN]; 8837c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 8847c478bd9Sstevel@tonic-gate int fd; 8857c478bd9Sstevel@tonic-gate int target; 8867c478bd9Sstevel@tonic-gate int ctrl; 8877c478bd9Sstevel@tonic-gate uint8_t t; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) { 8927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Invalid disk format.\n")); 8937c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate t = (uint8_t)target; 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate if (get_devctl(disk1, buf) != 0) { 9007c478bd9Sstevel@tonic-gate return (FAILURE); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate fd = open(buf, O_RDONLY); 9047c478bd9Sstevel@tonic-gate if (fd == -1) { 9057c478bd9Sstevel@tonic-gate perror(buf); 9067c478bd9Sstevel@tonic-gate return (FAILURE); 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config)) { 9107c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 9117c478bd9Sstevel@tonic-gate goto fail; 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate 914*8ba1bcfcSdduvall if (config.ndisks == 0) { 915*8ba1bcfcSdduvall (void) fprintf(stderr, gettext("No RAID Volume exists on " 9167c478bd9Sstevel@tonic-gate "controller '%d'\n"), ctrl); 9177c478bd9Sstevel@tonic-gate goto fail; 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 920*8ba1bcfcSdduvall if (config.targetid != t) { 9217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9227c478bd9Sstevel@tonic-gate gettext("RAID volume 'c%dt%dd0' does not exist\n"), 9237c478bd9Sstevel@tonic-gate ctrl, t); 9247c478bd9Sstevel@tonic-gate goto fail; 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_DELETE, &t)) { 9287c478bd9Sstevel@tonic-gate perror("RAID_DELETE"); 9297c478bd9Sstevel@tonic-gate goto fail; 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 932*8ba1bcfcSdduvall /* 933*8ba1bcfcSdduvall * Make secondary disk accessible to the system. 934*8ba1bcfcSdduvall * Ignore return value from do_config_change_state. 935*8ba1bcfcSdduvall */ 936*8ba1bcfcSdduvall (void) do_config_change_state(CFGA_CMD_CONFIGURE, config.disk[1], ctrl); 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), 9397c478bd9Sstevel@tonic-gate ctrl, target); 9407c478bd9Sstevel@tonic-gate (void) close(fd); 9417c478bd9Sstevel@tonic-gate return (SUCCESS); 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate fail: 9447c478bd9Sstevel@tonic-gate (void) close(fd); 9457c478bd9Sstevel@tonic-gate return (FAILURE); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate static int 9497c478bd9Sstevel@tonic-gate getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion) 9507c478bd9Sstevel@tonic-gate { 9517c478bd9Sstevel@tonic-gate int x, y, size; 9527c478bd9Sstevel@tonic-gate int found_1 = 0, found_2 = 0; 9537c478bd9Sstevel@tonic-gate int image_length = 0; 9547c478bd9Sstevel@tonic-gate int no_of_images = 0; 9557c478bd9Sstevel@tonic-gate uint8_t *rombuf_1 = NULL; 9567c478bd9Sstevel@tonic-gate uint16_t image_units = 0; 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate /* 9597c478bd9Sstevel@tonic-gate * Single Image - Open firmware image 9607c478bd9Sstevel@tonic-gate */ 9617c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) { 9627c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR; 9637c478bd9Sstevel@tonic-gate no_of_images = 1; 9647c478bd9Sstevel@tonic-gate goto process_image; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate /* 9687c478bd9Sstevel@tonic-gate * Combined Image - First Image - x86/PC-AT Bios image 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) { 9717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 9727c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 9737c478bd9Sstevel@tonic-gate return (1); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate /* 9777c478bd9Sstevel@tonic-gate * Seek to 2nd Image 9787c478bd9Sstevel@tonic-gate */ 9797c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR); 9807c478bd9Sstevel@tonic-gate image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH); 9817c478bd9Sstevel@tonic-gate image_length = image_units * PCI_IMAGE_UNIT_SIZE; 9827c478bd9Sstevel@tonic-gate rombuf_1 += image_length; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* 9857c478bd9Sstevel@tonic-gate * Combined Image - Second Image - Open Firmware image 9867c478bd9Sstevel@tonic-gate */ 9877c478bd9Sstevel@tonic-gate if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) { 9887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 9897c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 9907c478bd9Sstevel@tonic-gate return (1); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate rombuf_1 += PCI_PDS_INDICATOR; 9937c478bd9Sstevel@tonic-gate no_of_images = 2; 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate process_image: 9967c478bd9Sstevel@tonic-gate /* 9977c478bd9Sstevel@tonic-gate * This should be the last image 9987c478bd9Sstevel@tonic-gate */ 9997c478bd9Sstevel@tonic-gate if (*rombuf_1 != LAST_IMAGE) { 10007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is not a valid " 10017c478bd9Sstevel@tonic-gate "Bios/Fcode image file\n")); 10027c478bd9Sstevel@tonic-gate return (1); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* 10067c478bd9Sstevel@tonic-gate * Scan through the bois/fcode file to get the fcode version 10077c478bd9Sstevel@tonic-gate * 0x12 and 0x7 indicate the start of the fcode version string 10087c478bd9Sstevel@tonic-gate */ 10097c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 8); x++) { 10107c478bd9Sstevel@tonic-gate if ((rombuf[x] == FCODE_VERS_KEY1) && 10117c478bd9Sstevel@tonic-gate (rombuf[x+1] == FCODE_VERS_KEY2) && 10127c478bd9Sstevel@tonic-gate (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') && 10137c478bd9Sstevel@tonic-gate (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') && 10147c478bd9Sstevel@tonic-gate (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') && 10157c478bd9Sstevel@tonic-gate (rombuf[x+8] == 'n')) { 10167c478bd9Sstevel@tonic-gate found_1 = 1; 10177c478bd9Sstevel@tonic-gate break; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 10227c478bd9Sstevel@tonic-gate * Store the version string if we have found the beginning of it 10237c478bd9Sstevel@tonic-gate */ 10247c478bd9Sstevel@tonic-gate if (found_1) { 10257c478bd9Sstevel@tonic-gate while (x > 0) { 10267c478bd9Sstevel@tonic-gate if (rombuf[--x] == FCODE_VERS_KEY1) { 10277c478bd9Sstevel@tonic-gate if (rombuf[x-1] != FCODE_VERS_KEY1) { 10287c478bd9Sstevel@tonic-gate x++; 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate break; 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate if (x > 0) { 10347c478bd9Sstevel@tonic-gate *fcodeversion = (char *)malloc(rombuf[x] + 1); 10357c478bd9Sstevel@tonic-gate for (y = 0; y < rombuf[x]; y++) { 10367c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = rombuf[x+y+1]; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 10397c478bd9Sstevel@tonic-gate } else { 10407c478bd9Sstevel@tonic-gate found_1 = 0; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate /* 10457c478bd9Sstevel@tonic-gate * Scan through the bois/fcode file to get the Bios version 10467c478bd9Sstevel@tonic-gate * "@(#)" string indicates the start of the Bios version string 10477c478bd9Sstevel@tonic-gate * Append this version string, after already existing fcode version. 10487c478bd9Sstevel@tonic-gate */ 10497c478bd9Sstevel@tonic-gate if (no_of_images == 2) { 10507c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 4); x++) { 10517c478bd9Sstevel@tonic-gate if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 10527c478bd9Sstevel@tonic-gate (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 10537c478bd9Sstevel@tonic-gate found_2 = 1; 10547c478bd9Sstevel@tonic-gate break; 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate if (found_2) { 10597c478bd9Sstevel@tonic-gate x += 4; 10607c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\n'; 10617c478bd9Sstevel@tonic-gate size = y + strlen((char *)(rombuf + x)) + 10627c478bd9Sstevel@tonic-gate strlen(BIOS_STR) + 2; 10637c478bd9Sstevel@tonic-gate *fcodeversion = (char *)realloc((*fcodeversion), size); 10647c478bd9Sstevel@tonic-gate y++; 10657c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 10667c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, BIOS_STR, size); 10677c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, (char *)(rombuf + x), 10687c478bd9Sstevel@tonic-gate size); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate return ((found_1 || found_2) ? 0 : 1); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate static void 10767c478bd9Sstevel@tonic-gate getfwver(uint8_t *rombuf, char *fwversion) 10777c478bd9Sstevel@tonic-gate { 10787c478bd9Sstevel@tonic-gate (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d", 10797c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 3], 10807c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 2], 10817c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 1], 10827c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 0]); 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate static int 10867c478bd9Sstevel@tonic-gate checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype) 10877c478bd9Sstevel@tonic-gate { 10887c478bd9Sstevel@tonic-gate char *imageversion = NULL; 10897c478bd9Sstevel@tonic-gate char *fwversion; 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate fwversion = (char *)malloc(8); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate if (gw(&rombuf[0]) == PCIROM_SIG) { 10947c478bd9Sstevel@tonic-gate /* imageversion is malloc(2)'ed in getfcodever() */ 10957c478bd9Sstevel@tonic-gate if (getfcodever(rombuf, nbytes, &imageversion) == 0) { 10967c478bd9Sstevel@tonic-gate *imagetype = FCODE_IMAGE; 10977c478bd9Sstevel@tonic-gate } else { 10987c478bd9Sstevel@tonic-gate *imagetype = UNKNOWN_IMAGE; 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate if (*imagetype != UNKNOWN_IMAGE) { 11017c478bd9Sstevel@tonic-gate (void) printf(gettext("Image file contains:\n%s\n"), 11027c478bd9Sstevel@tonic-gate imageversion); 11037c478bd9Sstevel@tonic-gate free(imageversion); 11047c478bd9Sstevel@tonic-gate } else { 11057c478bd9Sstevel@tonic-gate if (imageversion != NULL) { 11067c478bd9Sstevel@tonic-gate free(imageversion); 11077c478bd9Sstevel@tonic-gate } 11087c478bd9Sstevel@tonic-gate return (-1); 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate } else if (gw(&rombuf[3]) == FW_ROM_ID) { 11117c478bd9Sstevel@tonic-gate if (chksum != 0) { 11127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11137c478bd9Sstevel@tonic-gate gettext("The ROM checksum appears bad " 11147c478bd9Sstevel@tonic-gate "(%d)\n"), chksum); 11157c478bd9Sstevel@tonic-gate return (-1); 11167c478bd9Sstevel@tonic-gate } 11177c478bd9Sstevel@tonic-gate getfwver(rombuf, fwversion); 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) & 11207c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_MASK) == 11217c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_IM_SCSI) { 11227c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 11237c478bd9Sstevel@tonic-gate "MPT firmware version %s " 11247c478bd9Sstevel@tonic-gate "(w/Integrated Mirroring)\n"), 11257c478bd9Sstevel@tonic-gate fwversion); 11267c478bd9Sstevel@tonic-gate } else { 11277c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 11287c478bd9Sstevel@tonic-gate "MPT firmware ""version %s\n"), 11297c478bd9Sstevel@tonic-gate fwversion); 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate free(fwversion); 11327c478bd9Sstevel@tonic-gate } else { 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate #ifdef DEBUG 11357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0])); 11367c478bd9Sstevel@tonic-gate #else 11377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Not valid FCODE image\n")); 11387c478bd9Sstevel@tonic-gate #endif 11397c478bd9Sstevel@tonic-gate return (-1); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate return (0); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate static int 11457c478bd9Sstevel@tonic-gate updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl) 11467c478bd9Sstevel@tonic-gate { 11477c478bd9Sstevel@tonic-gate int fd = 0; 11487c478bd9Sstevel@tonic-gate update_flash_t flashdata; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate fd = open(devctl, O_RDONLY); 11517c478bd9Sstevel@tonic-gate if (fd == -1) { 11527c478bd9Sstevel@tonic-gate perror(devctl); 11537c478bd9Sstevel@tonic-gate return (-1); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate (void) memset(&flashdata, 0, sizeof (flashdata)); 11567c478bd9Sstevel@tonic-gate flashdata.ptrbuffer = (caddr_t)rombuf; 11577c478bd9Sstevel@tonic-gate flashdata.size = nbytes; 11587c478bd9Sstevel@tonic-gate if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) { 11597c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_FCODE; 11607c478bd9Sstevel@tonic-gate } else { 11617c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_UCODE; 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_UPDATEFW, &flashdata)) { 11657c478bd9Sstevel@tonic-gate raidctl_error("RAID_UPDATEFW"); 11667c478bd9Sstevel@tonic-gate (void) close(fd); 11677c478bd9Sstevel@tonic-gate return (-1); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate 11707c478bd9Sstevel@tonic-gate (void) close(fd); 11717c478bd9Sstevel@tonic-gate return (0); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate static int 11757c478bd9Sstevel@tonic-gate readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum) 11767c478bd9Sstevel@tonic-gate { 11777c478bd9Sstevel@tonic-gate struct stat statbuf; 11787c478bd9Sstevel@tonic-gate uint32_t count; 11797c478bd9Sstevel@tonic-gate uint32_t checksum = 0; 11807c478bd9Sstevel@tonic-gate int fd, i; 11817c478bd9Sstevel@tonic-gate uint8_t *filebuf; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) { 11857c478bd9Sstevel@tonic-gate perror(filespec); 11867c478bd9Sstevel@tonic-gate return (-1); 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (fstat(fd, &statbuf) != 0) { 11907c478bd9Sstevel@tonic-gate perror("fstat"); 11917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11927c478bd9Sstevel@tonic-gate gettext("Error getting stats on file\n")); 11937c478bd9Sstevel@tonic-gate (void) close(fd); 11947c478bd9Sstevel@tonic-gate return (-1); 11957c478bd9Sstevel@tonic-gate } 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate #ifdef DEBUG 11987c478bd9Sstevel@tonic-gate (void) printf("Filesize = %ld\n", statbuf.st_size); 11997c478bd9Sstevel@tonic-gate #endif 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes); 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate count = read(fd, filebuf + *nbytes, statbuf.st_size); 12047c478bd9Sstevel@tonic-gate (void) close(fd); 12057c478bd9Sstevel@tonic-gate if (count != statbuf.st_size) { 12067c478bd9Sstevel@tonic-gate perror("size check"); 12077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("File is corrupt\n")); 12087c478bd9Sstevel@tonic-gate return (-1); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate for (i = 0; i < *nbytes; i++) 12127c478bd9Sstevel@tonic-gate checksum += filebuf[i] << (8 * (i & 3)); 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate *rombuf = filebuf; 12157c478bd9Sstevel@tonic-gate *nbytes = *nbytes + count; 12167c478bd9Sstevel@tonic-gate *chksum = checksum; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate return (0); 12197c478bd9Sstevel@tonic-gate } 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate static int 12227c478bd9Sstevel@tonic-gate yes(int c) 12237c478bd9Sstevel@tonic-gate { 12247c478bd9Sstevel@tonic-gate int i, b; 12257c478bd9Sstevel@tonic-gate char ans[SCHAR_MAX + 1]; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 12287c478bd9Sstevel@tonic-gate b = getchar(); 12297c478bd9Sstevel@tonic-gate if (b == '\n' || b == '\0' || b == EOF) { 12307c478bd9Sstevel@tonic-gate ans[i] = 0; 12317c478bd9Sstevel@tonic-gate break; 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate if (i < SCHAR_MAX) 12347c478bd9Sstevel@tonic-gate ans[i] = b; 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate if (i >= SCHAR_MAX) { 12377c478bd9Sstevel@tonic-gate i = SCHAR_MAX; 12387c478bd9Sstevel@tonic-gate ans[SCHAR_MAX] = 0; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0)) { 12417c478bd9Sstevel@tonic-gate return (1); 12427c478bd9Sstevel@tonic-gate } else { 12437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("User response is \"%s\", " 12447c478bd9Sstevel@tonic-gate "Controller %d not flashed.\n\n"), ans, c); 12457c478bd9Sstevel@tonic-gate return (0); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate static int 12507c478bd9Sstevel@tonic-gate do_flash(int c, char *fpath, int force) 12517c478bd9Sstevel@tonic-gate { 12527c478bd9Sstevel@tonic-gate char devctl[MAXPATHLEN] = {0}; 12537c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 12547c478bd9Sstevel@tonic-gate int rv = 0; 12557c478bd9Sstevel@tonic-gate int imagetype; 12567c478bd9Sstevel@tonic-gate uint32_t nbytes = 0; 12577c478bd9Sstevel@tonic-gate uint32_t chksum; 12587c478bd9Sstevel@tonic-gate uint8_t *rombuf = NULL; 12597c478bd9Sstevel@tonic-gate char cwd[MAXPATHLEN]; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate /* 12627c478bd9Sstevel@tonic-gate * Read fw file 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate rv = readfile(fpath, &rombuf, &nbytes, &chksum); 12657c478bd9Sstevel@tonic-gate if (rv != 0) { 12667c478bd9Sstevel@tonic-gate return (FAILURE); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate (void) getcwd(cwd, sizeof (cwd)); 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate /* Get link from "/dev/cfg" */ 12747c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c); 12757c478bd9Sstevel@tonic-gate if (get_link_path(buf, devctl) != 0) { 12767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12777c478bd9Sstevel@tonic-gate gettext("Invalid controller '%d'\n"), c); 12787c478bd9Sstevel@tonic-gate return (INVALID_ARG); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate /* Check File */ 12827c478bd9Sstevel@tonic-gate rv = checkfile(rombuf, nbytes, chksum, &imagetype); 12837c478bd9Sstevel@tonic-gate if (rv != 0) { 12847c478bd9Sstevel@tonic-gate return (FAILURE); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate /* Confirm */ 12887c478bd9Sstevel@tonic-gate if (!force) { 12897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Update flash image on " 12907c478bd9Sstevel@tonic-gate "controller %d (%s/%s)? "), c, yeschr, nochr); 12917c478bd9Sstevel@tonic-gate if (!yes(c)) { 12927c478bd9Sstevel@tonic-gate return (SUCCESS); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate /* Do Flash */ 12977c478bd9Sstevel@tonic-gate if (updateflash(rombuf, nbytes, devctl)) { 12987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Flash not updated on " 12997c478bd9Sstevel@tonic-gate "Controller %d.\n\n"), c); 13007c478bd9Sstevel@tonic-gate return (INVALID_ARG); 13017c478bd9Sstevel@tonic-gate } 13027c478bd9Sstevel@tonic-gate (void) printf(gettext("Flash updated successfully.\n\n")); 13037c478bd9Sstevel@tonic-gate return (SUCCESS); 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate static int 13077c478bd9Sstevel@tonic-gate fully_numeric(char *str) 13087c478bd9Sstevel@tonic-gate { 13097c478bd9Sstevel@tonic-gate int size = strlen(str); 13107c478bd9Sstevel@tonic-gate int i; 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 13137c478bd9Sstevel@tonic-gate if (i == 0 && str[i] == '-' && size != 1) 13147c478bd9Sstevel@tonic-gate continue; 13157c478bd9Sstevel@tonic-gate if (!isdigit(str[i])) 13167c478bd9Sstevel@tonic-gate return (0); 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate return (1); 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate /* 13227c478bd9Sstevel@tonic-gate * Useful parsing macros 13237c478bd9Sstevel@tonic-gate */ 13247c478bd9Sstevel@tonic-gate #define must_be(s, c) if (*s++ != c) return (0) 13257c478bd9Sstevel@tonic-gate #define skip_digits(s) while (isdigit(*s)) s++ 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate /* 13287c478bd9Sstevel@tonic-gate * Return true if a name is in the internal canonical form 13297c478bd9Sstevel@tonic-gate */ 13307c478bd9Sstevel@tonic-gate static int 13317c478bd9Sstevel@tonic-gate canonical_name(char *name) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate must_be(name, 'c'); 13347c478bd9Sstevel@tonic-gate skip_digits(name); 13357c478bd9Sstevel@tonic-gate if (*name == 't') { 13367c478bd9Sstevel@tonic-gate name++; 13377c478bd9Sstevel@tonic-gate skip_digits(name); 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate must_be(name, 'd'); 13407c478bd9Sstevel@tonic-gate skip_digits(name); 13417c478bd9Sstevel@tonic-gate return (*name == 0); 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate int 13457c478bd9Sstevel@tonic-gate main(int argc, char **argv) 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate int rv = SUCCESS; 13487c478bd9Sstevel@tonic-gate int i, c; 13497c478bd9Sstevel@tonic-gate int findex = DO_HW_RAID_INFO; 13507c478bd9Sstevel@tonic-gate int controller; 1351*8ba1bcfcSdduvall char *disks[N_DISKS]; 13527c478bd9Sstevel@tonic-gate char *darg; 13537c478bd9Sstevel@tonic-gate char *farg; 13547c478bd9Sstevel@tonic-gate char *progname; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate int l_flag = 0; 13577c478bd9Sstevel@tonic-gate int c_flag = 0; 13587c478bd9Sstevel@tonic-gate int d_flag = 0; 13597c478bd9Sstevel@tonic-gate int f_flag = 0; 13607c478bd9Sstevel@tonic-gate int F_flag = 0; 13617c478bd9Sstevel@tonic-gate int no_flags = 1; 13627c478bd9Sstevel@tonic-gate char *current_dir; 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 13657c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 13687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Must be root.\n")); 13697c478bd9Sstevel@tonic-gate exit(1); 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) == NULL) 13737c478bd9Sstevel@tonic-gate progname = argv[0]; 13747c478bd9Sstevel@tonic-gate else 13757c478bd9Sstevel@tonic-gate progname++; 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate raids = NULL; 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); 13807c478bd9Sstevel@tonic-gate (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); 13817c478bd9Sstevel@tonic-gate 1382*8ba1bcfcSdduvall while ((c = getopt(argc, argv, "clfd:F:")) != EOF) { 13837c478bd9Sstevel@tonic-gate switch (c) { 13847c478bd9Sstevel@tonic-gate case 'c': 1385*8ba1bcfcSdduvall if (f_flag || argc != 4) { 13867c478bd9Sstevel@tonic-gate usage(progname); 1387*8ba1bcfcSdduvall } 1388*8ba1bcfcSdduvall 13897c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_CREATE; 13907c478bd9Sstevel@tonic-gate c_flag = 1; 13917c478bd9Sstevel@tonic-gate no_flags = 0; 13927c478bd9Sstevel@tonic-gate break; 13937c478bd9Sstevel@tonic-gate case 'd': 13947c478bd9Sstevel@tonic-gate darg = optarg; 13957c478bd9Sstevel@tonic-gate d_flag = 1; 13967c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_DELETE; 13977c478bd9Sstevel@tonic-gate no_flags = 0; 13987c478bd9Sstevel@tonic-gate break; 13997c478bd9Sstevel@tonic-gate case 'l': 14007c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_INFO; 14017c478bd9Sstevel@tonic-gate l_flag = 1; 14027c478bd9Sstevel@tonic-gate no_flags = 0; 14037c478bd9Sstevel@tonic-gate break; 14047c478bd9Sstevel@tonic-gate case 'F': 14057c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_FLASH; 14067c478bd9Sstevel@tonic-gate farg = optarg; 14077c478bd9Sstevel@tonic-gate F_flag = 1; 14087c478bd9Sstevel@tonic-gate no_flags = 0; 14097c478bd9Sstevel@tonic-gate break; 14107c478bd9Sstevel@tonic-gate case 'f': 14117c478bd9Sstevel@tonic-gate f_flag = 1; 14127c478bd9Sstevel@tonic-gate no_flags = 0; 14137c478bd9Sstevel@tonic-gate break; 1414*8ba1bcfcSdduvall case '?': default: 14157c478bd9Sstevel@tonic-gate usage(progname); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate } 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate if (no_flags && argc > 1) 14207c478bd9Sstevel@tonic-gate usage(progname); 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* compatibility rules */ 14237c478bd9Sstevel@tonic-gate if (c_flag && d_flag) 14247c478bd9Sstevel@tonic-gate usage(progname); 1425*8ba1bcfcSdduvall if (l_flag && (d_flag || c_flag || f_flag || F_flag)) 14267c478bd9Sstevel@tonic-gate usage(progname); 1427*8ba1bcfcSdduvall if (F_flag && (d_flag || c_flag || l_flag)) 14287c478bd9Sstevel@tonic-gate usage(progname); 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate switch (findex) { 14317c478bd9Sstevel@tonic-gate case DO_HW_RAID_INFO: 14327c478bd9Sstevel@tonic-gate if (l_flag) { 14337c478bd9Sstevel@tonic-gate /* 14347c478bd9Sstevel@tonic-gate * "raidctl" makes argc == 1 14357c478bd9Sstevel@tonic-gate * "-l" makes argc == 2 14367c478bd9Sstevel@tonic-gate */ 14377c478bd9Sstevel@tonic-gate ctrl_nums = argc - 2; 14387c478bd9Sstevel@tonic-gate if (ctrl_nums != 0) { 14397c478bd9Sstevel@tonic-gate info_ctrl = (int **) 14407c478bd9Sstevel@tonic-gate malloc(ctrl_nums * sizeof (int)); 14417c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 14427c478bd9Sstevel@tonic-gate return (FAILURE); 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 14457c478bd9Sstevel@tonic-gate char *tmp = argv[i + 2]; 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate info_ctrl[i] = (int *)malloc(2 * sizeof (int)); 14487c478bd9Sstevel@tonic-gate if (info_ctrl[i] == NULL) { 14497c478bd9Sstevel@tonic-gate free(info_ctrl); 14507c478bd9Sstevel@tonic-gate return (FAILURE); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 14537c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", 14547c478bd9Sstevel@tonic-gate &info_ctrl[i][INFO_CTRL]); 14557c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 14567c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL; 14577c478bd9Sstevel@tonic-gate } else { 14587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14597c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 14607c478bd9Sstevel@tonic-gate tmp); 14617c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 14627c478bd9Sstevel@tonic-gate RAID_DONT_USE; 14637c478bd9Sstevel@tonic-gate } 14647c478bd9Sstevel@tonic-gate } 14657c478bd9Sstevel@tonic-gate } else if (argc > 1) { 14667c478bd9Sstevel@tonic-gate usage(progname); 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate do_info(); 14707c478bd9Sstevel@tonic-gate break; 14717c478bd9Sstevel@tonic-gate case DO_HW_RAID_CREATE: 14727c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 1473*8ba1bcfcSdduvall disks[i] = argv[argc - 2 + i]; 14747c478bd9Sstevel@tonic-gate if (!canonical_name(disks[i])) 14757c478bd9Sstevel@tonic-gate usage(progname); 14767c478bd9Sstevel@tonic-gate } 1477*8ba1bcfcSdduvall rv = do_create(disks); 14787c478bd9Sstevel@tonic-gate break; 14797c478bd9Sstevel@tonic-gate case DO_HW_RAID_DELETE: 14807c478bd9Sstevel@tonic-gate if (!canonical_name(darg)) 14817c478bd9Sstevel@tonic-gate usage(progname); 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate rv = do_delete(darg); 14847c478bd9Sstevel@tonic-gate break; 14857c478bd9Sstevel@tonic-gate case DO_HW_RAID_FLASH: 1486*8ba1bcfcSdduvall /* 1487*8ba1bcfcSdduvall * "raidctl" makes argc == 1 1488*8ba1bcfcSdduvall * "-F" makes argc == 2 1489*8ba1bcfcSdduvall * "filename" makes argc == 3 1490*8ba1bcfcSdduvall * "-f" makes argc == 4 if added. 1491*8ba1bcfcSdduvall */ 14927c478bd9Sstevel@tonic-gate ctrl_nums = argc - f_flag - 3; 14937c478bd9Sstevel@tonic-gate if (ctrl_nums == 0) 14947c478bd9Sstevel@tonic-gate usage(progname); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate current_dir = getcwd(NULL, MAXPATHLEN); 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 14997c478bd9Sstevel@tonic-gate char *tmp = argv[i + 3 + f_flag]; 15007c478bd9Sstevel@tonic-gate (void) chdir(current_dir); 15017c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 15027c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", &controller); 15037c478bd9Sstevel@tonic-gate rv = do_flash(controller, farg, f_flag); 15047c478bd9Sstevel@tonic-gate if (rv == FAILURE) 15057c478bd9Sstevel@tonic-gate break; 15067c478bd9Sstevel@tonic-gate } else { 15077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 15087c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 15097c478bd9Sstevel@tonic-gate tmp); 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate } 15127c478bd9Sstevel@tonic-gate free(current_dir); 15137c478bd9Sstevel@tonic-gate break; 15147c478bd9Sstevel@tonic-gate default: 15157c478bd9Sstevel@tonic-gate usage(progname); 15167c478bd9Sstevel@tonic-gate } 15177c478bd9Sstevel@tonic-gate return (rv); 15187c478bd9Sstevel@tonic-gate } 1519