0
|
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 #pragma ident "@(#)emul64ioctl.c 1.1 05/06/27 SMI"
|
|
28
|
|
29 /*
|
|
30 * This program provides a command line interface to the
|
|
31 * three new ioctls for the emul64 driver - EMUL64_WRITE_OFF,
|
|
32 * EMUL64_WRITE_ON and EMUL64_ZERO_RANGE. All three of these
|
|
33 * ioctls require the range of blocks to be specified. The
|
|
34 * range is specified by starting block number and block count
|
|
35 * both of which are 64 bit.
|
|
36 *
|
|
37 * Returns 0 on success, >0 on failure.
|
|
38 *
|
|
39 */
|
|
40 #include <stdio.h>
|
|
41 #include <fcntl.h>
|
|
42 #include <unistd.h>
|
|
43 #include <stropts.h>
|
|
44 #include <string.h>
|
|
45 #include <stdlib.h>
|
|
46 #include <errno.h>
|
|
47 #include <sys/types.h>
|
|
48 #include <sys/emul64.h>
|
|
49
|
|
50 #define DEBUG 1
|
|
51 #define ADMIN_DIR "/dev/cfg/"
|
|
52
|
|
53 char *Pname;
|
|
54
|
|
55 static int get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin);
|
|
56
|
|
57 static void
|
|
58 usage(void)
|
|
59 {
|
|
60 (void) fprintf(stderr, "Usage: emul64ioctl -s start_block "
|
|
61 "-b block_count -c write_off | write_on | zero emul64_dev\n");
|
|
62 exit(1);
|
|
63 }
|
|
64
|
|
65 int
|
|
66 main(int argc, char **argv)
|
|
67 {
|
|
68 extern char *optarg;
|
|
69 extern int optind;
|
|
70 char *admin;
|
|
71 int count_seen = 0;
|
|
72 int fd, retval;
|
|
73 int cmd = -1;
|
|
74 int do_usage = 0;
|
|
75 char *slice;
|
|
76 int sb_seen = 0;
|
|
77 emul64_tgt_range_t tr;
|
|
78
|
|
79 Pname = strrchr(argv[0], '/');
|
|
80 if (Pname == NULL)
|
|
81 Pname = argv[0];
|
|
82 else
|
|
83 Pname++;
|
|
84
|
|
85 while ((retval = getopt(argc, argv, "s:b:c:")) != -1) {
|
|
86 switch (retval) {
|
|
87 case 's':
|
|
88 sb_seen = 1;
|
|
89 tr.emul64_blkrange.emul64_sb = atoll(optarg);
|
|
90 break;
|
|
91 case 'b':
|
|
92 count_seen = 1;
|
|
93 tr.emul64_blkrange.emul64_blkcnt = atoll(optarg);
|
|
94 break;
|
|
95 case 'c':
|
|
96 if (strncmp(optarg, "write_off",
|
|
97 strlen("write_off")) == 0) {
|
|
98 cmd = EMUL64_WRITE_OFF;
|
|
99 } else if (strncmp(optarg, "write_on",
|
|
100 strlen("write_on")) == 0) {
|
|
101 cmd = EMUL64_WRITE_ON;
|
|
102 } else if (strncmp(optarg, "zero",
|
|
103 strlen("zero")) == 0) {
|
|
104 cmd = EMUL64_ZERO_RANGE;
|
|
105 } else {
|
|
106 do_usage = 1;
|
|
107 }
|
|
108 break;
|
|
109 default:
|
|
110 break;
|
|
111 }
|
|
112 }
|
|
113
|
|
114 if (do_usage || (optind != argc - 1)) {
|
|
115 usage();
|
|
116 }
|
|
117 if ((sb_seen == 0) || (count_seen == 0) || (cmd == -1))
|
|
118 usage();
|
|
119
|
|
120 slice = argv[optind];
|
|
121
|
|
122 /*
|
|
123 * Get admin device, target and lun
|
|
124 */
|
|
125 if (get_disk_addr(slice, &tr, &admin) != 0)
|
|
126 exit(1);
|
|
127
|
|
128 /*
|
|
129 * open the specified emul64_dev.
|
|
130 */
|
|
131 if ((fd = open(admin, O_RDONLY, 0444)) != -1) {
|
|
132
|
|
133 retval = ioctl(fd, cmd, &tr);
|
|
134 (void) close(fd);
|
|
135
|
|
136 if (retval != -1) {
|
|
137 free(admin);
|
|
138 return (0);
|
|
139 }
|
|
140 (void) printf("emul64ioctl: %s: ioctl %s\n",
|
|
141 admin, strerror(errno));
|
|
142 } else {
|
|
143 (void) printf("emul64ioctl: %s: open %s\n",
|
|
144 admin, strerror(errno));
|
|
145 }
|
|
146 free(admin);
|
|
147 return (1);
|
|
148 }
|
|
149
|
|
150 #define TOK_CHECK(s) if (token == NULL) {\
|
|
151 bogus = (s);\
|
|
152 goto err_out;\
|
|
153 }
|
|
154
|
|
155 static int
|
|
156 get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin)
|
|
157 {
|
|
158 size_t admin_size;
|
|
159 int ctlr_num;
|
|
160 int conversions;
|
|
161 char *ctds;
|
|
162
|
|
163 *admin = NULL;
|
|
164 ctds = strrchr(path, '/');
|
|
165 if (ctds == NULL)
|
|
166 ctds = path;
|
|
167 else
|
|
168 ctds++;
|
|
169 conversions = sscanf(ctds, "c%dt%hud%hu", &ctlr_num,
|
|
170 &tr->emul64_target, &tr->emul64_lun);
|
|
171 if (conversions != 3) {
|
|
172 (void) fprintf(stderr, "%s: \"%s\" is invalid disk name. "
|
|
173 "%d conversions\n", Pname, ctds, conversions);
|
|
174 return (-1);
|
|
175 }
|
|
176
|
|
177 /* Build controller name */
|
|
178 admin_size = strlen(ADMIN_DIR) +
|
|
179 10 + /* enough digits for an int */
|
|
180 1 + /* c */
|
|
181 1; /* Null terminator */
|
|
182 *admin = malloc(admin_size);
|
|
183 if (*admin == NULL) {
|
|
184 (void) fprintf(stderr, "%s: out of memory\n", Pname);
|
|
185 return (-1);
|
|
186 }
|
|
187 (void) snprintf(*admin, admin_size, "%sc%d", ADMIN_DIR, ctlr_num);
|
|
188 return (0);
|
|
189 }
|