Previous Home Next


Device Autoconfiguration Process

The NetBSD device architecture is a tree consisting of children (devices and buses) descended from parents (buses). The "family tree" of devices is (partially) defined in kernel configuration files named files.*, where each child (device or bus) is specified as being attached to a specific parent (bus). The syntax of this attachment is discussed in the kernel configuration section, and described in detail in the NetBSD man page on config. The root of the tree is the "root" bus; all other buses and devices are descendants of this. In particular, for ARM-based systems, the bus "mainbus" is attached to the root in the file files.arm, and this is the bus to which the cpu is attached (in files.arm) as well as all system buses (in the processor-specific files.vx115).

The above defines the basic relationship between devices and buses. However, the actual instances of a specific device or bus on a platform are defined in the main platform configuration file - here, the file VX115_VEP. In this file, instances of buses and devices are specified with the bus/device base name followed by a digit - for example, mainbus0. There may be multiple instances of the same device, differentiated by their numerical suffixes - for example, vx115_com0 and vx115_com1. In addition, the specification of a device instance can provide a device locator, which is a list of parameters specific to that instance - for example, the base address of the device instance, IRQ, etc.  The parameters that make up the locator, along with default values, are part of the parent (bus) specification in the files.* files. These parameters are used during the autoconfiguration process, described below.

The tree structure of devices is built by the kernel configuration process, in which the NetBSD config utility is run on the platform configuration files to create source files with data structures reflecting the specified device relationships. The tree structure created by the kernel configuration process is used during kernel initialization in a process called autoconfiguration. This involves the sequential initialization of devices in a depth-first search of the tree of devices, as follows.
Each parent uses the NetBSD config_search method and its own search method to probe its children. config_search provides the parent search method with a cfdata struct which contains the device instance-specific locator parameters defined in the device instance specification. This data is passed to the match( ) and attach( ) functions. The cfdata structure associated with a device has a very general structure, with a loc field that's an array containing the bus-specific locator parameters with array indices that are defines generated by the config utility from the parameter names in the bus specification. For convenience, the parameters are usually copied into a more "structured" struct before being passed to match( ) and attach( ).

A Few More Details

The parent device search routine uses the NetBSD kernel function config_match function to look up and call its children's match( ) functions. The config_match( ) function calls the match( ) function for a device as follows.

The cfdata structures passed to parents (buses) during the autoconfiguration process are generated in the file ioconf.c during the configuration process from files.vx115 and VX115_VEP. Each bus structure (parent) defines cfdata locator fields in files.vx115; the format of the declaration of a bus and its locator fields is
device foobus {[field1 = default1], ... [fieldn = defaultn]}
For example, the files.vx115 file defines its internal APB with the text
device  vx115_apb { [addr=-1], [size=0], [intr=-1], [index=0] }: bus_space_generic
This bus thus defines 4 locators, which result in the generation of the defines VX115_APBCF_ADDR, VX115_APBCF_SIZE, VX115_APBCF_INTR, and VX115_APBCF_INDEX for the locator positions in the cfdata struct's loc array, and the default-value defines VX115_APBCF_ADDR_DEFAULT = -1, VX115_APBCF_SIZE_DEFAULT = 0, VX115_APBCF_INTR_DEFAULT = -1, and VX115_APBCF_INDEX_DEFAULT = 0

Device instances and their locator values for cfdata loc fields are specified in VX115_VEP. The format of the device instance specification is defined in the NetBSD man page ****. The declarations for the timer device attached to the Vx115's APB is
vx115_clk0   at vx115_apb? addr 0x700C5000 size 0x68  intr 9
Any field not specified gets default value in cfdata loc field, so in this case index = 0. To make it easier to work with the locator values outside of the rather unstructured cfdata loc array, it's typical to define a struct for the bus that mirrors the cfdata loc fields. For the Vx115's buses we define in vx115_var.h the struct type
struct vx115_attach_args 
{
bus_space_tag_t sa_iot; /* bus tag */
bus_addr_t sa_addr; /* device base address */
bus_size_t sa_size; /* device io space size */
int sa_intr; /* interrupt number */
int sa_index; /* device index */
};

This is initialized when the bus's devices are being probed from the corresponding device's cfdata struct, and then passed to the device's match( ) and attach( ) functions; note the use of the locator defines as offsets in the loc array of the cfdata struct.

int vx115_apb_search(struct device * parent, struct cfdata * cf, void *aux)
{
    struct vx115_softc *sc = (struct vx115_softc *) parent;
    struct vx115_attach_args aa;

    DPRINTF("vx115_apb_search\n");
   
    aa.sa_iot   = sc->sc_iot;
    aa.sa_addr  = cf->cf_loc[VX115_APBCF_ADDR];
    aa.sa_size  = cf->cf_loc[VX115_APBCF_SIZE];
    aa.sa_index = cf->cf_loc[VX115_APBCF_INDEX];
    aa.sa_intr  = cf->cf_loc[VX115_APBCF_INTR];

    if (config_match(parent, cf, &aa))
        config_attach(parent, cf, &aa, vx115_apb_print);

    return 0;
}




Previous Home Next


Comments/questions: jsevy@cs.drexel.edu