Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /*- |
2 | * Copyright (c) 1997,1998 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 | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
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 | * | |
07d2fd35 | 26 | * $FreeBSD: src/sys/sys/bus.h,v 1.30.2.5 2004/03/17 17:54:25 njl Exp $ |
dbcd0c9b | 27 | * $DragonFly: src/sys/sys/bus.h,v 1.25 2007/05/01 00:05:18 dillon Exp $ |
984263bc MD |
28 | */ |
29 | ||
30 | #ifndef _SYS_BUS_H_ | |
31 | #define _SYS_BUS_H_ | |
32 | ||
7490f18b | 33 | #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) |
984263bc | 34 | |
1bd40720 MD |
35 | #ifndef _SYS_TYPES_H_ |
36 | #include <sys/types.h> | |
37 | #endif | |
38 | #ifndef _SYS_QUEUE_H_ | |
984263bc | 39 | #include <sys/queue.h> |
1bd40720 MD |
40 | #endif |
41 | #ifndef _SYS_KOBJ_H_ | |
80eff43d | 42 | #include <sys/kobj.h> |
1bd40720 | 43 | #endif |
7490f18b | 44 | #ifdef _KERNEL |
e9cb6d99 | 45 | #include <sys/serialize.h> |
7490f18b | 46 | #endif |
1f7ab7c9 MD |
47 | #ifndef _SYS_BUS_DMA_H_ |
48 | #include <sys/bus_dma.h> | |
49 | #endif | |
50 | #ifndef _SYS_BUS_RESOURCE_H_ | |
51 | #include <sys/bus_resource.h> | |
52 | #endif | |
984263bc MD |
53 | |
54 | /* | |
55 | * Forward declarations | |
56 | */ | |
57 | typedef struct device *device_t; | |
e1bc6fbb | 58 | typedef struct kobj_class driver_t; |
984263bc | 59 | typedef struct devclass *devclass_t; |
80eff43d | 60 | #define device_method_t kobj_method_t |
984263bc MD |
61 | |
62 | typedef void driver_intr_t(void*); | |
63 | ||
64 | /* | |
ee61f228 MD |
65 | * Interrupt features mask. Note that DragonFly no longer implements |
66 | * INTR_TYPE_* flags. | |
984263bc | 67 | */ |
ee61f228 MD |
68 | #define INTR_FAST 0x0080 |
69 | #define INTR_EXCL 0x0100 | |
70 | #define INTR_MPSAFE 0x0200 | |
8b3ec75a | 71 | #define INTR_NOENTROPY 0x0400 |
477d3c1c | 72 | #define INTR_NOPOLL 0x0800 /* interrupt cannot be polled (e.g. ata) */ |
bbe77fc3 | 73 | |
78195a76 MD |
74 | #define INTR_NETSAFE INTR_MPSAFE |
75 | ||
e126caf1 MD |
76 | enum intr_trigger { |
77 | INTR_TRIGGER_CONFORM = 0, | |
78 | INTR_TRIGGER_EDGE = 1, | |
79 | INTR_TRIGGER_LEVEL = 2 | |
80 | }; | |
81 | ||
82 | enum intr_polarity { | |
83 | INTR_POLARITY_CONFORM = 0, | |
84 | INTR_POLARITY_HIGH = 1, | |
85 | INTR_POLARITY_LOW = 2 | |
984263bc | 86 | }; |
984263bc MD |
87 | |
88 | typedef int (*devop_t)(void); | |
89 | ||
984263bc MD |
90 | typedef enum device_state { |
91 | DS_NOTPRESENT, /* not probed or probe failed */ | |
92 | DS_ALIVE, /* probe succeeded */ | |
dbcd0c9b | 93 | DS_INPROGRESS, /* attach in progress */ |
984263bc MD |
94 | DS_ATTACHED, /* attach method called */ |
95 | DS_BUSY /* device is open */ | |
96 | } device_state_t; | |
97 | ||
98 | /* | |
99 | * Definitions for drivers which need to keep simple lists of resources | |
100 | * for their child devices. | |
101 | */ | |
102 | struct resource; | |
103 | ||
104 | struct resource_list_entry { | |
105 | SLIST_ENTRY(resource_list_entry) link; | |
106 | int type; /* type argument to alloc_resource */ | |
107 | int rid; /* resource identifier */ | |
108 | struct resource *res; /* the real resource when allocated */ | |
109 | u_long start; /* start of resource range */ | |
110 | u_long end; /* end of resource range */ | |
111 | u_long count; /* count within range */ | |
112 | }; | |
113 | SLIST_HEAD(resource_list, resource_list_entry); | |
114 | ||
7490f18b SS |
115 | #endif /* _KERNEL || _KERNEL_STRUCTURES */ |
116 | #ifdef _KERNEL | |
117 | ||
984263bc MD |
118 | /* |
119 | * Initialise a resource list. | |
120 | */ | |
121 | void resource_list_init(struct resource_list *rl); | |
122 | ||
123 | /* | |
124 | * Reclaim memory used by a resource list. | |
125 | */ | |
126 | void resource_list_free(struct resource_list *rl); | |
127 | ||
128 | /* | |
129 | * Add a resource entry or modify an existing entry if one exists with | |
130 | * the same type and rid. | |
131 | */ | |
132 | void resource_list_add(struct resource_list *rl, | |
133 | int type, int rid, | |
134 | u_long start, u_long end, u_long count); | |
135 | ||
136 | /* | |
137 | * Find a resource entry by type and rid. | |
138 | */ | |
139 | struct resource_list_entry* | |
140 | resource_list_find(struct resource_list *rl, | |
141 | int type, int rid); | |
142 | ||
143 | /* | |
144 | * Delete a resource entry. | |
145 | */ | |
146 | void resource_list_delete(struct resource_list *rl, | |
147 | int type, int rid); | |
148 | ||
149 | /* | |
150 | * Implement BUS_ALLOC_RESOURCE by looking up a resource from the list | |
151 | * and passing the allocation up to the parent of bus. This assumes | |
152 | * that the first entry of device_get_ivars(child) is a struct | |
153 | * resource_list. This also handles 'passthrough' allocations where a | |
154 | * child is a remote descendant of bus by passing the allocation up to | |
155 | * the parent of bus. | |
156 | */ | |
157 | struct resource * | |
158 | resource_list_alloc(struct resource_list *rl, | |
159 | device_t bus, device_t child, | |
160 | int type, int *rid, | |
161 | u_long start, u_long end, | |
162 | u_long count, u_int flags); | |
163 | ||
164 | /* | |
165 | * Implement BUS_RELEASE_RESOURCE. | |
166 | */ | |
167 | int resource_list_release(struct resource_list *rl, | |
168 | device_t bus, device_t child, | |
169 | int type, int rid, struct resource *res); | |
170 | ||
171 | /* | |
172 | * Print all resources of a specified type, for use in bus_print_child. | |
173 | * The name is printed if at least one resource of the given type is available. | |
174 | * The format ist used to print resource start and end. | |
175 | */ | |
176 | int resource_list_print_type(struct resource_list *rl, | |
177 | const char *name, int type, | |
178 | const char *format); | |
179 | ||
180 | /* | |
181 | * The root bus, to which all top-level busses are attached. | |
182 | */ | |
183 | extern device_t root_bus; | |
984263bc MD |
184 | void root_bus_configure(void); |
185 | ||
186 | /* | |
187 | * Useful functions for implementing busses. | |
188 | */ | |
189 | ||
190 | int bus_generic_activate_resource(device_t dev, device_t child, int type, | |
191 | int rid, struct resource *r); | |
e126caf1 MD |
192 | struct resource * |
193 | bus_generic_alloc_resource(device_t bus, device_t child, | |
194 | int type, int *rid, | |
195 | u_long start, u_long end, | |
196 | u_long count, u_int flags); | |
197 | struct resource_list * | |
198 | bus_generic_get_resource_list (device_t, device_t); | |
199 | ||
200 | int bus_generic_config_intr(device_t, int, enum intr_trigger, | |
201 | enum intr_polarity); | |
984263bc | 202 | int bus_generic_attach(device_t dev); |
22457186 | 203 | int bus_generic_child_present(device_t dev, device_t child); |
984263bc MD |
204 | int bus_generic_deactivate_resource(device_t dev, device_t child, int type, |
205 | int rid, struct resource *r); | |
206 | int bus_generic_detach(device_t dev); | |
e9cb6d99 | 207 | int bus_generic_disable_intr(device_t dev, device_t child, void *cookie); |
984263bc | 208 | void bus_generic_driver_added(device_t dev, driver_t *driver); |
67a2436e | 209 | void bus_generic_enable_intr(device_t dev, device_t child, void *cookie); |
984263bc MD |
210 | int bus_print_child_header(device_t dev, device_t child); |
211 | int bus_print_child_footer(device_t dev, device_t child); | |
212 | int bus_generic_print_child(device_t dev, device_t child); | |
39b5d600 MD |
213 | int bus_generic_identify(driver_t *driver, device_t parent); |
214 | int bus_generic_identify_sameunit(driver_t *driver, device_t parent); | |
984263bc | 215 | int bus_generic_probe(device_t dev); |
39b5d600 | 216 | int bus_generic_probe_hack(device_t dev); |
2581072f | 217 | device_t bus_generic_add_child(device_t, device_t, int, const char *, int); |
984263bc MD |
218 | int bus_generic_read_ivar(device_t dev, device_t child, int which, |
219 | uintptr_t *result); | |
220 | int bus_generic_release_resource(device_t bus, device_t child, | |
221 | int type, int rid, struct resource *r); | |
2581072f MD |
222 | int bus_generic_get_resource(device_t dev, device_t child, int type, |
223 | int rid, u_long *startp, u_long *countp); | |
224 | int bus_generic_set_resource(device_t dev, device_t child, int type, | |
225 | int rid, u_long start, u_long count); | |
226 | void bus_generic_delete_resource(device_t dev, device_t child, | |
227 | int type, int rid); | |
984263bc MD |
228 | int bus_generic_resume(device_t dev); |
229 | int bus_generic_setup_intr(device_t dev, device_t child, | |
230 | struct resource *irq, int flags, | |
e9cb6d99 MD |
231 | driver_intr_t *intr, void *arg, |
232 | void **cookiep, lwkt_serialize_t serializer); | |
984263bc MD |
233 | int bus_generic_shutdown(device_t dev); |
234 | int bus_generic_suspend(device_t dev); | |
235 | int bus_generic_teardown_intr(device_t dev, device_t child, | |
236 | struct resource *irq, void *cookie); | |
237 | int bus_generic_write_ivar(device_t dev, device_t child, int which, | |
238 | uintptr_t value); | |
239 | ||
e126caf1 MD |
240 | struct resource * |
241 | bus_generic_rl_alloc_resource (device_t, device_t, int, int *, | |
242 | u_long, u_long, u_long, u_int); | |
243 | void bus_generic_rl_delete_resource (device_t, device_t, int, int); | |
244 | int bus_generic_rl_get_resource (device_t, device_t, int, int, u_long *, | |
245 | u_long *); | |
246 | int bus_generic_rl_set_resource (device_t, device_t, int, int, u_long, | |
247 | u_long); | |
248 | int bus_generic_rl_release_resource (device_t, device_t, int, int, | |
249 | struct resource *); | |
250 | ||
984263bc MD |
251 | /* |
252 | * Wrapper functions for the BUS_*_RESOURCE methods to make client code | |
253 | * a little simpler. | |
254 | */ | |
255 | struct resource *bus_alloc_resource(device_t dev, int type, int *rid, | |
256 | u_long start, u_long end, u_long count, | |
257 | u_int flags); | |
258 | int bus_activate_resource(device_t dev, int type, int rid, | |
259 | struct resource *r); | |
260 | int bus_deactivate_resource(device_t dev, int type, int rid, | |
261 | struct resource *r); | |
e9cb6d99 | 262 | int bus_disable_intr(device_t dev, void *cookie); |
67a2436e | 263 | void bus_enable_intr(device_t dev, void *cookie); |
984263bc MD |
264 | int bus_release_resource(device_t dev, int type, int rid, |
265 | struct resource *r); | |
266 | int bus_setup_intr(device_t dev, struct resource *r, int flags, | |
e9cb6d99 MD |
267 | driver_intr_t handler, void *arg, |
268 | void **cookiep, lwkt_serialize_t serializer); | |
984263bc MD |
269 | int bus_teardown_intr(device_t dev, struct resource *r, void *cookie); |
270 | int bus_set_resource(device_t dev, int type, int rid, | |
271 | u_long start, u_long count); | |
272 | int bus_get_resource(device_t dev, int type, int rid, | |
273 | u_long *startp, u_long *countp); | |
274 | u_long bus_get_resource_start(device_t dev, int type, int rid); | |
275 | u_long bus_get_resource_count(device_t dev, int type, int rid); | |
276 | void bus_delete_resource(device_t dev, int type, int rid); | |
cac6f3da JS |
277 | int bus_child_present(device_t child); |
278 | int bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen); | |
279 | int bus_child_location_str(device_t child, char *buf, size_t buflen); | |
984263bc | 280 | |
07d2fd35 HP |
281 | static __inline struct resource * |
282 | bus_alloc_resource_any(device_t dev, int type, int *rid, u_int flags) | |
283 | { | |
284 | return (bus_alloc_resource(dev, type, rid, 0ul, ~0ul, 1, flags)); | |
285 | } | |
286 | ||
984263bc MD |
287 | /* |
288 | * Access functions for device. | |
289 | */ | |
290 | device_t device_add_child(device_t dev, const char *name, int unit); | |
291 | device_t device_add_child_ordered(device_t dev, int order, | |
292 | const char *name, int unit); | |
293 | void device_busy(device_t dev); | |
294 | int device_delete_child(device_t dev, device_t child); | |
295 | int device_detach(device_t dev); | |
296 | void device_disable(device_t dev); | |
297 | void device_enable(device_t dev); | |
298 | device_t device_find_child(device_t dev, const char *classname, | |
299 | int unit); | |
300 | const char *device_get_desc(device_t dev); | |
301 | devclass_t device_get_devclass(device_t dev); | |
302 | driver_t *device_get_driver(device_t dev); | |
303 | u_int32_t device_get_flags(device_t dev); | |
304 | device_t device_get_parent(device_t dev); | |
305 | int device_get_children(device_t dev, device_t **listp, int *countp); | |
306 | void *device_get_ivars(device_t dev); | |
307 | void device_set_ivars(device_t dev, void *ivars); | |
308 | const char *device_get_name(device_t dev); | |
309 | const char *device_get_nameunit(device_t dev); | |
310 | void *device_get_softc(device_t dev); | |
311 | device_state_t device_get_state(device_t dev); | |
312 | int device_get_unit(device_t dev); | |
313 | int device_is_alive(device_t dev); /* did probe succeed? */ | |
2140e77f | 314 | int device_is_attached(device_t dev); /* did attach succeed? */ |
984263bc MD |
315 | int device_is_enabled(device_t dev); |
316 | int device_is_quiet(device_t dev); | |
317 | int device_print_prettyname(device_t dev); | |
318 | int device_printf(device_t dev, const char *, ...) __printflike(2, 3); | |
319 | int device_probe_and_attach(device_t dev); | |
320 | void device_quiet(device_t dev); | |
321 | void device_set_desc(device_t dev, const char* desc); | |
322 | void device_set_desc_copy(device_t dev, const char* desc); | |
323 | int device_set_devclass(device_t dev, const char *classname); | |
324 | int device_set_driver(device_t dev, driver_t *driver); | |
325 | void device_set_flags(device_t dev, u_int32_t flags); | |
326 | void device_set_softc(device_t dev, void *softc); | |
dbcd0c9b | 327 | void device_set_async_attach(device_t dev, int enable); |
984263bc MD |
328 | int device_set_unit(device_t dev, int unit); /* XXX DONT USE XXX */ |
329 | int device_shutdown(device_t dev); | |
330 | void device_unbusy(device_t dev); | |
331 | void device_verbose(device_t dev); | |
332 | ||
333 | /* | |
334 | * Access functions for devclass. | |
335 | */ | |
91a0c258 JS |
336 | int devclass_add_driver(devclass_t dc, kobj_class_t driver); |
337 | int devclass_delete_driver(devclass_t dc, kobj_class_t driver); | |
984263bc MD |
338 | devclass_t devclass_create(const char *classname); |
339 | devclass_t devclass_find(const char *classname); | |
2581072f | 340 | device_t devclass_find_unit(const char *classname, int unit); |
91a0c258 | 341 | kobj_class_t devclass_find_driver(devclass_t dc, const char *classname); |
984263bc MD |
342 | const char *devclass_get_name(devclass_t dc); |
343 | device_t devclass_get_device(devclass_t dc, int unit); | |
344 | void *devclass_get_softc(devclass_t dc, int unit); | |
345 | int devclass_get_devices(devclass_t dc, device_t **listp, int *countp); | |
346 | int devclass_get_maxunit(devclass_t dc); | |
91a0c258 JS |
347 | void devclass_set_parent(devclass_t dc, devclass_t pdc); |
348 | devclass_t devclass_get_parent(devclass_t dc); | |
984263bc MD |
349 | |
350 | /* | |
351 | * Access functions for device resources. | |
352 | */ | |
353 | ||
354 | int resource_int_value(const char *name, int unit, const char *resname, | |
355 | int *result); | |
356 | int resource_long_value(const char *name, int unit, const char *resname, | |
357 | long *result); | |
358 | int resource_string_value(const char *name, int unit, const char *resname, | |
359 | char **result); | |
e126caf1 | 360 | int resource_disabled(const char *name, int unit); |
984263bc MD |
361 | int resource_query_string(int i, const char *resname, const char *value); |
362 | char *resource_query_name(int i); | |
363 | int resource_query_unit(int i); | |
364 | int resource_locate(int i, const char *resname); | |
365 | int resource_set_int(const char *name, int unit, const char *resname, | |
366 | int value); | |
367 | int resource_set_long(const char *name, int unit, const char *resname, | |
368 | long value); | |
369 | int resource_set_string(const char *name, int unit, const char *resname, | |
370 | const char *value); | |
371 | int resource_count(void); | |
372 | ||
558a398b SS |
373 | /** |
374 | * Some convenience defines for probe routines to return. These are just | |
375 | * suggested values, and there's nothing magical about them. | |
376 | * BUS_PROBE_SPECIFIC is for devices that cannot be reprobed, and that no | |
377 | * possible other driver may exist (typically legacy drivers who don't fallow | |
378 | * all the rules, or special needs drivers). BUS_PROBE_VENDOR is the | |
379 | * suggested value that vendor supplied drivers use. This is for source or | |
380 | * binary drivers that are not yet integrated into the FreeBSD tree. Its use | |
381 | * in the base OS is prohibited. BUS_PROBE_DEFAULT is the normal return value | |
382 | * for drivers to use. It is intended that nearly all of the drivers in the | |
383 | * tree should return this value. BUS_PROBE_LOW_PRIORITY are for drivers that | |
384 | * have special requirements like when there are two drivers that support | |
385 | * overlapping series of hardware devices. In this case the one that supports | |
386 | * the older part of the line would return this value, while the one that | |
387 | * supports the newer ones would return BUS_PROBE_DEFAULT. BUS_PROBE_GENERIC | |
388 | * is for drivers that wish to have a generic form and a specialized form, | |
389 | * like is done with the pci bus and the acpi pci bus. BUS_PROBE_HOOVER is | |
390 | * for those busses that implement a generic device place-holder for devices on | |
391 | * the bus that have no more specific driver for them (aka ugen). | |
392 | */ | |
393 | #define BUS_PROBE_SPECIFIC 0 /* Only I can use this device */ | |
394 | #if notyet | |
395 | #define BUS_PROBE_VENDOR (-10) /* Vendor supplied driver */ | |
396 | #define BUS_PROBE_DEFAULT (-20) /* Base OS default driver */ | |
397 | #define BUS_PROBE_LOW_PRIORITY (-40) /* Older, less desirable drivers */ | |
398 | #define BUS_PROBE_GENERIC (-100) /* generic driver for dev */ | |
399 | #define BUS_PROBE_HOOVER (-500) /* Generic dev for all devs on bus */ | |
400 | #else | |
401 | #define BUS_PROBE_VENDOR 0 | |
402 | #define BUS_PROBE_DEFAULT 0 | |
403 | #define BUS_PROBE_LOW_PRIORITY 0 | |
404 | #define BUS_PROBE_GENERIC 0 | |
405 | #define BUS_PROBE_HOOVER 0 | |
406 | #endif | |
407 | ||
984263bc MD |
408 | /* |
409 | * Shorthand for constructing method tables. | |
410 | */ | |
80eff43d | 411 | #define DEVMETHOD KOBJMETHOD |
984263bc MD |
412 | |
413 | /* | |
414 | * Some common device interfaces. | |
415 | */ | |
416 | #include "device_if.h" | |
417 | #include "bus_if.h" | |
418 | ||
419 | struct module; | |
420 | ||
421 | int driver_module_handler(struct module *, int, void *); | |
422 | ||
423 | /* | |
424 | * Module support for automatically adding drivers to busses. | |
425 | */ | |
426 | struct driver_module_data { | |
427 | int (*dmd_chainevh)(struct module *, int, void *); | |
428 | void *dmd_chainarg; | |
429 | const char *dmd_busname; | |
91a0c258 | 430 | kobj_class_t dmd_driver; |
984263bc MD |
431 | devclass_t *dmd_devclass; |
432 | }; | |
433 | ||
434 | #define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ | |
435 | \ | |
984263bc MD |
436 | static struct driver_module_data name##_##busname##_driver_mod = { \ |
437 | evh, arg, \ | |
438 | #busname, \ | |
91a0c258 | 439 | (kobj_class_t) &driver, \ |
984263bc MD |
440 | &devclass \ |
441 | }; \ | |
442 | \ | |
443 | static moduledata_t name##_##busname##_mod = { \ | |
444 | #busname "/" #name, \ | |
445 | driver_module_handler, \ | |
446 | &name##_##busname##_driver_mod \ | |
447 | }; \ | |
448 | DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \ | |
449 | SI_SUB_DRIVERS, SI_ORDER_MIDDLE) | |
450 | ||
451 | #endif /* _KERNEL */ | |
452 | ||
453 | #endif /* !_SYS_BUS_H_ */ |