dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / th_tools / th_manage.c
blobff28e909c503619646f2647270f54c079208fa4b
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <libdevice.h>
35 #include <libdevinfo.h>
36 #define _KERNEL
37 #include <sys/dditypes.h>
38 #include <sys/devctl.h>
39 #include <sys/bofi.h>
41 static int online_device(char *path);
42 static int offline_device(char *path);
43 static int getstate_device(char *path);
44 static int getnameinst(char *path, int *instance, char *name, int namelen);
45 static int getpath(char *path, int instance, char *name, int pathlen);
47 static char buffer[50*1024];
49 #define CMD_TABLE_SIZE 11
50 #define BOFI_ONLINE 0
51 #define BOFI_OFFLINE 1
52 #define BOFI_GETSTATE 2
53 #define BOFI_GETPATH 3
55 static struct {
56 char *string;
57 int val;
58 int devctl_val;
59 } cmd_table[] = {
60 {"online", -1, BOFI_ONLINE},
61 {"offline", -1, BOFI_OFFLINE},
62 {"getstate", -1, BOFI_GETSTATE},
63 {"getpath", -1, BOFI_GETPATH},
64 {"broadcast", BOFI_BROADCAST, -1},
65 {"clear_acc_chk", BOFI_CLEAR_ACC_CHK, -1},
66 {"clear_errors", BOFI_CLEAR_ERRORS, -1},
67 {"clear_errdefs", BOFI_CLEAR_ERRDEFS, -1},
68 {"start", BOFI_START, -1},
69 {"stop", BOFI_STOP, -1},
70 {"get_handles", BOFI_GET_HANDLES, -1}
73 int
74 main(int argc, char **argv)
76 struct bofi_errctl errctl;
77 struct bofi_get_handles get_handles;
78 int command = -1;
79 int devctl_command = -1;
80 int i;
81 int fd;
83 char buf[MAXPATHLEN];
84 char path[MAXPATHLEN];
86 if (argc == 3) {
87 (void) strncpy(path, argv[1], MAXPATHLEN);
89 for (i = 0; i < CMD_TABLE_SIZE; i++) {
90 if (strcmp(argv[2], cmd_table[i].string) == 0) {
91 command = cmd_table[i].val;
92 devctl_command = cmd_table[i].devctl_val;
95 switch (devctl_command) {
96 case BOFI_ONLINE:
97 case BOFI_OFFLINE:
98 case BOFI_GETPATH:
99 case BOFI_GETSTATE:
100 break;
101 default:
102 if (getnameinst(argv[1], &errctl.instance, buf,
103 MAXPATHLEN) == -1) {
104 (void) fprintf(stderr,
105 "th_manage - invalid path\n");
106 exit(1);
108 (void) strncpy(errctl.name, buf, MAXNAMELEN);
109 errctl.namesize = strlen(errctl.name);
111 } else if (argc == 4) {
112 errctl.namesize = strlen(argv[1]);
113 (void) strncpy(errctl.name, argv[1], MAXNAMELEN);
114 errctl.instance = atoi(argv[2]);
115 for (i = 0; i < CMD_TABLE_SIZE; i++) {
116 if (strcmp(argv[3], cmd_table[i].string) == 0) {
117 command = cmd_table[i].val;
118 devctl_command = cmd_table[i].devctl_val;
121 switch (devctl_command) {
122 case BOFI_ONLINE:
123 case BOFI_OFFLINE:
124 case BOFI_GETPATH:
125 case BOFI_GETSTATE:
126 (void) strcpy(path, "/devices/");
127 if (getpath(&path[8], errctl.instance, errctl.name,
128 MAXPATHLEN) == -1) {
129 (void) fprintf(stderr,
130 "th_manage - invalid name/instance\n");
131 exit(1);
133 default:
134 break;
136 } else {
137 (void) fprintf(stderr, "usage:\n");
138 (void) fprintf(stderr,
139 " th_manage name instance state\n");
140 (void) fprintf(stderr,
141 " th_manage path state\n");
142 exit(2);
145 if (command == -1) {
147 * might have been a devctl command
149 if (devctl_command == BOFI_ONLINE) {
150 while (online_device(path) != 0) {
151 (void) sleep(3);
153 exit(0);
155 if (devctl_command == BOFI_OFFLINE) {
156 while (offline_device(path) != 0) {
157 (void) sleep(3);
159 exit(0);
161 if (devctl_command == BOFI_GETSTATE) {
162 if (getstate_device(path) != 0) {
163 perror("th_manage - getstate failed");
164 exit(1);
165 } else {
166 exit(0);
169 if (devctl_command == BOFI_GETPATH) {
170 (void) fprintf(stdout, "%s\n", path);
171 exit(0);
173 (void) fprintf(stderr,
174 "th_manage: invalid command\n");
175 (void) fprintf(stderr,
176 " Command must be one of start, stop, broadcast, "
177 "get_handles,\n");
178 (void) fprintf(stderr,
179 " clear_acc_chk, clear_errors or clear_errdefs\n");
180 exit(2);
182 fd = open("/devices/pseudo/bofi@0:bofi,ctl", O_RDWR);
183 if (fd == -1) {
184 perror("th_manage - open of bofi driver");
185 exit(2);
187 if (command == BOFI_GET_HANDLES) {
188 get_handles.namesize = errctl.namesize;
189 (void) strncpy(get_handles.name, errctl.name, MAXNAMELEN);
190 get_handles.instance = errctl.instance;
191 get_handles.buffer = buffer;
192 get_handles.count = sizeof (buffer) - 1;
193 if (ioctl(fd, command, &get_handles) == -1) {
194 perror("th_manage - setting state failed");
195 exit(2);
197 buffer[sizeof (buffer) - 1] = '\0';
198 (void) fprintf(stdout, "%s", buffer);
199 (void) fflush(stdout);
200 exit(0);
202 if (errctl.instance == -1) {
203 struct bofi_get_hdl_info hdli;
204 struct handle_info *hip, *hp;
205 int i, j, *instp;
207 hdli.namesize = errctl.namesize;
208 (void) strncpy(hdli.name, errctl.name, MAXNAMELEN);
209 hdli.hdli = 0;
210 hdli.count = 0;
212 * Ask the bofi driver for all handles created by the driver
213 * under test.
215 if (ioctl(fd, BOFI_GET_HANDLE_INFO, &hdli) == -1) {
216 perror("driver failed to return access handles");
217 exit(1);
219 if (hdli.count == 0) {
220 exit(0); /* no handles */
222 if ((hip = memalign(sizeof (void *),
223 hdli.count * sizeof (*hip))) == 0) {
224 perror("out of memory");
225 exit(1);
227 hdli.hdli = (caddr_t)hip;
228 if (ioctl(fd, BOFI_GET_HANDLE_INFO, &hdli) == -1) {
229 perror("couldn't obtain all handles");
230 exit(1);
232 if ((instp = malloc((hdli.count + 1) * sizeof (*instp))) == 0) {
233 perror("out of memory");
234 exit(1);
236 *instp = -1;
237 for (i = 0, hp = hip; i < hdli.count; hp++, i++) {
238 for (j = 0; instp[j] != -1; j++)
239 if (hp->instance == instp[j])
240 break;
241 if (instp[j] == -1) {
242 instp[j] = hp->instance;
243 instp[j+1] = -1;
246 for (i = 0; instp[i] != -1; i++) {
247 errctl.instance = instp[i];
248 if (ioctl(fd, command, &errctl) == -1) {
249 (void) fprintf(stderr,
250 "command failed on instance %d : %s\n",
251 errctl.instance, strerror(errno));
252 exit(1);
255 } else {
256 if (ioctl(fd, command, &errctl) == -1) {
257 perror("th_manage - setting state failed");
258 exit(1);
261 return (0);
266 * These functions provide access to the devctl functions,
268 static int
269 online_device(char *path)
271 devctl_hdl_t dcp;
273 if ((dcp = devctl_device_acquire(path, 0)) == NULL) {
274 return (-1);
276 if ((devctl_device_online(dcp)) == -1) {
277 devctl_release(dcp);
278 return (-1);
280 devctl_release(dcp);
281 return (0);
285 static int
286 offline_device(char *path)
288 devctl_hdl_t dcp;
290 if ((dcp = devctl_device_acquire(path, 0)) == NULL) {
291 return (-1);
293 if ((devctl_device_offline(dcp)) == -1) {
294 devctl_release(dcp);
295 return (-1);
297 devctl_release(dcp);
298 return (0);
301 static int
302 getstate_device(char *path)
304 devctl_hdl_t dcp;
305 uint_t state = 0;
307 if ((dcp = devctl_device_acquire(path, 0)) == NULL) {
308 (void) printf("%s unknown unknown\n", path);
309 return (-1);
311 if ((devctl_device_getstate(dcp, &state)) == -1) {
312 (void) printf("%s unknown unknown\n", path);
313 devctl_release(dcp);
314 return (-1);
316 devctl_release(dcp);
317 switch (state) {
318 case DEVICE_DOWN:
319 (void) printf("%s down not_busy\n", path);
320 break;
321 case DEVICE_OFFLINE:
322 (void) printf("%s offline not_busy\n", path);
323 break;
324 case DEVICE_ONLINE:
325 (void) printf("%s online not_busy\n", path);
326 break;
327 case (DEVICE_ONLINE | DEVICE_BUSY):
328 (void) printf("%s online busy\n", path);
329 break;
330 case (DEVICE_DOWN | DEVICE_BUSY):
331 (void) printf("%s down busy\n", path);
332 break;
333 default:
334 (void) printf("%s unknown unknown\n", path);
335 break;
337 return (0);
340 static int
341 getnameinst(char *path, int *instance, char *name, int namelen)
343 di_node_t node;
344 char *driver_name;
346 if ((node = di_init(&path[8], DINFOSUBTREE)) == DI_NODE_NIL)
347 return (-1);
348 if ((driver_name = di_driver_name(node)) == NULL) {
349 di_fini(node);
350 return (-1);
352 *instance = di_instance(node);
353 (void) strncpy(name, driver_name, namelen);
354 di_fini(node);
355 return (0);
358 struct walk_arg {
359 char *path;
360 int instance;
361 char name[MAXPATHLEN];
362 int found;
363 int pathlen;
366 static int
367 walk_callback(di_node_t node, void *arg)
369 struct walk_arg *warg = (struct walk_arg *)arg;
370 char *driver_name;
371 char *path;
373 driver_name = di_driver_name(node);
374 if (driver_name != NULL) {
375 if (strcmp(driver_name, warg->name) == 0 &&
376 di_instance(node) == warg->instance) {
377 path = di_devfs_path(node);
378 if (path != NULL) {
379 warg->found = 1;
380 (void) strncpy(warg->path, path, warg->pathlen);
382 return (DI_WALK_TERMINATE);
385 return (DI_WALK_CONTINUE);
388 static int
389 getpath(char *path, int instance, char *name, int pathlen)
391 di_node_t node;
392 struct walk_arg warg;
394 warg.instance = instance;
395 (void) strncpy(warg.name, name, MAXPATHLEN);
396 warg.path = path;
397 warg.pathlen = pathlen;
398 warg.found = 0;
399 if ((node = di_init("/", DINFOSUBTREE)) == DI_NODE_NIL)
400 return (-1);
401 if (di_walk_node(node, DI_WALK_CLDFIRST, &warg, walk_callback) == -1) {
402 di_fini(node);
403 return (-1);
405 if (warg.found == 0) {
406 di_fini(node);
407 return (-1);
409 di_fini(node);
410 return (0);