| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 1997,1998,2003 Doug Rabson |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | #ifndef _SYS_BUS_H_ |
| 30 | #define _SYS_BUS_H_ |
| 31 | |
| 32 | #include <machine/_limits.h> |
| 33 | #include <machine/_bus.h> |
| 34 | #include <sys/_bus_dma.h> |
| 35 | #include <sys/ioccom.h> |
| 36 | |
| 37 | /** |
| 38 | * @defgroup NEWBUS newbus - a generic framework for managing devices |
| 39 | * @{ |
| 40 | */ |
| 41 | |
| 42 | /** |
| 43 | * @brief Interface information structure. |
| 44 | */ |
| 45 | struct u_businfo { |
| 46 | 	int	ub_version;		/**< @brief interface version */ |
| 47 | #define BUS_USER_VERSION	2 |
| 48 | 	int	ub_generation;		/**< @brief generation count */ |
| 49 | }; |
| 50 | |
| 51 | /** |
| 52 | * @brief State of the device. |
| 53 | */ |
| 54 | typedef enum device_state { |
| 55 | 	DS_NOTPRESENT = 10,		/**< @brief not probed or probe failed */ |
| 56 | 	DS_ALIVE = 20,			/**< @brief probe succeeded */ |
| 57 | 	DS_ATTACHING = 25,		/**< @brief currently attaching */ |
| 58 | 	DS_ATTACHED = 30,		/**< @brief attach method called */ |
| 59 | } device_state_t; |
| 60 | |
| 61 | /** |
| 62 | * @brief Device proprty types. |
| 63 | * |
| 64 | * Those are used by bus logic to encode requested properties, |
| 65 | * e.g. in DT all properties are stored as BE and need to be converted |
| 66 | * to host endianness. |
| 67 | */ |
| 68 | typedef enum device_property_type { |
| 69 | 	DEVICE_PROP_ANY = 0, |
| 70 | 	DEVICE_PROP_BUFFER = 1, |
| 71 | 	DEVICE_PROP_UINT32 = 2, |
| 72 | 	DEVICE_PROP_UINT64 = 3, |
| 73 | 	DEVICE_PROP_HANDLE = 4, |
| 74 | } device_property_type_t; |
| 75 | |
| 76 | /** |
| 77 | * @brief Device information exported to userspace. |
| 78 | * The strings are placed one after the other, separated by NUL characters. |
| 79 | * Fields should be added after the last one and order maintained for compatibility |
| 80 | */ |
| 81 | #define BUS_USER_BUFFER		(3*1024) |
| 82 | struct u_device { |
| 83 | 	uintptr_t	dv_handle; |
| 84 | 	uintptr_t	dv_parent; |
| 85 | 	uint32_t	dv_devflags;		/**< @brief API Flags for device */ |
| 86 | 	uint16_t	dv_flags;		/**< @brief flags for dev state */ |
| 87 | 	device_state_t	dv_state;		/**< @brief State of attachment */ |
| 88 | 	char		dv_fields[BUS_USER_BUFFER]; /**< @brief NUL terminated fields */ |
| 89 | 	/* name (name of the device in tree) */ |
| 90 | 	/* desc (driver description) */ |
| 91 | 	/* drivername (Name of driver without unit number) */ |
| 92 | 	/* pnpinfo (Plug and play information from bus) */ |
| 93 | 	/* location (Location of device on parent */ |
| 94 | 	/* NUL */ |
| 95 | }; |
| 96 | |
| 97 | /* Flags exported via dv_flags. */ |
| 98 | #define	DF_ENABLED	0x01		/* device should be probed/attached */ |
| 99 | #define	DF_FIXEDCLASS	0x02		/* devclass specified at create time */ |
| 100 | #define	DF_WILDCARD	0x04		/* unit was originally wildcard */ |
| 101 | #define	DF_DESCMALLOCED	0x08		/* description was malloced */ |
| 102 | #define	DF_QUIET	0x10		/* don't print verbose attach message */ |
| 103 | #define	DF_DONENOMATCH	0x20		/* don't execute DEVICE_NOMATCH again */ |
| 104 | #define	DF_EXTERNALSOFTC 0x40		/* softc not allocated by us */ |
| 105 | #define	DF_SUSPENDED	0x100		/* Device is suspended. */ |
| 106 | #define	DF_QUIET_CHILDREN 0x200		/* Default to quiet for all my children */ |
| 107 | #define	DF_ATTACHED_ONCE 0x400		/* Has been attached at least once */ |
| 108 | #define	DF_NEEDNOMATCH	0x800		/* Has a pending NOMATCH event */ |
| 109 | |
| 110 | /** |
| 111 | * @brief Device request structure used for ioctl's. |
| 112 | * |
| 113 | * Used for ioctl's on /dev/devctl2. All device ioctl's |
| 114 | * must have parameter definitions which begin with dr_name. |
| 115 | */ |
| 116 | struct devreq_buffer { |
| 117 | 	void	*buffer; |
| 118 | 	size_t	length; |
| 119 | }; |
| 120 | |
| 121 | struct devreq { |
| 122 | 	char		dr_name[128]; |
| 123 | 	int		dr_flags;		/* request-specific flags */ |
| 124 | 	union { |
| 125 | 		struct devreq_buffer dru_buffer; |
| 126 | 		void	*dru_data; |
| 127 | 	} dr_dru; |
| 128 | #define	dr_buffer	dr_dru.dru_buffer	/* variable-sized buffer */ |
| 129 | #define	dr_data		dr_dru.dru_data		/* fixed-size buffer */ |
| 130 | }; |
| 131 | |
| 132 | #define	DEV_ATTACH	_IOW('D', 1, struct devreq) |
| 133 | #define	DEV_DETACH	_IOW('D', 2, struct devreq) |
| 134 | #define	DEV_ENABLE	_IOW('D', 3, struct devreq) |
| 135 | #define	DEV_DISABLE	_IOW('D', 4, struct devreq) |
| 136 | #define	DEV_SUSPEND	_IOW('D', 5, struct devreq) |
| 137 | #define	DEV_RESUME	_IOW('D', 6, struct devreq) |
| 138 | #define	DEV_SET_DRIVER	_IOW('D', 7, struct devreq) |
| 139 | #define	DEV_CLEAR_DRIVER _IOW('D', 8, struct devreq) |
| 140 | #define	DEV_RESCAN	_IOW('D', 9, struct devreq) |
| 141 | #define	DEV_DELETE	_IOW('D', 10, struct devreq) |
| 142 | #define	DEV_FREEZE	_IOW('D', 11, struct devreq) |
| 143 | #define	DEV_THAW	_IOW('D', 12, struct devreq) |
| 144 | #define	DEV_RESET	_IOW('D', 13, struct devreq) |
| 145 | #define	DEV_GET_PATH	_IOWR('D', 14, struct devreq) |
| 146 | |
| 147 | /* Flags for DEV_DETACH and DEV_DISABLE. */ |
| 148 | #define	DEVF_FORCE_DETACH	0x0000001 |
| 149 | |
| 150 | /* Flags for DEV_SET_DRIVER. */ |
| 151 | #define	DEVF_SET_DRIVER_DETACH	0x0000001	/* Detach existing driver. */ |
| 152 | |
| 153 | /* Flags for DEV_CLEAR_DRIVER. */ |
| 154 | #define	DEVF_CLEAR_DRIVER_DETACH 0x0000001	/* Detach existing driver. */ |
| 155 | |
| 156 | /* Flags for DEV_DELETE. */ |
| 157 | #define	DEVF_FORCE_DELETE	0x0000001 |
| 158 | |
| 159 | /* Flags for DEV_RESET */ |
| 160 | #define	DEVF_RESET_DETACH	0x0000001	/* Detach drivers vs suspend |
| 161 | 						 device */ |
| 162 | #define DEVICE_UNIT_ANY		(-1) |
| 163 | |
| 164 | #ifdef _KERNEL |
| 165 | |
| 166 | #include <sys/_eventhandler.h> |
| 167 | #include <sys/kobj.h> |
| 168 | #include <sys/systm.h> |
| 169 | #include <sys/devctl.h> |
| 170 | |
| 171 | /** |
| 172 | * Device name parsers. Hook to allow device enumerators to map |
| 173 | * scheme-specific names to a device. |
| 174 | */ |
| 175 | typedef void (*dev_lookup_fn)(void *arg, const char *name, |
| 176 | device_t *result); |
| 177 | EVENTHANDLER_DECLARE(dev_lookup, dev_lookup_fn); |
| 178 | |
| 179 | /** |
| 180 | * @brief A device driver. |
| 181 | * |
| 182 | * Provides an abstraction layer for driver dispatch. |
| 183 | */ |
| 184 | typedef struct kobj_class	driver_t; |
| 185 | |
| 186 | /** |
| 187 | * @brief A device class |
| 188 | * |
| 189 | * The devclass object has two main functions in the system. The first |
| 190 | * is to manage the allocation of unit numbers for device instances |
| 191 | * and the second is to hold the list of device drivers for a |
| 192 | * particular bus type. Each devclass has a name and there cannot be |
| 193 | * two devclasses with the same name. This ensures that unique unit |
| 194 | * numbers are allocated to device instances. |
| 195 | * |
| 196 | * Drivers that support several different bus attachments (e.g. isa, |
| 197 | * pci, pccard) should all use the same devclass to ensure that unit |
| 198 | * numbers do not conflict. |
| 199 | * |
| 200 | * Each devclass may also have a parent devclass. This is used when |
| 201 | * searching for device drivers to allow a form of inheritance. When |
| 202 | * matching drivers with devices, first the driver list of the parent |
| 203 | * device's devclass is searched. If no driver is found in that list, |
| 204 | * the search continues in the parent devclass (if any). |
| 205 | */ |
| 206 | typedef struct devclass		*devclass_t; |
| 207 | |
| 208 | /** |
| 209 | * @brief A device method |
| 210 | */ |
| 211 | #define device_method_t		kobj_method_t |
| 212 | |
| 213 | /** |
| 214 | * @brief Driver interrupt filter return values |
| 215 | * |
| 216 | * If a driver provides an interrupt filter routine it must return an |
| 217 | * integer consisting of oring together zero or more of the following |
| 218 | * flags: |
| 219 | * |
| 220 | *	FILTER_STRAY	- this device did not trigger the interrupt |
| 221 | *	FILTER_HANDLED	- the interrupt has been fully handled and can be EOId |
| 222 | *	FILTER_SCHEDULE_THREAD - the threaded interrupt handler should be |
| 223 | *			 scheduled to execute |
| 224 | * |
| 225 | * If the driver does not provide a filter, then the interrupt code will |
| 226 | * act is if the filter had returned FILTER_SCHEDULE_THREAD. Note that it |
| 227 | * is illegal to specify any other flag with FILTER_STRAY and that it is |
| 228 | * illegal to not specify either of FILTER_HANDLED or FILTER_SCHEDULE_THREAD |
| 229 | * if FILTER_STRAY is not specified. |
| 230 | */ |
| 231 | #define	FILTER_STRAY		0x01 |
| 232 | #define	FILTER_HANDLED		0x02 |
| 233 | #define	FILTER_SCHEDULE_THREAD	0x04 |
| 234 | |
| 235 | /** |
| 236 | * @brief Driver interrupt service routines |
| 237 | * |
| 238 | * The filter routine is run in primary interrupt context and may not |
| 239 | * block or use regular mutexes. It may only use spin mutexes for |
| 240 | * synchronization. The filter may either completely handle the |
| 241 | * interrupt or it may perform some of the work and defer more |
| 242 | * expensive work to the regular interrupt handler. If a filter |
| 243 | * routine is not registered by the driver, then the regular interrupt |
| 244 | * handler is always used to handle interrupts from this device. |
| 245 | * |
| 246 | * The regular interrupt handler executes in its own thread context |
| 247 | * and may use regular mutexes. However, it is prohibited from |
| 248 | * sleeping on a sleep queue. |
| 249 | */ |
| 250 | typedef int driver_filter_t(void*); |
| 251 | typedef void driver_intr_t(void*); |
| 252 | |
| 253 | /** |
| 254 | * @brief Interrupt type bits. |
| 255 | * |
| 256 | * These flags may be passed by drivers to bus_setup_intr(9) when |
| 257 | * registering a new interrupt handler. The field is overloaded to |
| 258 | * specify both the interrupt's type and any special properties. |
| 259 | * |
| 260 | * The INTR_TYPE* bits will be passed to intr_priority(9) to determine |
| 261 | * the scheduling priority of the handler's ithread. Historically, each |
| 262 | * type was assigned a unique scheduling preference, but now only |
| 263 | * INTR_TYPE_CLK receives a default priority higher than other |
| 264 | * interrupts. See sys/priority.h. |
| 265 | * |
| 266 | * Buses may choose to modify or augment these flags as appropriate, |
| 267 | * e.g. nexus may apply INTR_EXCL. |
| 268 | */ |
| 269 | enum intr_type { |
| 270 | 	INTR_TYPE_TTY = 1, |
| 271 | 	INTR_TYPE_BIO = 2, |
| 272 | 	INTR_TYPE_NET = 4, |
| 273 | 	INTR_TYPE_CAM = 8, |
| 274 | 	INTR_TYPE_MISC = 16, |
| 275 | 	INTR_TYPE_CLK = 32, |
| 276 | 	INTR_TYPE_AV = 64, |
| 277 | 	INTR_EXCL = 256,		/* exclusive interrupt */ |
| 278 | 	INTR_MPSAFE = 512,		/* this interrupt is SMP safe */ |
| 279 | 	INTR_ENTROPY = 1024,		/* this interrupt provides entropy */ |
| 280 | 	INTR_SLEEPABLE = 2048,		/* this interrupt handler can sleep */ |
| 281 | 	INTR_MD1 = 4096,		/* flag reserved for MD use */ |
| 282 | 	INTR_MD2 = 8192,		/* flag reserved for MD use */ |
| 283 | 	INTR_MD3 = 16384,		/* flag reserved for MD use */ |
| 284 | 	INTR_MD4 = 32768		/* flag reserved for MD use */ |
| 285 | }; |
| 286 | |
| 287 | enum intr_trigger { |
| 288 | 	INTR_TRIGGER_INVALID = -1, |
| 289 | 	INTR_TRIGGER_CONFORM = 0, |
| 290 | 	INTR_TRIGGER_EDGE = 1, |
| 291 | 	INTR_TRIGGER_LEVEL = 2 |
| 292 | }; |
| 293 | |
| 294 | enum intr_polarity { |
| 295 | 	INTR_POLARITY_CONFORM = 0, |
| 296 | 	INTR_POLARITY_HIGH = 1, |
| 297 | 	INTR_POLARITY_LOW = 2 |
| 298 | }; |
| 299 | |
| 300 | /** |
| 301 | * CPU sets supported by bus_get_cpus(). Note that not all sets may be |
| 302 | * supported for a given device. If a request is not supported by a |
| 303 | * device (or its parents), then bus_get_cpus() will fail with EINVAL. |
| 304 | */ |
| 305 | enum cpu_sets { |
| 306 | 	LOCAL_CPUS = 0, |
| 307 | 	INTR_CPUS |
| 308 | }; |
| 309 | |
| 310 | struct resource; |
| 311 | |
| 312 | /** |
| 313 | * @brief A resource mapping. |
| 314 | */ |
| 315 | struct resource_map { |
| 316 | 	bus_space_tag_t r_bustag; |
| 317 | 	bus_space_handle_t r_bushandle; |
| 318 | 	bus_size_t r_size; |
| 319 | 	void	*r_vaddr; |
| 320 | }; |
| 321 | |
| 322 | /** |
| 323 | * @brief Optional properties of a resource mapping request. |
| 324 | */ |
| 325 | struct resource_map_request { |
| 326 | 	size_t	size; |
| 327 | 	rman_res_t offset; |
| 328 | 	rman_res_t length; |
| 329 | 	vm_memattr_t memattr; |
| 330 | }; |
| 331 | |
| 332 | void	resource_init_map_request_impl(struct resource_map_request *_args, |
| 333 | 	 size_t _sz); |
| 334 | #define	resource_init_map_request(rmr) 					\ |
| 335 | 	resource_init_map_request_impl((rmr), sizeof(*(rmr))) |
| 336 | int	resource_validate_map_request(struct resource *r, |
| 337 | 	 struct resource_map_request *in, struct resource_map_request *out, |
| 338 | 	 rman_res_t *startp, rman_res_t *lengthp); |
| 339 | |
| 340 | /* |
| 341 | * Definitions for drivers which need to keep simple lists of resources |
| 342 | * for their child devices. |
| 343 | */ |
| 344 | |
| 345 | /** |
| 346 | * @brief An entry for a single resource in a resource list. |
| 347 | */ |
| 348 | struct resource_list_entry { |
| 349 | 	STAILQ_ENTRY(resource_list_entry) link; |
| 350 | 	int	type;			/**< @brief type argument to alloc_resource */ |
| 351 | 	int	rid;			/**< @brief resource identifier */ |
| 352 | 	int	flags;			/**< @brief resource flags */ |
| 353 | 	struct	resource *res;		/**< @brief the real resource when allocated */ |
| 354 | 	rman_res_t	start;		/**< @brief start of resource range */ |
| 355 | 	rman_res_t	end;		/**< @brief end of resource range */ |
| 356 | 	rman_res_t	count;			/**< @brief count within range */ |
| 357 | }; |
| 358 | STAILQ_HEAD(resource_list, resource_list_entry); |
| 359 | |
| 360 | #define	RLE_RESERVED		0x0001	/* Reserved by the parent bus. */ |
| 361 | #define	RLE_ALLOCATED		0x0002	/* Reserved resource is allocated. */ |
| 362 | #define	RLE_PREFETCH		0x0004	/* Resource is a prefetch range. */ |
| 363 | |
| 364 | void	resource_list_init(struct resource_list *rl); |
| 365 | void	resource_list_free(struct resource_list *rl); |
| 366 | struct resource_list_entry * |
| 367 | 	resource_list_add(struct resource_list *rl, |
| 368 | 			 int type, int rid, |
| 369 | 			 rman_res_t start, rman_res_t end, rman_res_t count); |
| 370 | int	resource_list_add_next(struct resource_list *rl, |
| 371 | 			 int type, |
| 372 | 			 rman_res_t start, rman_res_t end, rman_res_t count); |
| 373 | int	resource_list_busy(struct resource_list *rl, |
| 374 | 			 int type, int rid); |
| 375 | int	resource_list_reserved(struct resource_list *rl, int type, int rid); |
| 376 | struct resource_list_entry* |
| 377 | 	resource_list_find(struct resource_list *rl, |
| 378 | 			 int type, int rid); |
| 379 | void	resource_list_delete(struct resource_list *rl, |
| 380 | 			 int type, int rid); |
| 381 | struct resource * |
| 382 | 	resource_list_alloc(struct resource_list *rl, |
| 383 | 			 device_t bus, device_t child, |
| 384 | 			 int type, int *rid, |
| 385 | 			 rman_res_t start, rman_res_t end, |
| 386 | 			 rman_res_t count, u_int flags); |
| 387 | int	resource_list_release(struct resource_list *rl, |
| 388 | 			 device_t bus, device_t child, |
| 389 | 			 struct resource *res); |
| 390 | int	resource_list_release_active(struct resource_list *rl, |
| 391 | 				 device_t bus, device_t child, |
| 392 | 				 int type); |
| 393 | struct resource * |
| 394 | 	resource_list_reserve(struct resource_list *rl, |
| 395 | 			 device_t bus, device_t child, |
| 396 | 			 int type, int *rid, |
| 397 | 			 rman_res_t start, rman_res_t end, |
| 398 | 			 rman_res_t count, u_int flags); |
| 399 | int	resource_list_unreserve(struct resource_list *rl, |
| 400 | 				device_t bus, device_t child, |
| 401 | 				int type, int rid); |
| 402 | void	resource_list_purge(struct resource_list *rl); |
| 403 | int	resource_list_print_type(struct resource_list *rl, |
| 404 | 				 const char *name, int type, |
| 405 | 				 const char *format); |
| 406 | |
| 407 | /* |
| 408 | * The root bus, to which all top-level buses are attached. |
| 409 | */ |
| 410 | extern device_t root_bus; |
| 411 | extern devclass_t root_devclass; |
| 412 | void	root_bus_configure(void); |
| 413 | |
| 414 | /* |
| 415 | * Useful functions for implementing buses. |
| 416 | */ |
| 417 | |
| 418 | struct _cpuset; |
| 419 | |
| 420 | int	bus_generic_activate_resource(device_t dev, device_t child, |
| 421 | 				 struct resource *r); |
| 422 | device_t |
| 423 | 	bus_generic_add_child(device_t dev, u_int order, const char *name, |
| 424 | 			 int unit); |
| 425 | int	bus_generic_adjust_resource(device_t bus, device_t child, |
| 426 | 				 struct resource *r, rman_res_t start, |
| 427 | 				 rman_res_t end); |
| 428 | struct resource * |
| 429 | 	bus_generic_alloc_resource(device_t bus, device_t child, int type, |
| 430 | 				 int *rid, rman_res_t start, rman_res_t end, |
| 431 | 				 rman_res_t count, u_int flags); |
| 432 | int	bus_generic_translate_resource(device_t dev, int type, rman_res_t start, |
| 433 | 			 rman_res_t *newstart); |
| 434 | int	bus_generic_attach(device_t dev) |
| 435 | 	__deprecated1("Use bus_attach_children instead"); |
| 436 | int	bus_generic_bind_intr(device_t dev, device_t child, |
| 437 | 			 struct resource *irq, int cpu); |
| 438 | int	bus_generic_child_location(device_t dev, device_t child, struct sbuf *sb); |
| 439 | int	bus_generic_child_pnpinfo(device_t dev, device_t child, struct sbuf *sb); |
| 440 | int	bus_generic_child_present(device_t dev, device_t child); |
| 441 | int	bus_generic_config_intr(device_t, int, enum intr_trigger, |
| 442 | 				enum intr_polarity); |
| 443 | int	bus_generic_describe_intr(device_t dev, device_t child, |
| 444 | 				 struct resource *irq, void *cookie, |
| 445 | 				 const char *descr); |
| 446 | int	bus_generic_deactivate_resource(device_t dev, device_t child, |
| 447 | 					struct resource *r); |
| 448 | int	bus_generic_detach(device_t dev); |
| 449 | void	bus_generic_driver_added(device_t dev, driver_t *driver); |
| 450 | int	bus_generic_get_cpus(device_t dev, device_t child, enum cpu_sets op, |
| 451 | 			 size_t setsize, struct _cpuset *cpuset); |
| 452 | bus_dma_tag_t |
| 453 | 	bus_generic_get_dma_tag(device_t dev, device_t child); |
| 454 | bus_space_tag_t |
| 455 | 	bus_generic_get_bus_tag(device_t dev, device_t child); |
| 456 | int	bus_generic_get_domain(device_t dev, device_t child, int *domain); |
| 457 | ssize_t	bus_generic_get_property(device_t dev, device_t child, |
| 458 | 				 const char *propname, void *propvalue, |
| 459 | 				 size_t size, device_property_type_t type); |
| 460 | int	bus_generic_map_resource(device_t dev, device_t child, |
| 461 | 				 struct resource *r, |
| 462 | 				 struct resource_map_request *args, |
| 463 | 				 struct resource_map *map); |
| 464 | void	bus_generic_new_pass(device_t dev); |
| 465 | int	bus_print_child_header(device_t dev, device_t child); |
| 466 | int	bus_print_child_domain(device_t dev, device_t child); |
| 467 | int	bus_print_child_footer(device_t dev, device_t child); |
| 468 | int	bus_generic_print_child(device_t dev, device_t child); |
| 469 | int	bus_generic_probe(device_t dev) |
| 470 | 	__deprecated1("Use bus_identify_children instead"); |
| 471 | int	bus_generic_read_ivar(device_t dev, device_t child, int which, |
| 472 | 			 uintptr_t *result); |
| 473 | int	bus_generic_release_resource(device_t bus, device_t child, |
| 474 | 				 struct resource *r); |
| 475 | int	bus_generic_resume(device_t dev); |
| 476 | int	bus_generic_resume_child(device_t dev, device_t child); |
| 477 | int	bus_generic_setup_intr(device_t dev, device_t child, |
| 478 | 			 struct resource *irq, int flags, |
| 479 | 			 driver_filter_t *filter, driver_intr_t *intr, |
| 480 | 			 void *arg, void **cookiep); |
| 481 | |
| 482 | struct resource * |
| 483 | 	bus_generic_rl_alloc_resource (device_t, device_t, int, int *, |
| 484 | 				 rman_res_t, rman_res_t, rman_res_t, u_int); |
| 485 | void	bus_generic_rl_delete_resource (device_t, device_t, int, int); |
| 486 | int	bus_generic_rl_get_resource (device_t, device_t, int, int, rman_res_t *, |
| 487 | 				 rman_res_t *); |
| 488 | int	bus_generic_rl_set_resource (device_t, device_t, int, int, rman_res_t, |
| 489 | 				 rman_res_t); |
| 490 | int	bus_generic_rl_release_resource (device_t, device_t, struct resource *); |
| 491 | struct resource * |
| 492 | 	bus_generic_rman_alloc_resource(device_t dev, device_t child, int type, |
| 493 | 					int *rid, rman_res_t start, |
| 494 | 					rman_res_t end, rman_res_t count, |
| 495 | 					u_int flags); |
| 496 | int	bus_generic_rman_adjust_resource(device_t dev, device_t child, |
| 497 | 					 struct resource *r, rman_res_t start, |
| 498 | 					 rman_res_t end); |
| 499 | int	bus_generic_rman_release_resource(device_t dev, device_t child, |
| 500 | 					 struct resource *r); |
| 501 | int	bus_generic_rman_activate_resource(device_t dev, device_t child, |
| 502 | 					 struct resource *r); |
| 503 | int	bus_generic_rman_deactivate_resource(device_t dev, device_t child, |
| 504 | 					 struct resource *r); |
| 505 | |
| 506 | int	bus_generic_shutdown(device_t dev); |
| 507 | int	bus_generic_suspend(device_t dev); |
| 508 | int	bus_generic_suspend_child(device_t dev, device_t child); |
| 509 | int	bus_generic_teardown_intr(device_t dev, device_t child, |
| 510 | 				 struct resource *irq, void *cookie); |
| 511 | int	bus_generic_suspend_intr(device_t dev, device_t child, |
| 512 | 				 struct resource *irq); |
| 513 | int	bus_generic_resume_intr(device_t dev, device_t child, |
| 514 | 				 struct resource *irq); |
| 515 | int	bus_generic_unmap_resource(device_t dev, device_t child, |
| 516 | 				 struct resource *r, |
| 517 | 				 struct resource_map *map); |
| 518 | int	bus_generic_write_ivar(device_t dev, device_t child, int which, |
| 519 | 			 uintptr_t value); |
| 520 | int	bus_generic_get_device_path(device_t bus, device_t child, const char *locator, |
| 521 | 				 struct sbuf *sb); |
| 522 | int	bus_helper_reset_post(device_t dev, int flags); |
| 523 | int	bus_helper_reset_prepare(device_t dev, int flags); |
| 524 | int	bus_null_rescan(device_t dev); |
| 525 | |
| 526 | /* |
| 527 | * Wrapper functions for the BUS_*_RESOURCE methods to make client code |
| 528 | * a little simpler. |
| 529 | */ |
| 530 | |
| 531 | struct resource_spec { |
| 532 | 	int	type; |
| 533 | 	int	rid; |
| 534 | 	int	flags; |
| 535 | }; |
| 536 | #define	RESOURCE_SPEC_END	{-1, 0, 0} |
| 537 | |
| 538 | int	bus_alloc_resources(device_t dev, struct resource_spec *rs, |
| 539 | 			 struct resource **res); |
| 540 | void	bus_release_resources(device_t dev, const struct resource_spec *rs, |
| 541 | 			 struct resource **res); |
| 542 | |
| 543 | int	bus_adjust_resource(device_t child, struct resource *r, |
| 544 | 			 rman_res_t start, rman_res_t end); |
| 545 | int	bus_translate_resource(device_t child, int type, rman_res_t start, |
| 546 | 			 rman_res_t *newstart); |
| 547 | struct	resource *bus_alloc_resource(device_t dev, int type, int *rid, |
| 548 | 				 rman_res_t start, rman_res_t end, |
| 549 | 				 rman_res_t count, u_int flags); |
| 550 | int	bus_activate_resource(device_t dev, struct resource *r); |
| 551 | int	bus_deactivate_resource(device_t dev, struct resource *r); |
| 552 | int	bus_map_resource(device_t dev, struct resource *r, |
| 553 | 			 struct resource_map_request *args, |
| 554 | 			 struct resource_map *map); |
| 555 | int	bus_unmap_resource(device_t dev, struct resource *r, |
| 556 | 			 struct resource_map *map); |
| 557 | int	bus_get_cpus(device_t dev, enum cpu_sets op, size_t setsize, |
| 558 | 		 struct _cpuset *cpuset); |
| 559 | bus_dma_tag_t bus_get_dma_tag(device_t dev); |
| 560 | bus_space_tag_t bus_get_bus_tag(device_t dev); |
| 561 | int	bus_get_domain(device_t dev, int *domain); |
| 562 | int	bus_release_resource(device_t dev, struct resource *r); |
| 563 | int	bus_free_resource(device_t dev, int type, struct resource *r); |
| 564 | int	bus_setup_intr(device_t dev, struct resource *r, int flags, |
| 565 | 		 driver_filter_t filter, driver_intr_t handler, |
| 566 | 		 void *arg, void **cookiep); |
| 567 | int	bus_teardown_intr(device_t dev, struct resource *r, void *cookie); |
| 568 | int	bus_suspend_intr(device_t dev, struct resource *r); |
| 569 | int	bus_resume_intr(device_t dev, struct resource *r); |
| 570 | int	bus_bind_intr(device_t dev, struct resource *r, int cpu); |
| 571 | int	bus_describe_intr(device_t dev, struct resource *irq, void *cookie, |
| 572 | 			 const char *fmt, ...) __printflike(4, 5); |
| 573 | int	bus_set_resource(device_t dev, int type, int rid, |
| 574 | 			 rman_res_t start, rman_res_t count); |
| 575 | int	bus_get_resource(device_t dev, int type, int rid, |
| 576 | 			 rman_res_t *startp, rman_res_t *countp); |
| 577 | rman_res_t	bus_get_resource_start(device_t dev, int type, int rid); |
| 578 | rman_res_t	bus_get_resource_count(device_t dev, int type, int rid); |
| 579 | void	bus_delete_resource(device_t dev, int type, int rid); |
| 580 | int	bus_child_present(device_t child); |
| 581 | int	bus_child_pnpinfo(device_t child, struct sbuf *sb); |
| 582 | int	bus_child_location(device_t child, struct sbuf *sb); |
| 583 | |
| 584 | void	bus_attach_children(device_t dev); |
| 585 | void	bus_delayed_attach_children(device_t bus); |
| 586 | int	bus_detach_children(device_t dev); |
| 587 | void	bus_enumerate_hinted_children(device_t bus); |
| 588 | void	bus_identify_children(device_t dev); |
| 589 | |
| 590 | static __inline struct resource * |
| 591 | bus_alloc_resource_any(device_t dev, int type, int *rid, u_int flags) |
| 592 | { |
| 593 | 	return (bus_alloc_resource(dev, type, rid, 0, ~0, 1, flags)); |
| 594 | } |
| 595 | |
| 596 | static __inline struct resource * |
| 597 | bus_alloc_resource_anywhere(device_t dev, int type, int *rid, |
| 598 | rman_res_t count, u_int flags) |
| 599 | { |
| 600 | 	return (bus_alloc_resource(dev, type, rid, 0, ~0, count, flags)); |
| 601 | } |
| 602 | |
| 603 | /* Compat shims for simpler bus resource API. */ |
| 604 | int	bus_adjust_resource_old(device_t child, int type, struct resource *r, |
| 605 | rman_res_t start, rman_res_t end); |
| 606 | int	bus_activate_resource_old(device_t dev, int type, int rid, |
| 607 | 				 struct resource *r); |
| 608 | int	bus_deactivate_resource_old(device_t dev, int type, int rid, |
| 609 | 				 struct resource *r); |
| 610 | int	bus_map_resource_old(device_t dev, int type, struct resource *r, |
| 611 | 			 struct resource_map_request *args, |
| 612 | 			 struct resource_map *map); |
| 613 | int	bus_unmap_resource_old(device_t dev, int type, struct resource *r, |
| 614 | 			 struct resource_map *map); |
| 615 | int	bus_release_resource_old(device_t dev, int type, int rid, |
| 616 | 				 struct resource *r); |
| 617 | |
| 618 | #define	_BUS_API_MACRO(_1, _2, _3, _4, _5, NAME, ...)	NAME |
| 619 | |
| 620 | #define	bus_adjust_resource(...)					\ |
| 621 | 	_BUS_API_MACRO(__VA_ARGS__, bus_adjust_resource_old,		\ |
| 622 | 	 bus_adjust_resource)(__VA_ARGS__) |
| 623 | |
| 624 | #define	bus_activate_resource(...)					\ |
| 625 | 	_BUS_API_MACRO(__VA_ARGS__, INVALID, bus_activate_resource_old,	\ |
| 626 | 	 INVALID, bus_activate_resource)(__VA_ARGS__) |
| 627 | |
| 628 | #define	bus_deactivate_resource(...)					\ |
| 629 | 	_BUS_API_MACRO(__VA_ARGS__, INVALID, bus_deactivate_resource_old, \ |
| 630 | 	 INVALID, bus_deactivate_resource)(__VA_ARGS__) |
| 631 | |
| 632 | #define	bus_map_resource(...)						\ |
| 633 | 	_BUS_API_MACRO(__VA_ARGS__, bus_map_resource_old,		\ |
| 634 | 	 bus_map_resource)(__VA_ARGS__) |
| 635 | |
| 636 | #define	bus_unmap_resource(...)						\ |
| 637 | 	_BUS_API_MACRO(__VA_ARGS__, INVALID, bus_unmap_resource_old,	\ |
| 638 | 	 bus_unmap_resource)(__VA_ARGS__) |
| 639 | |
| 640 | #define	bus_release_resource(...)					\ |
| 641 | 	_BUS_API_MACRO(__VA_ARGS__, INVALID, bus_release_resource_old,	\ |
| 642 | 	 INVALID, bus_release_resource)(__VA_ARGS__) |
| 643 | |
| 644 | /* |
| 645 | * Access functions for device. |
| 646 | */ |
| 647 | device_t	device_add_child(device_t dev, const char *name, int unit); |
| 648 | device_t	device_add_child_ordered(device_t dev, u_int order, |
| 649 | 					 const char *name, int unit); |
| 650 | void	device_busy(device_t dev); |
| 651 | int	device_delete_child(device_t dev, device_t child); |
| 652 | int	device_delete_children(device_t dev); |
| 653 | int	device_attach(device_t dev); |
| 654 | int	device_detach(device_t dev); |
| 655 | void	device_disable(device_t dev); |
| 656 | void	device_enable(device_t dev); |
| 657 | device_t	device_find_child(device_t dev, const char *classname, |
| 658 | 				 int unit); |
| 659 | const char	*device_get_desc(device_t dev); |
| 660 | devclass_t	device_get_devclass(device_t dev); |
| 661 | driver_t	*device_get_driver(device_t dev); |
| 662 | u_int32_t	device_get_flags(device_t dev); |
| 663 | device_t	device_get_parent(device_t dev); |
| 664 | int	device_get_children(device_t dev, device_t **listp, int *countp); |
| 665 | void	*device_get_ivars(device_t dev); |
| 666 | void	device_set_ivars(device_t dev, void *ivars); |
| 667 | const	char *device_get_name(device_t dev); |
| 668 | const	char *device_get_nameunit(device_t dev); |
| 669 | void	*device_get_softc(device_t dev); |
| 670 | device_state_t	device_get_state(device_t dev); |
| 671 | int	device_get_unit(device_t dev); |
| 672 | struct sysctl_ctx_list *device_get_sysctl_ctx(device_t dev); |
| 673 | struct sysctl_oid *device_get_sysctl_tree(device_t dev); |
| 674 | int	device_has_quiet_children(device_t dev); |
| 675 | int	device_is_alive(device_t dev);	/* did probe succeed? */ |
| 676 | int	device_is_attached(device_t dev);	/* did attach succeed? */ |
| 677 | int	device_is_enabled(device_t dev); |
| 678 | int	device_is_suspended(device_t dev); |
| 679 | int	device_is_quiet(device_t dev); |
| 680 | device_t device_lookup_by_name(const char *name); |
| 681 | int	device_print_prettyname(device_t dev); |
| 682 | int	device_printf(device_t dev, const char *, ...) __printflike(2, 3); |
| 683 | int	device_log(device_t dev, int pri, const char *, ...) __printflike(3, 4); |
| 684 | int	device_probe(device_t dev); |
| 685 | int	device_probe_and_attach(device_t dev); |
| 686 | int	device_probe_child(device_t bus, device_t dev); |
| 687 | int	device_quiesce(device_t dev); |
| 688 | void	device_quiet(device_t dev); |
| 689 | void	device_quiet_children(device_t dev); |
| 690 | void	device_set_desc(device_t dev, const char* desc); |
| 691 | void	device_set_descf(device_t dev, const char* fmt, ...) __printflike(2, 3); |
| 692 | void	device_set_desc_copy(device_t dev, const char* desc); |
| 693 | int	device_set_devclass(device_t dev, const char *classname); |
| 694 | int	device_set_devclass_fixed(device_t dev, const char *classname); |
| 695 | bool	device_is_devclass_fixed(device_t dev); |
| 696 | int	device_set_driver(device_t dev, driver_t *driver); |
| 697 | void	device_set_flags(device_t dev, u_int32_t flags); |
| 698 | void	device_set_softc(device_t dev, void *softc); |
| 699 | void	device_free_softc(void *softc); |
| 700 | void	device_claim_softc(device_t dev); |
| 701 | int	device_set_unit(device_t dev, int unit);	/* XXX DONT USE XXX */ |
| 702 | int	device_shutdown(device_t dev); |
| 703 | void	device_unbusy(device_t dev); |
| 704 | void	device_verbose(device_t dev); |
| 705 | ssize_t	device_get_property(device_t dev, const char *prop, void *val, |
| 706 | size_t sz, device_property_type_t type); |
| 707 | bool device_has_property(device_t dev, const char *prop); |
| 708 | |
| 709 | /* |
| 710 | * Access functions for devclass. |
| 711 | */ |
| 712 | int		devclass_add_driver(devclass_t dc, driver_t *driver, |
| 713 | 				 int pass, devclass_t *dcp); |
| 714 | devclass_t	devclass_create(const char *classname); |
| 715 | int		devclass_delete_driver(devclass_t busclass, driver_t *driver); |
| 716 | devclass_t	devclass_find(const char *classname); |
| 717 | const char	*devclass_get_name(devclass_t dc); |
| 718 | device_t	devclass_get_device(devclass_t dc, int unit); |
| 719 | void	*devclass_get_softc(devclass_t dc, int unit); |
| 720 | int	devclass_get_devices(devclass_t dc, device_t **listp, int *countp); |
| 721 | int	devclass_get_drivers(devclass_t dc, driver_t ***listp, int *countp); |
| 722 | int	devclass_get_count(devclass_t dc); |
| 723 | int	devclass_get_maxunit(devclass_t dc); |
| 724 | int	devclass_find_free_unit(devclass_t dc, int unit); |
| 725 | void	devclass_set_parent(devclass_t dc, devclass_t pdc); |
| 726 | devclass_t	devclass_get_parent(devclass_t dc); |
| 727 | struct sysctl_ctx_list *devclass_get_sysctl_ctx(devclass_t dc); |
| 728 | struct sysctl_oid *devclass_get_sysctl_tree(devclass_t dc); |
| 729 | |
| 730 | /* |
| 731 | * Access functions for device resources. |
| 732 | */ |
| 733 | int	resource_int_value(const char *name, int unit, const char *resname, |
| 734 | 			 int *result); |
| 735 | int	resource_long_value(const char *name, int unit, const char *resname, |
| 736 | 			 long *result); |
| 737 | int	resource_string_value(const char *name, int unit, const char *resname, |
| 738 | 			 const char **result); |
| 739 | int	resource_disabled(const char *name, int unit); |
| 740 | int	resource_find_match(int *anchor, const char **name, int *unit, |
| 741 | 			 const char *resname, const char *value); |
| 742 | int	resource_find_dev(int *anchor, const char *name, int *unit, |
| 743 | 			 const char *resname, const char *value); |
| 744 | int	resource_unset_value(const char *name, int unit, const char *resname); |
| 745 | |
| 746 | /* |
| 747 | * Functions for maintaining and checking consistency of |
| 748 | * bus information exported to userspace. |
| 749 | */ |
| 750 | int	bus_data_generation_check(int generation); |
| 751 | void	bus_data_generation_update(void); |
| 752 | |
| 753 | /** |
| 754 | * Some convenience defines for probe routines to return. These are just |
| 755 | * suggested values, and there's nothing magical about them. |
| 756 | * BUS_PROBE_SPECIFIC is for devices that cannot be reprobed, and that no |
| 757 | * possible other driver may exist (typically legacy drivers who don't follow |
| 758 | * all the rules, or special needs drivers). BUS_PROBE_VENDOR is the |
| 759 | * suggested value that vendor supplied drivers use. This is for source or |
| 760 | * binary drivers that are not yet integrated into the FreeBSD tree. Its use |
| 761 | * in the base OS is prohibited. BUS_PROBE_DEFAULT is the normal return value |
| 762 | * for drivers to use. It is intended that nearly all of the drivers in the |
| 763 | * tree should return this value. BUS_PROBE_LOW_PRIORITY are for drivers that |
| 764 | * have special requirements like when there are two drivers that support |
| 765 | * overlapping series of hardware devices. In this case the one that supports |
| 766 | * the older part of the line would return this value, while the one that |
| 767 | * supports the newer ones would return BUS_PROBE_DEFAULT. BUS_PROBE_GENERIC |
| 768 | * is for drivers that wish to have a generic form and a specialized form, |
| 769 | * like is done with the pci bus and the acpi pci bus. BUS_PROBE_HOOVER is |
| 770 | * for those buses that implement a generic device placeholder for devices on |
| 771 | * the bus that have no more specific driver for them (aka ugen). |
| 772 | * BUS_PROBE_NOWILDCARD or lower means that the device isn't really bidding |
| 773 | * for a device node, but accepts only devices that its parent has told it |
| 774 | * use this driver. |
| 775 | */ |
| 776 | #define BUS_PROBE_SPECIFIC	0	/* Only I can use this device */ |
| 777 | #define BUS_PROBE_VENDOR	(-10)	/* Vendor supplied driver */ |
| 778 | #define BUS_PROBE_DEFAULT	(-20)	/* Base OS default driver */ |
| 779 | #define BUS_PROBE_LOW_PRIORITY	(-40)	/* Older, less desirable drivers */ |
| 780 | #define BUS_PROBE_GENERIC	(-100)	/* generic driver for dev */ |
| 781 | #define BUS_PROBE_HOOVER	(-1000000) /* Driver for any dev on bus */ |
| 782 | #define BUS_PROBE_NOWILDCARD	(-2000000000) /* No wildcard device matches */ |
| 783 | |
| 784 | /** |
| 785 | * During boot, the device tree is scanned multiple times. Each scan, |
| 786 | * or pass, drivers may be attached to devices. Each driver |
| 787 | * attachment is assigned a pass number. Drivers may only probe and |
| 788 | * attach to devices if their pass number is less than or equal to the |
| 789 | * current system-wide pass number. The default pass is the last pass |
| 790 | * and is used by most drivers. Drivers needed by the scheduler are |
| 791 | * probed in earlier passes. |
| 792 | */ |
| 793 | #define	BUS_PASS_ROOT		0	/* Used to attach root0. */ |
| 794 | #define	BUS_PASS_BUS		10	/* Buses and bridges. */ |
| 795 | #define	BUS_PASS_CPU		20	/* CPU devices. */ |
| 796 | #define	BUS_PASS_RESOURCE	30	/* Resource discovery. */ |
| 797 | #define	BUS_PASS_INTERRUPT	40	/* Interrupt controllers. */ |
| 798 | #define	BUS_PASS_TIMER		50	/* Timers and clocks. */ |
| 799 | #define	BUS_PASS_SCHEDULER	60	/* Start scheduler. */ |
| 800 | #define	BUS_PASS_SUPPORTDEV	100000	/* Drivers which support DEFAULT drivers. */ |
| 801 | #define	BUS_PASS_DEFAULT	__INT_MAX /* Everything else. */ |
| 802 | |
| 803 | #define	BUS_PASS_ORDER_FIRST	0 |
| 804 | #define	BUS_PASS_ORDER_EARLY	2 |
| 805 | #define	BUS_PASS_ORDER_MIDDLE	5 |
| 806 | #define	BUS_PASS_ORDER_LATE	7 |
| 807 | #define	BUS_PASS_ORDER_LAST	9 |
| 808 | |
| 809 | #define BUS_LOCATOR_ACPI	"ACPI" |
| 810 | #define BUS_LOCATOR_FREEBSD	"FreeBSD" |
| 811 | #define BUS_LOCATOR_UEFI	"UEFI" |
| 812 | #define BUS_LOCATOR_OFW		"OFW" |
| 813 | |
| 814 | int	bus_get_pass(void); |
| 815 | |
| 816 | /** |
| 817 | * Routines to lock / unlock the newbus lock. |
| 818 | * Must be taken out to interact with newbus. |
| 819 | */ |
| 820 | void bus_topo_lock(void); |
| 821 | void bus_topo_unlock(void); |
| 822 | struct mtx * bus_topo_mtx(void); |
| 823 | void bus_topo_assert(void); |
| 824 | |
| 825 | /** |
| 826 | * Shorthands for constructing method tables. |
| 827 | */ |
| 828 | #define	DEVMETHOD	KOBJMETHOD |
| 829 | #define	DEVMETHOD_END	KOBJMETHOD_END |
| 830 | |
| 831 | /* |
| 832 | * Some common device interfaces. |
| 833 | */ |
| 834 | #include "device_if.h" |
| 835 | #include "bus_if.h" |
| 836 | |
| 837 | struct	module; |
| 838 | |
| 839 | int	driver_module_handler(struct module *, int, void *); |
| 840 | |
| 841 | /** |
| 842 | * Module support for automatically adding drivers to buses. |
| 843 | */ |
| 844 | struct driver_module_data { |
| 845 | 	int		(*dmd_chainevh)(struct module *, int, void *); |
| 846 | 	void		*dmd_chainarg; |
| 847 | 	const char	*dmd_busname; |
| 848 | 	kobj_class_t	dmd_driver; |
| 849 | 	devclass_t	*dmd_devclass; |
| 850 | 	int		dmd_pass; |
| 851 | }; |
| 852 | |
| 853 | #define	EARLY_DRIVER_MODULE_ORDERED(_name, busname, driver, evh, arg,	\ |
| 854 | order, pass)							\ |
| 855 | 									\ |
| 856 | static struct driver_module_data _name##_##busname##_driver_mod = {	\ |
| 857 | 	.dmd_chainevh = evh,						\ |
| 858 | 	.dmd_chainarg = arg,						\ |
| 859 | 	.dmd_busname = #busname,					\ |
| 860 | 	.dmd_driver = (kobj_class_t)&driver,				\ |
| 861 | 	.dmd_devclass = NULL,						\ |
| 862 | 	.dmd_pass = pass,						\ |
| 863 | };									\ |
| 864 | 									\ |
| 865 | static moduledata_t _name##_##busname##_mod = {				\ |
| 866 | 	.name =	 #busname "/" #_name ,					\ |
| 867 | 	.evhand = driver_module_handler,				\ |
| 868 | 	.priv =	 &_name##_##busname##_driver_mod,			\ |
| 869 | };									\ |
| 870 | DECLARE_MODULE(_name##_##busname, _name##_##busname##_mod,		\ |
| 871 | SI_SUB_DRIVERS, order) |
| 872 | |
| 873 | #define	EARLY_DRIVER_MODULE(name, busname, driver, evh, arg, pass)	\ |
| 874 | 	EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, evh, arg,	\ |
| 875 | 	 SI_ORDER_MIDDLE, pass) |
| 876 | |
| 877 | #define	DRIVER_MODULE_ORDERED(name, busname, driver, evh, arg, order)	\ |
| 878 | 	EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, evh, arg,	\ |
| 879 | 	 order, BUS_PASS_DEFAULT) |
| 880 | |
| 881 | #define	DRIVER_MODULE(name, busname, driver, evh, arg)			\ |
| 882 | 	EARLY_DRIVER_MODULE(name, busname, driver, evh, arg,		\ |
| 883 | 	 BUS_PASS_DEFAULT) |
| 884 | |
| 885 | /** |
| 886 | * Generic ivar accessor generation macros for bus drivers |
| 887 | */ |
| 888 | #define __BUS_ACCESSOR(varp, var, ivarp, ivar, type)			\ |
| 889 | 									\ |
| 890 | static __inline type varp ## _get_ ## var(device_t dev)			\ |
| 891 | {									\ |
| 892 | 	uintptr_t v;							\ |
| 893 | 	int e __diagused;						\ |
| 894 | 	e = BUS_READ_IVAR(device_get_parent(dev), dev,			\ |
| 895 | 	 ivarp ## _IVAR_ ## ivar, &v);				\ |
| 896 | 	KASSERT(e == 0, ("%s failed for %s on bus %s, error = %d",	\ |
| 897 | 	 __func__, device_get_nameunit(dev),				\ |
| 898 | 	 device_get_nameunit(device_get_parent(dev)), e));		\ |
| 899 | 	return ((type) v);						\ |
| 900 | }									\ |
| 901 | 									\ |
| 902 | static __inline void varp ## _set_ ## var(device_t dev, type t)		\ |
| 903 | {									\ |
| 904 | 	uintptr_t v = (uintptr_t) t;					\ |
| 905 | 	int e __diagused;						\ |
| 906 | 	e = BUS_WRITE_IVAR(device_get_parent(dev), dev,			\ |
| 907 | 	 ivarp ## _IVAR_ ## ivar, v);				\ |
| 908 | 	KASSERT(e == 0, ("%s failed for %s on bus %s, error = %d",	\ |
| 909 | 	 __func__, device_get_nameunit(dev),				\ |
| 910 | 	 device_get_nameunit(device_get_parent(dev)), e));		\ |
| 911 | } |
| 912 | |
| 913 | struct device_location_cache; |
| 914 | typedef struct device_location_cache device_location_cache_t; |
| 915 | device_location_cache_t *dev_wired_cache_init(void); |
| 916 | void dev_wired_cache_fini(device_location_cache_t *dcp); |
| 917 | bool dev_wired_cache_match(device_location_cache_t *dcp, device_t dev, const char *at); |
| 918 | |
| 919 | #define	DEV_PROP_NAME_IOMMU	"iommu-unit" |
| 920 | typedef void (*device_prop_dtr_t)(device_t dev, const char *name, void *val, |
| 921 | void *dtr_ctx); |
| 922 | int device_set_prop(device_t dev, const char *name, void *val, |
| 923 | device_prop_dtr_t dtr, void *dtr_ctx); |
| 924 | int device_get_prop(device_t dev, const char *name, void **valp); |
| 925 | int device_clear_prop(device_t dev, const char *name); |
| 926 | void device_clear_prop_alldev(const char *name); |
| 927 | |
| 928 | /** |
| 929 | * Shorthand macros, taking resource argument |
| 930 | * Generated with sys/tools/bus_macro.sh |
| 931 | */ |
| 932 | |
| 933 | #define bus_barrier(r, o, l, f) \ |
| 934 | 	bus_space_barrier((r)->r_bustag, (r)->r_bushandle, (o), (l), (f)) |
| 935 | #define bus_poke_1(r, o, v) \ |
| 936 | 	bus_space_poke_1((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 937 | #define bus_peek_1(r, o, vp) \ |
| 938 | 	bus_space_peek_1((r)->r_bustag, (r)->r_bushandle, (o), (vp)) |
| 939 | #define bus_read_1(r, o) \ |
| 940 | 	bus_space_read_1((r)->r_bustag, (r)->r_bushandle, (o)) |
| 941 | #define bus_read_multi_1(r, o, d, c) \ |
| 942 | 	bus_space_read_multi_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 943 | #define bus_read_region_1(r, o, d, c) \ |
| 944 | 	bus_space_read_region_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 945 | #define bus_set_multi_1(r, o, v, c) \ |
| 946 | 	bus_space_set_multi_1((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 947 | #define bus_set_region_1(r, o, v, c) \ |
| 948 | 	bus_space_set_region_1((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 949 | #define bus_write_1(r, o, v) \ |
| 950 | 	bus_space_write_1((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 951 | #define bus_write_multi_1(r, o, d, c) \ |
| 952 | 	bus_space_write_multi_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 953 | #define bus_write_region_1(r, o, d, c) \ |
| 954 | 	bus_space_write_region_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 955 | #define bus_read_stream_1(r, o) \ |
| 956 | 	bus_space_read_stream_1((r)->r_bustag, (r)->r_bushandle, (o)) |
| 957 | #define bus_read_multi_stream_1(r, o, d, c) \ |
| 958 | 	bus_space_read_multi_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 959 | #define bus_read_region_stream_1(r, o, d, c) \ |
| 960 | 	bus_space_read_region_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 961 | #define bus_set_multi_stream_1(r, o, v, c) \ |
| 962 | 	bus_space_set_multi_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 963 | #define bus_set_region_stream_1(r, o, v, c) \ |
| 964 | 	bus_space_set_region_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 965 | #define bus_write_stream_1(r, o, v) \ |
| 966 | 	bus_space_write_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 967 | #define bus_write_multi_stream_1(r, o, d, c) \ |
| 968 | 	bus_space_write_multi_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 969 | #define bus_write_region_stream_1(r, o, d, c) \ |
| 970 | 	bus_space_write_region_stream_1((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 971 | #define bus_poke_2(r, o, v) \ |
| 972 | 	bus_space_poke_2((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 973 | #define bus_peek_2(r, o, vp) \ |
| 974 | 	bus_space_peek_2((r)->r_bustag, (r)->r_bushandle, (o), (vp)) |
| 975 | #define bus_read_2(r, o) \ |
| 976 | 	bus_space_read_2((r)->r_bustag, (r)->r_bushandle, (o)) |
| 977 | #define bus_read_multi_2(r, o, d, c) \ |
| 978 | 	bus_space_read_multi_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 979 | #define bus_read_region_2(r, o, d, c) \ |
| 980 | 	bus_space_read_region_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 981 | #define bus_set_multi_2(r, o, v, c) \ |
| 982 | 	bus_space_set_multi_2((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 983 | #define bus_set_region_2(r, o, v, c) \ |
| 984 | 	bus_space_set_region_2((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 985 | #define bus_write_2(r, o, v) \ |
| 986 | 	bus_space_write_2((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 987 | #define bus_write_multi_2(r, o, d, c) \ |
| 988 | 	bus_space_write_multi_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 989 | #define bus_write_region_2(r, o, d, c) \ |
| 990 | 	bus_space_write_region_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 991 | #define bus_read_stream_2(r, o) \ |
| 992 | 	bus_space_read_stream_2((r)->r_bustag, (r)->r_bushandle, (o)) |
| 993 | #define bus_read_multi_stream_2(r, o, d, c) \ |
| 994 | 	bus_space_read_multi_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 995 | #define bus_read_region_stream_2(r, o, d, c) \ |
| 996 | 	bus_space_read_region_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 997 | #define bus_set_multi_stream_2(r, o, v, c) \ |
| 998 | 	bus_space_set_multi_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 999 | #define bus_set_region_stream_2(r, o, v, c) \ |
| 1000 | 	bus_space_set_region_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1001 | #define bus_write_stream_2(r, o, v) \ |
| 1002 | 	bus_space_write_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1003 | #define bus_write_multi_stream_2(r, o, d, c) \ |
| 1004 | 	bus_space_write_multi_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1005 | #define bus_write_region_stream_2(r, o, d, c) \ |
| 1006 | 	bus_space_write_region_stream_2((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1007 | #define bus_poke_4(r, o, v) \ |
| 1008 | 	bus_space_poke_4((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1009 | #define bus_peek_4(r, o, vp) \ |
| 1010 | 	bus_space_peek_4((r)->r_bustag, (r)->r_bushandle, (o), (vp)) |
| 1011 | #define bus_read_4(r, o) \ |
| 1012 | 	bus_space_read_4((r)->r_bustag, (r)->r_bushandle, (o)) |
| 1013 | #define bus_read_multi_4(r, o, d, c) \ |
| 1014 | 	bus_space_read_multi_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1015 | #define bus_read_region_4(r, o, d, c) \ |
| 1016 | 	bus_space_read_region_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1017 | #define bus_set_multi_4(r, o, v, c) \ |
| 1018 | 	bus_space_set_multi_4((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1019 | #define bus_set_region_4(r, o, v, c) \ |
| 1020 | 	bus_space_set_region_4((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1021 | #define bus_write_4(r, o, v) \ |
| 1022 | 	bus_space_write_4((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1023 | #define bus_write_multi_4(r, o, d, c) \ |
| 1024 | 	bus_space_write_multi_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1025 | #define bus_write_region_4(r, o, d, c) \ |
| 1026 | 	bus_space_write_region_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1027 | #define bus_read_stream_4(r, o) \ |
| 1028 | 	bus_space_read_stream_4((r)->r_bustag, (r)->r_bushandle, (o)) |
| 1029 | #define bus_read_multi_stream_4(r, o, d, c) \ |
| 1030 | 	bus_space_read_multi_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1031 | #define bus_read_region_stream_4(r, o, d, c) \ |
| 1032 | 	bus_space_read_region_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1033 | #define bus_set_multi_stream_4(r, o, v, c) \ |
| 1034 | 	bus_space_set_multi_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1035 | #define bus_set_region_stream_4(r, o, v, c) \ |
| 1036 | 	bus_space_set_region_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1037 | #define bus_write_stream_4(r, o, v) \ |
| 1038 | 	bus_space_write_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1039 | #define bus_write_multi_stream_4(r, o, d, c) \ |
| 1040 | 	bus_space_write_multi_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1041 | #define bus_write_region_stream_4(r, o, d, c) \ |
| 1042 | 	bus_space_write_region_stream_4((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1043 | #define bus_poke_8(r, o, v) \ |
| 1044 | 	bus_space_poke_8((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1045 | #define bus_peek_8(r, o, vp) \ |
| 1046 | 	bus_space_peek_8((r)->r_bustag, (r)->r_bushandle, (o), (vp)) |
| 1047 | #define bus_read_8(r, o) \ |
| 1048 | 	bus_space_read_8((r)->r_bustag, (r)->r_bushandle, (o)) |
| 1049 | #define bus_read_multi_8(r, o, d, c) \ |
| 1050 | 	bus_space_read_multi_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1051 | #define bus_read_region_8(r, o, d, c) \ |
| 1052 | 	bus_space_read_region_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1053 | #define bus_set_multi_8(r, o, v, c) \ |
| 1054 | 	bus_space_set_multi_8((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1055 | #define bus_set_region_8(r, o, v, c) \ |
| 1056 | 	bus_space_set_region_8((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1057 | #define bus_write_8(r, o, v) \ |
| 1058 | 	bus_space_write_8((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1059 | #define bus_write_multi_8(r, o, d, c) \ |
| 1060 | 	bus_space_write_multi_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1061 | #define bus_write_region_8(r, o, d, c) \ |
| 1062 | 	bus_space_write_region_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1063 | #define bus_read_stream_8(r, o) \ |
| 1064 | 	bus_space_read_stream_8((r)->r_bustag, (r)->r_bushandle, (o)) |
| 1065 | #define bus_read_multi_stream_8(r, o, d, c) \ |
| 1066 | 	bus_space_read_multi_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1067 | #define bus_read_region_stream_8(r, o, d, c) \ |
| 1068 | 	bus_space_read_region_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1069 | #define bus_set_multi_stream_8(r, o, v, c) \ |
| 1070 | 	bus_space_set_multi_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1071 | #define bus_set_region_stream_8(r, o, v, c) \ |
| 1072 | 	bus_space_set_region_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (v), (c)) |
| 1073 | #define bus_write_stream_8(r, o, v) \ |
| 1074 | 	bus_space_write_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (v)) |
| 1075 | #define bus_write_multi_stream_8(r, o, d, c) \ |
| 1076 | 	bus_space_write_multi_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1077 | #define bus_write_region_stream_8(r, o, d, c) \ |
| 1078 | 	bus_space_write_region_stream_8((r)->r_bustag, (r)->r_bushandle, (o), (d), (c)) |
| 1079 | #endif /* _KERNEL */ |
| 1080 | |
| 1081 | #endif /* !_SYS_BUS_H_ */ |