devctl.c revision 278320
1278320Sjhb/*-
2278320Sjhb * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
3278320Sjhb * All rights reserved.
4278320Sjhb *
5278320Sjhb * Redistribution and use in source and binary forms, with or without
6278320Sjhb * modification, are permitted provided that the following conditions
7278320Sjhb * are met:
8278320Sjhb * 1. Redistributions of source code must retain the above copyright
9278320Sjhb *    notice, this list of conditions and the following disclaimer.
10278320Sjhb * 2. Redistributions in binary form must reproduce the above copyright
11278320Sjhb *    notice, this list of conditions and the following disclaimer in the
12278320Sjhb *    documentation and/or other materials provided with the distribution.
13278320Sjhb *
14278320Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15278320Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16278320Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17278320Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18278320Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19278320Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20278320Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21278320Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22278320Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23278320Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24278320Sjhb * SUCH DAMAGE.
25278320Sjhb */
26278320Sjhb
27278320Sjhb#include <sys/cdefs.h>
28278320Sjhb__FBSDID("$FreeBSD: head/lib/libdevctl/devctl.c 278320 2015-02-06 16:09:01Z jhb $");
29278320Sjhb
30278320Sjhb#include <sys/types.h>
31278320Sjhb#include <sys/bus.h>
32278320Sjhb#include <errno.h>
33278320Sjhb#include <fcntl.h>
34278320Sjhb#include <string.h>
35278320Sjhb#include "devctl.h"
36278320Sjhb
37278320Sjhbstatic int
38278320Sjhbdevctl_request(u_long cmd, struct devreq *req)
39278320Sjhb{
40278320Sjhb	static int devctl2_fd = -1;
41278320Sjhb
42278320Sjhb	if (devctl2_fd == -1) {
43278320Sjhb		devctl2_fd = open("/dev/devctl2", O_RDONLY);
44278320Sjhb		if (devctl2_fd == -1)
45278320Sjhb			return (-1);
46278320Sjhb	}
47278320Sjhb	return (ioctl(devctl2_fd, cmd, req));
48278320Sjhb}
49278320Sjhb
50278320Sjhbstatic int
51278320Sjhbdevctl_simple_request(u_long cmd, const char *name, int flags)
52278320Sjhb{
53278320Sjhb	struct devreq req;
54278320Sjhb
55278320Sjhb	memset(&req, 0, sizeof(req));
56278320Sjhb	if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >=
57278320Sjhb	    sizeof(req.dr_name)) {
58278320Sjhb		errno = EINVAL;
59278320Sjhb		return (-1);
60278320Sjhb	}
61278320Sjhb	req.dr_flags = flags;
62278320Sjhb	return (devctl_request(cmd, &req));
63278320Sjhb}
64278320Sjhb
65278320Sjhbint
66278320Sjhbdevctl_attach(const char *device)
67278320Sjhb{
68278320Sjhb
69278320Sjhb	return (devctl_simple_request(DEV_ATTACH, device, 0));
70278320Sjhb}
71278320Sjhb
72278320Sjhbint
73278320Sjhbdevctl_detach(const char *device, bool force)
74278320Sjhb{
75278320Sjhb
76278320Sjhb	return (devctl_simple_request(DEV_DETACH, device, force ?
77278320Sjhb	    DEVF_FORCE_DETACH : 0));
78278320Sjhb}
79278320Sjhb
80278320Sjhbint
81278320Sjhbdevctl_enable(const char *device)
82278320Sjhb{
83278320Sjhb
84278320Sjhb	return (devctl_simple_request(DEV_ENABLE, device, 0));
85278320Sjhb}
86278320Sjhb
87278320Sjhbint
88278320Sjhbdevctl_disable(const char *device, bool force_detach)
89278320Sjhb{
90278320Sjhb
91278320Sjhb	return (devctl_simple_request(DEV_DISABLE, device, force_detach ?
92278320Sjhb	    DEVF_FORCE_DETACH : 0));
93278320Sjhb}
94278320Sjhb
95278320Sjhbint
96278320Sjhbdevctl_suspend(const char *device)
97278320Sjhb{
98278320Sjhb
99278320Sjhb	return (devctl_simple_request(DEV_SUSPEND, device, 0));
100278320Sjhb}
101278320Sjhb
102278320Sjhbint
103278320Sjhbdevctl_resume(const char *device)
104278320Sjhb{
105278320Sjhb
106278320Sjhb	return (devctl_simple_request(DEV_RESUME, device, 0));
107278320Sjhb}
108278320Sjhb
109278320Sjhbint
110278320Sjhbdevctl_set_driver(const char *device, const char *driver, bool force)
111278320Sjhb{
112278320Sjhb	struct devreq req;
113278320Sjhb
114278320Sjhb	memset(&req, 0, sizeof(req));
115278320Sjhb	if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
116278320Sjhb	    sizeof(req.dr_name)) {
117278320Sjhb		errno = EINVAL;
118278320Sjhb		return (-1);
119278320Sjhb	}
120278320Sjhb	req.dr_data = __DECONST(char *, driver);
121278320Sjhb	if (force)
122278320Sjhb		req.dr_flags |= DEVF_SET_DRIVER_DETACH;
123278320Sjhb	return (devctl_request(DEV_SET_DRIVER, &req));
124278320Sjhb}
125