ChorusOS 4.0 Device Driver Framework Guide

Write the Bind Function

The bind routine enables the driver to perform a driver-to-device binding. Typical actions taken by a bind routine may be summarized as follows:

The driver examines properties attached to the device node to determine the type of device and to check whether the device may be serviced by the driver. Note that the properties examined by the driver are typically bus architecture specific. For instance, a PCI driver would examine the vendor and device identifier properties.

If the check is positive, the driver attaches a "driver" property to the device node. The property value specifies the driver name.

The parent bus/nexus driver should use the "driver" property to determine the name of the driver servicing the device. So, the child driver gives its name to the parent bus driver, through the "driver" property, asking the parent bus driver to invoke the drv_init routine on that device.

Note that, if a "driver" property is already present in the device node, then the drv_bind routine can not continue; drv_bind should not override an existing driver-to-device binding.

The driver-to-device binding mechanism used in the framework enables multiple implementations. A simple bind routine may be implemented by a device driver. Such an implementation would be device specific, only taking into account the devices known by the driver to be compatible with the driver's reference device.

Let us consider systems that support after-market, hot-plug devices and consult a network lookup service to locate the driver for a new device. It would be reasonable to provide a separate binder driver that would implement a smart driver-to-device mapping and a driver component download. Note that such a (generic) binder appears in the driver framework as a normal driver component. The binder driver provides the bind routine only and does not provide the probe and initialize routines.

		/*
     *  W83C553 driver bind method
     */
    static void
drv_bind (DevNode node)
{
    pciDevDrvBind(node, W83C553_VEND_ID, W83C553_DEV_ID, w83c553Drv.drv_name);
}

The pciDevDrvBind() function, detailed below, is implemented in the libebd.s.a library, not in the driver code itself.

		/*
     * Try to bind a given PCI driver to a given PCI device.
     * Basically, the driver is bound to the device node if
     * and only if the vendor/device ID pair specified by the
     * driver matches the vendor/device ID pair specified in
     * the device node.
     * This function is typically called by a drv_bind() method
     * of a PCI driver.
     */
    void
pciDevDrvBind (DevNode       dev_node,
               PciPropVendId drv_vid,
               PciPropDevId  drv_did,
               char*         drv_name)
{
    PciPropVendId dev_vid;
    PciPropDevId  dev_did;
    DevProperty   prop;
    
        /*
         * Do not bind the driver to an active device node.
         */
    if (dtreePropFind(dev_node, PROP_ACTIVE)) {
        return;
    }
        /*
         * Do not override an existing binding.
         */
    if (dtreePropFind(dev_node, PROP_DRIVER)) {
        return;
    }
        /*
         * Do not bind the driver if one of vendor/device ID's (or both)
         * is not specified.
         */
    prop = dtreePropFind(dev_node, PCI_PROP_VEND_ID);
    if (!prop) {
        return;
    }
    dev_vid = *(PciPropVendId*)dtreePropValue(prop);

    prop = dtreePropFind(dev_node, PCI_PROP_DEV_ID);
    if (!prop) {
        return;
    }
    dev_did = *(PciPropDevId*)dtreePropValue(prop);
        /*
         * Do not bind the driver if the device vendor/device IDs
         * do not match the driver ones.
         */
    if ((dev_vid != drv_vid) || (dev_did != drv_did)) {
        return;
    }   
        /*
         * Bind the driver to the device...
         */     
    dtreePropAdd(dev_node, PROP_DRIVER, drv_name, strlen(drv_name)+1);
}