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.
34 #include <libdevice.h>
35 #include <libdevinfo.h>
37 #include <sys/dditypes.h>
38 #include <sys/devctl.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
51 #define BOFI_OFFLINE 1
52 #define BOFI_GETSTATE 2
53 #define BOFI_GETPATH 3
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}
74 main(int argc
, char **argv
)
76 struct bofi_errctl errctl
;
77 struct bofi_get_handles get_handles
;
79 int devctl_command
= -1;
84 char path
[MAXPATHLEN
];
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
) {
102 if (getnameinst(argv
[1], &errctl
.instance
, buf
,
104 (void) fprintf(stderr
,
105 "th_manage - invalid path\n");
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
) {
126 (void) strcpy(path
, "/devices/");
127 if (getpath(&path
[8], errctl
.instance
, errctl
.name
,
129 (void) fprintf(stderr
,
130 "th_manage - invalid name/instance\n");
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");
147 * might have been a devctl command
149 if (devctl_command
== BOFI_ONLINE
) {
150 while (online_device(path
) != 0) {
155 if (devctl_command
== BOFI_OFFLINE
) {
156 while (offline_device(path
) != 0) {
161 if (devctl_command
== BOFI_GETSTATE
) {
162 if (getstate_device(path
) != 0) {
163 perror("th_manage - getstate failed");
169 if (devctl_command
== BOFI_GETPATH
) {
170 (void) fprintf(stdout
, "%s\n", path
);
173 (void) fprintf(stderr
,
174 "th_manage: invalid command\n");
175 (void) fprintf(stderr
,
176 " Command must be one of start, stop, broadcast, "
178 (void) fprintf(stderr
,
179 " clear_acc_chk, clear_errors or clear_errdefs\n");
182 fd
= open("/devices/pseudo/bofi@0:bofi,ctl", O_RDWR
);
184 perror("th_manage - open of bofi driver");
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");
197 buffer
[sizeof (buffer
) - 1] = '\0';
198 (void) fprintf(stdout
, "%s", buffer
);
199 (void) fflush(stdout
);
202 if (errctl
.instance
== -1) {
203 struct bofi_get_hdl_info hdli
;
204 struct handle_info
*hip
, *hp
;
207 hdli
.namesize
= errctl
.namesize
;
208 (void) strncpy(hdli
.name
, errctl
.name
, MAXNAMELEN
);
212 * Ask the bofi driver for all handles created by the driver
215 if (ioctl(fd
, BOFI_GET_HANDLE_INFO
, &hdli
) == -1) {
216 perror("driver failed to return access handles");
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");
227 hdli
.hdli
= (caddr_t
)hip
;
228 if (ioctl(fd
, BOFI_GET_HANDLE_INFO
, &hdli
) == -1) {
229 perror("couldn't obtain all handles");
232 if ((instp
= malloc((hdli
.count
+ 1) * sizeof (*instp
))) == 0) {
233 perror("out of memory");
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
])
241 if (instp
[j
] == -1) {
242 instp
[j
] = hp
->instance
;
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
));
256 if (ioctl(fd
, command
, &errctl
) == -1) {
257 perror("th_manage - setting state failed");
266 * These functions provide access to the devctl functions,
269 online_device(char *path
)
273 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
276 if ((devctl_device_online(dcp
)) == -1) {
286 offline_device(char *path
)
290 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
293 if ((devctl_device_offline(dcp
)) == -1) {
302 getstate_device(char *path
)
307 if ((dcp
= devctl_device_acquire(path
, 0)) == NULL
) {
308 (void) printf("%s unknown unknown\n", path
);
311 if ((devctl_device_getstate(dcp
, &state
)) == -1) {
312 (void) printf("%s unknown unknown\n", path
);
319 (void) printf("%s down not_busy\n", path
);
322 (void) printf("%s offline not_busy\n", path
);
325 (void) printf("%s online not_busy\n", path
);
327 case (DEVICE_ONLINE
| DEVICE_BUSY
):
328 (void) printf("%s online busy\n", path
);
330 case (DEVICE_DOWN
| DEVICE_BUSY
):
331 (void) printf("%s down busy\n", path
);
334 (void) printf("%s unknown unknown\n", path
);
341 getnameinst(char *path
, int *instance
, char *name
, int namelen
)
346 if ((node
= di_init(&path
[8], DINFOSUBTREE
)) == DI_NODE_NIL
)
348 if ((driver_name
= di_driver_name(node
)) == NULL
) {
352 *instance
= di_instance(node
);
353 (void) strncpy(name
, driver_name
, namelen
);
361 char name
[MAXPATHLEN
];
367 walk_callback(di_node_t node
, void *arg
)
369 struct walk_arg
*warg
= (struct walk_arg
*)arg
;
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
);
380 (void) strncpy(warg
->path
, path
, warg
->pathlen
);
382 return (DI_WALK_TERMINATE
);
385 return (DI_WALK_CONTINUE
);
389 getpath(char *path
, int instance
, char *name
, int pathlen
)
392 struct walk_arg warg
;
394 warg
.instance
= instance
;
395 (void) strncpy(warg
.name
, name
, MAXPATHLEN
);
397 warg
.pathlen
= pathlen
;
399 if ((node
= di_init("/", DINFOSUBTREE
)) == DI_NODE_NIL
)
401 if (di_walk_node(node
, DI_WALK_CLDFIRST
, &warg
, walk_callback
) == -1) {
405 if (warg
.found
== 0) {