ChorusOS 5.0 Board Support Package Developer's Guide

Initializing

At initialization, the fi bus driver's drv_init() method is called for each device node tested. The fi bus driver will then get the opportunity to:

Code Example 14-2 illustrates the initialization of a generic PCI Fault Injection bus driver (pciFi(9DRV)). In this example, the PciFiDev structure contains the fault injection driver instance specific data. This data is allocated and initialized in drv_init(). Fields of interest for the examples are:


Example 14-2 pciFi drv_init() routine

    /*
     * Try to start (initialize) tested child driver
     */
    static KnError
childInit(PciFiDev* pciFi)
{
    char*        drv_name;
    DrvRegId     drv_curr;
    DrvRegId     drv_prev;
    DrvRegEntry* entry;
    DevProperty  prop;
    DevNode      node;
        /*
         * Check if not already started
         */
    if (pciFi->dev.node) {
        return K_EBUSY;
    }
    node = pciFi->node;
        /* 
         * Check for PROP_FI_DRIVER property
         */
    prop = dtreePropFind(node, PROP_FI_DRIVER);
    if (prop == NULL) {
        DKI_ERR(("%s: error -- %s required property not found\n",
                 pciFi->path, PROP_FI_DRIVER));
        return K_EFAIL;
    }
        /* 
         * Try to start PROP_FI_DRIVER driver
         */
    drv_name = (char*)dtreePropValue(prop);
    drv_curr = svDriverLookupFirst();
    while (drv_curr) {
        entry = svDriverEntry(drv_curr);
        if (entry->drv_init &&
            !strcmp(pciFiDrv.bus_class, entry->bus_class) &&
            (pciFiDrv.bus_version >= entry->bus_version) &&
            !strcmp(drv_name, entry->drv_name)) {
            entry->drv_init(node, &pciFiPciBusOps, pciFi);
            if (pciFi->dev.node) {
                svDriverRelease(drv_curr);
                break;
            }
        }
        drv_prev = drv_curr;
        drv_curr = svDriverLookupNext(drv_curr);
        svDriverRelease(drv_prev);
    }

    return (pciFi->dev.node ? K_OK : K_EFAIL);
}

    /*
     * Driver initialization method
     */
    static void
drv_init (DevNode node, void* busOps, void* busId)
{
    PciFiDev*      pciFi;
    int            pathSz;
    char*          path;
    KnError        res;
    DevProperty    prop;
    PciPropBusNum  bus;
    PciPropDevNum  dev;
    PciPropFuncNum func;
        /*
         * Get my path name in the device tree (for errors)
         */
    pathSz = dtreePathLeng(node);
    path   = (char*)svMemAlloc(pathSz);
    if (!path) {
        DKI_ERR(("%s: error -- not enough memory\n", pciFiDrv.drv_name));
        return;
    }
    dtreePathGet(node, path);
        /*
         * Get mandatory properties
         */
    [...]
        /*
         * Allocate driver instance data
         */
    pciFi = (PciFiDev*)svMemAlloc(sizeof(PciFiDev));
    if (! pciFi) {
        DKI_ERR(("%s: error -- not enough memory\n", path));
        svMemFree(path, pathSz);
        return;
    }
        /*
         * Initialize driver instance data
         */
    [...]
        /*
         * Allocate objects associated to allocated resources
         */
    [...]
        /*
         * Open parent PCI bus connection
         */
    res = pciFi->pciOps->open(busId,
                              node,
                              eventHandler, /* my event handler   */
                              loadHandler,  /* my load handler    */
                              pciFi,        /* my handlers cookie */
                              &pciFi->pciDevId);
    if (res != K_OK) {
        DKI_ERR(("%s: error -- open() failed (%d)\n", path, res));
        svMemFree(path, pathSz);
        svMemFree(pciFi, sizeof(PciFiDev));
        return;
    }
        /*
         * Allocate PCI_FI instance driver descriptor in the device registry
         */
    pciFi->entry.dev_class = PCIFI_CLASS;
    pciFi->entry.dev_id    = pciFi;
    pciFi->entry.dev_node  = node;
    pciFi->entry.dev_ops   = &pciFiOps;
    pciFi->devRegId        = svDeviceAlloc(&pciFi->entry,
                                           PCIFI_VERSION_INITIAL,
                                           FALSE, /* pciFi cannot be 
                                                   * shared */
                                           relHandler);
    if (! pciFi->devRegId) {
        DKI_ERR(("%s: error -- not enough memory\n", path));
        pciFi->pciOps->close(pciFi->pciDevId);
        svMemFree(pciFi, sizeof(PciFiDev));
        svMemFree(path, pathSz);
        return;
    }
        /*
         * Chain driver instance in list
         */
    pciFi->next = pciFiDevs;
    pciFiDevs   = pciFi;
        /*
         * Finally, register the new device driver instance
         * in the device registry. In case a shut down event
         * has been signaled during the initialization, the device entry
         * remains invalid and the relHandler() handler is invoked
         * to shut down the device driver instance. Otherwise, the device
         * entry becames valid and therefore visible for driver clients.
         */
    svDeviceRegister(pciFi->devRegId);

    DKI_MSG(("%s: %s driver started\n", path, pciFiDrv.drv_name));

        /*
         * Try to start a tested driver. If this fails, a tested driver
         * may be started later by the loadHandler() handler.
         */
    (void)childInit(pciFi);
}