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
usage(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
main(int argc,char ** argv)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
get_disk_addr(char * path,emul64_tgt_range_t * tr,char ** admin)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