ChorusOS 5.0 Board Support Package Developer's Guide

Binding

The drv_bind() routine of a fi bus driver is called for each node that is a child node of the emulated bus class. In this routine, the driver gets the opportunity to detect a device requiring fault injection and binds itself to this device, instead of the initially bound device driver.

Code Example 14-1 illustrates how a generic PCI Fault Injection bus driver (pciFi(9DRV)) may bind itself to all PCI device nodes. By default, this driver is transparent and only becomes active for a particular device when requested by a client.


Example 14-1 pciFi drv_bind() routine

    /*
     * Driver bind method
     */
    static void
drv_bind (DevNode node)
{
    DevProperty propDriver;
    DevProperty propNewDriver;
    DevProperty propFiDriver;

    propDriver = dtreePropFind(node, PROP_DRIVER);
        /*
         * If the device node is not bound to any driver
         * try to bind it
         */
    if (! propDriver) {
        DrvRegId     drv_curr;
        DrvRegId     drv_prev;
        DrvRegEntry* entry;
        
        drv_curr = svDriverLookupFirst();
        while (drv_curr) {
            entry = svDriverEntry(drv_curr);
            if (entry != &pciFiDrv) {
                if (entry->drv_bind &&
                    !strcmp(pciFiDrv.bus_class, entry->bus_class) &&
                    (pciFiDrv.bus_version >= entry->bus_version)) {
                        /*
                         * Try to bind the node
                         */
                    entry->drv_bind(node);
                }
            }
            drv_prev = drv_curr;
            drv_curr = svDriverLookupNext(drv_curr);
            svDriverRelease(drv_prev);
        }
        propDriver = dtreePropFind(node, PROP_DRIVER);
    }
            /*
             * If node is bound to a driver, copy its PROP_DRIVER property
             * into a PROP_FI_DRIVER property. Then bind our own driver to
             * the node, in order to be started in place of the original
             * driver.
             */
    if (propDriver && !dtreePropFind(node, PROP_FI_DRIVER)) {
        propFiDriver = dtreePropAdd(node, PROP_FI_DRIVER,
                                    dtreePropValue(propDriver),
                                    dtreePropLength(propDriver));
        if (!propFiDriver) {
            return;
        }
                /*
                 * Replace old PROP_DRIVER with my own driver name
                 */
        propNewDriver = dtreePropAdd(node, PROP_DRIVER, pciFiDrv.drv_name,
                                     strlen(pciFiDrv.drv_name) + 1);
        if (!propNewDriver) {
            dtreePropDetach(propFiDriver);
            dtreePropFree(propFiDriver);
            return;
        }
        dtreePropDetach(propDriver);
        dtreePropFree(propDriver);
    }
}

At the end of the binding phase, all device nodes (children of the emulated bus class node) are bound to the fi bus driver. The standard binding mechanism is not disturbed and the original bindings are duplicated in a PROP_FI_DRIVER property in each node.