Author: jhb
Date: Mon Feb  1 23:07:31 2016
New Revision: 295131
URL: https://svnweb.freebsd.org/changeset/base/295131

Log:
  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)

Added:
  stable/10/lib/libdevctl/
     - copied from r278320, head/lib/libdevctl/
  stable/10/usr.sbin/devctl/
     - copied from r278320, head/usr.sbin/devctl/
Modified:
  stable/10/contrib/mdocml/lib.in
  stable/10/lib/Makefile
  stable/10/lib/libdevctl/devctl.3
  stable/10/lib/libdevctl/devctl.c
  stable/10/lib/libdevctl/devctl.h
  stable/10/share/mk/bsd.libnames.mk
  stable/10/sys/conf/files
  stable/10/sys/dev/acpica/acpi.c
  stable/10/sys/dev/pci/pci.c
  stable/10/sys/kern/subr_bus.c
  stable/10/sys/kern/subr_hints.c
  stable/10/sys/sys/bus.h
  stable/10/usr.sbin/Makefile
  stable/10/usr.sbin/devctl/Makefile
  stable/10/usr.sbin/devctl/devctl.8
  stable/10/usr.sbin/devctl/devctl.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/contrib/mdocml/lib.in
==============================================================================
--- stable/10/contrib/mdocml/lib.in     Mon Feb  1 22:16:41 2016        
(r295130)
+++ stable/10/contrib/mdocml/lib.in     Mon Feb  1 23:07:31 2016        
(r295131)
@@ -37,6 +37,7 @@ LINE("libcipher",     "FreeSec Crypt Library
 LINE("libcompat",      "Compatibility Library (libcompat, \\-lcompat)")
 LINE("libcrypt",       "Crypt Library (libcrypt, \\-lcrypt)")
 LINE("libcurses",      "Curses Library (libcurses, \\-lcurses)")
+LINE("libdevctl",      "Device Control Library (libdevctl, \\-ldevctl)")
 LINE("libdevinfo",     "Device and Resource Information Utility Library 
(libdevinfo, \\-ldevinfo)")
 LINE("libdevstat",     "Device Statistics Library (libdevstat, \\-ldevstat)")
 LINE("libdisk",                "Interface to Slice and Partition Labels 
Library (libdisk, \\-ldisk)")

Modified: stable/10/lib/Makefile
==============================================================================
--- stable/10/lib/Makefile      Mon Feb  1 22:16:41 2016        (r295130)
+++ stable/10/lib/Makefile      Mon Feb  1 23:07:31 2016        (r295131)
@@ -37,6 +37,7 @@ SUBDIR=       ${SUBDIR_ORDERED} \
        ${_libcom_err} \
        libcompat \
        libcrypt \
+       libdevctl \
        libdevinfo \
        libdevstat \
        libdpv \

Modified: stable/10/lib/libdevctl/devctl.3
==============================================================================
--- head/lib/libdevctl/devctl.3 Fri Feb  6 16:09:01 2015        (r278320)
+++ stable/10/lib/libdevctl/devctl.3    Mon Feb  1 23:07:31 2016        
(r295131)
@@ -33,9 +33,7 @@
 .Nm devctl_attach ,
 .Nm devctl_detach ,
 .Nm devctl_disable ,
-.Nm devctl_enable ,
-.Nm devctl_resume ,
-.Nm devctl_suspend
+.Nm devctl_enable
 .Nd device control library
 .Sh LIBRARY
 .Lb libdevctl
@@ -50,10 +48,6 @@
 .Ft int
 .Fn devctl_enable "const char *device"
 .Ft int
-.Fn devctl_resume "const char *device"
-.Ft int
-.Fn devctl_suspend "const char *device"
-.Ft int
 .Fn devctl_set_driver "const char *device" "const char *driver" "bool force"
 .Sh DESCRIPTION
 The
@@ -125,16 +119,6 @@ function re-enables a disabled device.
 The device will probe and attach if a suitable device driver is found.
 .Pp
 The
-.Fn devctl_suspend
-function suspends a device.
-This may include placing the device in a reduced power state,
-but any device driver currently attached to the device will remain attached.
-.Pp
-The
-.Fn devctl_resume
-function resumes a suspended device to a fully working state.
-.Pp
-The
 .Fn devctl_set_driver
 function attaches a device driver named
 .Fa driver
@@ -150,7 +134,7 @@ the device will be detached from its cur
 attached to the new device driver.
 .Sh RETURN VALUES
 .Rv -std devctl_attach devctl_detach devctl_disable devctl_enable \
-devctl_suspend devctl_resume devctl_set_driver
+devctl_set_driver
 .Sh ERRORS
 In addition to specific errors noted below,
 all of the
@@ -235,26 +219,6 @@ does not support detaching.
 .El
 .Pp
 The
-.Fn devctl_suspend
-function may fail if:
-.Bl -tag -width Er
-.It Bq Er EBUSY
-The device is already suspended.
-.It Bq Er EINVAL
-The device to be suspended is the root bus device.
-.El
-.Pp
-The
-.Fn devctl_resume
-function may fail if:
-.Bl -tag -width Er
-.It Bq Er EINVAL
-The device is not suspended.
-.It Bq Er EINVAL
-The device to be resumed is the root bus device.
-.El
-.Pp
-The
 .Fn devctl_set_driver
 function may fail if:
 .Bl -tag -width Er
@@ -288,8 +252,3 @@ The
 .Nm
 library first appeared in
 .Fx 11.0 .
-.Sh BUGS
-If a device is suspended individually via
-.Fn devctl_suspend
-and the entire machine is subsequently suspended,
-the device will be resumed when the machine resumes.

Modified: stable/10/lib/libdevctl/devctl.c
==============================================================================
--- head/lib/libdevctl/devctl.c Fri Feb  6 16:09:01 2015        (r278320)
+++ stable/10/lib/libdevctl/devctl.c    Mon Feb  1 23:07:31 2016        
(r295131)
@@ -93,20 +93,6 @@ devctl_disable(const char *device, bool 
 }
 
 int
-devctl_suspend(const char *device)
-{
-
-       return (devctl_simple_request(DEV_SUSPEND, device, 0));
-}
-
-int
-devctl_resume(const char *device)
-{
-
-       return (devctl_simple_request(DEV_RESUME, device, 0));
-}
-
-int
 devctl_set_driver(const char *device, const char *driver, bool force)
 {
        struct devreq req;

Modified: stable/10/lib/libdevctl/devctl.h
==============================================================================
--- head/lib/libdevctl/devctl.h Fri Feb  6 16:09:01 2015        (r278320)
+++ stable/10/lib/libdevctl/devctl.h    Mon Feb  1 23:07:31 2016        
(r295131)
@@ -35,8 +35,6 @@ 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_suspend(const char *device);
-int    devctl_resume(const char *device);
 int    devctl_set_driver(const char *device, const char *driver, bool force);
 
 #endif /* !__DEVCTL_H__ */

Modified: stable/10/share/mk/bsd.libnames.mk
==============================================================================
--- stable/10/share/mk/bsd.libnames.mk  Mon Feb  1 22:16:41 2016        
(r295130)
+++ stable/10/share/mk/bsd.libnames.mk  Mon Feb  1 23:07:31 2016        
(r295131)
@@ -38,6 +38,7 @@ LIBCRYPT?=    ${DESTDIR}${LIBDIR}/libcrypt.
 LIBCRYPTO?=    ${DESTDIR}${LIBDIR}/libcrypto.a
 LIBCTF?=       ${DESTDIR}${LIBDIR}/libctf.a
 LIBCURSES?=    ${DESTDIR}${LIBDIR}/libcurses.a
+LIBDEVCTL?=    ${DESTDIR}${LIBDIR}/libdevctl.a
 LIBDEVINFO?=   ${DESTDIR}${LIBDIR}/libdevinfo.a
 LIBDEVSTAT?=   ${DESTDIR}${LIBDIR}/libdevstat.a
 LIBDIALOG?=    ${DESTDIR}${LIBDIR}/libdialog.a

Modified: stable/10/sys/conf/files
==============================================================================
--- stable/10/sys/conf/files    Mon Feb  1 22:16:41 2016        (r295130)
+++ stable/10/sys/conf/files    Mon Feb  1 23:07:31 2016        (r295131)
@@ -3238,7 +3238,7 @@ libkern/jenkins_hash.c            standard
 libkern/murmur3_32.c           standard
 libkern/mcount.c               optional profiling-routine
 libkern/memcchr.c              standard
-libkern/memchr.c               optional fdt
+libkern/memchr.c               standard
 libkern/memcmp.c               standard
 libkern/qsort.c                        standard
 libkern/qsort_r.c              standard

Modified: stable/10/sys/dev/acpica/acpi.c
==============================================================================
--- stable/10/sys/dev/acpica/acpi.c     Mon Feb  1 22:16:41 2016        
(r295130)
+++ stable/10/sys/dev/acpica/acpi.c     Mon Feb  1 23:07:31 2016        
(r295131)
@@ -100,6 +100,7 @@ int         acpi_quirks;
 /* Supported sleep states. */
 static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT];
 
+static void    acpi_lookup(void *arg, const char *name, device_t *dev);
 static int     acpi_modevent(struct module *mod, int event, void *junk);
 static int     acpi_probe(device_t dev);
 static int     acpi_attach(device_t dev);
@@ -670,8 +671,10 @@ acpi_attach(device_t dev)
     /* Register ACPI again to pass the correct argument of pm_func. */
     power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
 
-    if (!acpi_disabled("bus"))
+    if (!acpi_disabled("bus")) {
+       EVENTHANDLER_REGISTER(dev_lookup, acpi_lookup, NULL, 1000);
        acpi_probe_children(dev);
+    }
 
     /* Update all GPEs and enable runtime GPEs. */
     status = AcpiUpdateAllGpes();
@@ -3404,6 +3407,31 @@ acpi_disabled(char *subsys)
     return (0);
 }
 
+static void
+acpi_lookup(void *arg, const char *name, device_t *dev)
+{
+    ACPI_HANDLE handle;
+
+    if (*dev != NULL)
+       return;
+
+    /*
+     * Allow any handle name that is specified as an absolute path and
+     * starts with '\'.  We could restrict this to \_SB and friends,
+     * but see acpi_probe_children() for notes on why we scan the entire
+     * namespace for devices.
+     *
+     * XXX: The pathname argument to AcpiGetHandle() should be fixed to
+     * be const.
+     */
+    if (name[0] != '\\')
+       return;
+    if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, __DECONST(char *, name),
+       &handle)))
+       return;
+    *dev = acpi_get_device(handle);
+}
+
 /*
  * Control interface.
  *

Modified: stable/10/sys/dev/pci/pci.c
==============================================================================
--- stable/10/sys/dev/pci/pci.c Mon Feb  1 22:16:41 2016        (r295130)
+++ stable/10/sys/dev/pci/pci.c Mon Feb  1 23:07:31 2016        (r295131)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
+#include <sys/limits.h>
 #include <sys/linker.h>
 #include <sys/fcntl.h>
 #include <sys/conf.h>
@@ -4924,8 +4925,8 @@ pci_child_location_str_method(device_t d
     size_t buflen)
 {
 
-       snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child),
-           pci_get_function(child));
+       snprintf(buf, buflen, "pci%d:%d:%d:%d", pci_get_domain(child),
+           pci_get_bus(child), pci_get_slot(child), pci_get_function(child));
        return (0);
 }
 
@@ -4955,10 +4956,60 @@ pci_assign_interrupt_method(device_t dev
            cfg->intpin));
 }
 
+static void
+pci_lookup(void *arg, const char *name, device_t *dev)
+{
+       long val;
+       char *end;
+       int domain, bus, slot, func;
+
+       if (*dev != NULL)
+               return;
+
+       /*
+        * Accept pciconf-style selectors of either pciD:B:S:F or
+        * pciB:S:F.  In the latter case, the domain is assumed to
+        * be zero.
+        */
+       if (strncmp(name, "pci", 3) != 0)
+               return;
+       val = strtol(name + 3, &end, 10);
+       if (val < 0 || val > INT_MAX || *end != ':')
+               return;
+       domain = val;
+       val = strtol(end + 1, &end, 10);
+       if (val < 0 || val > INT_MAX || *end != ':')
+               return;
+       bus = val;
+       val = strtol(end + 1, &end, 10);
+       if (val < 0 || val > INT_MAX)
+               return;
+       slot = val;
+       if (*end == ':') {
+               val = strtol(end + 1, &end, 10);
+               if (val < 0 || val > INT_MAX || *end != '\0')
+                       return;
+               func = val;
+       } else if (*end == '\0') {
+               func = slot;
+               slot = bus;
+               bus = domain;
+               domain = 0;
+       } else
+               return;
+
+       if (domain > PCI_DOMAINMAX || bus > PCI_BUSMAX || slot > PCI_SLOTMAX ||
+           func > PCIE_ARI_FUNCMAX || (slot != 0 && func > PCI_FUNCMAX))
+               return;
+
+       *dev = pci_find_dbsf(domain, bus, slot, func);
+}
+
 static int
 pci_modevent(module_t mod, int what, void *arg)
 {
        static struct cdev *pci_cdev;
+       static eventhandler_tag tag;
 
        switch (what) {
        case MOD_LOAD:
@@ -4967,9 +5018,13 @@ pci_modevent(module_t mod, int what, voi
                pci_cdev = make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644,
                    "pci");
                pci_load_vendor_data();
+               tag = EVENTHANDLER_REGISTER(dev_lookup, pci_lookup, NULL,
+                   1000);
                break;
 
        case MOD_UNLOAD:
+               if (tag != NULL)
+                       EVENTHANDLER_DEREGISTER(dev_lookup, tag);
                destroy_dev(pci_cdev);
                break;
        }

Modified: stable/10/sys/kern/subr_bus.c
==============================================================================
--- stable/10/sys/kern/subr_bus.c       Mon Feb  1 22:16:41 2016        
(r295130)
+++ stable/10/sys/kern/subr_bus.c       Mon Feb  1 23:07:31 2016        
(r295131)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/poll.h>
+#include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/condvar.h>
 #include <sys/queue.h>
@@ -147,6 +148,8 @@ struct device {
 static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
 static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc");
 
+static void devctl2_init(void);
+
 #ifdef BUS_DEBUG
 
 static int bus_debug = 1;
@@ -434,6 +437,7 @@ devinit(void)
        cv_init(&devsoftc.cv, "dev cv");
        TAILQ_INIT(&devsoftc.devq);
        knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
+       devctl2_init();
 }
 
 static int
@@ -4998,3 +5002,229 @@ bus_free_resource(device_t dev, int type
                return (0);
        return (bus_release_resource(dev, type, rman_get_rid(r), r));
 }
+
+/*
+ * /dev/devctl2 implementation.  The existing /dev/devctl device has
+ * implicit semantics on open, so it could not be reused for this.
+ * Another option would be to call this /dev/bus?
+ */
+static int
+find_device(struct devreq *req, device_t *devp)
+{
+       device_t dev;
+
+       /*
+        * First, ensure that the name is nul terminated.
+        */
+       if (memchr(req->dr_name, '\0', sizeof(req->dr_name)) == NULL)
+               return (EINVAL);
+
+       /*
+        * Second, try to find an attached device whose name matches
+        * 'name'.
+        */
+       TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+               if (dev->nameunit != NULL &&
+                   strcmp(dev->nameunit, req->dr_name) == 0) {
+                       *devp = dev;
+                       return (0);
+               }
+       }
+
+       /* Finally, give device enumerators a chance. */
+       dev = NULL;
+       EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev);
+       if (dev == NULL)
+               return (ENOENT);
+       *devp = dev;
+       return (0);
+}
+
+static bool
+driver_exists(struct device *bus, const char *driver)
+{
+       devclass_t dc;
+
+       for (dc = bus->devclass; dc != NULL; dc = dc->parent) {
+               if (devclass_find_driver_internal(dc, driver) != NULL)
+                       return (true);
+       }
+       return (false);
+}
+
+static int
+devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
+    struct thread *td)
+{
+       struct devreq *req;
+       device_t dev;
+       int error, old;
+
+       /* Locate the device to control. */
+       mtx_lock(&Giant);
+       req = (struct devreq *)data;
+       switch (cmd) {
+       case DEV_ATTACH:
+       case DEV_DETACH:
+       case DEV_ENABLE:
+       case DEV_DISABLE:
+       case DEV_SET_DRIVER:
+               error = priv_check(td, PRIV_DRIVER);
+               if (error == 0)
+                       error = find_device(req, &dev);
+               break;
+       default:
+               error = ENOTTY;
+               break;
+       }
+       if (error) {
+               mtx_unlock(&Giant);
+               return (error);
+       }
+
+       /* Perform the requested operation. */
+       switch (cmd) {
+       case DEV_ATTACH:
+               if (device_is_attached(dev) && (dev->flags & DF_REBID) == 0)
+                       error = EBUSY;
+               else if (!device_is_enabled(dev))
+                       error = ENXIO;
+               else
+                       error = device_probe_and_attach(dev);
+               break;
+       case DEV_DETACH:
+               if (!device_is_attached(dev)) {
+                       error = ENXIO;
+                       break;
+               }
+               if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
+                       error = device_quiesce(dev);
+                       if (error)
+                               break;
+               }
+               error = device_detach(dev);
+               break;
+       case DEV_ENABLE:
+               if (device_is_enabled(dev)) {
+                       error = EBUSY;
+                       break;
+               }
+
+               /*
+                * If the device has been probed but not attached (e.g.
+                * when it has been disabled by a loader hint), just
+                * attach the device rather than doing a full probe.
+                */
+               device_enable(dev);
+               if (device_is_alive(dev)) {
+                       /*
+                        * If the device was disabled via a hint, clear
+                        * the hint.
+                        */
+                       if (resource_disabled(dev->driver->name, dev->unit))
+                               resource_unset_value(dev->driver->name,
+                                   dev->unit, "disabled");
+                       error = device_attach(dev);
+               } else
+                       error = device_probe_and_attach(dev);
+               break;
+       case DEV_DISABLE:
+               if (!device_is_enabled(dev)) {
+                       error = ENXIO;
+                       break;
+               }
+
+               if (!(req->dr_flags & DEVF_FORCE_DETACH)) {
+                       error = device_quiesce(dev);
+                       if (error)
+                               break;
+               }
+
+               /*
+                * Force DF_FIXEDCLASS on around detach to preserve
+                * the existing name.
+                */
+               old = dev->flags;
+               dev->flags |= DF_FIXEDCLASS;
+               error = device_detach(dev);
+               if (!(old & DF_FIXEDCLASS))
+                       dev->flags &= ~DF_FIXEDCLASS;
+               if (error == 0)
+                       device_disable(dev);
+               break;
+       case DEV_SET_DRIVER: {
+               devclass_t dc;
+               char driver[128];
+
+               error = copyinstr(req->dr_data, driver, sizeof(driver), NULL);
+               if (error)
+                       break;
+               if (driver[0] == '\0') {
+                       error = EINVAL;
+                       break;
+               }
+               if (dev->devclass != NULL &&
+                   strcmp(driver, dev->devclass->name) == 0)
+                       /* XXX: Could possibly force DF_FIXEDCLASS on? */
+                       break;
+
+               /*
+                * Scan drivers for this device's bus looking for at
+                * least one matching driver.
+                */
+               if (dev->parent == NULL) {
+                       error = EINVAL;
+                       break;
+               }
+               if (!driver_exists(dev->parent, driver)) {
+                       error = ENOENT;
+                       break;
+               }
+               dc = devclass_create(driver);
+               if (dc == NULL) {
+                       error = ENOMEM;
+                       break;
+               }
+
+               /* Detach device if necessary. */
+               if (device_is_attached(dev)) {
+                       if (req->dr_flags & DEVF_SET_DRIVER_DETACH)
+                               error = device_detach(dev);
+                       else
+                               error = EBUSY;
+                       if (error)
+                               break;
+               }
+
+               /* Clear any previously-fixed device class and unit. */
+               if (dev->flags & DF_FIXEDCLASS)
+                       devclass_delete_device(dev->devclass, dev);
+               dev->flags |= DF_WILDCARD;
+               dev->unit = -1;
+
+               /* Force the new device class. */
+               error = devclass_add_device(dc, dev);
+               if (error)
+                       break;
+               dev->flags |= DF_FIXEDCLASS;
+               error = device_probe_and_attach(dev);
+               break;
+       }
+       }
+       mtx_unlock(&Giant);
+       return (error);
+}
+
+static struct cdevsw devctl2_cdevsw = {
+       .d_version =    D_VERSION,
+       .d_ioctl =      devctl2_ioctl,
+       .d_name =       "devctl2",
+};
+
+static void
+devctl2_init(void)
+{
+
+       make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL,
+           UID_ROOT, GID_WHEEL, 0600, "devctl2");
+}

