summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2004-07-18 16:30:31 +0000
committerdfr <dfr@FreeBSD.org>2004-07-18 16:30:31 +0000
commit030de024cc4aad05d83788d13d57474f5760ea50 (patch)
treee796c2cccde10a96741095e8ea4d6bf061f2dce4 /sys
parent7ad60316cd2a6fab33bff1ecd701c1d696895b96 (diff)
downloadFreeBSD-src-030de024cc4aad05d83788d13d57474f5760ea50.zip
FreeBSD-src-030de024cc4aad05d83788d13d57474f5760ea50.tar.gz
Add doxygen doc comments for most of newbus and the BUS interface.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/bus_if.m428
-rw-r--r--sys/kern/subr_bus.c965
-rw-r--r--sys/sys/bus.h158
3 files changed, 1323 insertions, 228 deletions
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index fb83013..6c6c668 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -1,5 +1,6 @@
+
#
-# Copyright (c) 1998 Doug Rabson
+# Copyright (c) 1998,2004 Doug Rabson
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -28,6 +29,12 @@
#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;
#
@@ -43,53 +50,90 @@ CODE {
}
};
-#
-# 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.9 for more
-# information.
-# This method returns the number of characters output.
-#
+/**
+ * @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;
+ device_t _dev;
+ device_t _child;
} DEFAULT bus_generic_print_child;
-#
-# Called for each child device that
-# did not succeed in probing for a
-# driver.
-#
+/**
+ * @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;
+ device_t _dev;
+ device_t _child;
};
-#
-# These two methods manage 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.
-
-#
-# Read an instance variable. Return 0 on success.
-#
+/**
+ * @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 _indx;
+ int _index;
uintptr_t *_result;
};
-#
-# Write an instance variable. Return 0 on success.
-#
+/**
+ * @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;
@@ -97,31 +141,55 @@ METHOD int write_ivar {
uintptr_t _value;
};
-#
-# Called after the child's DEVICE_DETACH method to allow the parent
-# to reclaim any resources allocated on behalf of the child.
-#
+/**
+ * @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;
};
-#
-# 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.
-#
+/**
+ * @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;
-#
-# For busses which use use drivers supporting DEVICE_IDENTIFY to
-# enumerate their devices, these methods are used to create new
-# device instances. If place is non-NULL, the new device will be
-# added after the last existing child with the same order.
-#
+/**
+ * @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;
@@ -129,20 +197,34 @@ METHOD device_t add_child {
int _unit;
};
-#
-# Allocate a system resource attached to `dev' on behalf of `child'.
-# The types are defined in <machine/resource.h>; the meaning of the
-# resource-ID field varies from bus to bus (but *rid == 0 is always
-# valid if the resource type is). start and end reflect the allowable
-# range, and should be passed as `0UL' and `~0UL', respectively, if
-# the client has no range restriction. count is the number of consecutive
-# indices in the resource required. flags is a set of sharing flags
-# as defined in <sys/rman.h>.
-#
-# Returns a resource or a null pointer on failure. The caller is
-# responsible for calling rman_activate_resource() when it actually
-# uses the resource.
-#
+/**
+ * @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;
@@ -154,6 +236,19 @@ METHOD struct resource * alloc_resource {
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;
@@ -162,6 +257,19 @@ METHOD int activate_resource {
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;
@@ -170,11 +278,19 @@ METHOD int deactivate_resource {
struct resource *_r;
};
-#
-# Free a resource allocated by the preceding method. The `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).
-#
+/**
+ * @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;
@@ -183,6 +299,29 @@ METHOD int release_resource {
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;
@@ -193,6 +332,19 @@ METHOD int setup_intr {
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;
@@ -200,10 +352,23 @@ METHOD int teardown_intr {
void *_cookie;
};
-#
-# Set the range used for a particular resource. Return EINVAL if
-# the type or rid are out of range.
-#
+/**
+ * @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;
@@ -213,10 +378,21 @@ METHOD int set_resource {
u_long _count;
};
-#
-# Get the range for a resource. Return ENOENT if the type or rid are
-# out of range or have not been set.
-#
+/**
+ * @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;
@@ -226,9 +402,17 @@ METHOD int get_resource {
u_long *_countp;
};
-#
-# Delete a resource.
-#
+/**
+ * @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;
@@ -236,33 +420,52 @@ METHOD void delete_resource {
int _rid;
};
-#
-# Return a struct resource_list.
-#
+/**
+ * @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;
-#
-# Is the hardware described by _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.
-#
+/**
+ * @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;
-#
-# Returns the pnp info for this device. Return it as a string. If the
-# string is insufficient for the storage, then return EOVERFLOW.
-#
+/**
+ * @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;
@@ -270,10 +473,18 @@ METHOD int child_pnpinfo_str {
size_t _buflen;
};
-#
-# Returns the location for this device. Return it as a string. If the
-# string is insufficient for the storage, then return EOVERFLOW.
-#
+/**
+ * @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;
@@ -281,10 +492,15 @@ METHOD int child_location_str {
size_t _buflen;
};
-#
-# Allow (bus) drivers to specify the trigger mode and polarity of the
-# specified interrupt.
-#
+/**
+ * @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;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index ae59230..6999a77 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -87,8 +87,8 @@ struct devclass {
struct sysctl_oid *sysctl_tree;
};
-/*
- * Implementation of device.
+/**
+ * @brief Implementation of device.
*/
struct device {
/*
@@ -100,44 +100,37 @@ struct device {
/*
* Device hierarchy.
*/
- TAILQ_ENTRY(device) link; /* list of devices in parent */
- TAILQ_ENTRY(device) devlink; /* global device list membership */
- device_t parent;
- device_list_t children; /* list of subordinate devices */
+ TAILQ_ENTRY(device) link; /**< list of devices in parent */
+ TAILQ_ENTRY(device) devlink; /**< global device list membership */
+ device_t parent; /**< parent of this device */
+ device_list_t children; /**< list of child devices */
/*
* Details of this device.
*/
- driver_t *driver;
- devclass_t devclass; /* device class which we are in */
- int unit;
- char* nameunit; /* name+unit e.g. foodev0 */
- char* desc; /* driver specific description */
- int busy; /* count of calls to device_busy() */
- device_state_t state;
- u_int32_t devflags; /* api level flags for device_get_flags() */
- u_short flags;
-#define DF_ENABLED 1 /* device should be probed/attached */
-#define DF_FIXEDCLASS 2 /* devclass specified at create time */
-#define DF_WILDCARD 4 /* unit was originally wildcard */
-#define DF_DESCMALLOCED 8 /* description was malloced */
-#define DF_QUIET 16 /* don't print verbose attach message */
-#define DF_DONENOMATCH 32 /* don't execute DEVICE_NOMATCH again */
-#define DF_EXTERNALSOFTC 64 /* softc not allocated by us */
- u_char order; /* order from device_add_child_ordered() */
+ driver_t *driver; /**< current driver */
+ devclass_t devclass; /**< current device class */
+ int unit; /**< current unit number */
+ char* nameunit; /**< name+unit e.g. foodev0 */
+ char* desc; /**< driver specific description */
+ int busy; /**< count of calls to device_busy() */
+ device_state_t state; /**< current device state */
+ u_int32_t devflags; /**< api level flags for device_get_flags() */
+ u_short flags; /**< internal device flags */
+#define DF_ENABLED 1 /* device should be probed/attached */
+#define DF_FIXEDCLASS 2 /* devclass specified at create time */
+#define DF_WILDCARD 4 /* unit was originally wildcard */
+#define DF_DESCMALLOCED 8 /* description was malloced */
+#define DF_QUIET 16 /* don't print verbose attach message */
+#define DF_DONENOMATCH 32 /* don't execute DEVICE_NOMATCH again */
+#define DF_EXTERNALSOFTC 64 /* softc not allocated by us */
+ u_char order; /**< order from device_add_child_ordered() */
u_char pad;
- void *ivars;
- void *softc;
-
- struct sysctl_ctx_list sysctl_ctx;
- struct sysctl_oid *sysctl_tree;
-};
+ void *ivars; /**< instance variables */
+ void *softc; /**< current driver's variables */
-struct device_op_desc {
- unsigned int offset; /* offset in driver ops */
- struct method* method; /* internal method implementation */
- devop_t deflt; /* default implementation */
- const char* name; /* unique name (for registration) */
+ struct sysctl_ctx_list sysctl_ctx; /**< state for sysctl variables */
+ struct sysctl_oid *sysctl_tree; /**< state for sysctl variables */
};
static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
@@ -155,7 +148,8 @@ SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RW, &bus_debug, 0,
#define DRIVERNAME(d) ((d)? d->name : "no driver")
#define DEVCLANAME(d) ((d)? d->name : "no devclass")
-/* Produce the indenting, indent*2 spaces plus a '.' ahead of that to
+/**
+ * Produce the indenting, indent*2 spaces plus a '.' ahead of that to
* prevent syslog from deleting initial spaces
*/
#define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while (0)
@@ -511,10 +505,12 @@ devpoll(struct cdev *dev, int events, d_thread_t *td)
return (revents);
}
-/*
+/**
+ * @brief Queue data to be read from the devctl device
+ *
* Generic interface to queue data to the devctl device. It is
- * assumed that data is properly formatted. It is further assumed
- * that data is allocated.
+ * assumed that @p data is properly formatted. It is further assumed
+ * that @p data is allocated using the M_BUS malloc type.
*/
void
devctl_queue_data(char *data)
@@ -539,8 +535,8 @@ devctl_queue_data(char *data)
}
}
-/*
- * Send a 'notification' to userland, using standard ways
+/**
+ * @brief Send a 'notification' to userland, using standard ways
*/
void
devctl_notify(const char *system, const char *subsystem, const char *type,
@@ -730,6 +726,22 @@ DEFINE_CLASS(null, null_methods, 0);
static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses);
+
+/**
+ * @internal
+ * @brief Find or create a device class
+ *
+ * If a device class with the name @p classname exists, return it,
+ * otherwise if @p create is non-zero create and return a new device
+ * class.
+ *
+ * If @p parentname is non-NULL, the parent of the devclass is set to
+ * the devclass of that name.
+ *
+ * @param classname the devclass name to find or create
+ * @param parentname the parent devclass name or @c NULL
+ * @param create non-zero to create a devclass
+ */
static devclass_t
devclass_find_internal(const char *classname, const char *parentname,
int create)
@@ -766,18 +778,45 @@ devclass_find_internal(const char *classname, const char *parentname,
return (dc);
}
+/**
+ * @brief Create a device class
+ *
+ * If a device class with the name @p classname exists, return it,
+ * otherwise create and return a new device class.
+ *
+ * @param classname the devclass name to find or create
+ */
devclass_t
devclass_create(const char *classname)
{
return (devclass_find_internal(classname, 0, TRUE));
}
+/**
+ * @brief Find a device class
+ *
+ * If a device class with the name @p classname exists, return it,
+ * otherwise return @c NULL.
+ *
+ * @param classname the devclass name to find
+ */
devclass_t
devclass_find(const char *classname)
{
return (devclass_find_internal(classname, 0, FALSE));
}
+/**
+ * @brief Add a device driver to a device class
+ *
+ * Add a device driver to a devclass. This is normally called
+ * automatically by DRIVER_MODULE(). The BUS_DRIVER_ADDED() method of
+ * all devices in the devclass will be called to allow them to attempt
+ * to re-probe any unmatched children.
+ *
+ * @param dc the devclass to edit
+ * @param driver the driver to register
+ */
int
devclass_add_driver(devclass_t dc, driver_t *driver)
{
@@ -818,6 +857,20 @@ devclass_add_driver(devclass_t dc, driver_t *driver)
return (0);
}
+/**
+ * @brief Delete a device driver from a device class
+ *
+ * Delete a device driver from a devclass. This is normally called
+ * automatically by DRIVER_MODULE().
+ *
+ * If the driver is currently attached to any devices,
+ * devclass_delete_driver() will first attempt to detach from each
+ * device. If one of the detach calls fails, the driver will not be
+ * deleted.
+ *
+ * @param dc the devclass to edit
+ * @param driver the driver to unregister
+ */
int
devclass_delete_driver(devclass_t busclass, driver_t *driver)
{
@@ -879,6 +932,9 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
return (0);
}
+/**
+ * @internal
+ */
static driverlink_t
devclass_find_driver_internal(devclass_t dc, const char *classname)
{
@@ -895,6 +951,16 @@ devclass_find_driver_internal(devclass_t dc, const char *classname)
return (NULL);
}
+/**
+ * @brief Search a devclass for a driver
+ *
+ * This function searches the devclass's list of drivers and returns
+ * the first driver whose name is @p classname or @c NULL if there is
+ * no driver of that name.
+ *
+ * @param dc the devclass to search
+ * @param classname the driver name to search for
+ */
kobj_class_t
devclass_find_driver(devclass_t dc, const char *classname)
{
@@ -906,12 +972,24 @@ devclass_find_driver(devclass_t dc, const char *classname)
return (NULL);
}
+/**
+ * @brief Return the name of the devclass
+ */
const char *
devclass_get_name(devclass_t dc)
{
return (dc->name);
}
+/**
+ * @brief Find a device given a unit number
+ *
+ * @param dc the devclass to search
+ * @param unit the unit number to search for
+ *
+ * @returns the device with the given unit number or @c
+ * NULL if there is no such device
+ */
device_t
devclass_get_device(devclass_t dc, int unit)
{
@@ -920,6 +998,16 @@ devclass_get_device(devclass_t dc, int unit)
return (dc->devices[unit]);
}
+/**
+ * @brief Find the softc field of a device given a unit number
+ *
+ * @param dc the devclass to search
+ * @param unit the unit number to search for
+ *
+ * @returns the softc field of the device with the given
+ * unit number or @c NULL if there is no such
+ * device
+ */
void *
devclass_get_softc(devclass_t dc, int unit)
{
@@ -932,6 +1020,22 @@ devclass_get_softc(devclass_t dc, int unit)
return (device_get_softc(dev));
}
+/**
+ * @brief Get a list of devices in the devclass
+ *
+ * An array containing a list of all the devices in the given devclass
+ * is allocated and returned in @p *devlistp. The number of devices
+ * in the array is returned in @p *devcountp. The caller should free
+ * the array using @c free(p, M_TEMP).
+ *
+ * @param dc the devclass to examine
+ * @param devlistp points at location for array pointer return
+ * value
+ * @param devcountp points at location for array size return value
+ *
+ * @retval 0 success
+ * @retval ENOMEM the array allocation failed
+ */
int
devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
{
@@ -962,12 +1066,26 @@ devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp)
return (0);
}
+/**
+ * @brief Get the maximum unit number used in a devclass
+ *
+ * @param dc the devclass to examine
+ */
int
devclass_get_maxunit(devclass_t dc)
{
return (dc->maxunit);
}
+/**
+ * @brief Find a free unit number in a devclass
+ *
+ * This function searches for the first unused unit number greater
+ * that or equal to @p unit.
+ *
+ * @param dc the devclass to examine
+ * @param unit the first unit number to check
+ */
int
devclass_find_free_unit(devclass_t dc, int unit)
{
@@ -978,12 +1096,26 @@ devclass_find_free_unit(devclass_t dc, int unit)
return (unit);
}
+/**
+ * @brief Set the parent of a devclass
+ *
+ * The parent class is normally initialised automatically by
+ * DRIVER_MODULE().
+ *
+ * @param dc the devclass to edit
+ * @param pdc the new parent devclass
+ */
void
devclass_set_parent(devclass_t dc, devclass_t pdc)
{
dc->parent = pdc;
}
+/**
+ * @brief Get the parent of a devclass
+ *
+ * @param dc the devclass to examine
+ */
devclass_t
devclass_get_parent(devclass_t dc)
{
@@ -1002,6 +1134,21 @@ devclass_get_sysctl_tree(devclass_t dc)
return (dc->sysctl_tree);
}
+/**
+ * @internal
+ * @brief Allocate a unit number
+ *
+ * On entry, @p *unitp is the desired unit number (or @c -1 if any
+ * will do). The allocated unit number is returned in @p *unitp.
+
+ * @param dc the devclass to allocate from
+ * @param unitp points at the location for the allocated unit
+ * number
+ *
+ * @retval 0 success
+ * @retval EEXIST the requested unit number is already allocated
+ * @retval ENOMEM memory allocation failure
+ */
static int
devclass_alloc_unit(devclass_t dc, int *unitp)
{
@@ -1053,6 +1200,22 @@ devclass_alloc_unit(devclass_t dc, int *unitp)
return (0);
}
+/**
+ * @internal
+ * @brief Add a device to a devclass
+ *
+ * A unit number is allocated for the device (using the device's
+ * preferred unit number if any) and the device is registered in the
+ * devclass. This allows the device to be looked up by its unit
+ * number, e.g. by decoding a dev_t minor number.
+ *
+ * @param dc the devclass to add to
+ * @param dev the device to add
+ *
+ * @retval 0 success
+ * @retval EEXIST the requested unit number is already allocated
+ * @retval ENOMEM memory allocation failure
+ */
static int
devclass_add_device(devclass_t dc, device_t dev)
{
@@ -1079,6 +1242,18 @@ devclass_add_device(devclass_t dc, device_t dev)
return (0);
}
+/**
+ * @internal
+ * @brief Delete a device from a devclass
+ *
+ * The device is removed from the devclass's device list and its unit
+ * number is freed.
+
+ * @param dc the devclass to delete from
+ * @param dev the device to delete
+ *
+ * @retval 0 success
+ */
static int
devclass_delete_device(devclass_t dc, device_t dev)
{
@@ -1099,6 +1274,18 @@ devclass_delete_device(devclass_t dc, device_t dev)
return (0);
}
+/**
+ * @internal
+ * @brief Make a new device and add it as a child of @p parent
+ *
+ * @param parent the parent of the new device
+ * @param name the devclass name of the new device or @c NULL
+ * to leave the devclass unspecified
+ * @parem unit the unit number of the new device of @c -1 to
+ * leave the unit number unspecified
+ *
+ * @returns the new device
+ */
static device_t
make_device(device_t parent, const char *name, int unit)
{
@@ -1154,6 +1341,10 @@ make_device(device_t parent, const char *name, int unit)
return (dev);
}
+/**
+ * @internal
+ * @brief Print a description of a device.
+ */
static int
device_print_child(device_t dev, device_t child)
{
@@ -1167,12 +1358,48 @@ device_print_child(device_t dev, device_t child)
return (retval);
}
+/**
+ * @brief Create a new device
+ *
+ * This creates a new device and adds it as a child of an existing
+ * parent device. The new device will be added after the last existing
+ * child with order zero.
+ *
+ * @param dev the device which will be the parent of the
+ * new child device
+ * @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
+ *
+ * @returns the new device
+ */
device_t
device_add_child(device_t dev, const char *name, int unit)
{
return (device_add_child_ordered(dev, 0, name, unit));
}
+/**
+ * @brief Create a new device
+ *
+ * This creates a new device and adds it as a child of an existing
+ * parent device. The new device will be added after the last existing
+ * child with the same order.
+ *
+ * @param dev the 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
+ *
+ * @returns the new device
+ */
device_t
device_add_child_ordered(device_t dev, int order, const char *name, int unit)
{
@@ -1210,6 +1437,19 @@ device_add_child_ordered(device_t dev, int order, const char *name, int unit)
return (child);
}
+/**
+ * @brief Delete a device
+ *
+ * This function deletes a device along with all of its children. If
+ * the device currently has a driver attached to it, the device is
+ * detached first using device_detach().
+ *
+ * @param dev the parent device
+ * @param child the device to delete
+ *
+ * @retval 0 success
+ * @retval non-zero a unit error code describing the error
+ */
int
device_delete_child(device_t dev, device_t child)
{
@@ -1238,8 +1478,17 @@ device_delete_child(device_t dev, device_t child)
return (0);
}
-/*
- * Find only devices attached to this bus.
+/**
+ * @brief Find a device given a unit number
+ *
+ * This is similar to devclass_get_devices() but only searches for
+ * devices which have @p dev as a parent.
+ *
+ * @param dev the parent device to search
+ * @param unit the unit number to search for
+ *
+ * @returns the device with the given unit number or @c
+ * NULL if there is no such device
*/
device_t
device_find_child(device_t dev, const char *classname, int unit)
@@ -1257,6 +1506,9 @@ device_find_child(device_t dev, const char *classname, int unit)
return (NULL);
}
+/**
+ * @internal
+ */
static driverlink_t
first_matching_driver(devclass_t dc, device_t dev)
{
@@ -1265,6 +1517,9 @@ first_matching_driver(devclass_t dc, device_t dev)
return (TAILQ_FIRST(&dc->drivers));
}
+/**
+ * @internal
+ */
static driverlink_t
next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
{
@@ -1278,6 +1533,9 @@ next_matching_driver(devclass_t dc, device_t dev, driverlink_t last)
return (TAILQ_NEXT(last, link));
}
+/**
+ * @internal
+ */
static int
device_probe_child(device_t dev, device_t child)
{
@@ -1367,12 +1625,31 @@ device_probe_child(device_t dev, device_t child)
return (ENXIO);
}
+/**
+ * @brief Return the parent of a device
+ */
device_t
device_get_parent(device_t dev)
{
return (dev->parent);
}
+/**
+ * @brief Get a list of children of a device
+ *
+ * An array containing a list of all the children of the given device
+ * is allocated and returned in @p *devlistp. The number of devices
+ * in the array is returned in @p *devcountp. The caller should free
+ * the array using @c free(p, M_TEMP).
+ *
+ * @param dev the device to examine
+ * @param devlistp points at location for array pointer return
+ * value
+ * @param devcountp points at location for array size return value
+ *
+ * @retval 0 success
+ * @retval ENOMEM the array allocation failed
+ */
int
device_get_children(device_t dev, device_t **devlistp, int *devcountp)
{
@@ -1401,18 +1678,30 @@ device_get_children(device_t dev, device_t **devlistp, int *devcountp)
return (0);
}
+/**
+ * @brief Return the current driver for the device or @c NULL if there
+ * is no driver currently attached
+ */
driver_t *
device_get_driver(device_t dev)
{
return (dev->driver);
}
+/**
+ * @brief Return the current devclass for the device or @c NULL if
+ * there is none.
+ */
devclass_t
device_get_devclass(device_t dev)
{
return (dev->devclass);
}
+/**
+ * @brief Return the name of the device's devclass or @c NULL if there
+ * is none.
+ */
const char *
device_get_name(device_t dev)
{
@@ -1421,24 +1710,38 @@ device_get_name(device_t dev)
return (NULL);
}
+/**
+ * @brief Return a string containing the device's devclass name
+ * followed by an ascii representation of the device's unit number
+ * (e.g. @c "foo2").
+ */
const char *
device_get_nameunit(device_t dev)
{
return (dev->nameunit);
}
+/**
+ * @brief Return the device's unit number.
+ */
int
device_get_unit(device_t dev)
{
return (dev->unit);
}
+/**
+ * @brief Return the device's description string
+ */
const char *
device_get_desc(device_t dev)
{
return (dev->desc);
}
+/**
+ * @brief Return the device's flags
+ */
u_int32_t
device_get_flags(device_t dev)
{
@@ -1457,6 +1760,11 @@ device_get_sysctl_tree(device_t dev)
return (dev->sysctl_tree);
}
+/**
+ * @brief Print the name of the device followed by a colon and a space
+ *
+ * @returns the number of characters printed
+ */
int
device_print_prettyname(device_t dev)
{
@@ -1467,6 +1775,13 @@ device_print_prettyname(device_t dev)
return (printf("%s%d: ", name, device_get_unit(dev)));
}
+/**
+ * @brief Print the name of the device followed by a colon, a space
+ * and the result of calling vprintf() with the value of @p fmt and
+ * the following arguments.
+ *
+ * @returns the number of characters printed
+ */
int
device_printf(device_t dev, const char * fmt, ...)
{
@@ -1480,6 +1795,9 @@ device_printf(device_t dev, const char * fmt, ...)
return (retval);
}
+/**
+ * @internal
+ */
static void
device_set_desc_internal(device_t dev, const char* desc, int copy)
{
@@ -1503,30 +1821,58 @@ device_set_desc_internal(device_t dev, const char* desc, int copy)
bus_data_generation_update();
}
+/**
+ * @brief Set the device's description
+ *
+ * The value of @c desc should be a string constant that will not
+ * change (at least until the description is changed in a subsequent
+ * call to device_set_desc() or device_set_desc_copy()).
+ */
void
device_set_desc(device_t dev, const char* desc)
{
device_set_desc_internal(dev, desc, FALSE);
}
+/**
+ * @brief Set the device's description
+ *
+ * The string pointed to by @c desc is copied. Use this function if
+ * the device description is generated, (e.g. with sprintf()).
+ */
void
device_set_desc_copy(device_t dev, const char* desc)
{
device_set_desc_internal(dev, desc, TRUE);
}
+/**
+ * @brief Set the device's flags
+ */
void
device_set_flags(device_t dev, u_int32_t flags)
{
dev->devflags = flags;
}
+/**
+ * @brief Return the device's softc field
+ *
+ * The softc is allocated and zeroed when a driver is attached, based
+ * on the size field of the driver.
+ */
void *
device_get_softc(device_t dev)
{
return (dev->softc);
}
+/**
+ * @brief Set the device's softc field
+ *
+ * Most drivers do not need to use this since the softc is allocated
+ * automatically when the driver is attached.
+ */
void
device_set_softc(device_t dev, void *softc)
{
@@ -1539,6 +1885,13 @@ device_set_softc(device_t dev, void *softc)
dev->flags &= ~DF_EXTERNALSOFTC;
}
+/**
+ * @brief Get the device's ivars field
+ *
+ * The ivars field is used by the parent device to store per-device
+ * state (e.g. the physical location of the device or a list of
+ * resources).
+ */
void *
device_get_ivars(device_t dev)
{
@@ -1547,6 +1900,9 @@ device_get_ivars(device_t dev)
return (dev->ivars);
}
+/**
+ * @brief Set the device's ivars field
+ */
void
device_set_ivars(device_t dev, void * ivars)
{
@@ -1555,24 +1911,36 @@ device_set_ivars(device_t dev, void * ivars)
dev->ivars = ivars;
}
+/**
+ * @brief Return the device's state
+ */
device_state_t
device_get_state(device_t dev)
{
return (dev->state);
}
+/**
+ * @brief Set the DF_ENABLED flag for the device
+ */
void
device_enable(device_t dev)
{
dev->flags |= DF_ENABLED;
}
+/**
+ * @brief Clear the DF_ENABLED flag for the device
+ */
void
device_disable(device_t dev)
{
dev->flags &= ~DF_ENABLED;
}
+/**
+ * @brief Increment the busy counter for the device
+ */
void
device_busy(device_t dev)
{
@@ -1584,6 +1952,9 @@ device_busy(device_t dev)
dev->state = DS_BUSY;
}
+/**
+ * @brief Decrement the busy counter for the device
+ */
void
device_unbusy(device_t dev)
{
@@ -1597,42 +1968,65 @@ device_unbusy(device_t dev)
}
}
+/**
+ * @brief Set the DF_QUIET flag for the device
+ */
void
device_quiet(device_t dev)
{
dev->flags |= DF_QUIET;
}
+/**
+ * @brief Clear the DF_QUIET flag for the device
+ */
void
device_verbose(device_t dev)
{
dev->flags &= ~DF_QUIET;
}
+/**
+ * @brief Return non-zero if the DF_QUIET flag is set on the device
+ */
int
device_is_quiet(device_t dev)
{
return ((dev->flags & DF_QUIET) != 0);
}
+/**
+ * @brief Return non-zero if the DF_ENABLED flag is set on the device
+ */
int
device_is_enabled(device_t dev)
{
return ((dev->flags & DF_ENABLED) != 0);
}
+/**
+ * @brief Return non-zero if the device was successfully probed
+ */
int
device_is_alive(device_t dev)
{
return (dev->state >= DS_ALIVE);
}
+/**
+ * @brief Return non-zero if the device currently has a driver
+ * attached to it
+ */
int
device_is_attached(device_t dev)
{
return (dev->state >= DS_ATTACHED);
}
+/**
+ * @brief Set the devclass of a device
+ * @see devclass_add_device().
+ */
int
device_set_devclass(device_t dev, const char *classname)
{
@@ -1660,6 +2054,13 @@ device_set_devclass(device_t dev, const char *classname)
return (error);
}
+/**
+ * @brief Set the driver of a device
+ *
+ * @retval 0 success
+ * @retval EBUSY the device already has a driver attached
+ * @retval ENOMEM a memory allocation failure occurred
+ */
int
device_set_driver(device_t dev, driver_t *driver)
{
@@ -1695,6 +2096,32 @@ device_set_driver(device_t dev, driver_t *driver)
return (0);
}
+/**
+ * @brief Probe a device and attach a driver if possible
+ *
+ * This function is the core of the device autoconfiguration
+ * system. Its purpose is to select a suitable driver for a device and
+ * then call that driver to initialise the hardware appropriately. The
+ * driver is selected by calling the DEVICE_PROBE() method of a set of
+ * candidate drivers and then choosing the driver which returned the
+ * best value. This driver is then attached to the device using
+ * device_attach().
+ *
+ * The set of suitable drivers is taken from the list of drivers in
+ * the parent device's devclass. If the device was originally created
+ * with a specific class name (see device_add_child()), only drivers
+ * with that name are probed, otherwise all drivers in the devclass
+ * are probed. If no drivers return successful probe values in the
+ * parent devclass, the search continues in the parent of that
+ * devclass (see devclass_get_parent()) if any.
+ *
+ * @param dev the device to initialise
+ *
+ * @retval 0 success
+ * @retval ENXIO no driver was found
+ * @retval ENOMEM memory allocation failure
+ * @retval non-zero some other unix error code
+ */
int
device_probe_and_attach(device_t dev)
{
@@ -1723,6 +2150,25 @@ device_probe_and_attach(device_t dev)
return (error);
}
+/**
+ * @brief Attach a device driver to a device
+ *
+ * This function is a wrapper around the DEVICE_ATTACH() driver
+ * method. In addition to calling DEVICE_ATTACH(), it initialises the
+ * device's sysctl tree, optionally prints a description of the device
+ * and queues a notification event for user-based device management
+ * services.
+ *
+ * Normally this function is only called internally from
+ * device_probe_and_attach().
+ *
+ * @param dev the device to initialise
+ *
+ * @retval 0 success
+ * @retval ENXIO no driver was found
+ * @retval ENOMEM memory allocation failure
+ * @retval non-zero some other unix error code
+ */
int
device_attach(device_t dev)
{
@@ -1747,6 +2193,22 @@ device_attach(device_t dev)
return (0);
}
+/**
+ * @brief Detach a driver from a device
+ *
+ * This function is a wrapper around the DEVICE_DETACH() driver
+ * method. If the call to DEVICE_DETACH() succeeds, it calls
+ * BUS_CHILD_DETACHED() for the parent of @p dev, queues a
+ * notification event for user-based device management services and
+ * cleans up the device's sysctl tree.
+ *
+ * @param dev the device to un-initialise
+ *
+ * @retval 0 success
+ * @retval ENXIO no driver was found
+ * @retval ENOMEM memory allocation failure
+ * @retval non-zero some other unix error code
+ */
int
device_detach(device_t dev)
{
@@ -1775,6 +2237,14 @@ device_detach(device_t dev)
return (0);
}
+/**
+ * @brief Notify a device of system shutdown
+ *
+ * This function calls the DEVICE_SHUTDOWN() driver method if the
+ * device currently has an attached driver.
+ *
+ * @returns the value returned by DEVICE_SHUTDOWN()
+ */
int
device_shutdown(device_t dev)
{
@@ -1783,6 +2253,12 @@ device_shutdown(device_t dev)
return (DEVICE_SHUTDOWN(dev));
}
+/**
+ * @brief Set the unit number of a device
+ *
+ * This function can be used to override the unit number used for a
+ * device (e.g. to wire a device to a pre-configured unit number).
+ */
int
device_set_unit(device_t dev, int unit)
{
@@ -1809,12 +2285,25 @@ device_set_unit(device_t dev, int unit)
* Some useful method implementations to make life easier for bus drivers.
*/
+/**
+ * @brief Initialise a resource list.
+ *
+ * @param rl the resource list to initialise
+ */
void
resource_list_init(struct resource_list *rl)
{
SLIST_INIT(rl);
}
+/**
+ * @brief Reclaim memory used by a resource list.
+ *
+ * This function frees the memory for all resource entries on the list
+ * (if any).
+ *
+ * @param rl the resource list to free
+ */
void
resource_list_free(struct resource_list *rl)
{
@@ -1828,6 +2317,19 @@ resource_list_free(struct resource_list *rl)
}
}
+/**
+ * @brief Add a resource entry.
+ *
+ * This function adds a resource entry using the given @p type, @p
+ * start, @p end and @p count values. A rid value is chosen by
+ * searching sequentially for the first unused rid starting at zero.
+ *
+ * @param rl the resource list to edit
+ * @param type the resource entry type (e.g. SYS_RES_MEMORY)
+ * @param start the start address of the resource
+ * @param end the end address of the resource
+ * @param count XXX end-start+1
+ */
int
resource_list_add_next(struct resource_list *rl, int type, u_long start,
u_long end, u_long count)
@@ -1841,6 +2343,21 @@ resource_list_add_next(struct resource_list *rl, int type, u_long start,
return (rid);
}
+/**
+ * @brief Add or modify a resource entry.
+ *
+ * If an existing entry exists with the same type and rid, it will be
+ * modified using the given values of @p start, @p end and @p
+ * count. If no entry exists, a new one will be created using the
+ * given values.
+ *
+ * @param rl the resource list to edit
+ * @param type the resource entry type (e.g. SYS_RES_MEMORY)
+ * @param rid the resource identifier
+ * @param start the start address of the resource
+ * @param end the end address of the resource
+ * @param count XXX end-start+1
+ */
void
resource_list_add(struct resource_list *rl, int type, int rid,
u_long start, u_long end, u_long count)
@@ -1867,6 +2384,16 @@ resource_list_add(struct resource_list *rl, int type, int rid,
rle->count = count;
}
+/**
+ * @brief Find a resource entry by type and rid.
+ *
+ * @param rl the resource list to search
+ * @param type the resource entry type (e.g. SYS_RES_MEMORY)
+ * @param rid the resource identifier
+ *
+ * @returns the resource entry pointer or NULL if there is no such
+ * entry.
+ */
struct resource_list_entry *
resource_list_find(struct resource_list *rl, int type, int rid)
{
@@ -1879,6 +2406,13 @@ resource_list_find(struct resource_list *rl, int type, int rid)
return (NULL);
}
+/**
+ * @brief Delete a resource entry.
+ *
+ * @param rl the resource list to edit
+ * @param type the resource entry type (e.g. SYS_RES_MEMORY)
+ * @param rid the resource identifier
+ */
void
resource_list_delete(struct resource_list *rl, int type, int rid)
{
@@ -1892,6 +2426,39 @@ resource_list_delete(struct resource_list *rl, int type, int rid)
}
}
+/**
+ * @brief Helper function for implementing BUS_ALLOC_RESOURCE()
+ *
+ * Implement BUS_ALLOC_RESOURCE() by looking up a resource from the list
+ * and passing the allocation up to the parent of @p bus. This assumes
+ * that the first entry of @c device_get_ivars(child) is a struct
+ * resource_list. This also handles 'passthrough' allocations where a
+ * child is a remote descendant of bus by passing the allocation up to
+ * the parent of bus.
+ *
+ * Typically, a bus driver would store a list of child resources
+ * somewhere in the child device's ivars (see device_get_ivars()) and
+ * its implementation of BUS_ALLOC_RESOURCE() would find that list and
+ * then call resource_list_alloc() to perform the allocation.
+ *
+ * @param rl the resource list to allocate from
+ * @param bus 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
+ */
struct resource *
resource_list_alloc(struct resource_list *rl, device_t bus, device_t child,
int type, int *rid, u_long start, u_long end, u_long count, u_int flags)
@@ -1934,6 +2501,23 @@ resource_list_alloc(struct resource_list *rl, device_t bus, device_t child,
return (rle->res);
}
+/**
+ * @brief Helper function for implementing BUS_RELEASE_RESOURCE()
+ *
+ * Implement BUS_RELEASE_RESOURCE() using a resource list. Normally
+ * used with resource_list_alloc().
+ *
+ * @param rl the resource list which was allocated from
+ * @param bus the parent device of @p child
+ * @param child the device which is requesting a release
+ * @param type the type of resource to allocate
+ * @param rid the resource identifier
+ * @param res the resource to release
+ *
+ * @retval 0 success
+ * @retval non-zero a standard unix error code indicating what
+ * error condition prevented the operation
+ */
int
resource_list_release(struct resource_list *rl, device_t bus, device_t child,
int type, int rid, struct resource *res)
@@ -1963,6 +2547,21 @@ resource_list_release(struct resource_list *rl, device_t bus, device_t child,
return (0);
}
+/**
+ * @brief Print a description of resources in a resource list
+ *
+ * Print all resources of a specified type, for use in BUS_PRINT_CHILD().
+ * The name is printed if at least one resource of the given type is available.
+ * The format is used to print resource start and end.
+ *
+ * @param rl the resource list to print
+ * @param name the name of @p type, e.g. @c "memory"
+ * @param type type type of resource entry to print
+ * @param format printf(9) format string to print resource
+ * start and end values
+ *
+ * @returns the number of characters printed
+ */
int
resource_list_print_type(struct resource_list *rl, const char *name, int type,
const char *format)
@@ -1991,8 +2590,13 @@ resource_list_print_type(struct resource_list *rl, const char *name, int type,
return (retval);
}
-/*
- * Call DEVICE_IDENTIFY for each driver.
+/**
+ * @brief Helper function for implementing DEVICE_PROBE()
+ *
+ * This function can be used to help implement the DEVICE_PROBE() for
+ * a bus (i.e. a device which has other devices attached to it). It
+ * calls the DEVICE_IDENTIFY() method of each driver in the device's
+ * devclass.
*/
int
bus_generic_probe(device_t dev)
@@ -2007,6 +2611,13 @@ bus_generic_probe(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing DEVICE_ATTACH()
+ *
+ * This function can be used to help implement the DEVICE_ATTACH() for
+ * a bus. It calls device_probe_and_attach() for each of the device's
+ * children.
+ */
int
bus_generic_attach(device_t dev)
{
@@ -2019,6 +2630,13 @@ bus_generic_attach(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing DEVICE_DETACH()
+ *
+ * This function can be used to help implement the DEVICE_DETACH() for
+ * a bus. It calls device_detach() for each of the device's
+ * children.
+ */
int
bus_generic_detach(device_t dev)
{
@@ -2036,6 +2654,13 @@ bus_generic_detach(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing DEVICE_SHUTDOWN()
+ *
+ * This function can be used to help implement the DEVICE_SHUTDOWN()
+ * for a bus. It calls device_shutdown() for each of the device's
+ * children.
+ */
int
bus_generic_shutdown(device_t dev)
{
@@ -2048,6 +2673,15 @@ bus_generic_shutdown(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing DEVICE_SUSPEND()
+ *
+ * This function can be used to help implement the DEVICE_SUSPEND()
+ * for a bus. It calls DEVICE_SUSPEND() for each of the device's
+ * children. If any call to DEVICE_SUSPEND() fails, the suspend
+ * operation is aborted and any devices which were suspended are
+ * resumed immediately by calling their DEVICE_RESUME() methods.
+ */
int
bus_generic_suspend(device_t dev)
{
@@ -2067,6 +2701,12 @@ bus_generic_suspend(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing DEVICE_RESUME()
+ *
+ * This function can be used to help implement the DEVICE_RESUME() for
+ * a bus. It calls DEVICE_RESUME() on each of the device's children.
+ */
int
bus_generic_resume(device_t dev)
{
@@ -2079,6 +2719,15 @@ bus_generic_resume(device_t dev)
return (0);
}
+/**
+ * @brief Helper function for implementing BUS_PRINT_CHILD().
+ *
+ * This function prints the first part of the ascii representation of
+ * @p child, including its name, unit and description (if any - see
+ * device_set_desc()).
+ *
+ * @returns the number of characters printed
+ */
int
bus_print_child_header(device_t dev, device_t child)
{
@@ -2093,12 +2742,29 @@ bus_print_child_header(device_t dev, device_t child)
return (retval);
}
+/**
+ * @brief Helper function for implementing BUS_PRINT_CHILD().
+ *
+ * This function prints the last part of the ascii representation of
+ * @p child, which consists of the string @c " on " followed by the
+ * name and unit of the @p dev.
+ *
+ * @returns the number of characters printed
+ */
int
bus_print_child_footer(device_t dev, device_t child)
{
return (printf(" on %s\n", device_get_nameunit(dev)));
}
+/**
+ * @brief Helper function for implementing BUS_PRINT_CHILD().
+ *
+ * This function simply calls bus_print_child_header() followed by
+ * bus_print_child_footer().
+ *
+ * @returns the number of characters printed
+ */
int
bus_generic_print_child(device_t dev, device_t child)
{
@@ -2110,6 +2776,11 @@ bus_generic_print_child(device_t dev, device_t child)
return (retval);
}
+/**
+ * @brief Stub function for implementing BUS_READ_IVAR().
+ *
+ * @returns ENOENT
+ */
int
bus_generic_read_ivar(device_t dev, device_t child, int index,
uintptr_t * result)
@@ -2117,6 +2788,11 @@ bus_generic_read_ivar(device_t dev, device_t child, int index,
return (ENOENT);
}
+/**
+ * @brief Stub function for implementing BUS_WRITE_IVAR().
+ *
+ * @returns ENOENT
+ */
int
bus_generic_write_ivar(device_t dev, device_t child, int index,
uintptr_t value)
@@ -2124,12 +2800,24 @@ bus_generic_write_ivar(device_t dev, device_t child, int index,
return (ENOENT);
}
+/**
+ * @brief Stub function for implementing BUS_GET_RESOURCE_LIST().
+ *
+ * @returns NULL
+ */
struct resource_list *
bus_generic_get_resource_list(device_t dev, device_t child)
{
return (NULL);
}
+/**
+ * @brief Helper function for implementing BUS_DRIVER_ADDED().
+ *
+ * This implementation of BUS_DRIVER_ADDED() simply calls the driver's
+ * DEVICE_IDENTIFY() method to allow it to add new children to the bus
+ * and then calls device_probe_and_attach() for each unattached child.
+ */
void
bus_generic_driver_added(device_t dev, driver_t *driver)
{
@@ -2142,6 +2830,12 @@ bus_generic_driver_added(device_t dev, driver_t *driver)
}
}
+/**
+ * @brief Helper function for implementing BUS_SETUP_INTR().
+ *
+ * This simple implementation of BUS_SETUP_INTR() simply calls the
+ * BUS_SETUP_INTR() method of the parent of @p dev.
+ */
int
bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_intr_t *intr, void *arg, void **cookiep)
@@ -2153,6 +2847,12 @@ bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_TEARDOWN_INTR().
+ *
+ * This simple implementation of BUS_TEARDOWN_INTR() simply calls the
+ * BUS_TEARDOWN_INTR() method of the parent of @p dev.
+ */
int
bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookie)
@@ -2163,6 +2863,12 @@ bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_ALLOC_RESOURCE().
+ *
+ * This simple implementation of BUS_ALLOC_RESOURCE() simply calls the
+ * BUS_ALLOC_RESOURCE() method of the parent of @p dev.
+ */
struct resource *
bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
@@ -2174,6 +2880,12 @@ bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (NULL);
}
+/**
+ * @brief Helper function for implementing BUS_RELEASE_RESOURCE().
+ *
+ * This simple implementation of BUS_RELEASE_RESOURCE() simply calls the
+ * BUS_RELEASE_RESOURCE() method of the parent of @p dev.
+ */
int
bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
@@ -2185,6 +2897,12 @@ bus_generic_release_resource(device_t dev, device_t child, int type, int rid,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_ACTIVATE_RESOURCE().
+ *
+ * This simple implementation of BUS_ACTIVATE_RESOURCE() simply calls the
+ * BUS_ACTIVATE_RESOURCE() method of the parent of @p dev.
+ */
int
bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
@@ -2196,6 +2914,12 @@ bus_generic_activate_resource(device_t dev, device_t child, int type, int rid,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_DEACTIVATE_RESOURCE().
+ *
+ * This simple implementation of BUS_DEACTIVATE_RESOURCE() simply calls the
+ * BUS_DEACTIVATE_RESOURCE() method of the parent of @p dev.
+ */
int
bus_generic_deactivate_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
@@ -2207,6 +2931,12 @@ bus_generic_deactivate_resource(device_t dev, device_t child, int type,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_CONFIG_INTR().
+ *
+ * This simple implementation of BUS_CONFIG_INTR() simply calls the
+ * BUS_CONFIG_INTR() method of the parent of @p dev.
+ */
int
bus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol)
@@ -2218,6 +2948,14 @@ bus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig,
return (EINVAL);
}
+/**
+ * @brief Helper function for implementing BUS_GET_RESOURCE().
+ *
+ * This implementation of BUS_GET_RESOURCE() uses the
+ * resource_list_find() function to do most of the work. It calls
+ * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
+ * search.
+ */
int
bus_generic_rl_get_resource(device_t dev, device_t child, int type, int rid,
u_long *startp, u_long *countp)
@@ -2241,6 +2979,14 @@ bus_generic_rl_get_resource(device_t dev, device_t child, int type, int rid,
return (0);
}
+/**
+ * @brief Helper function for implementing BUS_SET_RESOURCE().
+ *
+ * This implementation of BUS_SET_RESOURCE() uses the
+ * resource_list_add() function to do most of the work. It calls
+ * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
+ * edit.
+ */
int
bus_generic_rl_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
@@ -2256,6 +3002,14 @@ bus_generic_rl_set_resource(device_t dev, device_t child, int type, int rid,
return (0);
}
+/**
+ * @brief Helper function for implementing BUS_DELETE_RESOURCE().
+ *
+ * This implementation of BUS_DELETE_RESOURCE() uses the
+ * resource_list_delete() function to do most of the work. It calls
+ * BUS_GET_RESOURCE_LIST() to find a suitable resource list to
+ * edit.
+ */
void
bus_generic_rl_delete_resource(device_t dev, device_t child, int type, int rid)
{
@@ -2270,6 +3024,13 @@ bus_generic_rl_delete_resource(device_t dev, device_t child, int type, int rid)
return;
}
+/**
+ * @brief Helper function for implementing BUS_RELEASE_RESOURCE().
+ *
+ * This implementation of BUS_RELEASE_RESOURCE() uses the
+ * resource_list_release() function to do most of the work. It calls
+ * BUS_GET_RESOURCE_LIST() to find a suitable resource list.
+ */
int
bus_generic_rl_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
@@ -2283,6 +3044,13 @@ bus_generic_rl_release_resource(device_t dev, device_t child, int type,
return (resource_list_release(rl, dev, child, type, rid, r));
}
+/**
+ * @brief Helper function for implementing BUS_ALLOC_RESOURCE().
+ *
+ * This implementation of BUS_ALLOC_RESOURCE() uses the
+ * resource_list_alloc() function to do most of the work. It calls
+ * BUS_GET_RESOURCE_LIST() to find a suitable resource list.
+ */
struct resource *
bus_generic_rl_alloc_resource(device_t dev, device_t child, int type,
int *rid, u_long start, u_long end, u_long count, u_int flags)
@@ -2297,10 +3065,16 @@ bus_generic_rl_alloc_resource(device_t dev, device_t child, int type,
start, end, count, flags));
}
+/**
+ * @brief Helper function for implementing BUS_CHILD_PRESENT().
+ *
+ * This simple implementation of BUS_CHILD_PRESENT() simply calls the
+ * BUS_CHILD_PRESENT() method of the parent of @p dev.
+ */
int
-bus_generic_child_present(device_t bus, device_t child)
+bus_generic_child_present(device_t dev, device_t child)
{
- return (BUS_CHILD_PRESENT(device_get_parent(bus), bus));
+ return (BUS_CHILD_PRESENT(device_get_parent(dev), dev));
}
/*
@@ -2310,6 +3084,13 @@ bus_generic_child_present(device_t bus, device_t child)
* less-wordy code. In the future, it might make sense for this code
* to maintain some sort of a list of resources allocated by each device.
*/
+
+/**
+ * @brief Wrapper function for BUS_ALLOC_RESOURCE().
+ *
+ * This function simply calls the BUS_ALLOC_RESOURCE() method of the
+ * parent of @p dev.
+ */
struct resource *
bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
u_long count, u_int flags)
@@ -2320,6 +3101,12 @@ bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end,
count, flags));
}
+/**
+ * @brief Wrapper function for BUS_ACTIVATE_RESOURCE().
+ *
+ * This function simply calls the BUS_ACTIVATE_RESOURCE() method of the
+ * parent of @p dev.
+ */
int
bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
{
@@ -2328,6 +3115,12 @@ bus_activate_resource(device_t dev, int type, int rid, struct resource *r)
return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
}
+/**
+ * @brief Wrapper function for BUS_DEACTIVATE_RESOURCE().
+ *
+ * This function simply calls the BUS_DEACTIVATE_RESOURCE() method of the
+ * parent of @p dev.
+ */
int
bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
{
@@ -2336,6 +3129,12 @@ bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)
return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r));
}
+/**
+ * @brief Wrapper function for BUS_RELEASE_RESOURCE().
+ *
+ * This function simply calls the BUS_RELEASE_RESOURCE() method of the
+ * parent of @p dev.
+ */
int
bus_release_resource(device_t dev, int type, int rid, struct resource *r)
{
@@ -2344,6 +3143,12 @@ bus_release_resource(device_t dev, int type, int rid, struct resource *r)
return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
}
+/**
+ * @brief Wrapper function for BUS_SETUP_INTR().
+ *
+ * This function simply calls the BUS_SETUP_INTR() method of the
+ * parent of @p dev.
+ */
int
bus_setup_intr(device_t dev, struct resource *r, int flags,
driver_intr_t handler, void *arg, void **cookiep)
@@ -2369,6 +3174,12 @@ bus_setup_intr(device_t dev, struct resource *r, int flags,
return (error);
}
+/**
+ * @brief Wrapper function for BUS_TEARDOWN_INTR().
+ *
+ * This function simply calls the BUS_TEARDOWN_INTR() method of the
+ * parent of @p dev.
+ */
int
bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
{
@@ -2377,6 +3188,12 @@ bus_teardown_intr(device_t dev, struct resource *r, void *cookie)
return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie));
}
+/**
+ * @brief Wrapper function for BUS_SET_RESOURCE().
+ *
+ * This function simply calls the BUS_SET_RESOURCE() method of the
+ * parent of @p dev.
+ */
int
bus_set_resource(device_t dev, int type, int rid,
u_long start, u_long count)
@@ -2385,6 +3202,12 @@ bus_set_resource(device_t dev, int type, int rid,
start, count));
}
+/**
+ * @brief Wrapper function for BUS_GET_RESOURCE().
+ *
+ * This function simply calls the BUS_GET_RESOURCE() method of the
+ * parent of @p dev.
+ */
int
bus_get_resource(device_t dev, int type, int rid,
u_long *startp, u_long *countp)
@@ -2393,6 +3216,12 @@ bus_get_resource(device_t dev, int type, int rid,
startp, countp));
}
+/**
+ * @brief Wrapper function for BUS_GET_RESOURCE().
+ *
+ * This function simply calls the BUS_GET_RESOURCE() method of the
+ * parent of @p dev and returns the start value.
+ */
u_long
bus_get_resource_start(device_t dev, int type, int rid)
{
@@ -2406,6 +3235,12 @@ bus_get_resource_start(device_t dev, int type, int rid)
return (start);
}
+/**
+ * @brief Wrapper function for BUS_GET_RESOURCE().
+ *
+ * This function simply calls the BUS_GET_RESOURCE() method of the
+ * parent of @p dev and returns the count value.
+ */
u_long
bus_get_resource_count(device_t dev, int type, int rid)
{
@@ -2419,18 +3254,36 @@ bus_get_resource_count(device_t dev, int type, int rid)
return (count);
}
+/**
+ * @brief Wrapper function for BUS_DELETE_RESOURCE().
+ *
+ * This function simply calls the BUS_DELETE_RESOURCE() method of the
+ * parent of @p dev.
+ */
void
bus_delete_resource(device_t dev, int type, int rid)
{
BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid);
}
+/**
+ * @brief Wrapper function for BUS_CHILD_PRESENT().
+ *
+ * This function simply calls the BUS_CHILD_PRESENT() method of the
+ * parent of @p dev.
+ */
int
bus_child_present(device_t child)
{
return (BUS_CHILD_PRESENT(device_get_parent(child), child));
}
+/**
+ * @brief Wrapper function for BUS_CHILD_PNPINFO_STR().
+ *
+ * This function simply calls the BUS_CHILD_PNPINFO_STR() method of the
+ * parent of @p dev.
+ */
int
bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen)
{
@@ -2444,6 +3297,12 @@ bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen)
return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen));
}
+/**
+ * @brief Wrapper function for BUS_CHILD_LOCATION_STR().
+ *
+ * This function simply calls the BUS_CHILD_LOCATION_STR() method of the
+ * parent of @p dev.
+ */
int
bus_child_location_str(device_t child, char *buf, size_t buflen)
{
@@ -2549,6 +3408,12 @@ static moduledata_t root_bus_mod = {
};
DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
+/**
+ * @brief Automatically configure devices
+ *
+ * This function begins the autoconfiguration process by calling
+ * device_probe_and_attach() for each child of the @c root0 device.
+ */
void
root_bus_configure(void)
{
@@ -2561,6 +3426,14 @@ root_bus_configure(void)
}
}
+/**
+ * @brief Module handler for registering device drivers
+ *
+ * This module handler is used to automatically register device
+ * drivers when modules are loaded. If @p what is MOD_LOAD, it calls
+ * devclass_add_driver() for the driver described by the
+ * driver_module_data structure pointed to by @p arg
+ */
int
driver_module_handler(module_t mod, int what, void *arg)
{
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 842f3ab..3c88b4d 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -29,40 +29,45 @@
#ifndef _SYS_BUS_H_
#define _SYS_BUS_H_
-/*
- * Interface information structure.
+/**
+ * @defgroup NEWBUS newbus - a generic framework for managing devices
+ * @{
+ */
+
+/**
+ * @brief Interface information structure.
*/
struct u_businfo {
- int ub_version; /* interface version */
+ int ub_version; /**< @brief interface version */
#define BUS_USER_VERSION 1
- int ub_generation; /* generation count */
+ int ub_generation; /**< @brief generation count */
};
-/*
- * State of the device.
+/**
+ * @brief State of the device.
*/
typedef enum device_state {
- DS_NOTPRESENT, /* not probed or probe failed */
- DS_ALIVE, /* probe succeeded */
- DS_ATTACHED, /* attach method called */
- DS_BUSY /* device is open */
+ DS_NOTPRESENT, /**< @brief not probed or probe failed */
+ DS_ALIVE, /**< @brief probe succeeded */
+ DS_ATTACHED, /**< @brief attach method called */
+ DS_BUSY /**< @brief device is open */
} device_state_t;
-/*
- * Device information exported to userspace.
+/**
+ * @brief Device information exported to userspace.
*/
struct u_device {
uintptr_t dv_handle;
uintptr_t dv_parent;
- char dv_name[32]; /* Name of device in tree. */
- char dv_desc[32]; /* Driver description */
- char dv_drivername[32]; /* Driver name */
- char dv_pnpinfo[128]; /* Plug and play info */
- char dv_location[128]; /* Where is the device? */
- uint32_t dv_devflags; /* API Flags for device */
- uint16_t dv_flags; /* flags for dev date */
- device_state_t dv_state; /* State of attachment */
+ char dv_name[32]; /**< @brief Name of device in tree. */
+ char dv_desc[32]; /**< @brief Driver description */
+ char dv_drivername[32]; /**< @brief Driver name */
+ char dv_pnpinfo[128]; /**< @brief Plug and play info */
+ char dv_location[128]; /**< @brief Where is the device? */
+ uint32_t dv_devflags; /**< @brief API Flags for device */
+ uint16_t dv_flags; /**< @brief flags for dev date */
+ device_state_t dv_state; /**< @brief State of attachment */
/* XXX more driver info? */
};
@@ -71,7 +76,7 @@ struct u_device {
#include <sys/queue.h>
#include <sys/kobj.h>
-/*
+/**
* devctl hooks. Typically one should use the devctl_notify
* hook to send the message. However, devctl_queue_data is also
* included in case devctl_notify isn't sufficiently general.
@@ -84,25 +89,61 @@ void devctl_queue_data(char *__data);
* Forward declarations
*/
typedef struct device *device_t;
+
+/**
+ * @brief A device driver (included mainly for compatibility with
+ * FreeBSD 4.x).
+ */
typedef struct kobj_class driver_t;
+
+/**
+ * @brief A device class
+ *
+ * The devclass object has two main functions in the system. The first
+ * is to manage the allocation of unit numbers for device instances
+ * and the second is to hold the list of device drivers for a
+ * particular bus type. Each devclass has a name and there cannot be
+ * two devclasses with the same name. This ensures that unique unit
+ * numbers are allocated to device instances.
+ *
+ * Drivers that support several different bus attachments (e.g. isa,
+ * pci, pccard) should all use the same devclass to ensure that unit
+ * numbers do not conflict.
+ *
+ * Each devclass may also have a parent devclass. This is used when
+ * searching for device drivers to allow a form of inheritance. When
+ * matching drivers with devices, first the driver list of the parent
+ * device's devclass is searched. If no driver is found in that list,
+ * the search continues in the parent devclass (if any).
+ */
typedef struct devclass *devclass_t;
+
+/**
+ * @brief A device method (included mainly for compatibility with
+ * FreeBSD 4.x).
+ */
#define device_method_t kobj_method_t
+/**
+ * @brief A driver interrupt service routine
+ */
typedef void driver_intr_t(void*);
-/*
- * Interrupt type bits. These flags are used both by newbus interrupt
+/**
+ * @brief Interrupt type bits.
+ *
+ * These flags are used both by newbus interrupt
* registration (nexus.c) and also in struct intrec, which defines
* interrupt properties.
*
* XXX We should probably revisit this and remove the vestiges of the
- * spls implicit in names like INTR_TYPE_TTY. In the meantime, don't
+ * spls implicit in names like INTR_TYPE_TTY. In the meantime, don't
* confuse things by renaming them (Grog, 18 July 2000).
*
* We define this in terms of bits because some devices may belong
* to multiple classes (and therefore need to be included in
* multiple interrupt masks, which is what this really serves to
- * indicate. Buses which do interrupt remapping will want to
+ * indicate. Buses which do interrupt remapping will want to
* change their type to reflect what sort of devices are underneath.
*/
enum intr_type {
@@ -133,8 +174,10 @@ enum intr_polarity {
typedef int (*devop_t)(void);
-/*
- * This structure is deprecated. Use the kobj(9) macro DEFINE_CLASS to
+/**
+ * @brief This structure is deprecated.
+ *
+ * Use the kobj(9) macro DEFINE_CLASS to
* declare classes which implement device drivers.
*/
struct driver {
@@ -147,79 +190,42 @@ struct driver {
*/
struct resource;
+/**
+ * @brief An entry for a single resource in a resource list.
+ */
struct resource_list_entry {
SLIST_ENTRY(resource_list_entry) link;
- int type; /* type argument to alloc_resource */
- int rid; /* resource identifier */
- struct resource *res; /* the real resource when allocated */
- u_long start; /* start of resource range */
- u_long end; /* end of resource range */
- u_long count; /* count within range */
+ int type; /**< @brief type argument to alloc_resource */
+ int rid; /**< @brief resource identifier */
+ struct resource *res; /**< @brief the real resource when allocated */
+ u_long start; /**< @brief start of resource range */
+ u_long end; /**< @brief end of resource range */
+ u_long count; /**< @brief count within range */
};
SLIST_HEAD(resource_list, resource_list_entry);
-/*
- * Initialise a resource list.
- */
void resource_list_init(struct resource_list *rl);
-
-/*
- * Reclaim memory used by a resource list.
- */
void resource_list_free(struct resource_list *rl);
-
-/*
- * Add a resource entry or modify an existing entry if one exists with
- * the same type and rid.
- */
void resource_list_add(struct resource_list *rl,
int type, int rid,
u_long start, u_long end, u_long count);
int resource_list_add_next(struct resource_list *rl,
int type,
u_long start, u_long end, u_long count);
-
-
-/*
- * Find a resource entry by type and rid.
- */
struct resource_list_entry*
resource_list_find(struct resource_list *rl,
int type, int rid);
-
-/*
- * Delete a resource entry.
- */
void resource_list_delete(struct resource_list *rl,
int type, int rid);
-
-/*
- * Implement BUS_ALLOC_RESOURCE by looking up a resource from the list
- * and passing the allocation up to the parent of bus. This assumes
- * that the first entry of device_get_ivars(child) is a struct
- * resource_list. This also handles 'passthrough' allocations where a
- * child is a remote descendant of bus by passing the allocation up to
- * the parent of bus.
- */
struct resource *
resource_list_alloc(struct resource_list *rl,
device_t bus, device_t child,
int type, int *rid,
u_long start, u_long end,
u_long count, u_int flags);
-
-/*
- * Implement BUS_RELEASE_RESOURCE.
- */
int resource_list_release(struct resource_list *rl,
device_t bus, device_t child,
int type, int rid, struct resource *res);
-
-/*
- * Print all resources of a specified type, for use in bus_print_child.
- * The name is printed if at least one resource of the given type is available.
- * The format ist used to print resource start and end.
- */
int resource_list_print_type(struct resource_list *rl,
const char *name, int type,
const char *format);
@@ -410,7 +416,7 @@ int resource_set_string(const char *name, int unit, const char *resname,
int bus_data_generation_check(int generation);
void bus_data_generation_update(void);
-/*
+/**
* Shorthand for constructing method tables.
*/
#define DEVMETHOD KOBJMETHOD
@@ -425,7 +431,7 @@ struct module;
int driver_module_handler(struct module *, int, void *);
-/*
+/**
* Module support for automatically adding drivers to busses.
*/
struct driver_module_data {
@@ -453,7 +459,7 @@ static moduledata_t name##_##busname##_mod = { \
DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \
SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
-/*
+/**
* Generic ivar accessor generation macros for bus drivers
*/
#define __BUS_ACCESSOR(varp, var, ivarp, ivar, type) \
OpenPOWER on IntegriCloud