diff options
author | jhb <jhb@FreeBSD.org> | 2016-02-01 23:07:31 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-02-01 23:07:31 +0000 |
commit | 05de7f15435827d273d924fd9d03c09d36bb19b6 (patch) | |
tree | 8ea3c2613bb0dac29850ab9ba9b462ff3ca84571 /lib/libdevctl | |
parent | 90b6006f8d6ccaaaa6ebef08c2fa902a3b796e21 (diff) | |
download | FreeBSD-src-05de7f15435827d273d924fd9d03c09d36bb19b6.zip FreeBSD-src-05de7f15435827d273d924fd9d03c09d36bb19b6.tar.gz |
MFC 278320,278336,278830,285621:
Add devctl(8): a utility for manipulating new-bus devices. Note that
this version does not include the 'suspend' and 'resume' commands
present in HEAD as those depend on larger changes to the suspend and
resume code in the kernel.
278320:
Add a new device control utility for new-bus devices called devctl. This
allows the user to request administrative changes to individual devices
such as attach or detaching drivers or disabling and re-enabling devices.
- Add a new /dev/devctl2 character device which uses ioctls for device
requests. The ioctls use a common 'struct devreq' which is somewhat
similar to 'struct ifreq'.
- The ioctls identify the device to operate on via a string. This
string can either by the device's name, or it can be a bus-specific
address. (For unattached devices, a bus address is the only way to
locate a device.) Bus drivers register an eventhandler to claim
unrecognized device names that the driver recognizes as a valid address.
Two buses currently support addresses: ACPI recognizes any device
in the ACPI namespace via its full path starting with "\" and
the PCI bus driver recognizes an address specification of
'pci[<domain>:]<bus>:<slot>:<func>' (identical to the PCI selector
strings supported by pciconf).
- To make it easier to cut and paste, change the PnP location string
in the PCI bus driver to output a full PCI selector string rather
than 'slot=<slot> function=<func>'.
- Add a devctl(3) interface in libdevctl which provides a wrapper around
the ioctls and is the preferred interface for other userland code.
- Add a devctl(8) program which is a simple wrapper around the requests
supported by devctl(3).
- Add a resource_unset_value() function that can be used to remove a
hint from the kernel environment. This is used to clear a
hint.<driver>.<unit>.disabled hint when re-enabling a boot-time
disabled device.
278336:
Unbreak the build (memchr is explicitly required by devctl(9) after r278320)
278830:
install the man page...
285621:
Fix formatting.
Approved by: re (marius)
Diffstat (limited to 'lib/libdevctl')
-rw-r--r-- | lib/libdevctl/Makefile | 8 | ||||
-rw-r--r-- | lib/libdevctl/devctl.3 | 254 | ||||
-rw-r--r-- | lib/libdevctl/devctl.c | 110 | ||||
-rw-r--r-- | lib/libdevctl/devctl.h | 40 |
4 files changed, 412 insertions, 0 deletions
diff --git a/lib/libdevctl/Makefile b/lib/libdevctl/Makefile new file mode 100644 index 0000000..74687ec --- /dev/null +++ b/lib/libdevctl/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +LIB= devctl +SRCS= devctl.c +INCS= devctl.h +MAN= devctl.3 + +.include <bsd.lib.mk> diff --git a/lib/libdevctl/devctl.3 b/lib/libdevctl/devctl.3 new file mode 100644 index 0000000..b8a84d4 --- /dev/null +++ b/lib/libdevctl/devctl.3 @@ -0,0 +1,254 @@ +.\" +.\" Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd December 26, 2014 +.Dt DEVCTL 3 +.Os +.Sh NAME +.Nm devctl , +.Nm devctl_attach , +.Nm devctl_detach , +.Nm devctl_disable , +.Nm devctl_enable +.Nd device control library +.Sh LIBRARY +.Lb libdevctl +.Sh SYNOPSIS +.In devctl.h +.Ft int +.Fn devctl_attach "const char *device" +.Ft int +.Fn devctl_detach "const char *device" "bool force" +.Ft int +.Fn devctl_disable "const char *device" "bool force_detach" +.Ft int +.Fn devctl_enable "const char *device" +.Ft int +.Fn devctl_set_driver "const char *device" "const char *driver" "bool force" +.Sh DESCRIPTION +The +.Nm +library adjusts the state of devices in the kernel's internal device +hierarchy. +Each control operation accepts a +.Fa device +argument that identifies the device to adjust. +The +.Fa device +may be specified as either the name of an existing device or as a +bus-specific address. +The following bus-specific address formats are currently supported: +.Bl -tag -offset indent +.It Sy pci Ns Fa domain Ns : Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function +A PCI device with the specified +.Fa domain , +.Fa bus , +.Fa slot , +and +.Fa function . +.It Sy pci Ns Fa bus Ns : Ns Fa slot Ns : Ns Fa function +A PCI device in domain zero with the specified +.Fa bus , +.Fa slot , +and +.Fa function . +.It Fa handle +A device with an ACPI handle of +.Fa handle . +The handle must be specified as an absolute path and must begin with a +.Dq \e . +.El +.Pp +The +.Fn devctl_attach +function probes a device and attaches a suitable device driver if one is +found. +.Pp +The +.Fn devctl_detach +function detaches a device from its current device driver. +The device is left detached until either a new driver for its parent +bus is loaded or the device is explicitly probed via +.Fn devctl_attach . +If +.Fa force +is true, +the current device driver will be detached even if the device is busy. +.Pp +The +.Fn devctl_disable +function disables a device. +If the device is currently attached to a device driver, +the device driver will be detached from the device, +but the device will retain its current name. +If +.Fa force_detach +is true, +the current device driver will be detached even if the device is busy. +The device will remain disabled and detached until it is explicitly enabled +via +.Fn devctl_enable . +.Pp +The +.Fn devctl_enable +function re-enables a disabled device. +The device will probe and attach if a suitable device driver is found. +.Pp +The +.Fn devctl_set_driver +function attaches a device driver named +.Fa driver +to a device. +If the device is already attached and +.Fa force +is false, +the request will fail. +If the device is already attached and +.Fa force +is true, +the device will be detached from its current device driver before it is +attached to the new device driver. +.Sh RETURN VALUES +.Rv -std devctl_attach devctl_detach devctl_disable devctl_enable \ +devctl_set_driver +.Sh ERRORS +In addition to specific errors noted below, +all of the +.Nm +functions may fail for any of the errors described in +.Xr open 2 +as well as: +.Bl -tag -width Er +.It Bq Er EINVAL +The device name is too long. +.It Bq Er ENOENT +No existing device matches the specified name or location. +.It Bq Er EPERM +The current process is not permitted to adjust the state of +.Fa device . +.El +.Pp +The +.Fn devctl_attach +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The device is already attached. +.It Bq Er ENOMEM +An internal memory allocation request failed. +.It Bq Er ENXIO +The device is disabled. +.It Bq Er ENXIO +No suitable driver for the device could be found, +or the driver failed to attach. +.El +.Pp +The +.Fn devctl_detach +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The current device driver for +.Fa device +is busy and cannot detach at this time. +Note that some drivers may return this even if +.Fa force +is true. +.It Bq Er ENXIO +The device is not attached to a driver. +.It Bq Er ENXIO +The current device driver for +.Fa device +does not support detaching. +.El +.Pp +The +.Fn devctl_enable +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The device is already enabled. +.It Bq Er ENOMEM +An internal memory allocation request failed. +.It Bq Er ENXIO +No suitable driver for the device could be found, +or the driver failed to attach. +.El +.Pp +The +.Fn devctl_disable +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The current device driver for +.Fa device +is busy and cannot detach at this time. +Note that some drivers may return this even if +.Fa force_detach +is true. +.It Bq Er ENXIO +The device is already disabled. +.It Bq Er ENXIO +The current device driver for +.Fa device +does not support detaching. +.El +.Pp +The +.Fn devctl_set_driver +function may fail if: +.Bl -tag -width Er +.It Bq Er EBUSY +The device is currently attached to a device driver and +.Fa force +is false. +.It Bq Er EBUSY +The current device driver for +.Fa device +is busy and cannot detach at this time. +.It Bq Er EFAULT +The +.Fa driver +argument points outside the process' allocated address space. +.It Bq Er ENOENT +No device driver with the requested name exists. +.It Bq Er ENOMEM +An internal memory allocation request failed. +.It Bq Er ENXIO +The device is disabled. +.It Bq Er ENXIO +The new device driver failed to attach. +.El +.Sh SEE ALSO +.Xr devinfo 3 , +.Xr devstat 3 , +.Xr devctl 8 +.Sh HISTORY +The +.Nm +library first appeared in +.Fx 11.0 . diff --git a/lib/libdevctl/devctl.c b/lib/libdevctl/devctl.c new file mode 100644 index 0000000..fa0e6a5 --- /dev/null +++ b/lib/libdevctl/devctl.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/bus.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include "devctl.h" + +static int +devctl_request(u_long cmd, struct devreq *req) +{ + static int devctl2_fd = -1; + + if (devctl2_fd == -1) { + devctl2_fd = open("/dev/devctl2", O_RDONLY); + if (devctl2_fd == -1) + return (-1); + } + return (ioctl(devctl2_fd, cmd, req)); +} + +static int +devctl_simple_request(u_long cmd, const char *name, int flags) +{ + struct devreq req; + + memset(&req, 0, sizeof(req)); + if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >= + sizeof(req.dr_name)) { + errno = EINVAL; + return (-1); + } + req.dr_flags = flags; + return (devctl_request(cmd, &req)); +} + +int +devctl_attach(const char *device) +{ + + return (devctl_simple_request(DEV_ATTACH, device, 0)); +} + +int +devctl_detach(const char *device, bool force) +{ + + return (devctl_simple_request(DEV_DETACH, device, force ? + DEVF_FORCE_DETACH : 0)); +} + +int +devctl_enable(const char *device) +{ + + return (devctl_simple_request(DEV_ENABLE, device, 0)); +} + +int +devctl_disable(const char *device, bool force_detach) +{ + + return (devctl_simple_request(DEV_DISABLE, device, force_detach ? + DEVF_FORCE_DETACH : 0)); +} + +int +devctl_set_driver(const char *device, const char *driver, bool force) +{ + struct devreq req; + + memset(&req, 0, sizeof(req)); + if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >= + sizeof(req.dr_name)) { + errno = EINVAL; + return (-1); + } + req.dr_data = __DECONST(char *, driver); + if (force) + req.dr_flags |= DEVF_SET_DRIVER_DETACH; + return (devctl_request(DEV_SET_DRIVER, &req)); +} diff --git a/lib/libdevctl/devctl.h b/lib/libdevctl/devctl.h new file mode 100644 index 0000000..3426cce --- /dev/null +++ b/lib/libdevctl/devctl.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __DEVCTL_H__ +#define __DEVCTL_H__ + +#include <stdbool.h> + +int devctl_attach(const char *device); +int devctl_detach(const char *device, bool force); +int devctl_enable(const char *device); +int devctl_disable(const char *device, bool force_detach); +int devctl_set_driver(const char *device, const char *driver, bool force); + +#endif /* !__DEVCTL_H__ */ |