Modified: stable/10/sys/kern/subr_hints.c
==============================================================================
--- stable/10/sys/kern/subr_hints.c     Mon Feb  1 22:16:41 2016        
(r295130)
+++ stable/10/sys/kern/subr_hints.c     Mon Feb  1 23:07:31 2016        
(r295131)
@@ -461,3 +461,31 @@ resource_disabled(const char *name, int 
               return (0);
        return (value);
 }
+
+/*
+ * Clear a value associated with a device by removing it from
+ * the kernel environment.  This only removes a hint for an
+ * exact unit.
+ */
+int
+resource_unset_value(const char *name, int unit, const char *resname)
+{
+       char varname[128];
+       const char *retname, *retvalue;
+       int error, line;
+       size_t len;
+
+       line = 0;
+       error = resource_find(&line, NULL, name, &unit, resname, NULL,
+           &retname, NULL, NULL, NULL, NULL, &retvalue);
+       if (error)
+               return (error);
+
+       retname -= strlen("hint.");
+       len = retvalue - retname - 1;
+       if (len > sizeof(varname) - 1)
+               return (ENAMETOOLONG);
+       memcpy(varname, retname, len);
+       varname[len] = '\0';
+       return (unsetenv(varname));
+}

Modified: stable/10/sys/sys/bus.h
==============================================================================
--- stable/10/sys/sys/bus.h     Mon Feb  1 22:16:41 2016        (r295130)
+++ stable/10/sys/sys/bus.h     Mon Feb  1 23:07:31 2016        (r295131)
@@ -31,6 +31,7 @@
 
 #include <machine/_limits.h>
 #include <sys/_bus_dma.h>
