subr_bus.c (278299) | subr_bus.c (278320) |
---|---|
1/*- 2 * Copyright (c) 1997,1998,2003 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1997,1998,2003 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 278299 2015-02-05 22:42:44Z jhb $"); | 28__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 278320 2015-02-06 16:09:01Z jhb $"); |
29 30#include "opt_bus.h" 31#include "opt_random.h" 32 33#include <sys/param.h> 34#include <sys/conf.h> 35#include <sys/filio.h> 36#include <sys/lock.h> 37#include <sys/kernel.h> 38#include <sys/kobj.h> 39#include <sys/limits.h> 40#include <sys/malloc.h> 41#include <sys/module.h> 42#include <sys/mutex.h> 43#include <sys/poll.h> | 29 30#include "opt_bus.h" 31#include "opt_random.h" 32 33#include <sys/param.h> 34#include <sys/conf.h> 35#include <sys/filio.h> 36#include <sys/lock.h> 37#include <sys/kernel.h> 38#include <sys/kobj.h> 39#include <sys/limits.h> 40#include <sys/malloc.h> 41#include <sys/module.h> 42#include <sys/mutex.h> 43#include <sys/poll.h> |
44#include <sys/priv.h> |
|
44#include <sys/proc.h> 45#include <sys/condvar.h> 46#include <sys/queue.h> 47#include <machine/bus.h> 48#include <sys/random.h> 49#include <sys/rman.h> 50#include <sys/selinfo.h> 51#include <sys/signalvar.h> --- 82 unchanged lines hidden (view full) --- 134 135 struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */ 136 struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */ 137}; 138 139static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); 140static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); 141 | 45#include <sys/proc.h> 46#include <sys/condvar.h> 47#include <sys/queue.h> 48#include <machine/bus.h> 49#include <sys/random.h> 50#include <sys/rman.h> 51#include <sys/selinfo.h> 52#include <sys/signalvar.h> --- 82 unchanged lines hidden (view full) --- 135 136 struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */ 137 struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */ 138}; 139 140static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); 141static MALLOC_DEFINE(M_BUS_SC, "bus-sc", "Bus data structures, softc"); 142 |
143static void devctl2_init(void); 144 |
|
142#ifdef BUS_DEBUG 143 144static int bus_debug = 1; 145SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0, 146 "Bus debug level"); 147 148#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} 149#define DEVICENAME(d) ((d)? device_get_name(d): "no device") --- 268 unchanged lines hidden (view full) --- 418devinit(void) 419{ 420 devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL, 421 UID_ROOT, GID_WHEEL, 0600, "devctl"); 422 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF); 423 cv_init(&devsoftc.cv, "dev cv"); 424 TAILQ_INIT(&devsoftc.devq); 425 knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx); | 145#ifdef BUS_DEBUG 146 147static int bus_debug = 1; 148SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RWTUN, &bus_debug, 0, 149 "Bus debug level"); 150 151#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} 152#define DEVICENAME(d) ((d)? device_get_name(d): "no device") --- 268 unchanged lines hidden (view full) --- 421devinit(void) 422{ 423 devctl_dev = make_dev_credf(MAKEDEV_ETERNAL, &dev_cdevsw, 0, NULL, 424 UID_ROOT, GID_WHEEL, 0600, "devctl"); 425 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF); 426 cv_init(&devsoftc.cv, "dev cv"); 427 TAILQ_INIT(&devsoftc.devq); 428 knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx); |
429 devctl2_init(); |
|
426} 427 428static int 429devopen(struct cdev *dev, int oflags, int devtype, struct thread *td) 430{ 431 432 mtx_lock(&devsoftc.mtx); 433 if (devsoftc.inuse) { --- 2200 unchanged lines hidden (view full) --- 2634 */ 2635int 2636device_is_attached(device_t dev) 2637{ 2638 return (dev->state >= DS_ATTACHED); 2639} 2640 2641/** | 430} 431 432static int 433devopen(struct cdev *dev, int oflags, int devtype, struct thread *td) 434{ 435 436 mtx_lock(&devsoftc.mtx); 437 if (devsoftc.inuse) { --- 2200 unchanged lines hidden (view full) --- 2638 */ 2639int 2640device_is_attached(device_t dev) 2641{ 2642 return (dev->state >= DS_ATTACHED); 2643} 2644 2645/** |
2646 * @brief Return non-zero if the device is currently suspended. 2647 */ 2648int 2649device_is_suspended(device_t dev) 2650{ 2651 return ((dev->flags & DF_SUSPENDED) != 0); 2652} 2653 2654/** |
|
2642 * @brief Set the devclass of a device 2643 * @see devclass_add_device(). 2644 */ 2645int 2646device_set_devclass(device_t dev, const char *classname) 2647{ 2648 devclass_t dc; 2649 int error; --- 2367 unchanged lines hidden (view full) --- 5017 5018int 5019bus_free_resource(device_t dev, int type, struct resource *r) 5020{ 5021 if (r == NULL) 5022 return (0); 5023 return (bus_release_resource(dev, type, rman_get_rid(r), r)); 5024} | 2655 * @brief Set the devclass of a device 2656 * @see devclass_add_device(). 2657 */ 2658int 2659device_set_devclass(device_t dev, const char *classname) 2660{ 2661 devclass_t dc; 2662 int error; --- 2367 unchanged lines hidden (view full) --- 5030 5031int 5032bus_free_resource(device_t dev, int type, struct resource *r) 5033{ 5034 if (r == NULL) 5035 return (0); 5036 return (bus_release_resource(dev, type, rman_get_rid(r), r)); 5037} |
5038 5039/* 5040 * /dev/devctl2 implementation. The existing /dev/devctl device has 5041 * implicit semantics on open, so it could not be reused for this. 5042 * Another option would be to call this /dev/bus? 5043 */ 5044static int 5045find_device(struct devreq *req, device_t *devp) 5046{ 5047 device_t dev; 5048 5049 /* 5050 * First, ensure that the name is nul terminated. 5051 */ 5052 if (memchr(req->dr_name, '\0', sizeof(req->dr_name)) == NULL) 5053 return (EINVAL); 5054 5055 /* 5056 * Second, try to find an attached device whose name matches 5057 * 'name'. 5058 */ 5059 TAILQ_FOREACH(dev, &bus_data_devices, devlink) { 5060 if (dev->nameunit != NULL && 5061 strcmp(dev->nameunit, req->dr_name) == 0) { 5062 *devp = dev; 5063 return (0); 5064 } 5065 } 5066 5067 /* Finally, give device enumerators a chance. */ 5068 dev = NULL; 5069 EVENTHANDLER_INVOKE(dev_lookup, req->dr_name, &dev); 5070 if (dev == NULL) 5071 return (ENOENT); 5072 *devp = dev; 5073 return (0); 5074} 5075 5076static bool 5077driver_exists(struct device *bus, const char *driver) 5078{ 5079 devclass_t dc; 5080 5081 for (dc = bus->devclass; dc != NULL; dc = dc->parent) { 5082 if (devclass_find_driver_internal(dc, driver) != NULL) 5083 return (true); 5084 } 5085 return (false); 5086} 5087 5088static int 5089devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, 5090 struct thread *td) 5091{ 5092 struct devreq *req; 5093 device_t dev; 5094 int error, old; 5095 5096 /* Locate the device to control. */ 5097 mtx_lock(&Giant); 5098 req = (struct devreq *)data; 5099 switch (cmd) { 5100 case DEV_ATTACH: 5101 case DEV_DETACH: 5102 case DEV_ENABLE: 5103 case DEV_DISABLE: 5104 case DEV_SUSPEND: 5105 case DEV_RESUME: 5106 case DEV_SET_DRIVER: 5107 error = priv_check(td, PRIV_DRIVER); 5108 if (error == 0) 5109 error = find_device(req, &dev); 5110 break; 5111 default: 5112 error = ENOTTY; 5113 break; 5114 } 5115 if (error) { 5116 mtx_unlock(&Giant); 5117 return (error); 5118 } 5119 5120 /* Perform the requested operation. */ 5121 switch (cmd) { 5122 case DEV_ATTACH: 5123 if (device_is_attached(dev) && (dev->flags & DF_REBID) == 0) 5124 error = EBUSY; 5125 else if (!device_is_enabled(dev)) 5126 error = ENXIO; 5127 else 5128 error = device_probe_and_attach(dev); 5129 break; 5130 case DEV_DETACH: 5131 if (!device_is_attached(dev)) { 5132 error = ENXIO; 5133 break; 5134 } 5135 if (!(req->dr_flags & DEVF_FORCE_DETACH)) { 5136 error = device_quiesce(dev); 5137 if (error) 5138 break; 5139 } 5140 error = device_detach(dev); 5141 break; 5142 case DEV_ENABLE: 5143 if (device_is_enabled(dev)) { 5144 error = EBUSY; 5145 break; 5146 } 5147 5148 /* 5149 * If the device has been probed but not attached (e.g. 5150 * when it has been disabled by a loader hint), just 5151 * attach the device rather than doing a full probe. 5152 */ 5153 device_enable(dev); 5154 if (device_is_alive(dev)) { 5155 /* 5156 * If the device was disabled via a hint, clear 5157 * the hint. 5158 */ 5159 if (resource_disabled(dev->driver->name, dev->unit)) 5160 resource_unset_value(dev->driver->name, 5161 dev->unit, "disabled"); 5162 error = device_attach(dev); 5163 } else 5164 error = device_probe_and_attach(dev); 5165 break; 5166 case DEV_DISABLE: 5167 if (!device_is_enabled(dev)) { 5168 error = ENXIO; 5169 break; 5170 } 5171 5172 if (!(req->dr_flags & DEVF_FORCE_DETACH)) { 5173 error = device_quiesce(dev); 5174 if (error) 5175 break; 5176 } 5177 5178 /* 5179 * Force DF_FIXEDCLASS on around detach to preserve 5180 * the existing name. 5181 */ 5182 old = dev->flags; 5183 dev->flags |= DF_FIXEDCLASS; 5184 error = device_detach(dev); 5185 if (!(old & DF_FIXEDCLASS)) 5186 dev->flags &= ~DF_FIXEDCLASS; 5187 if (error == 0) 5188 device_disable(dev); 5189 break; 5190 case DEV_SUSPEND: 5191 if (device_is_suspended(dev)) { 5192 error = EBUSY; 5193 break; 5194 } 5195 if (device_get_parent(dev) == NULL) { 5196 error = EINVAL; 5197 break; 5198 } 5199 error = BUS_SUSPEND_CHILD(device_get_parent(dev), dev); 5200 break; 5201 case DEV_RESUME: 5202 if (!device_is_suspended(dev)) { 5203 error = EINVAL; 5204 break; 5205 } 5206 if (device_get_parent(dev) == NULL) { 5207 error = EINVAL; 5208 break; 5209 } 5210 error = BUS_RESUME_CHILD(device_get_parent(dev), dev); 5211 break; 5212 case DEV_SET_DRIVER: { 5213 devclass_t dc; 5214 char driver[128]; 5215 5216 error = copyinstr(req->dr_data, driver, sizeof(driver), NULL); 5217 if (error) 5218 break; 5219 if (driver[0] == '\0') { 5220 error = EINVAL; 5221 break; 5222 } 5223 if (dev->devclass != NULL && 5224 strcmp(driver, dev->devclass->name) == 0) 5225 /* XXX: Could possibly force DF_FIXEDCLASS on? */ 5226 break; 5227 5228 /* 5229 * Scan drivers for this device's bus looking for at 5230 * least one matching driver. 5231 */ 5232 if (dev->parent == NULL) { 5233 error = EINVAL; 5234 break; 5235 } 5236 if (!driver_exists(dev->parent, driver)) { 5237 error = ENOENT; 5238 break; 5239 } 5240 dc = devclass_create(driver); 5241 if (dc == NULL) { 5242 error = ENOMEM; 5243 break; 5244 } 5245 5246 /* Detach device if necessary. */ 5247 if (device_is_attached(dev)) { 5248 if (req->dr_flags & DEVF_SET_DRIVER_DETACH) 5249 error = device_detach(dev); 5250 else 5251 error = EBUSY; 5252 if (error) 5253 break; 5254 } 5255 5256 /* Clear any previously-fixed device class and unit. */ 5257 if (dev->flags & DF_FIXEDCLASS) 5258 devclass_delete_device(dev->devclass, dev); 5259 dev->flags |= DF_WILDCARD; 5260 dev->unit = -1; 5261 5262 /* Force the new device class. */ 5263 error = devclass_add_device(dc, dev); 5264 if (error) 5265 break; 5266 dev->flags |= DF_FIXEDCLASS; 5267 error = device_probe_and_attach(dev); 5268 break; 5269 } 5270 } 5271 mtx_unlock(&Giant); 5272 return (error); 5273} 5274 5275static struct cdevsw devctl2_cdevsw = { 5276 .d_version = D_VERSION, 5277 .d_ioctl = devctl2_ioctl, 5278 .d_name = "devctl2", 5279}; 5280 5281static void 5282devctl2_init(void) 5283{ 5284 5285 make_dev_credf(MAKEDEV_ETERNAL, &devctl2_cdevsw, 0, NULL, 5286 UID_ROOT, GID_WHEEL, 0600, "devctl2"); 5287} |
|