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