+#include <sys/ioccom.h>
 
 /**
  * @defgroup NEWBUS newbus - a generic framework for managing devices
@@ -75,9 +76,43 @@ struct u_device {
        /* XXX more driver info? */
 };
 
+/**
+ * @brief Device request structure used for ioctl's.
+ *
+ * Used for ioctl's on /dev/devctl2.  All device ioctl's
+ * must have parameter definitions which begin with dr_name.
+ */
+struct devreq_buffer {
+       void    *buffer;
+       size_t  length;
+};
+
+struct devreq {
+       char            dr_name[128];
+       int             dr_flags;               /* request-specific flags */
+       union {
+               struct devreq_buffer dru_buffer;
+               void    *dru_data;
+       } dr_dru;
+#define        dr_buffer       dr_dru.dru_buffer       /* variable-sized 
buffer */
+#define        dr_data         dr_dru.dru_data         /* fixed-size buffer */
+};
+
+#define        DEV_ATTACH      _IOW('D', 1, struct devreq)
+#define        DEV_DETACH      _IOW('D', 2, struct devreq)
+#define        DEV_ENABLE      _IOW('D', 3, struct devreq)
+#define        DEV_DISABLE     _IOW('D', 4, struct devreq)
+#define        DEV_SET_DRIVER  _IOW('D', 7, struct devreq)
+
+/* Flags for DEV_DETACH and DEV_DISABLE. */
+#define        DEVF_FORCE_DETACH       0x0000001
+
+/* Flags for DEV_SET_DRIVER. */
+#define        DEVF_SET_DRIVER_DETACH  0x0000001       /* Detach existing 
driver. */
+
 #ifdef _KERNEL
 
