summaryrefslogblamecommitdiffstats
path: root/tools/cpu/nios2/devices.c
blob: 112191f4875344d3d8da7db147dc5241300ebf9d (plain) (tree)



































































































































                                                                                            
/*
 *  Copyright (c) 2006 Kolja Waschk rtemsdev/ixo.de
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 *
 *  $Id$
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ptf.h"
#include "bridges.h"
#include "devices.h"

void add_device(device_desc **dl, struct ptf *dev)
{
    device_desc *eds;

    for(eds = *dl; eds; eds = eds->next)
    {
        if(eds->ptf == dev)
        {
            eds->slaves++;
            return;
        };
    };

    eds = (device_desc *)malloc(sizeof(device_desc));
    eds->slaves = 1;
    eds->ptf = dev;
    eds->next = *dl;
    *dl = eds;
}

void check_and_add_device(struct ptf_item *pi, void *arg)
{
    struct ptf *module = pi->item[pi->level-3];
    struct ptf *sysinfo  = pi->item[pi->level-2];
    char *master_name  = pi->item[pi->level]->value;

    struct { char *dm; char *im; device_desc **dl; bus_bridge_pair *bridges; } *dinfo = arg;

    if(is_bridged(dinfo->dm, master_name, dinfo->bridges) ||
       is_bridged(dinfo->im, master_name, dinfo->bridges))
    {
       struct ptf *ni = ptf_alloc_item(item, "N2G_Selected", "1");
       if(ni != NULL)
       {
         ni->next = sysinfo->sub;
         sysinfo->sub = ni;
       };
       add_device(dinfo->dl, module);
    };
}

void set_dev_cfgname(struct ptf_item *pi, void *arg)
{
  device_desc *dev = arg;
  dev->cfgname = pi->item[pi->level]->name;
}


device_desc *find_devices(
  struct ptf *ptf, 
  struct ptf *cfg, 
  struct ptf *cpu, 
  bus_bridge_pair *bridges)
{
    struct ptf system     = { section, "SYSTEM", 0, 0, 0 };
    struct ptf module     = { section, "MODULE", 0, 0, 0 };
    struct ptf slave      = { section, "SLAVE",  0, 0, 0 };
    struct ptf syb        = { section, "SYSTEM_BUILDER_INFO", 0, 0, 0 };
    struct ptf maby       = { section, "MASTERED_BY", 0, 0, 0 };
    struct ptf_item brdg  = { 5, &system, &module, &slave, &syb, &maby };

    struct ptf modules    = { section, "MODULES", 0, 0, 0 };
    struct ptf named      = { item, 0, 0, 0, 0};
    struct ptf_item devcf = { 2, &modules, &named };

    struct { char *dm; char *im; device_desc **dl; bus_bridge_pair *bridges; } dinfo;

    device_desc *found, *reverse;

    found = NULL;

    add_device(&found, cpu); /* The CPU is "self-connected", add it */

    dinfo.dl = &found;
    dinfo.bridges = bridges;
    dinfo.dm = (char *)malloc(strlen(cpu->value)+13);
    dinfo.im = (char *)malloc(strlen(cpu->value)+20);

    strcpy(dinfo.im, cpu->value);
    strcat(dinfo.im, "/");
    strcpy(dinfo.dm, dinfo.im);
    strcat(dinfo.dm, "data_master");
    strcat(dinfo.im, "instruction_master");

    /* "Available" is any MODULE with a SLAVE section that is MASTERED_BY
        either instr_master or data_master of selected CPU, either directly
        or through a bridge. See code above for more info about bridges.
     */

    ptf_match(ptf, &brdg, check_and_add_device, &dinfo);

    free(dinfo.dm);
    free(dinfo.im);

    /* Reverse the linked list */

    reverse = NULL;
    while(found)
    {
      device_desc *tmp = found;
      found = found->next;

      tmp->next = reverse;
      reverse = tmp;

      named.value = tmp->ptf->value;
      tmp->cfgname = NULL;
      ptf_match(cfg, &devcf, set_dev_cfgname, tmp);
      if(tmp->cfgname == NULL) tmp->cfgname = ptf_defused_name(tmp->ptf->value);
     };

    return reverse;
}