summaryrefslogtreecommitdiffstats
path: root/sys/kern/bus_if.m
blob: 05aad097c73580411d0f1223cd29698449317528 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
#-
# Copyright (c) 1998-2004 Doug Rabson
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#

#include <sys/bus.h>

/**
 * @defgroup BUS bus - KObj methods for drivers of devices with children
 * @brief A set of methods required device drivers that support
 * child devices.
 * @{
 */
INTERFACE bus;

#
# Default implementations of some methods.
#
CODE {
	static struct resource *
	null_alloc_resource(device_t dev, device_t child,
	    int type, int *rid, u_long start, u_long end,
	    u_long count, u_int flags)
	{
	    return (0);
	}
};

/**
 * @brief Print a description of a child device
 *
 * This is called from system code which prints out a description of a
 * device. It should describe the attachment that the child has with
 * the parent. For instance the TurboLaser bus prints which node the
 * device is attached to. See bus_generic_print_child() for more 
 * information.
 *
 * @param _dev		the device whose child is being printed
 * @param _child	the child device to describe
 *
 * @returns		the number of characters output.
 */
METHOD int print_child {
	device_t _dev;
	device_t _child;
} DEFAULT bus_generic_print_child;

/**
 * @brief Print a notification about an unprobed child device.
 *
 * Called for each child device that did not succeed in probing for a
 * driver.
 *
 * @param _dev		the device whose child was being probed
 * @param _child	the child device which failed to probe
 */   
METHOD void probe_nomatch {
        device_t _dev;
        device_t _child;
};

/**
 * @brief Read the value of a bus-specific attribute of a device
 *
 * This method, along with BUS_WRITE_IVAR() manages a bus-specific set
 * of instance variables of a child device.  The intention is that
 * each different type of bus defines a set of appropriate instance
 * variables (such as ports and irqs for ISA bus etc.)
 *
 * This information could be given to the child device as a struct but
 * that makes it hard for a bus to add or remove variables without
 * forcing an edit and recompile for all drivers which may not be
 * possible for vendor supplied binary drivers.
 *
 * This method copies the value of an instance variable to the
 * location specified by @p *_result.
 * 
 * @param _dev		the device whose child was being examined
 * @param _child	the child device whose instance variable is
 *			being read
 * @param _index	the instance variable to read
 * @param _result	a loction to recieve the instance variable
 *			value
 * 
 * @retval 0		success
 * @retval ENOENT	no such instance variable is supported by @p
 *			_dev 
 */
METHOD int read_ivar {
	device_t _dev;
	device_t _child;
	int _index;
	uintptr_t *_result;
};

/**
 * @brief Write the value of a bus-specific attribute of a device
 * 
 * This method sets the value of an instance variable to @p _value.
 * 
 * @param _dev		the device whose child was being updated
 * @param _child	the child device whose instance variable is
 *			being written
 * @param _index	the instance variable to write
 * @param _value	the value to write to that instance variable
 * 
 * @retval 0		success
 * @retval ENOENT	no such instance variable is supported by @p
 *			_dev 
 * @retval EINVAL	the instance variable was recognised but
 *			contains a read-only value
 */
METHOD int write_ivar {
	device_t _dev;
	device_t _child;
	int _indx;
	uintptr_t _value;
};

/**
 * @brief Notify a bus that a child was detached
 *
 * Called after the child's DEVICE_DETACH() method to allow the parent
 * to reclaim any resources allocated on behalf of the child.
 * 
 * @param _dev		the device whose child changed state
 * @param _child	the child device which changed state
 */
METHOD void child_detached {
	device_t _dev;
	device_t _child;
};

/**
 * @brief Notify a bus that a new driver was added
 * 
 * Called when a new driver is added to the devclass which owns this
 * bus. The generic implementation of this method attempts to probe and
 * attach any un-matched children of the bus.
 * 
 * @param _dev		the device whose devclass had a new driver
 *			added to it
 * @param _driver	the new driver which was added
 */
METHOD void driver_added {
	device_t _dev;
	driver_t *_driver;
} DEFAULT bus_generic_driver_added;

/**
 * @brief Create a new child device
 *
 * For busses which use use drivers supporting DEVICE_IDENTIFY() to
 * enumerate their devices, this method is used to create new
 * device instances. The new device will be added after the last
 * existing child with the same order.
 * 
 * @param _dev		the bus device which will be the parent of the
 *			new child device
 * @param _order	a value which is used to partially sort the
 *			children of @p _dev - devices created using
 *			lower values of @p _order appear first in @p
 *			_dev's list of children
 * @param _name		devclass name for new device or @c NULL if not
 *			specified
 * @param _unit		unit number for new device or @c -1 if not
 *			specified
 */