-#include <sys/queue.h>
+#include <sys/eventhandler.h>
 #include <sys/kobj.h>
 
 /**
@@ -94,6 +129,14 @@ void devctl_queue_data_f(char *__data, i
 void devctl_queue_data(char *__data);
 
 /**
+ * Device name parsers.  Hook to allow device enumerators to map
+ * scheme-specific names to a device.
+ */
+typedef void (*dev_lookup_fn)(void *arg, const char *name,
+    device_t *result);
+EVENTHANDLER_DECLARE(dev_lookup, dev_lookup_fn);
+
+/**
  * @brief A device driver (included mainly for compatibility with
  * FreeBSD 4.x).
  */
@@ -454,6 +497,7 @@ struct sysctl_oid *device_get_sysctl_tre
 int    device_is_alive(device_t dev);  /* did probe succeed? */
 int    device_is_attached(device_t dev);       /* did attach succeed? */
 int    device_is_enabled(device_t dev);
+int    device_is_suspended(device_t dev);
 int    device_is_quiet(device_t dev);
 int    device_print_prettyname(device_t dev);
 int    device_printf(device_t dev, const char *, ...) __printflike(2, 3);
@@ -517,6 +561,8 @@ int resource_set_long(const char *name, 
                          long value);
 int    resource_set_string(const char *name, int unit, const char *resname,
                            const char *value);
