From owner-svn-src-stable@freebsd.org Mon Feb 1 23:07:34 2016 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6B25EA970EC; Mon, 1 Feb 2016 23:07:34 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3ADF71396; Mon, 1 Feb 2016 23:07:34 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u11N7X5r064614; Mon, 1 Feb 2016 23:07:33 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u11N7Vom064597; Mon, 1 Feb 2016 23:07:31 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201602012307.u11N7Vom064597@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Mon, 1 Feb 2016 23:07:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r295131 - in stable/10: contrib/mdocml lib lib/libdevctl share/mk sys/conf sys/dev/acpica sys/dev/pci sys/kern sys/sys usr.sbin usr.sbin/devctl X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Feb 2016 23:07:34 -0000 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[:]::' (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= function='. - 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...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 #include #include +#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 #include +#include /** * @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 +#include #include /** @@ -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 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) {