The information that a user enters into the kernel
        configuration file is processed and passed to the kernel as
        configuration resources. This information is parsed by the bus
        configuration code and transformed into a value of structure
        device_t and the bus resources associated with it. The drivers
        may access the configuration resources directly using
        functions resource_* for more complex cases of
        configuration. However, generally this is neither needed nor recommended,
        so this issue is not discussed further here.
The bus resources are associated with each device. They are identified by type and number within the type. For the ISA bus the following types are defined:
SYS_RES_IRQ - interrupt number
SYS_RES_DRQ - ISA DMA channel number
SYS_RES_MEMORY - range of device memory mapped into the system memory space
SYS_RES_IOPORT - range of device I/O registers
The enumeration within types starts from 0, so if a device
        has two memory regions it would have resources of type
        SYS_RES_MEMORY numbered 0 and 1.  The resource type has
        nothing to do with the C language type, all the resource
        values have the C language type unsigned long and must be
        cast as necessary. The resource numbers do not have to be
        contiguous, although for ISA they normally would be. The
        permitted resource numbers for ISA devices are:
          IRQ: 0-1
          DRQ: 0-1
          MEMORY: 0-3
          IOPORT: 0-7All the resources are represented as ranges, with a start value and count. For IRQ and DRQ resources the count would normally be equal to 1. The values for memory refer to the physical addresses.
Three types of activities can be performed on resources:
set/get
allocate/release
activate/deactivate
Setting sets the range used by the resource. Allocation reserves the requested range that no other driver would be able to reserve it (and checking that no other driver reserved this range already). Activation makes the resource accessible to the driver by doing whatever is necessary for that (for example, for memory it would be mapping into the kernel virtual address space).
The functions to manipulate resources are:
int bus_set_resource(device_t dev, int type,
            int rid, u_long start, u_long count)
Set a range for a resource. Returns 0 if successful,
            error code otherwise.  Normally, this function will
            return an error only if one of type,
            rid, start or
            count has a value that falls out of the
            permitted range.
dev - driver's device
type - type of resource, SYS_RES_*
rid - resource number (ID) within type
start, count - resource range
int bus_get_resource(device_t dev, int type,
          int rid, u_long *startp, u_long *countp)
Get the range of resource. Returns 0 if successful, error code if the resource is not defined yet.
u_long bus_get_resource_start(device_t dev,
            int type, int rid) u_long bus_get_resource_count (device_t
            dev, int type, int rid)
Convenience functions to get only the start or count. Return 0 in case of error, so if the resource start has 0 among the legitimate values it would be impossible to tell if the value is 0 or an error occurred. Luckily, no ISA resources for add-on drivers may have a start value equal to 0.
void bus_delete_resource(device_t dev, int
            type, int rid)
Delete a resource, make it undefined.
struct resource *
            bus_alloc_resource(device_t dev, int type, int *rid,
            u_long start, u_long end, u_long count, u_int
            flags)
Allocate a resource as a range of count values not
            allocated by anyone else, somewhere between start and
            end. Alas, alignment is not supported.  If the resource
            was not set yet it is automatically created. The special
            values of start 0 and end ~0 (all ones) means that the
            fixed values previously set by
            bus_set_resource() must be used
            instead: start and count as themselves and
            end=(start+count), in this case if the resource was not
            defined before then an error is returned.  Although rid is
            passed by reference it is not set anywhere by the resource
            allocation code of the ISA bus. (The other buses may use a
            different approach and modify it).
Flags are a bitmap, the flags interesting for the caller are:
RF_ACTIVE - causes the resource to be automatically activated after allocation.
RF_SHAREABLE - resource may be shared at the same time by multiple drivers.
RF_TIMESHARE - resource may be time-shared by multiple drivers, i.e., allocated at the same time by many but activated only by one at any given moment of time.
Returns 0 on error. The allocated values may be
            obtained from the returned handle using methods
            rhand_*().
int bus_release_resource(device_t dev, int
            type, int rid, struct resource *r)
Release the resource, r is the handle returned by
            bus_alloc_resource().  Returns 0 on
            success, error code otherwise.
int bus_activate_resource(device_t dev, int
            type, int rid, struct resource *r)
            int bus_deactivate_resource(device_t dev, int
            type, int rid, struct resource *r)
Activate or deactivate resource. Return 0 on success,
            error code otherwise.  If the resource is time-shared and
            currently activated by another driver then EBUSY is
            returned.
int bus_setup_intr(device_t dev, struct
            resource *r, int flags, driver_intr_t *handler, void *arg,
            void **cookiep) int
            bus_teardown_intr(device_t dev, struct resource *r, void
            *cookie)
Associate or de-associate the interrupt handler with a device. Return 0 on success, error code otherwise.
r - the activated resource handler describing the IRQ
flags - the interrupt priority level, one of:
INTR_TYPE_TTY - terminals and
                other likewise character-type devices. To mask them
                use spltty().
(INTR_TYPE_TTY |
                INTR_TYPE_FAST) - terminal type devices
                with small input buffer, critical to the data loss on
                input (such as the old-fashioned serial ports). To
                mask them use spltty().
INTR_TYPE_BIO - block-type
                devices, except those on the CAM controllers. To mask
                them use splbio().
INTR_TYPE_CAM - CAM (Common
                Access Method) bus controllers. To mask them use
                splcam().
INTR_TYPE_NET - network
                interface controllers. To mask them use
                splimp().
INTR_TYPE_MISC -
                miscellaneous devices.  There is no other way to mask
                them than by splhigh() which
                masks all interrupts.
When an interrupt handler executes all the other interrupts matching its priority level will be masked. The only exception is the MISC level for which no other interrupts are masked and which is not masked by any other interrupt.
handler - pointer to the handler
            function, the type driver_intr_t is defined as void
            driver_intr_t(void *)
arg - the argument passed to the handler to identify this particular device. It is cast from void* to any real type by the handler. The old convention for the ISA interrupt handlers was to use the unit number as argument, the new (recommended) convention is using a pointer to the device softc structure.
cookie[p] - the value received
            from setup() is used to identify the
            handler when passed to
            teardown()
A number of methods are defined to operate on the resource handlers (struct resource *). Those of interest to the device driver writers are:
u_long rman_get_start(r) u_long
            rman_get_end(r) Get the start and end of
            allocated resource range.
void *rman_get_virtual(r) Get
            the virtual address of activated memory resource.
All FreeBSD documents are available for download at http://ftp.FreeBSD.org/pub/FreeBSD/doc/
Questions that are not answered by the
    documentation may be
    sent to <freebsd-questions@FreeBSD.org>.
    Send questions about this document to <freebsd-doc@FreeBSD.org>.