/* * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * author: Jerome Glisse */ #include #include #include #include #include "rdb.h" /* Build rdb out of header format as : * (no space for reg name and offset, 2 space for reg field and mask) CP_STALLED_STAT1 = 0x8674, RBIU_TO_DMA_NOT_RDY_TO_RCV_bit = 1 << 0, */ struct ctx { struct rdb rdb; struct rdb_reg *lreg; struct rdb_field *lfield; char tokens[8][64]; unsigned ntokens; unsigned line; unsigned last_value_value; }; static void ptoken(struct ctx *ctx) { unsigned i; for (i = 0; i < ctx->ntokens; i++) { fprintf(stderr, "token[%d] %s\n", i, ctx->tokens[i]); } } static int parse_enum(struct ctx *ctx, const char *line) { struct rdb_value *value; value = malloc(sizeof(*value)); if (value == NULL) { return -ENOMEM; } if (ctx->ntokens > 2) { fprintf(stderr, "%s %d [%d] wrong nomber of token for reg %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); return -EINVAL; } value->name = strdup(ctx->tokens[0]); if (ctx->ntokens == 2) { value->value = strtoul(ctx->tokens[1], NULL, 0); } else { value->value = ctx->last_value_value + 1; } ctx->last_value_value = value->value; value->description = NULL; list_add_tail(&value->list, &ctx->lfield->values); return 0; } static int parse_field(struct ctx *ctx, const char *line) { struct rdb_field *field; char *tmp; if (ctx->ntokens != 3) { fprintf(stderr, "%s %d [%d] wrong nomber of token for field %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); ptoken(ctx); return -EINVAL; } if (ctx->lreg == NULL) { return -EINVAL; } field = malloc(sizeof(*field)); if (field == NULL) { return -ENOMEM; } tmp = strstr(ctx->tokens[0], "_bit"); if (tmp) { *tmp = 0; } tmp = strstr(ctx->tokens[0], "_mask"); if (tmp) { *tmp = 0; } field->name = strdup(ctx->tokens[0]); field->mask = strtoul(ctx->tokens[1], NULL, 0); field->shift = strtoul(ctx->tokens[2], NULL, 0); list_init_head(&field->values); field->dvalue = 0; field->description = NULL; ctx->lfield = field; list_add_tail(&field->list, &ctx->lreg->fields); return 0; } static int parse_reg(struct ctx *ctx, const char *line) { struct rdb_reg *reg; if (ctx->ntokens != 2) { fprintf(stderr, "%s %d [%d] wrong nomber of token for reg %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); return -EINVAL; } reg = malloc(sizeof(*reg)); if (reg == NULL) { return -ENOMEM; } reg->name = strdup(ctx->tokens[0]); reg->offset = strtoul(ctx->tokens[1], NULL, 0); reg->domain = RDB_DOMAIN_MMIO; list_init_head(®->fields); reg->base = 0; reg->nrepeat = 1; reg->stride = 0; reg->size = 32; reg->description = NULL; ctx->lreg = reg; list_add_tail(®->list, &ctx->rdb.regs); return 0; } static int valid_char(unsigned ts, char c) { if (c >= 'A' && c <= 'Z') return 1; if (c >= 'a' && c <= 'z') return 1; if (ts) { if (c >= '0' && c <= '9') return 1; if (c == '_') return 1; } return 0; } static int valid_value(unsigned ts, char c) { if (c >= '0' && c <= '9') return 1; if (ts == 1) { if (c == 'x') return 1; } if (ts > 1) { if (c >= 'a' && c <= 'f') return 1; if (c >= 'A' && c <= 'F') return 1; } return 0; } static int parse_tokenize(struct ctx *ctx, const char *line) { unsigned i = 0; unsigned ts = 0; unsigned is_char = 0; ctx->ntokens = 0; do { if (!ts && valid_char(ts, line[i])) { ctx->tokens[ctx->ntokens][ts++] = line[i]; is_char = 1; continue; } if (is_char && valid_char(ts, line[i])) { ctx->tokens[ctx->ntokens][ts++] = line[i]; continue; } if (valid_value(ts, line[i])) { ctx->tokens[ctx->ntokens][ts++] = line[i]; continue; } if (!line[i]) { ctx->tokens[ctx->ntokens][ts] = 0; return 0; } if (ts) { ctx->tokens[ctx->ntokens][ts] = 0; ts = 0; is_char = 0; ctx->ntokens++; } } while (line[i++]); return 0; } static int parse(struct ctx *ctx, const char *filename) { FILE *file; char line[128]; int r = 0; file = fopen(filename, "r"); if (file == NULL) { fprintf(stderr, "%s %d failed opening %s\n", __func__, __LINE__, filename); return -EINVAL; } while (!feof(file)) { if (fgets(line, sizeof(line), file) == NULL) { continue; } ctx->line++; if (!strstr(line, " = ") && line[strlen(line) - 2] != ',') { continue; } if (strstr(line, "_shift")) { continue; } if (strstr(line, "_num")) { continue; } if (strstr(line, "_offset")) { continue; } r = parse_tokenize(ctx, line); if (r) { return r; } if (line[0] == '/' && line[1] == '*') { continue; } if (strlen(line) < 3) { continue; } if (line[0] == ' ' && line[1] == ' ' && line[2] == ' ' && line[3] == ' ') { r = parse_enum(ctx, line); } else if (line[0] == ' ' && line[1] == ' ') { r = parse_field(ctx, line); } else { r = parse_reg(ctx, line); } if (r) { return r; } } return 0; } void pspace(unsigned n, unsigned s) { unsigned i; if (s >= n) { printf(" "); return; } for (i = 0; i < (n - s - 1); i++) { printf(" "); } } int main(int argc, char *argv[]) { struct ctx *ctx; int r; if (argc != 2) { printf("usage %s headerfile\n", argv[0]); return -1; } ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return -ENOMEM; } rdb_init(&ctx->rdb); r = parse(ctx, argv[1]); if (r) { return r; } rdb_write(stdout, &ctx->rdb); }