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 297c478bd9Sstevel@tonic-gate #include <ctype.h> 307c478bd9Sstevel@tonic-gate #include <dirent.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <fcntl.h> 337c478bd9Sstevel@tonic-gate #include <langinfo.h> 347c478bd9Sstevel@tonic-gate #include <libintl.h> 357c478bd9Sstevel@tonic-gate #include <limits.h> 367c478bd9Sstevel@tonic-gate #include <locale.h> 377c478bd9Sstevel@tonic-gate #include <stdarg.h> 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #include <stdlib.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 417c478bd9Sstevel@tonic-gate #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 437c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi.h> 447c478bd9Sstevel@tonic-gate #include <sys/mpt/mpi_ioc.h> 457c478bd9Sstevel@tonic-gate #include <sys/stat.h> 467c478bd9Sstevel@tonic-gate #include <sys/types.h> 477c478bd9Sstevel@tonic-gate #include <sys/pci.h> 487c478bd9Sstevel@tonic-gate #include <unistd.h> 497c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 507c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 517c478bd9Sstevel@tonic-gate #include <config_admin.h> 527c478bd9Sstevel@tonic-gate #include <sys/param.h> 537c478bd9Sstevel@tonic-gate #include <sys/raidioctl.h> 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * list of controllers to list 577c478bd9Sstevel@tonic-gate * setup like this: 587c478bd9Sstevel@tonic-gate * [ctrl_num] [status] 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * where status is: 617c478bd9Sstevel@tonic-gate * RAID Found, 627c478bd9Sstevel@tonic-gate * No RAID Found 637c478bd9Sstevel@tonic-gate * RAID not supported on this controller 647c478bd9Sstevel@tonic-gate * Invalid Controller 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate typedef enum { 687c478bd9Sstevel@tonic-gate RAID_FOUND = 0x0, 697c478bd9Sstevel@tonic-gate RAID_NOT_FOUND, 707c478bd9Sstevel@tonic-gate RAID_NOT_SUPPORTED, 717c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL, 727c478bd9Sstevel@tonic-gate RAID_DONT_USE 737c478bd9Sstevel@tonic-gate } raidctl_errno_t; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* For no-mixup indexing of info_ctrl */ 767c478bd9Sstevel@tonic-gate #define INFO_CTRL 0 777c478bd9Sstevel@tonic-gate #define INFO_STATUS 1 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static int **info_ctrl = NULL; 807c478bd9Sstevel@tonic-gate /* Length of conrollers list */ 817c478bd9Sstevel@tonic-gate static int ctrl_nums = 0; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #define DEVDIR "/dev/rdsk" 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #define DO_HW_RAID_NOP -1 877c478bd9Sstevel@tonic-gate #define DO_HW_RAID_INFO 0 887c478bd9Sstevel@tonic-gate #define DO_HW_RAID_CREATE 1 897c478bd9Sstevel@tonic-gate #define DO_HW_RAID_DELETE 2 907c478bd9Sstevel@tonic-gate #define DO_HW_RAID_FLASH 3 917c478bd9Sstevel@tonic-gate 92*05411564Sjesseb /* values to use for raid level in raidctl */ 93*05411564Sjesseb #define RAID_STRIPE 0 94*05411564Sjesseb #define RAID_MIRROR 1 95*05411564Sjesseb 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * Error return codes 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate #define SUCCESS 0 1007c478bd9Sstevel@tonic-gate #define INVALID_ARG 1 1017c478bd9Sstevel@tonic-gate #define FAILURE 2 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * FW Update Stuff 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* signature and initial offset for PCI expansion rom images */ 1087c478bd9Sstevel@tonic-gate #define PCIROM_SIG 0xaa55 /* offset 0h, length 2 bytes */ 1097c478bd9Sstevel@tonic-gate #define PCIR_OFF 0x18 /* Pointer to PCI Data Structure */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* offsets in PCI data structure header */ 1127c478bd9Sstevel@tonic-gate #define PCIR_DEVID 0x6 /* PCI device id */ 1137c478bd9Sstevel@tonic-gate #define PCIR_CODETYPE 0x14 /* type of code (intel/fcode) */ 1147c478bd9Sstevel@tonic-gate #define PCIR_INDICATOR 0x15 /* "last image" indicator */ 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* flags for image types */ 1177c478bd9Sstevel@tonic-gate #define BIOS_IMAGE 0x1 1187c478bd9Sstevel@tonic-gate #define FCODE_IMAGE 0x2 1197c478bd9Sstevel@tonic-gate #define UNKNOWN_IMAGE 0x3 1207c478bd9Sstevel@tonic-gate #define LAST_IMAGE 0x80 1217c478bd9Sstevel@tonic-gate #define NOT_LAST_IMAGE 0 1227c478bd9Sstevel@tonic-gate #define PCI_IMAGE_UNIT_SIZE 512 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* ID's and offsets for MPT Firmware images */ 1257c478bd9Sstevel@tonic-gate #define FW_ROM_ID 0x5aea /* bytes 4 & 5 of file */ 1267c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_CHIP_TYPE 0x22 /* (U16) */ 1277c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION 0x24 /* (U16) */ 1287c478bd9Sstevel@tonic-gate #define FW_ROM_OFFSET_VERSION_NAME 0x44 /* (32 U8) */ 1297c478bd9Sstevel@tonic-gate 130*05411564Sjesseb /* ID's for supported chips */ 131*05411564Sjesseb #define LSI_1030 0x30 132*05411564Sjesseb #define LSI_1064 0x50 133*05411564Sjesseb #define LSI_1064E 0x56 134*05411564Sjesseb 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 1387c478bd9Sstevel@tonic-gate #define BIOS_STR "LSI1030 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 143*05411564Sjesseb /* Number of disks currently supported, per RAID volume */ 144*05411564Sjesseb #define N_DISKS 8 145*05411564Sjesseb 146*05411564Sjesseb /* Number of RAID volumes currently supported, per HBA */ 147*05411564Sjesseb #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 */ 1547c478bd9Sstevel@tonic-gate static int yes(int c); 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 { 159*05411564Sjesseb 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 167*05411564Sjesseb /* 168*05411564Sjesseb * usage: raidctl 169*05411564Sjesseb * usage: raidctl -c primary secondary 170*05411564Sjesseb * usage: raidctl -c -r 1 primary secondary 171*05411564Sjesseb * usage: raidctl -c -r 0 disk1 disk2 [disk3] ... 172*05411564Sjesseb * usage: raidctl -d volume 173*05411564Sjesseb * usage: raidctl [-f] -F image_file controller 174*05411564Sjesseb * usage: raidctl -l [controller...] 175*05411564Sjesseb * example: 176*05411564Sjesseb * raidctl -c c1t1d0 c1t2d0 177*05411564Sjesseb * raidctl -c -r 0 c1t1d0 c1t2d0 c1t3d0 c1t4d0 178*05411564Sjesseb * raidctl -d c1t1d0 179*05411564Sjesseb * raidctl -F image 1 180*05411564Sjesseb */ 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 186*05411564Sjesseb (void) fprintf(stderr, gettext("usage: %s -c primary secondary\n"), 1877c478bd9Sstevel@tonic-gate prog_name); 188*05411564Sjesseb 189*05411564Sjesseb (void) fprintf(stderr, gettext("usage: %s -c -r 1 primary secondary\n"), 190*05411564Sjesseb prog_name); 191*05411564Sjesseb 192*05411564Sjesseb (void) fprintf(stderr, gettext("usage: %s -c -r 0 disk1 disk2 " 193*05411564Sjesseb "[disk3] ...\n"), prog_name); 194*05411564Sjesseb 195*05411564Sjesseb (void) fprintf(stderr, gettext("usage: %s -d volume\n"), prog_name); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1987c478bd9Sstevel@tonic-gate gettext("usage: %s [-f] -F image_file controller \n"), 1997c478bd9Sstevel@tonic-gate prog_name); 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s -l [controller...]\n"), 2027c478bd9Sstevel@tonic-gate prog_name); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("example:\n")); 2057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -c c1t1d0 c1t2d0\n", prog_name); 206*05411564Sjesseb (void) fprintf(stderr, "%s -c -r 0 c1t1d0 c1t2d0 " 207*05411564Sjesseb "c1t3d0 c1t4d0\n", prog_name); 2087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -d c1t1d0\n", prog_name); 2097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s -F image 1\n", prog_name); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate exit(1); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* Make errno message more "user friendly" */ 2157c478bd9Sstevel@tonic-gate static void 2167c478bd9Sstevel@tonic-gate raidctl_error(char *str) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate switch (errno) { 2193a4e43d3Ssafa case EINVAL: 2203a4e43d3Ssafa (void) fprintf(stderr, gettext("Error: " 2213a4e43d3Ssafa "invalid argument would be returned\n")); 2223a4e43d3Ssafa break; 2237c478bd9Sstevel@tonic-gate case EIO: 2247c478bd9Sstevel@tonic-gate case EFAULT: 2257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2267c478bd9Sstevel@tonic-gate gettext("Error: Device inaccessible.\n")); 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate case ENOTTY: 2297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error: " 2307c478bd9Sstevel@tonic-gate "Device does not support requested action.\n")); 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate default: 2337c478bd9Sstevel@tonic-gate perror(str); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate static int 2387c478bd9Sstevel@tonic-gate get_link_path(const char *thing, char *buf) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate if (readlink(thing, buf, MAXPATHLEN) < 0) 2417c478bd9Sstevel@tonic-gate return (1); 2427c478bd9Sstevel@tonic-gate return (0); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate static int 2467c478bd9Sstevel@tonic-gate get_ctrl_devctl(char *ctrl, char *b) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2497c478bd9Sstevel@tonic-gate char *colon; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, ctrl, MAXPATHLEN); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate colon = strrchr(devctl_buf, ':'); 2547c478bd9Sstevel@tonic-gate if (colon == NULL) 2557c478bd9Sstevel@tonic-gate return (1); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate *colon = 0; 2587c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s:devctl", devctl_buf); 2597c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 2607c478bd9Sstevel@tonic-gate return (0); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate static int 2647c478bd9Sstevel@tonic-gate get_devctl(char *disk, char *b) 2657c478bd9Sstevel@tonic-gate { 2667c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 2677c478bd9Sstevel@tonic-gate char devctl_buf[MAXPATHLEN]; 2687c478bd9Sstevel@tonic-gate char *slash; 2697c478bd9Sstevel@tonic-gate char devname[32]; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (get_link_path(disk, buf1)) 2727c478bd9Sstevel@tonic-gate return (1); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate (void) strlcpy(devctl_buf, buf1, MAXPATHLEN); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2777c478bd9Sstevel@tonic-gate if (slash == NULL) 2787c478bd9Sstevel@tonic-gate return (1); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate *slash = 0; 2817c478bd9Sstevel@tonic-gate slash = strrchr(devctl_buf, '/'); 2827c478bd9Sstevel@tonic-gate (void) strlcpy(devname, slash, 32); 2837c478bd9Sstevel@tonic-gate *slash = 0; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate (void) snprintf(devctl_buf, MAXPATHLEN, "%s%s:devctl", 2867c478bd9Sstevel@tonic-gate devctl_buf, devname); 287*05411564Sjesseb 2887c478bd9Sstevel@tonic-gate (void) strlcpy(b, devctl_buf, MAXPATHLEN); 289*05411564Sjesseb 2907c478bd9Sstevel@tonic-gate return (0); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate static int 2947c478bd9Sstevel@tonic-gate already_there(int controller) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate while (curr != NULL) { 2997c478bd9Sstevel@tonic-gate if (curr->controller == controller) 3007c478bd9Sstevel@tonic-gate return (1); 3017c478bd9Sstevel@tonic-gate curr = curr->next; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate return (0); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * Display those controllers where RAID volumes were not found 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate static void 3117c478bd9Sstevel@tonic-gate print_no_raids() 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate int i, space = 0; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 3167c478bd9Sstevel@tonic-gate return; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 3197c478bd9Sstevel@tonic-gate /* Status of '0' means RAID exists at that controller */ 3207c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_FOUND || 3217c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 3227c478bd9Sstevel@tonic-gate continue; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate if (!space && raids != NULL) { 3257c478bd9Sstevel@tonic-gate (void) printf("\n"); 3267c478bd9Sstevel@tonic-gate space = 1; 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* switch statement used to enable gettext()'ing of text */ 3307c478bd9Sstevel@tonic-gate switch (info_ctrl[i][INFO_STATUS]) { 3317c478bd9Sstevel@tonic-gate case RAID_INVALID_CTRL: 3327c478bd9Sstevel@tonic-gate (void) printf(gettext("Invalid controller '%d'\n"), 3337c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 3347c478bd9Sstevel@tonic-gate break; 3357c478bd9Sstevel@tonic-gate case RAID_NOT_SUPPORTED: 3367c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID supported " 3377c478bd9Sstevel@tonic-gate "on controller '%d'\n"), 3387c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_CTRL]); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate break; 3417c478bd9Sstevel@tonic-gate default: 3427c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found on " 3437c478bd9Sstevel@tonic-gate "controller '%d'\n"), info_ctrl[i][INFO_CTRL]); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate static void 3497c478bd9Sstevel@tonic-gate add_raid_to_raidlist(char *ctrl_name, int controller) 3507c478bd9Sstevel@tonic-gate { 351*05411564Sjesseb raid_config_t config[N_RAIDVOLS]; 3527c478bd9Sstevel@tonic-gate raidlist_t *curr; 3537c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 3547c478bd9Sstevel@tonic-gate char buf1[MAXPATHLEN] = {0}; 355*05411564Sjesseb int fd, i, n; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (readlink(ctrl_name, buf, sizeof (buf)) < 0) 3587c478bd9Sstevel@tonic-gate return; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (get_ctrl_devctl(buf, buf1)) 3617c478bd9Sstevel@tonic-gate return; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * If "-l" was specified, then only look at those controllers 3657c478bd9Sstevel@tonic-gate * listed as part of the command line input. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 3687c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 3697c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_STATUS] == RAID_DONT_USE) 3707c478bd9Sstevel@tonic-gate continue; 371*05411564Sjesseb if (controller == info_ctrl[i][INFO_CTRL]) 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate } 374*05411564Sjesseb /* return if we didn't find a controller */ 375*05411564Sjesseb if (i == ctrl_nums) 3767c478bd9Sstevel@tonic-gate return; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate fd = open(buf1, O_RDONLY); 3807c478bd9Sstevel@tonic-gate if (fd == -1) { 3817c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3827c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_INVALID_CTRL; 3837c478bd9Sstevel@tonic-gate return; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 3877c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 3887c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_NOT_SUPPORTED; 3897c478bd9Sstevel@tonic-gate (void) close(fd); 3907c478bd9Sstevel@tonic-gate /* Fail silently */ 3917c478bd9Sstevel@tonic-gate return; 3927c478bd9Sstevel@tonic-gate } 393*05411564Sjesseb 3947c478bd9Sstevel@tonic-gate (void) close(fd); 3957c478bd9Sstevel@tonic-gate 396*05411564Sjesseb /* check if there are any raid volumes on this hba */ 397*05411564Sjesseb for (n = 0; n < N_RAIDVOLS; n++) { 398*05411564Sjesseb if (config[n].ndisks != 0) 399*05411564Sjesseb break; 400*05411564Sjesseb } 401*05411564Sjesseb 402*05411564Sjesseb if (n == N_RAIDVOLS) { 403*05411564Sjesseb /* no raid volumes were found */ 4047c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 4057c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_NOT_FOUND; 4067c478bd9Sstevel@tonic-gate return; 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 409*05411564Sjesseb /* we've at least one raid volume on this hba */ 4107c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) 4117c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = RAID_FOUND; 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (raids == NULL) { 4147c478bd9Sstevel@tonic-gate raids = (raidlist_t *)malloc(sizeof (raidlist_t)); 4157c478bd9Sstevel@tonic-gate curr = raids; 4167c478bd9Sstevel@tonic-gate } else { 4177c478bd9Sstevel@tonic-gate if (already_there(controller)) { 4187c478bd9Sstevel@tonic-gate return; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate curr = raids; 4227c478bd9Sstevel@tonic-gate /* Seek to the end */ 4237c478bd9Sstevel@tonic-gate while (curr->next != NULL) 4247c478bd9Sstevel@tonic-gate curr = curr->next; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate curr->next = (raidlist_t *)malloc(sizeof (raidlist_t)); 4277c478bd9Sstevel@tonic-gate curr = curr->next; 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate curr->next = NULL; 4307c478bd9Sstevel@tonic-gate curr->controller = controller; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate (void) strlcpy(curr->devctl, buf1, sizeof (curr->devctl)); 4337c478bd9Sstevel@tonic-gate (void) fflush(stdout); 434*05411564Sjesseb 435*05411564Sjesseb (void) memcpy(&curr->raid_config, &config, 436*05411564Sjesseb (sizeof (raid_config_t) * N_RAIDVOLS)); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate static void 4407c478bd9Sstevel@tonic-gate print_header() 4417c478bd9Sstevel@tonic-gate { 442*05411564Sjesseb (void) printf(gettext("RAID\tVolume\tRAID\t\tRAID\t\tDisk")); 4437c478bd9Sstevel@tonic-gate (void) printf("\n"); 444*05411564Sjesseb (void) printf(gettext("Volume\tType\tStatus\t\tDisk\t\tStatus")); 4457c478bd9Sstevel@tonic-gate (void) printf("\n"); 4467c478bd9Sstevel@tonic-gate (void) printf("------------------------------------------------------"); 4477c478bd9Sstevel@tonic-gate (void) printf("\n"); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate static void 4517c478bd9Sstevel@tonic-gate print_raidconfig(int c, raid_config_t config) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate int i; 454*05411564Sjesseb char voltype[8]; 4557c478bd9Sstevel@tonic-gate 456*05411564Sjesseb /* print RAID volume target ID and volume type */ 457*05411564Sjesseb if (config.raid_level == RAID_STRIPE) { 458*05411564Sjesseb (void) snprintf(voltype, sizeof (voltype), "IS"); 459*05411564Sjesseb } else if (config.raid_level == RAID_MIRROR) { 460*05411564Sjesseb (void) snprintf(voltype, sizeof (voltype), "IM"); 461*05411564Sjesseb } 462*05411564Sjesseb 463*05411564Sjesseb (void) printf("c%dt%dd0\t%s\t", c, config.targetid, voltype); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* Get RAID Info */ 4667c478bd9Sstevel@tonic-gate if (config.flags & RAID_FLAG_RESYNCING && 4677c478bd9Sstevel@tonic-gate config.state == RAID_STATE_DEGRADED) { 4687c478bd9Sstevel@tonic-gate (void) printf(gettext("RESYNCING\t")); 4697c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_DEGRADED) { 4707c478bd9Sstevel@tonic-gate (void) printf(gettext("DEGRADED\t")); 4717c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_OPTIMAL) { 4727c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\t\t")); 4737c478bd9Sstevel@tonic-gate } else if (config.state == RAID_STATE_FAILED) { 4747c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\t\t")); 4757c478bd9Sstevel@tonic-gate } else { 4767c478bd9Sstevel@tonic-gate (void) printf(gettext("ERROR\t\t")); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* Get RAID Disks */ 4807c478bd9Sstevel@tonic-gate (void) printf("c%dt%dd0\t\t", c, config.disk[0]); 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* Get RAID Disk's Status */ 4837c478bd9Sstevel@tonic-gate if (config.diskstatus[0] & RAID_DISKSTATUS_FAILED) { 4847c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 4857c478bd9Sstevel@tonic-gate } else if (config.diskstatus[0] & RAID_DISKSTATUS_MISSING) { 4867c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 4877c478bd9Sstevel@tonic-gate } else { 4887c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate for (i = 1; i < config.ndisks; i++) { 4927c478bd9Sstevel@tonic-gate (void) printf("\t\t\t\tc%dt%dd0\t\t", c, config.disk[i]); 4937c478bd9Sstevel@tonic-gate if (config.diskstatus[i] & RAID_DISKSTATUS_FAILED) { 4947c478bd9Sstevel@tonic-gate (void) printf(gettext("FAILED\n")); 4957c478bd9Sstevel@tonic-gate } else if (config.diskstatus[i] & RAID_DISKSTATUS_MISSING) { 4967c478bd9Sstevel@tonic-gate (void) printf(gettext("MISSING\n")); 4977c478bd9Sstevel@tonic-gate } else { 4987c478bd9Sstevel@tonic-gate (void) printf(gettext("OK\n")); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate static void 5047c478bd9Sstevel@tonic-gate print_disklist() 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 507*05411564Sjesseb int i; 508*05411564Sjesseb 5097c478bd9Sstevel@tonic-gate while (curr != NULL) { 510*05411564Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 511*05411564Sjesseb if (curr->raid_config[i].ndisks != 0) { 512*05411564Sjesseb print_raidconfig(curr->controller, 513*05411564Sjesseb curr->raid_config[i]); 514*05411564Sjesseb } 515*05411564Sjesseb } 5167c478bd9Sstevel@tonic-gate curr = curr->next; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate static void 5217c478bd9Sstevel@tonic-gate free_disklist() 5227c478bd9Sstevel@tonic-gate { 5237c478bd9Sstevel@tonic-gate raidlist_t *curr = raids; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate while (curr != NULL) { 5267c478bd9Sstevel@tonic-gate raidlist_t *temp; 5277c478bd9Sstevel@tonic-gate temp = curr; 5287c478bd9Sstevel@tonic-gate curr = curr->next; 5297c478bd9Sstevel@tonic-gate free(temp); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate static void 5347c478bd9Sstevel@tonic-gate do_search() 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate DIR *dir; 5377c478bd9Sstevel@tonic-gate struct dirent *dp; 5387c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 5397c478bd9Sstevel@tonic-gate int c; 5407c478bd9Sstevel@tonic-gate int i, j; 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * In case repeated numbers were found, assign the repititions as 5447c478bd9Sstevel@tonic-gate * RAID_DONT_USE 5457c478bd9Sstevel@tonic-gate */ 5467c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 5477c478bd9Sstevel@tonic-gate int first_one = 1; 5487c478bd9Sstevel@tonic-gate for (j = 0; j < ctrl_nums; j++) { 5497c478bd9Sstevel@tonic-gate if (info_ctrl[i][INFO_CTRL] == 5507c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_CTRL]) { 5517c478bd9Sstevel@tonic-gate if (info_ctrl[j][INFO_STATUS] == RAID_DONT_USE) 5527c478bd9Sstevel@tonic-gate continue; 5537c478bd9Sstevel@tonic-gate if (first_one) { 5547c478bd9Sstevel@tonic-gate first_one = 0; 5557c478bd9Sstevel@tonic-gate } else { 5567c478bd9Sstevel@tonic-gate info_ctrl[j][INFO_STATUS] = 5577c478bd9Sstevel@tonic-gate RAID_DONT_USE; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if ((dir = opendir("/dev/cfg")) == NULL) { 5647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5657c478bd9Sstevel@tonic-gate gettext("Cannot open /dev/cfg: %s\n"), strerror(errno)); 5667c478bd9Sstevel@tonic-gate return; 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate while ((dp = readdir(dir)) != NULL) { 5697c478bd9Sstevel@tonic-gate if (strcmp(dp->d_name, ".") == 0 || 5707c478bd9Sstevel@tonic-gate strcmp(dp->d_name, "..") == 0) 5717c478bd9Sstevel@tonic-gate continue; 5727c478bd9Sstevel@tonic-gate if (sscanf(dp->d_name, "c%d", &c) != 1) 5737c478bd9Sstevel@tonic-gate continue; 5747c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/%s", dp->d_name); 5757c478bd9Sstevel@tonic-gate add_raid_to_raidlist(buf, c); 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate (void) closedir(dir); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* 5817c478bd9Sstevel@tonic-gate * do_info() will do the following: 5827c478bd9Sstevel@tonic-gate * - create a list of disks' devctls 5837c478bd9Sstevel@tonic-gate * - try to talk to each of the devctls found 5847c478bd9Sstevel@tonic-gate * - if raid configuration is found, display it. 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate static void 5877c478bd9Sstevel@tonic-gate do_info() 5887c478bd9Sstevel@tonic-gate { 5897c478bd9Sstevel@tonic-gate int i; 5907c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate do_search(); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate if (raids == NULL) { 5957c478bd9Sstevel@tonic-gate if (info_ctrl != NULL) { 5967c478bd9Sstevel@tonic-gate print_no_raids(); 5977c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 5987c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 5997c478bd9Sstevel@tonic-gate free(info_ctrl); 6007c478bd9Sstevel@tonic-gate } else { 6017c478bd9Sstevel@tonic-gate (void) printf(gettext("No RAID volumes found\n")); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate return; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate print_header(); 6077c478bd9Sstevel@tonic-gate print_disklist(); 6087c478bd9Sstevel@tonic-gate print_no_raids(); 6097c478bd9Sstevel@tonic-gate free_disklist(); 6107c478bd9Sstevel@tonic-gate if (info_ctrl) { 6117c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) 6127c478bd9Sstevel@tonic-gate free(info_ctrl[i]); 6137c478bd9Sstevel@tonic-gate free(info_ctrl); 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate static int 618*05411564Sjesseb disk_in_raid(int c, int t) 619*05411564Sjesseb { 620*05411564Sjesseb raidlist_t *curr; 621*05411564Sjesseb raid_config_t raid; 622*05411564Sjesseb int i, j, n; 623*05411564Sjesseb 624*05411564Sjesseb do_search(); 625*05411564Sjesseb curr = raids; 626*05411564Sjesseb 627*05411564Sjesseb while (curr != NULL) { 628*05411564Sjesseb if (curr->controller == c) { 629*05411564Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 630*05411564Sjesseb raid = curr->raid_config[i]; 631*05411564Sjesseb if ((n = raid.ndisks) != 0) { 632*05411564Sjesseb for (j = 0; j < n; j++) { 633*05411564Sjesseb if (raid.disk[j] == t) { 634*05411564Sjesseb return (1); 635*05411564Sjesseb } 636*05411564Sjesseb } 637*05411564Sjesseb } 638*05411564Sjesseb } 639*05411564Sjesseb } 640*05411564Sjesseb curr = curr->next; 641*05411564Sjesseb } 642*05411564Sjesseb return (0); 643*05411564Sjesseb } 644*05411564Sjesseb 645*05411564Sjesseb static int 6467c478bd9Sstevel@tonic-gate disk_there(int c, int t) 6477c478bd9Sstevel@tonic-gate { 6487c478bd9Sstevel@tonic-gate char disk[100]; 6497c478bd9Sstevel@tonic-gate int fd; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate (void) snprintf(disk, sizeof (disk), "c%dt%dd0s2", c, t); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate fd = open(disk, O_RDWR | O_NDELAY); 6547c478bd9Sstevel@tonic-gate if (fd == -1) { 6557c478bd9Sstevel@tonic-gate return (-1); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate (void) close(fd); 6597c478bd9Sstevel@tonic-gate return (0); 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate static int 6637c478bd9Sstevel@tonic-gate get_controller(char *dev) 6647c478bd9Sstevel@tonic-gate { 6657c478bd9Sstevel@tonic-gate raidlist_t *curr; 6667c478bd9Sstevel@tonic-gate int c; 6677c478bd9Sstevel@tonic-gate do_search(); 6687c478bd9Sstevel@tonic-gate curr = raids; 6697c478bd9Sstevel@tonic-gate while (curr != NULL) { 6707c478bd9Sstevel@tonic-gate if (strcmp(curr->devctl, dev) == 0) { 6717c478bd9Sstevel@tonic-gate c = curr->controller; 6727c478bd9Sstevel@tonic-gate break; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate curr = curr->next; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate free_disklist(); 6787c478bd9Sstevel@tonic-gate return (c); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate static int 6827c478bd9Sstevel@tonic-gate disk_mounted(char *d) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate struct mnttab mt; 6857c478bd9Sstevel@tonic-gate FILE *f = fopen("/etc/mnttab", "r"); 6867c478bd9Sstevel@tonic-gate 687*05411564Sjesseb while (getmntent(f, &mt) != EOF) { 6887c478bd9Sstevel@tonic-gate if (strstr(mt.mnt_special, d) != NULL) 6897c478bd9Sstevel@tonic-gate return (1); 690*05411564Sjesseb } 6917c478bd9Sstevel@tonic-gate return (0); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate static int 6957c478bd9Sstevel@tonic-gate disk_big_enough(char **d, diskaddr_t *cap, int *errcond) 6967c478bd9Sstevel@tonic-gate { 6977c478bd9Sstevel@tonic-gate struct dk_minfo minfo; 6987c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN]; 699*05411564Sjesseb uint_t disk_lbsize[N_DISKS]; 7007c478bd9Sstevel@tonic-gate diskaddr_t disk_capacity[N_DISKS]; 7017c478bd9Sstevel@tonic-gate int i, fd; 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 704*05411564Sjesseb if (d[i] == NULL) 705*05411564Sjesseb break; 706*05411564Sjesseb 7077c478bd9Sstevel@tonic-gate (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 7087c478bd9Sstevel@tonic-gate fd = open(disk[i], O_RDWR | O_NDELAY); 709*05411564Sjesseb if (fd == -1) 7107c478bd9Sstevel@tonic-gate return (FAILURE); 7117c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGMEDIAINFO, &minfo) == -1) { 7127c478bd9Sstevel@tonic-gate (void) close(fd); 7137c478bd9Sstevel@tonic-gate return (FAILURE); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate disk_lbsize[i] = minfo.dki_lbsize; 7177c478bd9Sstevel@tonic-gate disk_capacity[i] = minfo.dki_capacity; 7187c478bd9Sstevel@tonic-gate 719*05411564Sjesseb /* lbsize must be the same on all disks */ 720*05411564Sjesseb if (disk_lbsize[0] != disk_lbsize[i]) { 7217c478bd9Sstevel@tonic-gate *errcond = 2; 7227c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate 725*05411564Sjesseb /* ensure drive capacity is greater than or equal to first */ 726*05411564Sjesseb if (disk_capacity[0] > disk_capacity[i]) { 7277c478bd9Sstevel@tonic-gate *errcond = 1; 7287c478bd9Sstevel@tonic-gate return (INVALID_ARG); 7297c478bd9Sstevel@tonic-gate } 730*05411564Sjesseb (void) close(fd); 731*05411564Sjesseb } 7327c478bd9Sstevel@tonic-gate 733*05411564Sjesseb /* 734*05411564Sjesseb * setting capacity as the dk_minfo.dki_capacity of d[0] 735*05411564Sjesseb * this is the number of dki_lbsize blocks on disk 736*05411564Sjesseb */ 7377c478bd9Sstevel@tonic-gate *cap = disk_capacity[0]; 7387c478bd9Sstevel@tonic-gate return (SUCCESS); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate static int 7427c478bd9Sstevel@tonic-gate do_config_change_state(cfga_cmd_t cmd, int d, int c) 7437c478bd9Sstevel@tonic-gate { 7447c478bd9Sstevel@tonic-gate cfga_err_t cfga_err; 7457c478bd9Sstevel@tonic-gate char *ap_id; 7467c478bd9Sstevel@tonic-gate int rv = SUCCESS; 7477c478bd9Sstevel@tonic-gate int count = 0; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate ap_id = (char *)malloc(100); 7507c478bd9Sstevel@tonic-gate if (ap_id == NULL) 7517c478bd9Sstevel@tonic-gate return (FAILURE); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate (void) snprintf(ap_id, 100, "c%d::dsk/c%dt%dd0", c, c, d); 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* 7567c478bd9Sstevel@tonic-gate * If the config_change_state() funcation fails, we want to 7577c478bd9Sstevel@tonic-gate * retry. If the retry fails, then we return failure to fail. 7587c478bd9Sstevel@tonic-gate * 7597c478bd9Sstevel@tonic-gate * If we fail: 7607c478bd9Sstevel@tonic-gate * 7617c478bd9Sstevel@tonic-gate * If we were called from create, then we fail the raid 7627c478bd9Sstevel@tonic-gate * creation. 7637c478bd9Sstevel@tonic-gate * 7647c478bd9Sstevel@tonic-gate * If we were called from delete, then the disk will not 7657c478bd9Sstevel@tonic-gate * be re-configured by raidctl. 7667c478bd9Sstevel@tonic-gate */ 7677c478bd9Sstevel@tonic-gate do { 7687c478bd9Sstevel@tonic-gate cfga_err = config_change_state(cmd, 1, &ap_id, NULL, 7697c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 7707c478bd9Sstevel@tonic-gate count++; 7717c478bd9Sstevel@tonic-gate } while (cfga_err != CFGA_OK && count < 2); 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate if (cfga_err != CFGA_OK) 7747c478bd9Sstevel@tonic-gate rv = FAILURE; 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate free(ap_id); 7777c478bd9Sstevel@tonic-gate return (rv); 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate static int 781*05411564Sjesseb do_create(char **d, int rlevel) 7827c478bd9Sstevel@tonic-gate { 783*05411564Sjesseb raid_config_t config[N_RAIDVOLS]; 784*05411564Sjesseb raid_config_t newvol; 7857c478bd9Sstevel@tonic-gate char disk[N_DISKS][MAXPATHLEN] = {0}; 786*05411564Sjesseb int map[N_DISKS]; 7877c478bd9Sstevel@tonic-gate char channel1[MAXPATHLEN]; 7887c478bd9Sstevel@tonic-gate char channel2[MAXPATHLEN]; 7897c478bd9Sstevel@tonic-gate diskaddr_t capacity; 790*05411564Sjesseb int fd, fd2, size, errcond; 7917c478bd9Sstevel@tonic-gate int c[N_DISKS]; 7927c478bd9Sstevel@tonic-gate int t[N_DISKS]; 7937c478bd9Sstevel@tonic-gate char *tmp; 794*05411564Sjesseb int loc, i; 795*05411564Sjesseb int ndisks = 0; 796*05411564Sjesseb ushort_t devid; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 7997c478bd9Sstevel@tonic-gate 800*05411564Sjesseb /* initialize target map */ 801*05411564Sjesseb for (i = 0; i < N_DISKS; i++) 802*05411564Sjesseb map[i] = -1; 803*05411564Sjesseb 8047c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 805*05411564Sjesseb if (d[i] == NULL) 806*05411564Sjesseb break; 807*05411564Sjesseb 8087c478bd9Sstevel@tonic-gate if ((sscanf(d[i], "c%dt%dd0", &c[i], &t[i])) != 2 || 8097c478bd9Sstevel@tonic-gate t[i] < 0) { 8107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8117c478bd9Sstevel@tonic-gate gettext("Invalid disk format.\n")); 8127c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8137c478bd9Sstevel@tonic-gate } 8147c478bd9Sstevel@tonic-gate 815*05411564Sjesseb /* ensure that all disks are on the same controller, */ 816*05411564Sjesseb if (c[i] != c[0]) { 817*05411564Sjesseb (void) fprintf(stderr, gettext("Disks must be " 818*05411564Sjesseb "on the same controller.\n")); 8197c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 822*05411564Sjesseb /* that all disks are online, */ 823*05411564Sjesseb if (disk_there(c[0], t[i])) { 824*05411564Sjesseb (void) printf(gettext("Disk 'c%dt%dd0' is not " 825*05411564Sjesseb "present.\n"), c[0], t[i]); 8267c478bd9Sstevel@tonic-gate (void) printf(gettext("Cannot create RAID volume.\n")); 8277c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8287c478bd9Sstevel@tonic-gate } 8297c478bd9Sstevel@tonic-gate 830*05411564Sjesseb /* that there are no duplicate disks, */ 831*05411564Sjesseb loc = t[i]; 832*05411564Sjesseb if (map[loc] == -1) { 833*05411564Sjesseb map[loc] = t[i]; 834*05411564Sjesseb } else { 835*05411564Sjesseb (void) fprintf(stderr, 836*05411564Sjesseb gettext("Disks must be different.\n")); 837*05411564Sjesseb return (INVALID_ARG); 838*05411564Sjesseb } 839*05411564Sjesseb 840*05411564Sjesseb /* that no disk is already in use by another volume, */ 841*05411564Sjesseb if (disk_in_raid(c[0], t[i])) { 842*05411564Sjesseb (void) fprintf(stderr, gettext("Disk %s is already in " 843*05411564Sjesseb "a RAID volume.\n"), d[i]); 844*05411564Sjesseb return (INVALID_ARG); 845*05411564Sjesseb } 846*05411564Sjesseb 847*05411564Sjesseb /* that no target's id is lower than the raidtarg, */ 848*05411564Sjesseb if (t[0] > t[i]) { 849*05411564Sjesseb (void) fprintf(stderr, gettext("First target ID must " 850*05411564Sjesseb "be less than other member target IDs.\n")); 851*05411564Sjesseb return (INVALID_ARG); 852*05411564Sjesseb } 853*05411564Sjesseb 854*05411564Sjesseb /* and that no disk other than a mirror primary is mounted */ 855*05411564Sjesseb if (disk_mounted(d[i])) { 856*05411564Sjesseb /* data on all stripe disks will be destroyed */ 857*05411564Sjesseb if ((rlevel == RAID_STRIPE) && (i != 0)) { 858*05411564Sjesseb (void) fprintf(stderr, gettext("Cannot " 859*05411564Sjesseb "create RAID0 volume, secondary disk " 860*05411564Sjesseb "\"%s\" is mounted.\n"), d[i]); 861*05411564Sjesseb return (INVALID_ARG); 862*05411564Sjesseb } 863*05411564Sjesseb /* data on mirror's secondary will be destroyed */ 864*05411564Sjesseb if (i != 0) { 865*05411564Sjesseb (void) fprintf(stderr, gettext("Cannot " 866*05411564Sjesseb "create RAID mirror, secondary " 867*05411564Sjesseb "disk \"%s\" is mounted.\n"), d[i]); 868*05411564Sjesseb return (INVALID_ARG); 869*05411564Sjesseb } 870*05411564Sjesseb } 871*05411564Sjesseb 872*05411564Sjesseb (void) snprintf(disk[i], sizeof (disk[i]), DEVDIR"/%ss2", d[i]); 873*05411564Sjesseb ndisks++; 874*05411564Sjesseb } 875*05411564Sjesseb 876*05411564Sjesseb /* validate the drive capacities */ 8777c478bd9Sstevel@tonic-gate switch (disk_big_enough(d, &capacity, &errcond)) { 8787c478bd9Sstevel@tonic-gate case FAILURE: 8797c478bd9Sstevel@tonic-gate return (FAILURE); 8807c478bd9Sstevel@tonic-gate case INVALID_ARG: 8817c478bd9Sstevel@tonic-gate switch (errcond) { 8827c478bd9Sstevel@tonic-gate case 1: 8837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 8847c478bd9Sstevel@tonic-gate "primary disk is larger than secondary disk.\n")); 8857c478bd9Sstevel@tonic-gate break; 8867c478bd9Sstevel@tonic-gate case 2: 8877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Cannot create RAID volume when " 8887c478bd9Sstevel@tonic-gate "disk block sizes differ.\n")); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate return (INVALID_ARG); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 893*05411564Sjesseb /* 894*05411564Sjesseb * capacity is now set to the number of blocks on a disk, which is 895*05411564Sjesseb * the total capacity of a mirror. the capacity of a stripe is the 896*05411564Sjesseb * cumulative amount of blocks on all disks 897*05411564Sjesseb */ 898*05411564Sjesseb if (rlevel == RAID_STRIPE) 899*05411564Sjesseb capacity *= ndisks; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate if (get_devctl(disk[0], channel1)) 9027c478bd9Sstevel@tonic-gate return (FAILURE); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate fd = open(channel1, O_RDONLY); 9057c478bd9Sstevel@tonic-gate if (fd == -1) { 9067c478bd9Sstevel@tonic-gate perror(channel1); 9077c478bd9Sstevel@tonic-gate return (FAILURE); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 910*05411564Sjesseb /* get the current configuration */ 9117c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config) < 0) { 9127c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 913*05411564Sjesseb goto fail; 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate /* 917*05411564Sjesseb * current support for both LSI1030 and LSI1064 HBAs 918*05411564Sjesseb * get the devid of the HBA so we can determine capabilities 919*05411564Sjesseb */ 920*05411564Sjesseb if (ioctl(fd, RAID_GETDEVID, &devid) < 0) { 921*05411564Sjesseb raidctl_error("RAID_GETDEVID"); 922*05411564Sjesseb goto fail; 923*05411564Sjesseb } 924*05411564Sjesseb 925*05411564Sjesseb if ((devid == LSI_1064) || (devid == LSI_1064E)) { 926*05411564Sjesseb /* 927*05411564Sjesseb * 2 raid volumes supported, single channel 928*05411564Sjesseb */ 929*05411564Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 930*05411564Sjesseb if (config[i].ndisks == 0) 931*05411564Sjesseb goto no_secondary_channel; 932*05411564Sjesseb } 933*05411564Sjesseb 934*05411564Sjesseb (void) printf(gettext("HBA supports a maximum of 2 " 935*05411564Sjesseb "RAID Volumes, HBA is full\n")); 936*05411564Sjesseb goto fail; 937*05411564Sjesseb } 938*05411564Sjesseb 939*05411564Sjesseb /* 940*05411564Sjesseb * LSI1030, support for single IM volume 941*05411564Sjesseb */ 942*05411564Sjesseb if (rlevel != RAID_MIRROR) { 943*05411564Sjesseb (void) printf(gettext("HBA only supports RAID " 944*05411564Sjesseb "level 1 (mirrored) volumes\n")); 945*05411564Sjesseb goto fail; 946*05411564Sjesseb } 947*05411564Sjesseb 948*05411564Sjesseb if (config[0].ndisks != 0) { 949*05411564Sjesseb (void) printf(gettext("RAID Volume already exists " 950*05411564Sjesseb "on this controller 'c%dt%dd0'\n"), 951*05411564Sjesseb c[0], config[0].targetid); 952*05411564Sjesseb goto fail; 953*05411564Sjesseb } 954*05411564Sjesseb /* 9557c478bd9Sstevel@tonic-gate * Make sure there isn't a raid created on this controller's 956*05411564Sjesseb * other channel, if it has multiple channels 9577c478bd9Sstevel@tonic-gate */ 9587c478bd9Sstevel@tonic-gate (void) strlcpy(channel2, channel1, sizeof (channel2)); 9597c478bd9Sstevel@tonic-gate tmp = strrchr(channel2, ':'); 9607c478bd9Sstevel@tonic-gate tmp[0] = 0; 9617c478bd9Sstevel@tonic-gate size = strlen(channel2); 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate /* 9647c478bd9Sstevel@tonic-gate * Format the channel string for the other channel so we can 965*05411564Sjesseb * see if a raid exists on it. In this case if we are being 966*05411564Sjesseb * asked to create a raid on channel 2 (indicated by the 1,1 967*05411564Sjesseb * at the end of the string) we want to check channel 1), 968*05411564Sjesseb * otherwise we will check channel 2. 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate if (channel2[size - 2] == ',') { 9717c478bd9Sstevel@tonic-gate channel2[size - 1] = 0; 9727c478bd9Sstevel@tonic-gate channel2[size - 2] = 0; 973*05411564Sjesseb (void) snprintf(channel2, sizeof (channel2), 974*05411564Sjesseb "%s:devctl", channel2); 9757c478bd9Sstevel@tonic-gate } else { 976*05411564Sjesseb (void) snprintf(channel2, sizeof (channel2), 977*05411564Sjesseb "%s,1:devctl", channel2); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate fd2 = open(channel2, O_RDONLY); 9817c478bd9Sstevel@tonic-gate if (fd2 == -1) { 9827c478bd9Sstevel@tonic-gate if (errno == ENOENT) 9837c478bd9Sstevel@tonic-gate goto no_secondary_channel; 9847c478bd9Sstevel@tonic-gate perror(channel2); 985*05411564Sjesseb goto fail; 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (ioctl(fd2, RAID_GETCONFIG, &config) < 0) { 989*05411564Sjesseb goto fail; 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 992*05411564Sjesseb if (config[0].ndisks != 0) { 9937c478bd9Sstevel@tonic-gate int cx; 9947c478bd9Sstevel@tonic-gate cx = get_controller(channel2); 995*05411564Sjesseb (void) printf(gettext("RAID Volume already exists " 996*05411564Sjesseb "on this controller 'c%dt%dd0'\n"), cx, 997*05411564Sjesseb config[0].targetid); 998*05411564Sjesseb goto fail; 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate no_secondary_channel: 10027c478bd9Sstevel@tonic-gate 1003*05411564Sjesseb /* all checks complete, fill in the config */ 1004*05411564Sjesseb newvol.targetid = t[0]; 1005*05411564Sjesseb newvol.disk[0] = t[0]; 1006*05411564Sjesseb newvol.raid_level = rlevel; 1007*05411564Sjesseb newvol.ndisks = ndisks; 1008*05411564Sjesseb newvol.raid_capacity = capacity; 10097c478bd9Sstevel@tonic-gate 1010*05411564Sjesseb /* populate config.disk, and unconfigure all disks, except targetid */ 1011*05411564Sjesseb for (i = 1; i < ndisks; i++) { 10127c478bd9Sstevel@tonic-gate if (do_config_change_state(CFGA_CMD_UNCONFIGURE, 1013*05411564Sjesseb t[i], c[0])) { 10147c478bd9Sstevel@tonic-gate perror("config_change_state"); 1015*05411564Sjesseb goto fail; 1016*05411564Sjesseb } 1017*05411564Sjesseb newvol.disk[i] = t[i]; 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 1020*05411564Sjesseb if (ioctl(fd, RAID_CREATE, &newvol)) { 1021*05411564Sjesseb /* reconfigure all disks, except targetid */ 1022*05411564Sjesseb for (i = 1; i < ndisks; i++) { 10237c478bd9Sstevel@tonic-gate (void) do_config_change_state(CFGA_CMD_CONFIGURE, 1024*05411564Sjesseb newvol.disk[i], c[0]); 1025*05411564Sjesseb } 10267c478bd9Sstevel@tonic-gate raidctl_error("RAID_CREATE"); 1027*05411564Sjesseb goto fail; 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate (void) printf(gettext("Volume 'c%dt%dd0' created\n"), c[0], t[0]); 10317c478bd9Sstevel@tonic-gate (void) close(fd); 10327c478bd9Sstevel@tonic-gate (void) close(fd2); 10337c478bd9Sstevel@tonic-gate return (SUCCESS); 10347c478bd9Sstevel@tonic-gate 1035*05411564Sjesseb fail: 10367c478bd9Sstevel@tonic-gate (void) close(fd); 1037*05411564Sjesseb (void) close(fd2); 10387c478bd9Sstevel@tonic-gate return (FAILURE); 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate static int 10427c478bd9Sstevel@tonic-gate do_delete(char *d) 10437c478bd9Sstevel@tonic-gate { 1044*05411564Sjesseb raid_config_t config[N_RAIDVOLS]; 10457c478bd9Sstevel@tonic-gate char disk1[MAXPATHLEN]; 10467c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 10477c478bd9Sstevel@tonic-gate int fd; 10487c478bd9Sstevel@tonic-gate int target; 10497c478bd9Sstevel@tonic-gate int ctrl; 1050*05411564Sjesseb int i, j; 1051*05411564Sjesseb int wrong_targ = 0; 10527c478bd9Sstevel@tonic-gate uint8_t t; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate if ((sscanf(d, "c%dt%dd0", &ctrl, &target)) != 2) { 10577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Invalid disk format.\n")); 10587c478bd9Sstevel@tonic-gate return (INVALID_ARG); 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate t = (uint8_t)target; 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate (void) snprintf(disk1, sizeof (disk1), DEVDIR"/%ss2", d); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (get_devctl(disk1, buf) != 0) { 1065*05411564Sjesseb (void) fprintf(stderr, gettext("Not a volume '%s'\n"), d); 10667c478bd9Sstevel@tonic-gate return (FAILURE); 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate fd = open(buf, O_RDONLY); 10707c478bd9Sstevel@tonic-gate if (fd == -1) { 10717c478bd9Sstevel@tonic-gate perror(buf); 10727c478bd9Sstevel@tonic-gate return (FAILURE); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_GETCONFIG, &config)) { 10767c478bd9Sstevel@tonic-gate raidctl_error("RAID_GETCONFIG"); 10777c478bd9Sstevel@tonic-gate goto fail; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 1080*05411564Sjesseb for (i = 0; i < N_RAIDVOLS; i++) { 1081*05411564Sjesseb if (config[i].ndisks != 0) { 1082*05411564Sjesseb /* there is a RAID volume in this slot */ 1083*05411564Sjesseb if (config[i].targetid != t) { 1084*05411564Sjesseb wrong_targ++; 1085*05411564Sjesseb continue; 1086*05411564Sjesseb } 1087*05411564Sjesseb /* and it's our target */ 1088*05411564Sjesseb break; 1089*05411564Sjesseb } 1090*05411564Sjesseb } 1091*05411564Sjesseb 1092*05411564Sjesseb if (i == N_RAIDVOLS) { 1093*05411564Sjesseb /* we found no RAID volumes */ 1094*05411564Sjesseb (void) fprintf(stderr, gettext("No RAID volumes exist on " 10957c478bd9Sstevel@tonic-gate "controller '%d'\n"), ctrl); 10967c478bd9Sstevel@tonic-gate goto fail; 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate 1099*05411564Sjesseb if (wrong_targ == N_RAIDVOLS) { 1100*05411564Sjesseb /* we found RAID volumes, but none matched */ 11017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11027c478bd9Sstevel@tonic-gate gettext("RAID volume 'c%dt%dd0' does not exist\n"), 11037c478bd9Sstevel@tonic-gate ctrl, t); 11047c478bd9Sstevel@tonic-gate goto fail; 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_DELETE, &t)) { 11087c478bd9Sstevel@tonic-gate perror("RAID_DELETE"); 11097c478bd9Sstevel@tonic-gate goto fail; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 1112*05411564Sjesseb /* reconfigure all disks, except targetid */ 1113*05411564Sjesseb for (j = 1; j < config[i].ndisks; j++) { 1114*05411564Sjesseb (void) do_config_change_state(CFGA_CMD_CONFIGURE, 1115*05411564Sjesseb config[i].disk[j], ctrl); 1116*05411564Sjesseb } 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Volume 'c%dt%dd0' deleted.\n"), 11197c478bd9Sstevel@tonic-gate ctrl, target); 11207c478bd9Sstevel@tonic-gate (void) close(fd); 11217c478bd9Sstevel@tonic-gate return (SUCCESS); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate fail: 11247c478bd9Sstevel@tonic-gate (void) close(fd); 11257c478bd9Sstevel@tonic-gate return (FAILURE); 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate static int 11297c478bd9Sstevel@tonic-gate getfcodever(uint8_t *rombuf, uint32_t nbytes, char **fcodeversion) 11307c478bd9Sstevel@tonic-gate { 11317c478bd9Sstevel@tonic-gate int x, y, size; 11327c478bd9Sstevel@tonic-gate int found_1 = 0, found_2 = 0; 11337c478bd9Sstevel@tonic-gate int image_length = 0; 11347c478bd9Sstevel@tonic-gate int no_of_images = 0; 11357c478bd9Sstevel@tonic-gate uint8_t *rombuf_1 = NULL; 11367c478bd9Sstevel@tonic-gate uint16_t image_units = 0; 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate /* 11397c478bd9Sstevel@tonic-gate * Single Image - Open firmware image 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] == 1) { 11427c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCIR_OFF) + PCI_PDS_INDICATOR; 11437c478bd9Sstevel@tonic-gate no_of_images = 1; 11447c478bd9Sstevel@tonic-gate goto process_image; 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * Combined Image - First Image - x86/PC-AT Bios image 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate if (rombuf[gw(&rombuf[PCIR_OFF]) + PCIR_CODETYPE] != 0) { 11517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 11527c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 11537c478bd9Sstevel@tonic-gate return (1); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate /* 11577c478bd9Sstevel@tonic-gate * Seek to 2nd Image 11587c478bd9Sstevel@tonic-gate */ 11597c478bd9Sstevel@tonic-gate rombuf_1 = rombuf + gw(rombuf + PCI_ROM_PCI_DATA_STRUCT_PTR); 11607c478bd9Sstevel@tonic-gate image_units = gw(rombuf_1 + PCI_PDS_IMAGE_LENGTH); 11617c478bd9Sstevel@tonic-gate image_length = image_units * PCI_IMAGE_UNIT_SIZE; 11627c478bd9Sstevel@tonic-gate rombuf_1 += image_length; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * Combined Image - Second Image - Open Firmware image 11667c478bd9Sstevel@tonic-gate */ 11677c478bd9Sstevel@tonic-gate if (rombuf_1[PCI_PDS_CODE_TYPE] != 1) { 11687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is neither open image" 11697c478bd9Sstevel@tonic-gate " nor Bios/Fcode combined image\n")); 11707c478bd9Sstevel@tonic-gate return (1); 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate rombuf_1 += PCI_PDS_INDICATOR; 11737c478bd9Sstevel@tonic-gate no_of_images = 2; 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate process_image: 11767c478bd9Sstevel@tonic-gate /* 11777c478bd9Sstevel@tonic-gate * This should be the last image 11787c478bd9Sstevel@tonic-gate */ 11797c478bd9Sstevel@tonic-gate if (*rombuf_1 != LAST_IMAGE) { 11807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("This is not a valid " 11817c478bd9Sstevel@tonic-gate "Bios/Fcode image file\n")); 11827c478bd9Sstevel@tonic-gate return (1); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* 11867c478bd9Sstevel@tonic-gate * Scan through the bois/fcode file to get the fcode version 11877c478bd9Sstevel@tonic-gate * 0x12 and 0x7 indicate the start of the fcode version string 11887c478bd9Sstevel@tonic-gate */ 11897c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 8); x++) { 11907c478bd9Sstevel@tonic-gate if ((rombuf[x] == FCODE_VERS_KEY1) && 11917c478bd9Sstevel@tonic-gate (rombuf[x+1] == FCODE_VERS_KEY2) && 11927c478bd9Sstevel@tonic-gate (rombuf[x+2] == 'v') && (rombuf[x+3] == 'e') && 11937c478bd9Sstevel@tonic-gate (rombuf[x+4] == 'r') && (rombuf[x+5] == 's') && 11947c478bd9Sstevel@tonic-gate (rombuf[x+6] == 'i') && (rombuf[x+7] == 'o') && 11957c478bd9Sstevel@tonic-gate (rombuf[x+8] == 'n')) { 11967c478bd9Sstevel@tonic-gate found_1 = 1; 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Store the version string if we have found the beginning of it 12037c478bd9Sstevel@tonic-gate */ 12047c478bd9Sstevel@tonic-gate if (found_1) { 12057c478bd9Sstevel@tonic-gate while (x > 0) { 12067c478bd9Sstevel@tonic-gate if (rombuf[--x] == FCODE_VERS_KEY1) { 12077c478bd9Sstevel@tonic-gate if (rombuf[x-1] != FCODE_VERS_KEY1) { 12087c478bd9Sstevel@tonic-gate x++; 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate break; 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate } 12137c478bd9Sstevel@tonic-gate if (x > 0) { 12147c478bd9Sstevel@tonic-gate *fcodeversion = (char *)malloc(rombuf[x] + 1); 12157c478bd9Sstevel@tonic-gate for (y = 0; y < rombuf[x]; y++) { 12167c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = rombuf[x+y+1]; 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 12197c478bd9Sstevel@tonic-gate } else { 12207c478bd9Sstevel@tonic-gate found_1 = 0; 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* 12257c478bd9Sstevel@tonic-gate * Scan through the bois/fcode file to get the Bios version 12267c478bd9Sstevel@tonic-gate * "@(#)" string indicates the start of the Bios version string 12277c478bd9Sstevel@tonic-gate * Append this version string, after already existing fcode version. 12287c478bd9Sstevel@tonic-gate */ 12297c478bd9Sstevel@tonic-gate if (no_of_images == 2) { 12307c478bd9Sstevel@tonic-gate for (x = 0; x < (nbytes - 4); x++) { 12317c478bd9Sstevel@tonic-gate if ((rombuf[x] == '@') && (rombuf[x+1] == '(') && 12327c478bd9Sstevel@tonic-gate (rombuf[x+2] == '#') && (rombuf[x+3] == ')')) { 12337c478bd9Sstevel@tonic-gate found_2 = 1; 12347c478bd9Sstevel@tonic-gate break; 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate } 12377c478bd9Sstevel@tonic-gate 12387c478bd9Sstevel@tonic-gate if (found_2) { 12397c478bd9Sstevel@tonic-gate x += 4; 12407c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\n'; 12417c478bd9Sstevel@tonic-gate size = y + strlen((char *)(rombuf + x)) + 12427c478bd9Sstevel@tonic-gate strlen(BIOS_STR) + 2; 12437c478bd9Sstevel@tonic-gate *fcodeversion = (char *)realloc((*fcodeversion), size); 12447c478bd9Sstevel@tonic-gate y++; 12457c478bd9Sstevel@tonic-gate (*fcodeversion)[y] = '\0'; 12467c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, BIOS_STR, size); 12477c478bd9Sstevel@tonic-gate (void) strlcat(*fcodeversion, (char *)(rombuf + x), 12487c478bd9Sstevel@tonic-gate size); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate 12527c478bd9Sstevel@tonic-gate return ((found_1 || found_2) ? 0 : 1); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate static void 12567c478bd9Sstevel@tonic-gate getfwver(uint8_t *rombuf, char *fwversion) 12577c478bd9Sstevel@tonic-gate { 12587c478bd9Sstevel@tonic-gate (void) snprintf(fwversion, 8, "%d.%.2d.%.2d.%.2d", 12597c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 3], 12607c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 2], 12617c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 1], 12627c478bd9Sstevel@tonic-gate rombuf[FW_ROM_OFFSET_VERSION + 0]); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate static int 12667c478bd9Sstevel@tonic-gate checkfile(uint8_t *rombuf, uint32_t nbytes, uint32_t chksum, int *imagetype) 12677c478bd9Sstevel@tonic-gate { 12687c478bd9Sstevel@tonic-gate char *imageversion = NULL; 12697c478bd9Sstevel@tonic-gate char *fwversion; 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate fwversion = (char *)malloc(8); 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate if (gw(&rombuf[0]) == PCIROM_SIG) { 12747c478bd9Sstevel@tonic-gate /* imageversion is malloc(2)'ed in getfcodever() */ 12757c478bd9Sstevel@tonic-gate if (getfcodever(rombuf, nbytes, &imageversion) == 0) { 12767c478bd9Sstevel@tonic-gate *imagetype = FCODE_IMAGE; 12777c478bd9Sstevel@tonic-gate } else { 12787c478bd9Sstevel@tonic-gate *imagetype = UNKNOWN_IMAGE; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate if (*imagetype != UNKNOWN_IMAGE) { 12817c478bd9Sstevel@tonic-gate (void) printf(gettext("Image file contains:\n%s\n"), 12827c478bd9Sstevel@tonic-gate imageversion); 12837c478bd9Sstevel@tonic-gate free(imageversion); 12847c478bd9Sstevel@tonic-gate } else { 12857c478bd9Sstevel@tonic-gate if (imageversion != NULL) { 12867c478bd9Sstevel@tonic-gate free(imageversion); 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate return (-1); 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate } else if (gw(&rombuf[3]) == FW_ROM_ID) { 12917c478bd9Sstevel@tonic-gate if (chksum != 0) { 12927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12937c478bd9Sstevel@tonic-gate gettext("The ROM checksum appears bad " 12947c478bd9Sstevel@tonic-gate "(%d)\n"), chksum); 12957c478bd9Sstevel@tonic-gate return (-1); 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate getfwver(rombuf, fwversion); 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate if ((gw(&rombuf[FW_ROM_OFFSET_CHIP_TYPE]) & 13007c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_MASK) == 13017c478bd9Sstevel@tonic-gate MPI_FW_HEADER_PID_PROD_IM_SCSI) { 13027c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 13037c478bd9Sstevel@tonic-gate "MPT firmware version %s " 13047c478bd9Sstevel@tonic-gate "(w/Integrated Mirroring)\n"), 13057c478bd9Sstevel@tonic-gate fwversion); 13067c478bd9Sstevel@tonic-gate } else { 13077c478bd9Sstevel@tonic-gate (void) printf(gettext("ROM image contains " 13087c478bd9Sstevel@tonic-gate "MPT firmware ""version %s\n"), 13097c478bd9Sstevel@tonic-gate fwversion); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate free(fwversion); 13127c478bd9Sstevel@tonic-gate } else { 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate #ifdef DEBUG 13157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Not valid FCODE image %x\n", gw(&rombuf[0])); 13167c478bd9Sstevel@tonic-gate #else 13177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Not valid FCODE image\n")); 13187c478bd9Sstevel@tonic-gate #endif 13197c478bd9Sstevel@tonic-gate return (-1); 13207c478bd9Sstevel@tonic-gate } 13217c478bd9Sstevel@tonic-gate return (0); 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate static int 13257c478bd9Sstevel@tonic-gate updateflash(uint8_t *rombuf, uint32_t nbytes, char *devctl) 13267c478bd9Sstevel@tonic-gate { 13277c478bd9Sstevel@tonic-gate int fd = 0; 13287c478bd9Sstevel@tonic-gate update_flash_t flashdata; 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate fd = open(devctl, O_RDONLY); 13317c478bd9Sstevel@tonic-gate if (fd == -1) { 13327c478bd9Sstevel@tonic-gate perror(devctl); 13337c478bd9Sstevel@tonic-gate return (-1); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate (void) memset(&flashdata, 0, sizeof (flashdata)); 13367c478bd9Sstevel@tonic-gate flashdata.ptrbuffer = (caddr_t)rombuf; 13377c478bd9Sstevel@tonic-gate flashdata.size = nbytes; 13387c478bd9Sstevel@tonic-gate if ((rombuf[0] == 0x55) && (rombuf[1] == 0xaa)) { 13397c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_FCODE; 13407c478bd9Sstevel@tonic-gate } else { 13417c478bd9Sstevel@tonic-gate flashdata.type = FW_TYPE_UCODE; 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate if (ioctl(fd, RAID_UPDATEFW, &flashdata)) { 13457c478bd9Sstevel@tonic-gate raidctl_error("RAID_UPDATEFW"); 13467c478bd9Sstevel@tonic-gate (void) close(fd); 13477c478bd9Sstevel@tonic-gate return (-1); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate (void) close(fd); 13517c478bd9Sstevel@tonic-gate return (0); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate static int 13557c478bd9Sstevel@tonic-gate readfile(char *filespec, uint8_t **rombuf, uint32_t *nbytes, uint32_t *chksum) 13567c478bd9Sstevel@tonic-gate { 13577c478bd9Sstevel@tonic-gate struct stat statbuf; 13587c478bd9Sstevel@tonic-gate uint32_t count; 13597c478bd9Sstevel@tonic-gate uint32_t checksum = 0; 13607c478bd9Sstevel@tonic-gate int fd, i; 13617c478bd9Sstevel@tonic-gate uint8_t *filebuf; 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate if ((fd = open((const char *)filespec, O_RDONLY | O_NDELAY)) == -1) { 13657c478bd9Sstevel@tonic-gate perror(filespec); 13667c478bd9Sstevel@tonic-gate return (-1); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate 13697c478bd9Sstevel@tonic-gate if (fstat(fd, &statbuf) != 0) { 13707c478bd9Sstevel@tonic-gate perror("fstat"); 13717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13727c478bd9Sstevel@tonic-gate gettext("Error getting stats on file\n")); 13737c478bd9Sstevel@tonic-gate (void) close(fd); 13747c478bd9Sstevel@tonic-gate return (-1); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate #ifdef DEBUG 13787c478bd9Sstevel@tonic-gate (void) printf("Filesize = %ld\n", statbuf.st_size); 13797c478bd9Sstevel@tonic-gate #endif 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate filebuf = (uint8_t *)realloc(*rombuf, statbuf.st_size + *nbytes); 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate count = read(fd, filebuf + *nbytes, statbuf.st_size); 13847c478bd9Sstevel@tonic-gate (void) close(fd); 13857c478bd9Sstevel@tonic-gate if (count != statbuf.st_size) { 13867c478bd9Sstevel@tonic-gate perror("size check"); 13877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("File is corrupt\n")); 13887c478bd9Sstevel@tonic-gate return (-1); 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate 13917c478bd9Sstevel@tonic-gate for (i = 0; i < *nbytes; i++) 13927c478bd9Sstevel@tonic-gate checksum += filebuf[i] << (8 * (i & 3)); 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate *rombuf = filebuf; 13957c478bd9Sstevel@tonic-gate *nbytes = *nbytes + count; 13967c478bd9Sstevel@tonic-gate *chksum = checksum; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate return (0); 13997c478bd9Sstevel@tonic-gate } 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate static int 14027c478bd9Sstevel@tonic-gate yes(int c) 14037c478bd9Sstevel@tonic-gate { 14047c478bd9Sstevel@tonic-gate int i, b; 14057c478bd9Sstevel@tonic-gate char ans[SCHAR_MAX + 1]; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 14087c478bd9Sstevel@tonic-gate b = getchar(); 14097c478bd9Sstevel@tonic-gate if (b == '\n' || b == '\0' || b == EOF) { 14107c478bd9Sstevel@tonic-gate ans[i] = 0; 14117c478bd9Sstevel@tonic-gate break; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate if (i < SCHAR_MAX) 14147c478bd9Sstevel@tonic-gate ans[i] = b; 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate if (i >= SCHAR_MAX) { 14177c478bd9Sstevel@tonic-gate i = SCHAR_MAX; 14187c478bd9Sstevel@tonic-gate ans[SCHAR_MAX] = 0; 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate if ((i != 0) && ((strncmp(yeschr, ans, i)) == 0)) { 14217c478bd9Sstevel@tonic-gate return (1); 14227c478bd9Sstevel@tonic-gate } else { 14237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("User response is \"%s\", " 14247c478bd9Sstevel@tonic-gate "Controller %d not flashed.\n\n"), ans, c); 14257c478bd9Sstevel@tonic-gate return (0); 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate static int 14307c478bd9Sstevel@tonic-gate do_flash(int c, char *fpath, int force) 14317c478bd9Sstevel@tonic-gate { 14327c478bd9Sstevel@tonic-gate char devctl[MAXPATHLEN] = {0}; 14337c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN] = {0}; 14347c478bd9Sstevel@tonic-gate int rv = 0; 14357c478bd9Sstevel@tonic-gate int imagetype; 14367c478bd9Sstevel@tonic-gate uint32_t nbytes = 0; 14377c478bd9Sstevel@tonic-gate uint32_t chksum; 14387c478bd9Sstevel@tonic-gate uint8_t *rombuf = NULL; 14397c478bd9Sstevel@tonic-gate char cwd[MAXPATHLEN]; 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate /* 14427c478bd9Sstevel@tonic-gate * Read fw file 14437c478bd9Sstevel@tonic-gate */ 14447c478bd9Sstevel@tonic-gate rv = readfile(fpath, &rombuf, &nbytes, &chksum); 14457c478bd9Sstevel@tonic-gate if (rv != 0) { 14467c478bd9Sstevel@tonic-gate return (FAILURE); 14477c478bd9Sstevel@tonic-gate } 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate (void) getcwd(cwd, sizeof (cwd)); 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate (void) chdir(DEVDIR); 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* Get link from "/dev/cfg" */ 14547c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "/dev/cfg/c%d", c); 14557c478bd9Sstevel@tonic-gate if (get_link_path(buf, devctl) != 0) { 14567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 14577c478bd9Sstevel@tonic-gate gettext("Invalid controller '%d'\n"), c); 14587c478bd9Sstevel@tonic-gate return (INVALID_ARG); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate /* Check File */ 14627c478bd9Sstevel@tonic-gate rv = checkfile(rombuf, nbytes, chksum, &imagetype); 14637c478bd9Sstevel@tonic-gate if (rv != 0) { 14647c478bd9Sstevel@tonic-gate return (FAILURE); 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate /* Confirm */ 14687c478bd9Sstevel@tonic-gate if (!force) { 14697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Update flash image on " 14707c478bd9Sstevel@tonic-gate "controller %d (%s/%s)? "), c, yeschr, nochr); 14717c478bd9Sstevel@tonic-gate if (!yes(c)) { 14727c478bd9Sstevel@tonic-gate return (SUCCESS); 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate /* Do Flash */ 14777c478bd9Sstevel@tonic-gate if (updateflash(rombuf, nbytes, devctl)) { 14787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Flash not updated on " 14797c478bd9Sstevel@tonic-gate "Controller %d.\n\n"), c); 14807c478bd9Sstevel@tonic-gate return (INVALID_ARG); 14817c478bd9Sstevel@tonic-gate } 14827c478bd9Sstevel@tonic-gate (void) printf(gettext("Flash updated successfully.\n\n")); 14837c478bd9Sstevel@tonic-gate return (SUCCESS); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate static int 14877c478bd9Sstevel@tonic-gate fully_numeric(char *str) 14887c478bd9Sstevel@tonic-gate { 14897c478bd9Sstevel@tonic-gate int size = strlen(str); 14907c478bd9Sstevel@tonic-gate int i; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++) { 14937c478bd9Sstevel@tonic-gate if (i == 0 && str[i] == '-' && size != 1) 14947c478bd9Sstevel@tonic-gate continue; 14957c478bd9Sstevel@tonic-gate if (!isdigit(str[i])) 14967c478bd9Sstevel@tonic-gate return (0); 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate return (1); 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate /* 15027c478bd9Sstevel@tonic-gate * Useful parsing macros 15037c478bd9Sstevel@tonic-gate */ 15047c478bd9Sstevel@tonic-gate #define must_be(s, c) if (*s++ != c) return (0) 15057c478bd9Sstevel@tonic-gate #define skip_digits(s) while (isdigit(*s)) s++ 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate /* 15087c478bd9Sstevel@tonic-gate * Return true if a name is in the internal canonical form 15097c478bd9Sstevel@tonic-gate */ 15107c478bd9Sstevel@tonic-gate static int 15117c478bd9Sstevel@tonic-gate canonical_name(char *name) 15127c478bd9Sstevel@tonic-gate { 15137c478bd9Sstevel@tonic-gate must_be(name, 'c'); 15147c478bd9Sstevel@tonic-gate skip_digits(name); 15157c478bd9Sstevel@tonic-gate if (*name == 't') { 15167c478bd9Sstevel@tonic-gate name++; 15177c478bd9Sstevel@tonic-gate skip_digits(name); 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate must_be(name, 'd'); 15207c478bd9Sstevel@tonic-gate skip_digits(name); 15217c478bd9Sstevel@tonic-gate return (*name == 0); 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate int 15257c478bd9Sstevel@tonic-gate main(int argc, char **argv) 15267c478bd9Sstevel@tonic-gate { 15277c478bd9Sstevel@tonic-gate int rv = SUCCESS; 15287c478bd9Sstevel@tonic-gate int i, c; 15297c478bd9Sstevel@tonic-gate int findex = DO_HW_RAID_INFO; 15307c478bd9Sstevel@tonic-gate int controller; 1531*05411564Sjesseb char *disks[N_DISKS] = {0}; 15327c478bd9Sstevel@tonic-gate char *darg; 15337c478bd9Sstevel@tonic-gate char *farg; 1534*05411564Sjesseb char *rarg; 15357c478bd9Sstevel@tonic-gate char *progname; 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate int l_flag = 0; 15387c478bd9Sstevel@tonic-gate int c_flag = 0; 15397c478bd9Sstevel@tonic-gate int d_flag = 0; 15407c478bd9Sstevel@tonic-gate int f_flag = 0; 15417c478bd9Sstevel@tonic-gate int F_flag = 0; 1542*05411564Sjesseb int r_flag = 0; 15437c478bd9Sstevel@tonic-gate int no_flags = 1; 1544*05411564Sjesseb int r = RAID_MIRROR; /* default raid level is 1 */ 15457c478bd9Sstevel@tonic-gate char *current_dir; 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 15487c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 15517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Must be root.\n")); 15527c478bd9Sstevel@tonic-gate exit(1); 15537c478bd9Sstevel@tonic-gate } 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate if ((progname = strrchr(argv[0], '/')) == NULL) 15567c478bd9Sstevel@tonic-gate progname = argv[0]; 15577c478bd9Sstevel@tonic-gate else 15587c478bd9Sstevel@tonic-gate progname++; 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate raids = NULL; 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate (void) strncpy(yeschr, nl_langinfo(YESSTR), SCHAR_MAX + 1); 15637c478bd9Sstevel@tonic-gate (void) strncpy(nochr, nl_langinfo(NOSTR), SCHAR_MAX + 1); 15647c478bd9Sstevel@tonic-gate 1565*05411564Sjesseb while ((c = getopt(argc, argv, "cr:lfd:F:")) != EOF) { 15667c478bd9Sstevel@tonic-gate switch (c) { 15677c478bd9Sstevel@tonic-gate case 'c': 1568*05411564Sjesseb if (f_flag || argc < 4) 15697c478bd9Sstevel@tonic-gate usage(progname); 15707c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_CREATE; 15717c478bd9Sstevel@tonic-gate c_flag = 1; 15727c478bd9Sstevel@tonic-gate no_flags = 0; 15737c478bd9Sstevel@tonic-gate break; 1574*05411564Sjesseb case 'r': 1575*05411564Sjesseb rarg = optarg; 1576*05411564Sjesseb r = atoi(rarg); 1577*05411564Sjesseb if ((r != RAID_STRIPE) && (r != RAID_MIRROR)) 1578*05411564Sjesseb usage(progname); 1579*05411564Sjesseb r_flag = 1; 1580*05411564Sjesseb break; 15817c478bd9Sstevel@tonic-gate case 'd': 15827c478bd9Sstevel@tonic-gate darg = optarg; 15837c478bd9Sstevel@tonic-gate d_flag = 1; 15847c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_DELETE; 15857c478bd9Sstevel@tonic-gate no_flags = 0; 15867c478bd9Sstevel@tonic-gate break; 15877c478bd9Sstevel@tonic-gate case 'l': 15887c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_INFO; 15897c478bd9Sstevel@tonic-gate l_flag = 1; 15907c478bd9Sstevel@tonic-gate no_flags = 0; 15917c478bd9Sstevel@tonic-gate break; 15927c478bd9Sstevel@tonic-gate case 'F': 15937c478bd9Sstevel@tonic-gate findex = DO_HW_RAID_FLASH; 15947c478bd9Sstevel@tonic-gate farg = optarg; 15957c478bd9Sstevel@tonic-gate F_flag = 1; 15967c478bd9Sstevel@tonic-gate no_flags = 0; 15977c478bd9Sstevel@tonic-gate break; 15987c478bd9Sstevel@tonic-gate case 'f': 15997c478bd9Sstevel@tonic-gate f_flag = 1; 16007c478bd9Sstevel@tonic-gate no_flags = 0; 16017c478bd9Sstevel@tonic-gate break; 1602*05411564Sjesseb case '?': 1603*05411564Sjesseb default: 16047c478bd9Sstevel@tonic-gate usage(progname); 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate if (no_flags && argc > 1) 16097c478bd9Sstevel@tonic-gate usage(progname); 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* compatibility rules */ 16127c478bd9Sstevel@tonic-gate if (c_flag && d_flag) 16137c478bd9Sstevel@tonic-gate usage(progname); 1614*05411564Sjesseb if (r_flag && !(c_flag)) 16157c478bd9Sstevel@tonic-gate usage(progname); 1616*05411564Sjesseb if (l_flag && (d_flag || c_flag || f_flag || F_flag || r_flag)) 1617*05411564Sjesseb usage(progname); 1618*05411564Sjesseb if (F_flag && (d_flag || c_flag || l_flag || r_flag)) 16197c478bd9Sstevel@tonic-gate usage(progname); 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate switch (findex) { 16227c478bd9Sstevel@tonic-gate case DO_HW_RAID_INFO: 16237c478bd9Sstevel@tonic-gate if (l_flag) { 16247c478bd9Sstevel@tonic-gate /* 16257c478bd9Sstevel@tonic-gate * "raidctl" makes argc == 1 16267c478bd9Sstevel@tonic-gate * "-l" makes argc == 2 16277c478bd9Sstevel@tonic-gate */ 16287c478bd9Sstevel@tonic-gate ctrl_nums = argc - 2; 16297c478bd9Sstevel@tonic-gate if (ctrl_nums != 0) { 16307c478bd9Sstevel@tonic-gate info_ctrl = (int **) 16317c478bd9Sstevel@tonic-gate malloc(ctrl_nums * sizeof (int)); 16327c478bd9Sstevel@tonic-gate if (info_ctrl == NULL) 16337c478bd9Sstevel@tonic-gate return (FAILURE); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 16367c478bd9Sstevel@tonic-gate char *tmp = argv[i + 2]; 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate info_ctrl[i] = (int *)malloc(2 * sizeof (int)); 16397c478bd9Sstevel@tonic-gate if (info_ctrl[i] == NULL) { 16407c478bd9Sstevel@tonic-gate free(info_ctrl); 16417c478bd9Sstevel@tonic-gate return (FAILURE); 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 16447c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", 16457c478bd9Sstevel@tonic-gate &info_ctrl[i][INFO_CTRL]); 16467c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 16477c478bd9Sstevel@tonic-gate RAID_INVALID_CTRL; 16487c478bd9Sstevel@tonic-gate } else { 16497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16507c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 16517c478bd9Sstevel@tonic-gate tmp); 16527c478bd9Sstevel@tonic-gate info_ctrl[i][INFO_STATUS] = 16537c478bd9Sstevel@tonic-gate RAID_DONT_USE; 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate } else if (argc > 1) { 16577c478bd9Sstevel@tonic-gate usage(progname); 16587c478bd9Sstevel@tonic-gate } 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate do_info(); 16617c478bd9Sstevel@tonic-gate break; 16627c478bd9Sstevel@tonic-gate case DO_HW_RAID_CREATE: 16637c478bd9Sstevel@tonic-gate for (i = 0; i < N_DISKS; i++) { 1664*05411564Sjesseb int p = 2 + (r_flag * 2) + i; 1665*05411564Sjesseb 1666*05411564Sjesseb if (p == argc) 1667*05411564Sjesseb break; 1668*05411564Sjesseb 1669*05411564Sjesseb disks[i] = argv[p]; 1670*05411564Sjesseb 16717c478bd9Sstevel@tonic-gate if (!canonical_name(disks[i])) 16727c478bd9Sstevel@tonic-gate usage(progname); 1673*05411564Sjesseb 1674*05411564Sjesseb /* no more than 2 disks for raid level 1 */ 1675*05411564Sjesseb if ((r == RAID_MIRROR) && (i > 1)) 1676*05411564Sjesseb usage(progname); 16777c478bd9Sstevel@tonic-gate } 1678*05411564Sjesseb 1679*05411564Sjesseb rv = do_create(disks, r); 16807c478bd9Sstevel@tonic-gate break; 16817c478bd9Sstevel@tonic-gate case DO_HW_RAID_DELETE: 16827c478bd9Sstevel@tonic-gate if (!canonical_name(darg)) 16837c478bd9Sstevel@tonic-gate usage(progname); 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate rv = do_delete(darg); 16867c478bd9Sstevel@tonic-gate break; 16877c478bd9Sstevel@tonic-gate case DO_HW_RAID_FLASH: 16887c478bd9Sstevel@tonic-gate ctrl_nums = argc - f_flag - 3; 16897c478bd9Sstevel@tonic-gate if (ctrl_nums == 0) 16907c478bd9Sstevel@tonic-gate usage(progname); 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate current_dir = getcwd(NULL, MAXPATHLEN); 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate for (i = 0; i < ctrl_nums; i++) { 16957c478bd9Sstevel@tonic-gate char *tmp = argv[i + 3 + f_flag]; 16967c478bd9Sstevel@tonic-gate (void) chdir(current_dir); 16977c478bd9Sstevel@tonic-gate if (fully_numeric(tmp)) { 16987c478bd9Sstevel@tonic-gate (void) sscanf(tmp, "%d", &controller); 16997c478bd9Sstevel@tonic-gate rv = do_flash(controller, farg, f_flag); 17007c478bd9Sstevel@tonic-gate if (rv == FAILURE) 17017c478bd9Sstevel@tonic-gate break; 17027c478bd9Sstevel@tonic-gate } else { 17037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17047c478bd9Sstevel@tonic-gate gettext("Invalid controller '%s'\n"), 17057c478bd9Sstevel@tonic-gate tmp); 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate free(current_dir); 17097c478bd9Sstevel@tonic-gate break; 17107c478bd9Sstevel@tonic-gate default: 17117c478bd9Sstevel@tonic-gate usage(progname); 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate return (rv); 17147c478bd9Sstevel@tonic-gate } 1715