+int    resource_unset_value(const char *name, int unit, const char *resname);
+
 /*
  * Functions for maintaining and checking consistency of
  * bus information exported to userspace.

Modified: stable/10/usr.sbin/Makefile
==============================================================================
--- stable/10/usr.sbin/Makefile Mon Feb  1 22:16:41 2016        (r295130)
+++ stable/10/usr.sbin/Makefile Mon Feb  1 23:07:31 2016        (r295131)
@@ -20,6 +20,7 @@ SUBDIR=       adduser \
        ctld \
        daemon \
        dconschat \
+       devctl \
        devinfo \
        digictl \
        diskinfo \

Modified: stable/10/usr.sbin/devctl/Makefile
==============================================================================
--- head/usr.sbin/devctl/Makefile       Fri Feb  6 16:09:01 2015        
(r278320)
+++ stable/10/usr.sbin/devctl/Makefile  Mon Feb  1 23:07:31 2016        
(r295131)
@@ -2,8 +2,8 @@
 
 PROG=  devctl
 MAN=   devctl.8
-MAN=
 
-LIBADD=        devctl
+DPADD= ${LIBDEVCTL}
+LDADD= -ldevctl
 
 .include <bsd.prog.mk>

Modified: stable/10/usr.sbin/devctl/devctl.8
==============================================================================
--- head/usr.sbin/devctl/devctl.8       Fri Feb  6 16:09:01 2015        
(r278320)
+++ stable/10/usr.sbin/devctl/devctl.8  Mon Feb  1 23:07:31 2016        
(r295131)
@@ -47,12 +47,6 @@
 .Cm enable
 .Ar device
 .Nm
-.Cm suspend
-.Ar device
-.Nm
-.Cm resume
-.Ar device
-.Nm
 .Cm set driver
 .Op Fl f
 .Ar device driver
@@ -106,11 +100,6 @@ Enable a device.
 The device will probe and attach if a suitable device driver is found.
 Note that this can re-enable a device disabled at boot time via a
 loader tunable.
-.It Cm suspend Ar device
-Suspend a device.
-This may include placing the device in a reduced power state.
-.It Cm resume device
-Resume a suspended device to a fully working state.
 .It Xo Cm set driver
 .Op Fl f
 .Ar device driver

Modified: stable/10/usr.sbin/devctl/devctl.c
==============================================================================
--- head/usr.sbin/devctl/devctl.c       Fri Feb  6 16:09:01 2015        
(r278320)
+++ stable/10/usr.sbin/devctl/devctl.c  Mon Feb  1 23:07:31 2016        
(r295131)
@@ -70,13 +70,11 @@ DEVCTL_TABLE(top, set);
 static void
 usage(void)
 {
-       fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+       fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
            "usage: devctl attach device",
            "       devctl detach [-f] device",
            "       devctl disable [-f] device",
            "       devctl enable device",
-           "       devctl suspend device",
-           "       devctl resume device",
            "       devctl set driver [-f] device driver");
        exit(1);
 }
@@ -201,30 +199,6 @@ enable(int ac, char **av)
 }
 DEVCTL_COMMAND(top, enable, enable);
 
-static int
-suspend(int ac, char **av)
-{
-
-       if (ac != 2)
-               usage();
-       if (devctl_suspend(av[1]) < 0)
-               err(1, "Failed to suspend %s", av[1]);
-       return (0);
-}
-DEVCTL_COMMAND(top, suspend, suspend);
-
-static int
-resume(int ac, char **av)
-{
-
-       if (ac != 2)
-               usage();
-       if (devctl_resume(av[1]) < 0)
-               err(1, "Failed to resume %s", av[1]);
-       return (0);
-}
-DEVCTL_COMMAND(top, resume, resume);
-
 static void
 set_driver_usage(void)
 {
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "[email protected]"

Reply via email to