METHOD device_t add_child {
	device_t _dev;
	int _order;
	const char *_name;
	int _unit;
};

/**
 * @brief Allocate a system resource
 *
 * This method is called by child devices of a bus to allocate resources.
 * The types are defined in <machine/resource.h>; the meaning of the
 * resource-ID field varies from bus to bus (but @p *rid == 0 is always
 * valid if the resource type is). If a resource was allocated and the
 * caller did not use the RF_ACTIVE to specify that it should be
 * activated immediately, the caller is responsible for calling
 * BUS_ACTIVATE_RESOURCE() when it actually uses the resource.
 *
 * @param _dev		the parent device of @p _child
 * @param _child	the device which is requesting an allocation
 * @param _type		the type of resource to allocate
 * @param _rid		a pointer to the resource identifier
 * @param _start	hint at the start of the resource range - pass
 *			@c 0UL for any start address
 * @param _end		hint at the end of the resource range - pass
 *			@c ~0UL for any end address
 * @param _count	hint at the size of range required - pass @c 1
 *			for any size
 * @param _flags	any extra flags to control the resource
 *			allocation - see @c RF_XXX flags in
 *			<sys/rman.h> for details
 * 
 * @returns		the resource which was allocated or @c NULL if no
 *			resource could be allocated
 */
METHOD struct resource * alloc_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int	       *_rid;
	u_long		_start;
	u_long		_end;
	u_long		_count;
	u_int		_flags;
} DEFAULT null_alloc_resource;

/**
 * @brief Activate a resource
 *
 * Activate a resource previously allocated with
 * BUS_ALLOC_RESOURCE(). This may for instance map a memory region
 * into the kernel's virtual address space.
 *
 * @param _dev		the parent device of @p _child
 * @param _child	the device which allocated the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 * @param _r		the resource to activate
 */
METHOD int activate_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
	struct resource *_r;
};

/**
 * @brief Deactivate a resource
 *
 * Deactivate a resource previously allocated with
 * BUS_ALLOC_RESOURCE(). This may for instance unmap a memory region
 * from the kernel's virtual address space.
 *
 * @param _dev		the parent device of @p _child
 * @param _child	the device which allocated the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 * @param _r		the resource to deactivate
 */
METHOD int deactivate_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
	struct resource *_r;
};

/**
 * @brief Release a resource
 *
 * Free a resource allocated by the BUS_ALLOC_RESOURCE.  The @p _rid
 * value must be the same as the one returned by BUS_ALLOC_RESOURCE()
 * (which is not necessarily the same as the one the client passed).
 *
 * @param _dev		the parent device of @p _child
 * @param _child	the device which allocated the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 * @param _r		the resource to release
 */
METHOD int release_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
	struct resource *_res;
};

/**
 * @brief Install an interrupt handler
 *
 * This method is used to associate an interrupt handler function with
 * an irq resource. When the interrupt triggers, the function @p _intr
 * will be called with the value of @p _arg as its single
 * argument. The value returned in @p *_cookiep is used to cancel the
 * interrupt handler - the caller should save this value to use in a
 * future call to BUS_TEARDOWN_INTR().
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which allocated the resource
 * @param _irq		the resource representing the interrupt
 * @param _flags	a set of bits from enum intr_type specifying
 *			the class of interrupt
 * @param _intr		the function to call when the interrupt
 *			triggers
 * @param _arg		a value to use as the single argument in calls
 *			to @p _intr
 * @param _cookiep	a pointer to a location to recieve a cookie
 *			value that may be used to remove the interrupt
 *			handler
 */
METHOD int setup_intr {
	device_t	_dev;
	device_t	_child;
	struct resource *_irq;
	int		_flags;
	driver_intr_t	*_intr;
	void		*_arg;
	void		**_cookiep;
};

/**
 * @brief Uninstall an interrupt handler
 *
 * This method is used to disassociate an interrupt handler function
 * with an irq resource. The value of @p _cookie must be the value
 * returned from a previous call to BUS_SETUP_INTR().
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which allocated the resource
 * @param _irq		the resource representing the interrupt
 * @param _cookie	the cookie value returned when the interrupt
 *			was originally registered
 */
