Automatic and Manual Configuration

Several parameters that a driver needs to know can change from system to system. For instance, the driver must know the hardware’s actual I/O addresses, or memory range.

Note that most of the problems discussed in this section don’t apply to PCI devices (described in Chapter 15.

Depending on the device, there may be other parameters in addition to the I/O address that affect the driver’s behavior, such as device brand and release number. It’s essential for the driver to know the value of these parameters in order to work correctly. Setting up the driver with the correct values (i.e., configuring it) is one of the tricky tasks that need to be performed during driver initialization.

Basically, there are two ways to obtain the correct values: either the user specifies them explicitly or the driver autodetects them. While autodetection is undoubtedly the best approach to driver configuration, user configuration is much easier to implement; a suitable tradeoff for a driver writer is to implement automatic configuration whenever possible, while allowing user configuration as an option to override autodetection. An additional advantage of this approach to configuration is that the initial development can be done without autodetection, by specifying the parameters at load time, and autodetection can be implemented later.

Parameter values can be assigned at load time by insmod, which accepts specification of integer and string values on the command line. The command can modify all the global variables defined in the module. For example, if your source contains the variables:

int skull_ival=0;
char *skull_sval;

then the following command can be used to load the module:

insmod skull skull_ival=666 skull_sval="the beast"

A sample run using printk will show that the assignments are already in effect when init_module gets invoked. Note that insmod can assign a value to any integer or char-pointer variable in the module. It does this for both static and global variables, whether they are part of the public symbol table or not. Strings declared as arrays, on the other hand, can’t be assigned at load time because the pointer is resolved at compile time and can’t be changed after that.

Automatic configuration, then, can be designed to work this way: ``If the configuration variables have the default value, perform autodetection; otherwise, keep the current value.'' In order for this technique to work, the ``default'' value should be one that the user would never actually want to specify at load time.

The following code shows how skull autodetects the port address of a device. In this example, autodetection is used to look for multiple devices, while manual configuration is restricted to a single device. Note that the function skull_detect was shown above, while skull_init_board is in charge of device-specific initialization, and thus is not shown.

/*
 * port ranges: the device can reside between
 * 0x280 and 0x300, in step of 0x10. It uses 0x10 ports.
 */
#define SKULL_PORT_FLOOR 0x280
#define SKULL_PORT_CEIL  0x300
#define SKULL_PORT_RANGE 0x010

/*
 * the following function performs autodetection, unless a specific
 * value was assigned by insmod to "skull_port_base"
 */

static int skull_port_base=0; /* 0 forces autodetection */

static int skull_find_hw(void) /* returns the # of devices */
{
    /* base is either the load-time value or the first trial */
    int base = skull_port_base ? skull_port_base 
                             : SKULL_PORT_FLOOR; 
    int result = 0;

    /* loop one time if value assigned, try them all if autodetecting */
    do {
        if (skull_detect(base, SKULL_PORT_RANGE) == 0) {
            skull_init_board(base);
            result++;
        }
        base += SKULL_PORT_RANGE; /* prepare for next trial */
    }
    while (skull_port_base == 0 && base < SKULL_PORT_CEIL);

    return result;
}

A real driver can avoid using the prefix (in this case, skull_) for the configuration variables in order to make things easier for the user who specifies them on the insmod command line, provided that those symbols are not going to be published in the main symbol table. If they are, a good choice can be to declare two symbols: one without the prefix, which is assigned at load time and one with the prefix, which is published by register_symtab.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.78.41