/* * 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 : * (#define for reg name and offset, # define for reg field and mask) #define GENERAL_PWRMGT 0x618 # define OPEN_DRAIN_PADS(x) (x & 1 << 11) */ struct ctx { struct rdb rdb; struct rdb_reg *lreg; struct rdb_field *lfield; char tokens[8][64]; unsigned ntokens; unsigned line; }; 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; if (ctx->ntokens != 3) { fprintf(stderr, "%s %d [%d] wrong nomber of token for value %d\n", __func__, __LINE__, ctx->line, ctx->ntokens); ptoken(ctx); return -EINVAL; } value = malloc(sizeof(*value)); if (value == NULL) { return -ENOMEM; } value->name = strdup(ctx->tokens[1]); value->value = strtoul(ctx->tokens[2], NULL, 0); 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; if (ctx->ntokens != 6) { 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; } field->name = strdup(ctx->tokens[1]); field->mask = strtoul(ctx->tokens[4], NULL, 0); field->shift = strtoul(ctx->tokens[5], 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 != 3) { 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[1]); reg->offset = strtoul(ctx->tokens[2], 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; ctx->ntokens = 0; do { if (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; 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++; r = parse_tokenize(ctx, line); if (r) { return r; } if (line[0] == '/' && line[1] == '*') { continue; } if (strlen(line) < 3) { continue; } if (strstr(line, "# define")) { r = parse_field(ctx, line); } else if (strstr(line, "# define")) { r = parse_enum(ctx, line); } else if (strstr(line, "#define")) { r = parse_reg(ctx, line); } else { r = 0; } 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); }