METHOD int teardown_intr {
	device_t	_dev;
	device_t	_child;
	struct resource	*_irq;
	void		*_cookie;
};

/**
 * @brief Define a resource which can be allocated with
 * BUS_ALLOC_RESOURCE().
 *
 * This method is used by some busses (typically ISA) to allow a
 * driver to describe a resource range that it would like to
 * allocate. The resource defined by @p _type and @p _rid is defined
 * to start at @p _start and to include @p _count indices in its
 * range.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which owns the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 * @param _start	the start of the resource range
 * @param _count	the size of the resource range
 */
METHOD int set_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
	u_long		_start;
	u_long		_count;
};

/**
 * @brief Describe a resource
 *
 * This method allows a driver to examine the range used for a given
 * resource without actually allocating it.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which owns the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 * @param _start	the address of a location to recieve the start
 *			index of the resource range
 * @param _count	the address of a location to recieve the size
 *			of the resource range
 */
METHOD int get_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
	u_long		*_startp;
	u_long		*_countp;
};

/**
 * @brief Delete a resource.
 * 
 * Use this to delete a resource (possibly one previously added with
 * BUS_SET_RESOURCE()).
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which owns the resource
 * @param _type		the type of resource
 * @param _rid		the resource identifier
 */
METHOD void delete_resource {
	device_t	_dev;
	device_t	_child;
	int		_type;
	int		_rid;
};

/**
 * @brief Return a struct resource_list.
 *
 * Used by drivers which use bus_generic_rl_alloc_resource() etc. to
 * implement their resource handling. It should return the resource
 * list of the given child device.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which owns the resource list
 */
METHOD struct resource_list * get_resource_list {
	device_t	_dev;
	device_t	_child;
} DEFAULT bus_generic_get_resource_list;

/**
 * @brief Is the hardware described by @p _child still attached to the
 * system?
 *
 * This method should return 0 if the device is not present.  It
 * should return -1 if it is present.  Any errors in determining
 * should be returned as a normal errno value.  Client drivers are to
 * assume that the device is present, even if there is an error
 * determining if it is there.  Busses are to try to avoid returning
 * errors, but newcard will return an error if the device fails to
 * implement this method.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which is being examined
 */
METHOD int child_present {
	device_t	_dev;
	device_t	_child;
} DEFAULT bus_generic_child_present;

/**
 * @brief Returns the pnp info for this device.
 *
 * Return it as a string.  If the string is insufficient for the
 * storage, then return EOVERFLOW.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which is being examined
 * @param _buf		the address of a buffer to receive the pnp
 *			string
 * @param _buflen	the size of the buffer pointed to by @p _buf
 */
METHOD int child_pnpinfo_str {
	device_t	_dev;
	device_t	_child;
	char		*_buf;
	size_t		_buflen;
};

/**
 * @brief Returns the location for this device.
 *
 * Return it as a string.  If the string is insufficient for the
 * storage, then return EOVERFLOW.
 * 
 * @param _dev		the parent device of @p _child
 * @param _child	the device which is being examined
 * @param _buf		the address of a buffer to receive the location
 *			string
 * @param _buflen	the size of the buffer pointed to by @p _buf
 */
METHOD int child_location_str {
	device_t	_dev;
	device_t	_child;
	char		*_buf;
	size_t		_buflen;
};

/**
 * @brief Allow (bus) drivers to specify the trigger mode and polarity
 * of the specified interrupt.
 * 
 * @param _dev		the bus device
 * @param _irq		the interrupt number to modify
 * @param _trig		the trigger mode required
 * @param _pol		the interrupt polarity required
 */
METHOD int config_intr {
	device_t	_dev;
	int		_irq;
	enum intr_trigger _trig;
	enum intr_polarity _pol;
} DEFAULT bus_generic_config_intr;

/**
 * @brief Notify a (bus) driver about a child that the hints mechanism
 * believes it has discovered.
 *
 * The bus is responsible for then adding the child in the right order
 * and discovering other things about the child.  The bus driver is
 * free to ignore this hint, to do special things, etc.  It is all up
 * to the bus driver to interpret.
 *
 * This method is only called in response to the parent bus asking for
 * hinted devices to be enumerated.
 *
 * @param _dev		the bus device
 * @param _dname	the name of the device w/o unit numbers
 * @param _dunit	the unit number of the device
 */
METHOD void hinted_child {
	device_t	_dev;
	const char *	_dname;
	int		_dunit;
};
OpenPOWER on IntegriCloud