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: stable/10/lib/libdevctl/devctl.c 306533 2016-09-30 22:05:47Z 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_set_driver(const char *device, const char *driver, bool force)
97278320Sjhb{
98278320Sjhb	struct devreq req;
99278320Sjhb
100278320Sjhb	memset(&req, 0, sizeof(req));
101278320Sjhb	if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
102278320Sjhb	    sizeof(req.dr_name)) {
103278320Sjhb		errno = EINVAL;
104278320Sjhb		return (-1);
105278320Sjhb	}
106278320Sjhb	req.dr_data = __DECONST(char *, driver);
107278320Sjhb	if (force)
108278320Sjhb		req.dr_flags |= DEVF_SET_DRIVER_DETACH;
109278320Sjhb	return (devctl_request(DEV_SET_DRIVER, &req));
110278320Sjhb}
111306533Sjhb
112306533Sjhbint
113306533Sjhbdevctl_clear_driver(const char *device, bool force)
114306533Sjhb{
115306533Sjhb
116306533Sjhb	return (devctl_simple_request(DEV_CLEAR_DRIVER, device, force ?
117306533Sjhb	    DEVF_CLEAR_DRIVER_DETACH : 0));
118306533Sjhb}
119