1*b1dd958fScth /* 2*b1dd958fScth * CDDL HEADER START 3*b1dd958fScth * 4*b1dd958fScth * The contents of this file are subject to the terms of the 5*b1dd958fScth * Common Development and Distribution License, Version 1.0 only 6*b1dd958fScth * (the "License"). You may not use this file except in compliance 7*b1dd958fScth * with the License. 8*b1dd958fScth * 9*b1dd958fScth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*b1dd958fScth * or http://www.opensolaris.org/os/licensing. 11*b1dd958fScth * See the License for the specific language governing permissions 12*b1dd958fScth * and limitations under the License. 13*b1dd958fScth * 14*b1dd958fScth * When distributing Covered Code, include this CDDL HEADER in each 15*b1dd958fScth * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*b1dd958fScth * If applicable, add the following below this CDDL HEADER, with the 17*b1dd958fScth * fields enclosed by brackets "[]" replaced with your own identifying 18*b1dd958fScth * information: Portions Copyright [yyyy] [name of copyright owner] 19*b1dd958fScth * 20*b1dd958fScth * CDDL HEADER END 21*b1dd958fScth */ 22*b1dd958fScth /* 23*b1dd958fScth * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*b1dd958fScth * Use is subject to license terms. 25*b1dd958fScth */ 26*b1dd958fScth 27*b1dd958fScth #pragma ident "%Z%%M% %I% %E% SMI" 28*b1dd958fScth 29*b1dd958fScth /* 30*b1dd958fScth * This program provides a command line interface to the 31*b1dd958fScth * three new ioctls for the emul64 driver - EMUL64_WRITE_OFF, 32*b1dd958fScth * EMUL64_WRITE_ON and EMUL64_ZERO_RANGE. All three of these 33*b1dd958fScth * ioctls require the range of blocks to be specified. The 34*b1dd958fScth * range is specified by starting block number and block count 35*b1dd958fScth * both of which are 64 bit. 36*b1dd958fScth * 37*b1dd958fScth * Returns 0 on success, >0 on failure. 38*b1dd958fScth * 39*b1dd958fScth */ 40*b1dd958fScth #include <stdio.h> 41*b1dd958fScth #include <fcntl.h> 42*b1dd958fScth #include <unistd.h> 43*b1dd958fScth #include <stropts.h> 44*b1dd958fScth #include <string.h> 45*b1dd958fScth #include <stdlib.h> 46*b1dd958fScth #include <errno.h> 47*b1dd958fScth #include <sys/types.h> 48*b1dd958fScth #include <sys/emul64.h> 49*b1dd958fScth 50*b1dd958fScth #define DEBUG 1 51*b1dd958fScth #define ADMIN_DIR "/dev/cfg/" 52*b1dd958fScth 53*b1dd958fScth char *Pname; 54*b1dd958fScth 55*b1dd958fScth static int get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin); 56*b1dd958fScth 57*b1dd958fScth static void 58*b1dd958fScth usage(void) 59*b1dd958fScth { 60*b1dd958fScth (void) fprintf(stderr, "Usage: emul64ioctl -s start_block " 61*b1dd958fScth "-b block_count -c write_off | write_on | zero emul64_dev\n"); 62*b1dd958fScth exit(1); 63*b1dd958fScth } 64*b1dd958fScth 65*b1dd958fScth int 66*b1dd958fScth main(int argc, char **argv) 67*b1dd958fScth { 68*b1dd958fScth extern char *optarg; 69*b1dd958fScth extern int optind; 70*b1dd958fScth char *admin; 71*b1dd958fScth int count_seen = 0; 72*b1dd958fScth int fd, retval; 73*b1dd958fScth int cmd = -1; 74*b1dd958fScth int do_usage = 0; 75*b1dd958fScth char *slice; 76*b1dd958fScth int sb_seen = 0; 77*b1dd958fScth emul64_tgt_range_t tr; 78*b1dd958fScth 79*b1dd958fScth Pname = strrchr(argv[0], '/'); 80*b1dd958fScth if (Pname == NULL) 81*b1dd958fScth Pname = argv[0]; 82*b1dd958fScth else 83*b1dd958fScth Pname++; 84*b1dd958fScth 85*b1dd958fScth while ((retval = getopt(argc, argv, "s:b:c:")) != -1) { 86*b1dd958fScth switch (retval) { 87*b1dd958fScth case 's': 88*b1dd958fScth sb_seen = 1; 89*b1dd958fScth tr.emul64_blkrange.emul64_sb = atoll(optarg); 90*b1dd958fScth break; 91*b1dd958fScth case 'b': 92*b1dd958fScth count_seen = 1; 93*b1dd958fScth tr.emul64_blkrange.emul64_blkcnt = atoll(optarg); 94*b1dd958fScth break; 95*b1dd958fScth case 'c': 96*b1dd958fScth if (strncmp(optarg, "write_off", 97*b1dd958fScth strlen("write_off")) == 0) { 98*b1dd958fScth cmd = EMUL64_WRITE_OFF; 99*b1dd958fScth } else if (strncmp(optarg, "write_on", 100*b1dd958fScth strlen("write_on")) == 0) { 101*b1dd958fScth cmd = EMUL64_WRITE_ON; 102*b1dd958fScth } else if (strncmp(optarg, "zero", 103*b1dd958fScth strlen("zero")) == 0) { 104*b1dd958fScth cmd = EMUL64_ZERO_RANGE; 105*b1dd958fScth } else { 106*b1dd958fScth do_usage = 1; 107*b1dd958fScth } 108*b1dd958fScth break; 109*b1dd958fScth default: 110*b1dd958fScth break; 111*b1dd958fScth } 112*b1dd958fScth } 113*b1dd958fScth 114*b1dd958fScth if (do_usage || (optind != argc - 1)) { 115*b1dd958fScth usage(); 116*b1dd958fScth } 117*b1dd958fScth if ((sb_seen == 0) || (count_seen == 0) || (cmd == -1)) 118*b1dd958fScth usage(); 119*b1dd958fScth 120*b1dd958fScth slice = argv[optind]; 121*b1dd958fScth 122*b1dd958fScth /* 123*b1dd958fScth * Get admin device, target and lun 124*b1dd958fScth */ 125*b1dd958fScth if (get_disk_addr(slice, &tr, &admin) != 0) 126*b1dd958fScth exit(1); 127*b1dd958fScth 128*b1dd958fScth /* 129*b1dd958fScth * open the specified emul64_dev. 130*b1dd958fScth */ 131*b1dd958fScth if ((fd = open(admin, O_RDONLY, 0444)) != -1) { 132*b1dd958fScth 133*b1dd958fScth retval = ioctl(fd, cmd, &tr); 134*b1dd958fScth (void) close(fd); 135*b1dd958fScth 136*b1dd958fScth if (retval != -1) { 137*b1dd958fScth free(admin); 138*b1dd958fScth return (0); 139*b1dd958fScth } 140*b1dd958fScth (void) printf("emul64ioctl: %s: ioctl %s\n", 141*b1dd958fScth admin, strerror(errno)); 142*b1dd958fScth } else { 143*b1dd958fScth (void) printf("emul64ioctl: %s: open %s\n", 144*b1dd958fScth admin, strerror(errno)); 145*b1dd958fScth } 146*b1dd958fScth free(admin); 147*b1dd958fScth return (1); 148*b1dd958fScth } 149*b1dd958fScth 150*b1dd958fScth #define TOK_CHECK(s) if (token == NULL) {\ 151*b1dd958fScth bogus = (s);\ 152*b1dd958fScth goto err_out;\ 153*b1dd958fScth } 154*b1dd958fScth 155*b1dd958fScth static int 156*b1dd958fScth get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin) 157*b1dd958fScth { 158*b1dd958fScth size_t admin_size; 159*b1dd958fScth int ctlr_num; 160*b1dd958fScth int conversions; 161*b1dd958fScth char *ctds; 162*b1dd958fScth 163*b1dd958fScth *admin = NULL; 164*b1dd958fScth ctds = strrchr(path, '/'); 165*b1dd958fScth if (ctds == NULL) 166*b1dd958fScth ctds = path; 167*b1dd958fScth else 168*b1dd958fScth ctds++; 169*b1dd958fScth conversions = sscanf(ctds, "c%dt%hud%hu", &ctlr_num, 170*b1dd958fScth &tr->emul64_target, &tr->emul64_lun); 171*b1dd958fScth if (conversions != 3) { 172*b1dd958fScth (void) fprintf(stderr, "%s: \"%s\" is invalid disk name. " 173*b1dd958fScth "%d conversions\n", Pname, ctds, conversions); 174*b1dd958fScth return (-1); 175*b1dd958fScth } 176*b1dd958fScth 177*b1dd958fScth /* Build controller name */ 178*b1dd958fScth admin_size = strlen(ADMIN_DIR) + 179*b1dd958fScth 10 + /* enough digits for an int */ 180*b1dd958fScth 1 + /* c */ 181*b1dd958fScth 1; /* Null terminator */ 182*b1dd958fScth *admin = malloc(admin_size); 183*b1dd958fScth if (*admin == NULL) { 184*b1dd958fScth (void) fprintf(stderr, "%s: out of memory\n", Pname); 185*b1dd958fScth return (-1); 186*b1dd958fScth } 187*b1dd958fScth (void) snprintf(*admin, admin_size, "%sc%d", ADMIN_DIR, ctlr_num); 188*b1dd958fScth return (0); 189*b1dd958fScth } 190