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
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]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include <libdevice.h>
37 #include <libdevinfo.h>
39 #include <sys/dditypes.h>
40 #include <sys/devctl.h>
43 static int online_device(char *path
);
44 static int offline_device(char *path
);
45 static int getstate_device(char *path
);
46 static int getnameinst(char *path
, int *instance
, char *name
, int namelen
);
47 static int getpath(char *path
, int instance
, char *name
, int pathlen
);
49 static char buffer
[50*1024];
51 #define CMD_TABLE_SIZE 11
53 #define BOFI_OFFLINE 1
54 #define BOFI_GETSTATE 2
55 #define BOFI_GETPATH 3
62 {"online", -1, BOFI_ONLINE
},
63 {"offline", -1, BOFI_OFFLINE
},
64 {"getstate", -1, BOFI_GETSTATE
},
65 {"getpath", -1, BOFI_GETPATH
},
66 {"broadcast", BOFI_BROADCAST
, -1},
67 {"clear_acc_chk", BOFI_CLEAR_ACC_CHK
, -1},
68 {"clear_errors", BOFI_CLEAR_ERRORS
, -1},
69 {"clear_errdefs", BOFI_CLEAR_ERRDEFS
, -1},
70 {"start", BOFI_START
, -1},
71 {"stop", BOFI_STOP
, -1},
72 {"get_handles", BOFI_GET_HANDLES
, -1}
76 main(int argc
, char **argv
)
78 struct bofi_errctl errctl
;
79 struct bofi_get_handles get_handles
;
81 int devctl_command
= -1;
86 char path
[MAXPATHLEN
];
89 (void) strncpy(path
, argv
[1], MAXPATHLEN
);
91 for (i
= 0; i
< CMD_TABLE_SIZE
; i
++) {
92 if (strcmp(argv
[2], cmd_table
[i
].string
) == NULL
) {
93 command
= cmd_table
[i
].val
;
94 devctl_command
= cmd_table
[i
].devctl_val
;
97 switch (devctl_command
) {
104 if (getnameinst(argv
[1], &errctl
.instance
, buf
,
106 (void) fprintf(stderr
,
107 "th_manage - invalid path\n");
110 (void) strncpy(errctl
.name
, buf
, MAXNAMELEN
);
111 errctl
.namesize
= strlen(errctl
.name
);
113 } else if (argc
== 4) {
114 errctl
.namesize
= strlen(argv
[1]);
115 (void) strncpy(errctl
.name
, argv
[1], MAXNAMELEN
);
116 errctl
.instance
= atoi(argv
[2]);
117 for (i
= 0; i
< CMD_TABLE_SIZE
; i
++) {
118 if (strcmp(argv
[3], cmd_table
[i
].string
) == NULL
) {
119 command
= cmd_table
[i
].val
;
120 devctl_command
= cmd_table
[i
].devctl_val
;
123 switch (devctl_command
) {
128 (void) strcpy(path
, "/devices/");
129 if (getpath(&path
[8], errctl
.instance
, errctl
.name
,
131 (void) fprintf(stderr
,
132 "th_manage - invalid name/instance\n");
139 (void) fprintf(stderr
, "usage:\n");
140 (void) fprintf(stderr
,
141 " th_manage name instance state\n");
142 (void) fprintf(stderr
,
143 " th_manage path state\n");
149 * might have been a devctl command
151 if (devctl_command
== BOFI_ONLINE
) {
152 while (online_device(path
) != 0) {
157 if (devctl_command
== BOFI_OFFLINE
) {
158 while (offline_device(path
) != 0) {
163 if (devctl_command
== BOFI_GETSTATE
) {
164 if (getstate_device(path
) != 0) {
165 perror("th_manage - getstate failed");
171 if (devctl_command
== BOFI_GETPATH
) {
172 (void) fprintf(stdout
, "%s\n", path
);
175 (void) fprintf(stderr
,
176 "th_manage: invalid command\n");
177 (void) fprintf(stderr
,
178 " Command must be one of start, stop, broadcast, "
180 (void) fprintf(stderr
,
181 " clear_acc_chk, clear_errors or clear_errdefs\n");
184 fd
= open("/devices/pseudo/bofi@0:bofi,ctl", O_RDWR
);
186 perror("th_manage - open of bofi driver");
189 if (command
== BOFI_GET_HANDLES
) {
190 get_handles
.namesize
= errctl
.namesize
;
191 (void) strncpy(get_handles
.name
, errctl
.name
, MAXNAMELEN
);
192 get_handles
.instance
= errctl
.instance
;
193 get_handles
.buffer
= buffer
;
194 get_handles
.count
= sizeof (buffer
) - 1;
195 if (ioctl(fd
, command
, &get_handles
) == -1) {
196 perror("th_manage - setting state failed");
199 buffer
[sizeof (buffer
) - 1] = '\0';
200 (void) fprintf(stdout
, "%s", buffer
);
201 (void) fflush(stdout
);
204 if (errctl
.instance
== -1) {
205 struct bofi_get_hdl_info hdli
;
206 struct handle_info
*hip
, *hp
;
209 hdli
.namesize
= errctl
.namesize
;
210 (void) strncpy(hdli
.name
, errctl
.name
, MAXNAMELEN
);
214 * Ask the bofi driver for all handles created by the driver
217 if (ioctl(fd
, BOFI_GET_HANDLE_INFO
, &hdli
) == -1) {
218 perror("driver failed to return access handles");
221 if (hdli
.count
== 0) {
222 exit(0); /* no handles */
224 if ((hip
= memalign(sizeof (void *),
225 hdli
.count
* sizeof (*hip
))) == 0) {
226 perror("out of memory");
229 hdli
.hdli
= (caddr_t
)hip
;
230 if (ioctl(fd
, BOFI_GET_HANDLE_INFO
, &hdli
) == -1) {
231 perror("couldn't obtain all handles");
234 if ((instp
= malloc((hdli
.count
+ 1) * sizeof (*instp
))) == 0) {
235 perror("out of memory");
239 for (i
= 0, hp
= hip
; i
< hdli
.count
; hp
++, i
++) {
240 for (j
= 0; instp
[j
] != -1; j
++)
241 if (hp
->instance
== instp
[j
])
243 if (instp
[j
] == -1) {
244 instp
[j
] = hp
->instance
;
248 for (i
= 0; instp
[i
] != -1; i
++) {
249 errctl
.instance
= instp
[i
];
250 if (ioctl(fd
, command
, &errctl
) == -1) {
251 (void) fprintf(stderr
,
252 "command failed on instance %d : %s\n",
253 errctl
.instance
, strerror(errno
));
258 if (ioctl(fd
, command
, &errctl
) == -1) {
259 perror("th_manage - setting state failed");
268 * These functions provide access to the devctl functions,
271 online_device(char *path
)
275 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
278 if ((devctl_device_online(dcp
)) == -1) {
288 offline_device(char *path
)
292 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
295 if ((devctl_device_offline(dcp
)) == -1) {
304 getstate_device(char *path
)
309 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
310 (void) printf("%s unknown unknown\n", path
);
313 if ((devctl_device_getstate(dcp
, &state
)) == -1) {
314 (void) printf("%s unknown unknown\n", path
);
321 (void) printf("%s down not_busy\n", path
);
324 (void) printf("%s offline not_busy\n", path
);
327 (void) printf("%s online not_busy\n", path
);
329 case (DEVICE_ONLINE
| DEVICE_BUSY
):
330 (void) printf("%s online busy\n", path
);
332 case (DEVICE_DOWN
| DEVICE_BUSY
):
333 (void) printf("%s down busy\n", path
);
336 (void) printf("%s unknown unknown\n", path
);
343 getnameinst(char *path
, int *instance
, char *name
, int namelen
)
348 if ((node
= di_init(&path
[8], DINFOSUBTREE
)) == DI_NODE_NIL
)
350 if ((driver_name
= di_driver_name(node
)) == NULL
) {
354 *instance
= di_instance(node
);
355 (void) strncpy(name
, driver_name
, namelen
);
363 char name
[MAXPATHLEN
];
369 walk_callback(di_node_t node
, void *arg
)
371 struct walk_arg
*warg
= (struct walk_arg
*)arg
;
375 driver_name
= di_driver_name(node
);
376 if (driver_name
!= NULL
) {
377 if (strcmp(driver_name
, warg
->name
) == 0 &&
378 di_instance(node
) == warg
->instance
) {
379 path
= di_devfs_path(node
);
382 (void) strncpy(warg
->path
, path
, warg
->pathlen
);
384 return (DI_WALK_TERMINATE
);
387 return (DI_WALK_CONTINUE
);
391 getpath(char *path
, int instance
, char *name
, int pathlen
)
394 struct walk_arg warg
;
396 warg
.instance
= instance
;
397 (void) strncpy(warg
.name
, name
, MAXPATHLEN
);
399 warg
.pathlen
= pathlen
;
401 if ((node
= di_init("/", DINFOSUBTREE
)) == DI_NODE_NIL
)
403 if (di_walk_node(node
, DI_WALK_CLDFIRST
, &warg
, walk_callback
) == -1) {
407 if (warg
.found
== 0) {