diff options
Diffstat (limited to 'util/sconfig/main.c')
-rw-r--r-- | util/sconfig/main.c | 213 |
1 files changed, 134 insertions, 79 deletions
diff --git a/util/sconfig/main.c b/util/sconfig/main.c index 2e34d85ad5..382d5e5c7b 100644 --- a/util/sconfig/main.c +++ b/util/sconfig/main.c @@ -24,7 +24,13 @@ struct device *head, *lastdev; struct header headers; -static int devcount = 0; +static struct chip *chip_head; + +/* + * This is intentionally shared between chip and device structure ids because it + * is easier to track the order of parsing for chip and device. + */ +static int count = 0; typedef enum { UNSLASH, @@ -34,22 +40,15 @@ typedef enum { } translate_t; static struct device root; -static struct device mainboard = { +static struct chip mainboard = { .name = "mainboard", .name_underscore = "mainboard", - .id = 0, - .chip = &mainboard, - .type = chip, - .chiph_exists = 0, - .children = &root }; static struct device root = { .name = "dev_root", - .name_underscore = "dev_root", .id = 0, .chip = &mainboard, - .type = device, .path = " .type = DEVICE_PATH_ROOT ", .ops = "&default_dev_ops_root", .parent = &root, @@ -57,11 +56,64 @@ static struct device root = { .enabled = 1 }; +static struct queue { + void *data; + struct queue *next; + struct queue *prev; +} *q; + +struct queue *new_queue_entry(void *data) +{ + struct queue *e = malloc(sizeof(*e)); + + if (!e) { + fprintf(stderr, "%s: malloc failure!\n", __func__); + exit(1); + } + + e->data = data; + e->next = e->prev = e; + return e; +} + +void chip_enqueue_tail(void *data) +{ + struct queue *tmp = new_queue_entry(data); + + if (!q) { + q = tmp; + return; + } + + q->prev->next = tmp; + tmp->prev = q->prev; + q->prev = tmp; + tmp->next = q; +} + +void *chip_dequeue_tail(void) +{ + struct queue *tmp = q->prev; + void *data; + + if (tmp == q) + q = NULL; + else { + tmp->prev->next = q; + q->prev = tmp->prev; + } + + data = tmp->data; + free(tmp); + + return data; +} + static struct device *new_dev(struct device *parent, struct device *bus) { struct device *dev = malloc(sizeof(struct device)); memset(dev, 0, sizeof(struct device)); - dev->id = ++devcount; + dev->id = ++count; dev->parent = parent; dev->bus = bus; dev->subsystem_vendor = -1; @@ -109,22 +161,18 @@ void yyerror(char const *str) void postprocess_devtree(void) { root.next_sibling = root.children; - root.next_sibling->next_sibling = root.next_sibling->children; + + /* + * Since root is statically created we need to call fold_in explicitly + * here to have the next_sibling and latestchild setup correctly. + */ + fold_in(&root); struct device *dev = &root; while (dev) { - /* skip "chip" elements in children chain */ - while (dev->children && (dev->children->type == chip)) - dev->children = dev->children->children; - /* skip "chip" elements and functions of the same device in sibling chain */ + /* skip functions of the same device in sibling chain */ while (dev->sibling && dev->sibling->used) dev->sibling = dev->sibling->sibling; - /* If end of chain, and parent is a chip, move on */ - if (!dev->sibling && (dev->parent->type == chip)) - dev->sibling = dev->parent->sibling; - /* skip chips */ - while (dev->sibling && dev->sibling->type == chip) - dev->sibling = dev->sibling->children; /* skip duplicate function elements in nextdev chain */ while (dev->nextdev && dev->nextdev->used) dev->nextdev = dev->nextdev->nextdev; @@ -154,14 +202,20 @@ char *translate_name(const char *str, translate_t mode) return b; } -struct device *new_chip(struct device *parent, struct device *bus, char *path) +struct chip *new_chip(char *path) { - struct device *new_chip = new_dev(parent, bus); + struct chip *new_chip = malloc(sizeof(*new_chip)); + if (!new_chip) { + fprintf(stderr, "%s: malloc failure!\n", __func__); + exit(1); + } + + memset(new_chip, 0, sizeof(*new_chip)); + + new_chip->id = ++count; new_chip->chiph_exists = 1; new_chip->name = path; new_chip->name_underscore = translate_name(new_chip->name, UNSLASH); - new_chip->type = chip; - new_chip->chip = new_chip; struct stat st; char *chip_h = malloc(strlen(path) + 18); @@ -182,23 +236,20 @@ struct device *new_chip(struct device *parent, struct device *bus, char *path) if ((stat(chip_h, &st) == -1) && (errno == ENOENT)) new_chip->chiph_exists = 0; - if (parent->latestchild) { - parent->latestchild->next_sibling = new_chip; - parent->latestchild->sibling = new_chip; - } - parent->latestchild = new_chip; - if (!parent->children) - parent->children = new_chip; free(chip_h); + + new_chip->next = chip_head; + chip_head = new_chip; + return new_chip; } -void add_header(struct device *dev) +void add_header(struct chip *chip) { int include_exists = 0; struct header *h = &headers; while (h->next) { - int result = strcmp(dev->name, h->next->name); + int result = strcmp(chip->name, h->next->name); if (result == 0) { include_exists = 1; break; @@ -211,14 +262,15 @@ void add_header(struct device *dev) struct header *tmp = h->next; h->next = malloc(sizeof(struct header)); memset(h->next, 0, sizeof(struct header)); - h->next->chiph_exists = dev->chiph_exists; - h->next->name = dev->name; + h->next->chiph_exists = chip->chiph_exists; + h->next->name = chip->name; h->next->next = tmp; } } struct device *new_device(struct device *parent, struct device *busdev, - const int bus, const char *devnum, int enabled) + struct chip *chip, const int bus, const char *devnum, + int enabled) { struct device *new_d = new_dev(parent, busdev); new_d->bustype = bus; @@ -233,10 +285,9 @@ struct device *new_device(struct device *parent, struct device *busdev, char *name = malloc(10); sprintf(name, "_dev%d", new_d->id); new_d->name = name; - new_d->name_underscore = name; // shouldn't be necessary, but avoid 0-ptr - new_d->type = device; + new_d->enabled = enabled; - new_d->chip = new_d->parent->chip; + new_d->chip = chip; if (parent->latestchild) { parent->latestchild->next_sibling = new_d; @@ -309,7 +360,7 @@ void alias_siblings(struct device *d) struct device *cmp = d->next_sibling; while (cmp && (cmp->bus == d->bus) && (cmp->path_a == d->path_a) && (cmp->path_b == d->path_b)) { - if (cmp->type == device && !cmp->used) { + if (!cmp->used) { if (device_match(d, cmp)) { d->multidev = 1; @@ -343,14 +394,14 @@ void add_resource(struct device *dev, int type, int index, int base) dev->rescnt++; } -void add_register(struct device *dev, char *name, char *val) +void add_register(struct chip *chip, char *name, char *val) { struct reg *r = malloc(sizeof(struct reg)); memset(r, 0, sizeof(struct reg)); r->key = name; r->value = val; - if (dev->reg) { - struct reg *head = dev->reg; + if (chip->reg) { + struct reg *head = chip->reg; // sorting to be equal to sconfig's behaviour int sort = strcmp(r->key, head->key); if (sort == 0) { @@ -359,7 +410,7 @@ void add_register(struct device *dev, char *name, char *val) } if (sort < 0) { r->next = head; - dev->reg = r; + chip->reg = r; } else { while ((head->next) && (strcmp(head->next->key, r->key) < 0)) @@ -368,7 +419,7 @@ void add_register(struct device *dev, char *name, char *val) head->next = r; } } else { - dev->reg = r; + chip->reg = r; } } @@ -412,13 +463,13 @@ void add_ioapic_info(struct device *dev, int apicid, const char *_srcpin, dev->pci_irq_info[srcpin].ioapic_dst_id = apicid; } -static void pass0(FILE * fil, struct device *ptr) +static void pass0(FILE *fil, struct device *ptr) { - if (ptr->type == device && ptr->id == 0) + if (ptr->id == 0) fprintf(fil, "DEVTREE_CONST struct bus %s_links[];\n", ptr->name); - if ((ptr->type == device) && (ptr->id != 0) && (!ptr->used)) { + if ((ptr->id != 0) && (!ptr->used)) { fprintf(fil, "DEVTREE_CONST static struct device %s;\n", ptr->name); if (ptr->rescnt > 0) @@ -431,10 +482,11 @@ static void pass0(FILE * fil, struct device *ptr) } } -static void pass1(FILE * fil, struct device *ptr) +static void pass1(FILE *fil, struct device *ptr) { int pin; - if (!ptr->used && (ptr->type == device)) { + + if (!ptr->used) { if (ptr->id != 0) fprintf(fil, "static "); fprintf(fil, "DEVTREE_CONST struct device %s = {\n", @@ -481,7 +533,7 @@ static void pass1(FILE * fil, struct device *ptr) fprintf(fil, "#if !DEVTREE_EARLY\n"); fprintf(fil, "\t.chip_ops = &%s_ops,\n", ptr->chip->name_underscore); - if (ptr->chip->chip == &mainboard) + if (ptr->chip == &mainboard) fprintf(fil, "\t.name = mainboard_name,\n"); fprintf(fil, "#endif\n"); if (ptr->chip->chiph_exists) @@ -516,8 +568,7 @@ static void pass1(FILE * fil, struct device *ptr) } fprintf(fil, "\t };\n"); } - if (!ptr->used && ptr->type == device - && (ptr->children || ptr->multidev)) { + if (!ptr->used && (ptr->children || ptr->multidev)) { fprintf(fil, "DEVTREE_CONST struct bus %s_links[] = {\n", ptr->name); if (ptr->multidev) { @@ -559,13 +610,32 @@ static void pass1(FILE * fil, struct device *ptr) } fprintf(fil, "\t};\n"); } - if ((ptr->type == chip) && (ptr->chiph_exists)) { - if (ptr->reg) { +} + +static void walk_device_tree(FILE *fil, struct device *ptr, + void (*func)(FILE *, struct device *), + struct device *chips) +{ + do { + func(fil, ptr); + ptr = ptr->next_sibling; + } while (ptr); +} + +static void emit_chips(FILE *fil) +{ + struct chip *chip; + + for (chip = chip_head; chip; chip = chip->next) { + if (!chip->chiph_exists) + continue; + + if (chip->reg) { fprintf(fil, "DEVTREE_CONST struct %s_config %s_info_%d = {\n", - ptr->name_underscore, ptr->name_underscore, - ptr->id); - struct reg *r = ptr->reg; + chip->name_underscore, chip->name_underscore, + chip->id); + struct reg *r = chip->reg; while (r) { fprintf(fil, "\t.%s = %s,\n", r->key, r->value); r = r->next; @@ -574,23 +644,13 @@ static void pass1(FILE * fil, struct device *ptr) } else { fprintf(fil, "DEVTREE_CONST struct %s_config %s_info_%d = { };\n", - ptr->name_underscore, ptr->name_underscore, - ptr->id); + chip->name_underscore, chip->name_underscore, + chip->id); } } } -static void walk_device_tree(FILE * fil, struct device *ptr, - void (*func) (FILE *, struct device *), - struct device *chips) -{ - do { - func(fil, ptr); - ptr = ptr->next_sibling; - } while (ptr); -} - -static void inherit_subsystem_ids(FILE * file, struct device *dev) +static void inherit_subsystem_ids(FILE *file, struct device *dev) { struct device *p; @@ -649,13 +709,6 @@ int main(int argc, char **argv) fclose(filec); - if ((head->type == chip) && (!head->chiph_exists)) { - struct device *tmp = head; - head = &root; - while (head->next != tmp) - head = head->next; - } - FILE *autogen = fopen(outputc, "w"); if (!autogen) { fprintf(stderr, "Could not open file '%s' for writing: ", @@ -687,6 +740,8 @@ int main(int argc, char **argv) } fprintf(autogen, "#endif\n"); + emit_chips(autogen); + walk_device_tree(autogen, &root, inherit_subsystem_ids, NULL); fprintf(autogen, "\n/* pass 0 */\n"); walk_device_tree(autogen, &root, pass0, NULL); |