xref: /titanic_51/usr/src/cmd/emul64ioctl/emul64ioctl.c (revision b1dd958f54f8bfa984d306bb8ca8264855761d7b)
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