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