123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- /*
- * Copyright (C) 2007 Michael Buesch <m@bues.ch>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #include "initvals.h"
- #include "list.h"
- #include "util.h"
- #include "args.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- struct initval {
- unsigned int offset;
- unsigned int size;
- #define SIZE_16BIT 2
- #define SIZE_32BIT 4
- unsigned int value;
- struct list_head list;
- };
- /* The IV in the binary file */
- struct initval_raw {
- be16_t offset_size;
- union {
- be16_t d16;
- be32_t d32;
- } data __attribute__((__packed__));
- } __attribute__((__packed__));
- #define FW_IV_OFFSET_MASK 0x7FFF
- #define FW_IV_32BIT 0x8000
- struct ivals_context {
- /* Pointer to the parsed section structure */
- const struct initvals_sect *sect;
- /* List of struct initval */
- struct list_head ivals;
- /* Number of initvals. */
- unsigned int ivals_count;
- };
- #define _msg_helper(type, ctx, msg, x...) do { \
- fprintf(stderr, "InitVals " type); \
- fprintf(stderr, " (Section \"%s\")", ctx->sect->name); \
- fprintf(stderr, ":\n " msg "\n" ,##x); \
- } while (0)
- #define iv_error(ctx, msg, x...) do { \
- _msg_helper("ERROR", ctx, msg ,##x); \
- exit(1); \
- } while (0)
- #define iv_warn(ctx, msg, x...) \
- _msg_helper("warning", ctx, msg ,##x)
- #define iv_info(ctx, msg, x...) \
- _msg_helper("info", ctx, msg ,##x)
- static void assemble_write_mmio(struct ivals_context *ctx,
- unsigned int offset,
- unsigned int size,
- unsigned int value)
- {
- struct initval *iv;
- iv = xmalloc(sizeof(struct initval));
- iv->offset = offset;
- iv->size = size;
- iv->value = value;
- INIT_LIST_HEAD(&iv->list);
- list_add_tail(&iv->list, &ctx->ivals);
- ctx->ivals_count++;
- }
- static void assemble_write_phy(struct ivals_context *ctx,
- unsigned int offset,
- unsigned int value)
- {
- assemble_write_mmio(ctx, 0x3FC, SIZE_16BIT, offset);
- assemble_write_mmio(ctx, 0x3FE, SIZE_16BIT, value);
- }
- static void assemble_write_radio(struct ivals_context *ctx,
- unsigned int offset,
- unsigned int value)
- {
- assemble_write_mmio(ctx, 0x3F6, SIZE_16BIT, offset);
- assemble_write_mmio(ctx, 0x3FA, SIZE_16BIT, value);
- }
- static void shm_control_word(struct ivals_context *ctx,
- unsigned int routing,
- unsigned int offset)
- {
- unsigned int control;
- control = (routing & 0xFFFF);
- control <<= 16;
- control |= (offset & 0xFFFF);
- assemble_write_mmio(ctx, 0x160, SIZE_32BIT, control);
- }
- static void shm_write32(struct ivals_context *ctx,
- unsigned int routing,
- unsigned int offset,
- unsigned int value)
- {
- if ((routing & 0xFF) == 0x01) {
- /* Is SHM Shared-memory */
- //TODO assert((offset & 0x0001) == 0);
- if (offset & 0x0003) {
- /* Unaligned access */
- shm_control_word(ctx, routing, offset >> 2);
- assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
- (value >> 16) & 0xFFFF);
- shm_control_word(ctx, routing, (offset >> 2) + 1);
- assemble_write_mmio(ctx, 0x164, SIZE_16BIT,
- (value & 0xFFFF));
- return;
- }
- offset >>= 2;
- }
- shm_control_word(ctx, routing, offset);
- assemble_write_mmio(ctx, 0x164, SIZE_32BIT, value);
- }
- static void shm_write16(struct ivals_context *ctx,
- unsigned int routing,
- unsigned int offset,
- unsigned int value)
- {
- if ((routing & 0xFF) == 0x01) {
- /* Is SHM Shared-memory */
- //TODO assert((offset & 0x0001) == 0);
- if (offset & 0x0003) {
- /* Unaligned access */
- shm_control_word(ctx, routing, offset >> 2);
- assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
- value);
- return;
- }
- offset >>= 2;
- }
- shm_control_word(ctx, routing, offset);
- assemble_write_mmio(ctx, 0x164, SIZE_16BIT, value);
- }
- static void assemble_write_shm(struct ivals_context *ctx,
- unsigned int routing,
- unsigned int offset,
- unsigned int value,
- unsigned int size)
- {
- switch (routing & 0xFF) {
- case 0: case 1: case 2: case 3: case 4:
- break;
- default:
- //TODO error
- break;
- }
- //TODO check offset
- //TODO check value
- switch (size) {
- case SIZE_16BIT:
- shm_write16(ctx, routing, offset, value);
- break;
- case SIZE_32BIT:
- shm_write32(ctx, routing, offset, value);
- break;
- default:
- fprintf(stderr, "Internal assembler BUG. SHMwrite invalid size\n");
- exit(1);
- }
- }
- /* Template RAM write */
- static void assemble_write_tram(struct ivals_context *ctx,
- unsigned int offset,
- unsigned int value)
- {
- assemble_write_mmio(ctx, 0x130, SIZE_32BIT, offset);
- assemble_write_mmio(ctx, 0x134, SIZE_32BIT, value);
- }
- static void assemble_ival_section(struct ivals_context *ctx,
- const struct initvals_sect *sect)
- {
- struct initval_op *op;
- ctx->sect = sect;
- if (list_empty(§->ops)) {
- //TODO warning
- return;
- }
- list_for_each_entry(op, §->ops, list) {
- switch (op->type) {
- case IVAL_W_MMIO16:
- assemble_write_mmio(ctx, op->args[1],
- SIZE_16BIT,
- op->args[0]);
- break;
- case IVAL_W_MMIO32:
- assemble_write_mmio(ctx, op->args[1],
- SIZE_32BIT,
- op->args[0]);
- break;
- case IVAL_W_PHY:
- assemble_write_phy(ctx, op->args[1],
- op->args[0]);
- break;
- case IVAL_W_RADIO:
- assemble_write_radio(ctx, op->args[1],
- op->args[0]);
- break;
- case IVAL_W_SHM16:
- assemble_write_shm(ctx, op->args[1],
- op->args[2],
- op->args[0],
- SIZE_16BIT);
- break;
- case IVAL_W_SHM32:
- assemble_write_shm(ctx, op->args[1],
- op->args[2],
- op->args[0],
- SIZE_32BIT);
- break;
- case IVAL_W_TRAM:
- assemble_write_tram(ctx, op->args[1],
- op->args[0]);
- break;
- }
- }
- }
- static unsigned int initval_to_raw(struct ivals_context *ctx,
- struct initval_raw *raw,
- const struct initval *iv)
- {
- unsigned int size;
- memset(raw, 0, sizeof(*raw));
- if (iv->offset & ~FW_IV_OFFSET_MASK) {
- iv_error(ctx, "Initval offset 0x%04X too big. "
- "Offset must be <= 0x%04X",
- iv->offset, FW_IV_OFFSET_MASK);
- }
- raw->offset_size = cpu_to_be16(iv->offset);
- switch (iv->size) {
- case SIZE_16BIT:
- raw->data.d16 = cpu_to_be16(iv->value);
- size = sizeof(be16_t) + sizeof(be16_t);
- break;
- case SIZE_32BIT:
- raw->data.d32 = cpu_to_be32(iv->value);
- raw->offset_size |= cpu_to_be16(FW_IV_32BIT);
- size = sizeof(be16_t) + sizeof(be32_t);
- break;
- default:
- iv_error(ctx, "Internal error. initval_to_raw invalid size.");
- break;
- }
- return size;
- }
- static void emit_ival_section(struct ivals_context *ctx)
- {
- FILE *fd;
- char *fn;
- size_t fn_len;
- struct initval *iv;
- struct initval_raw raw;
- struct fw_header hdr;
- unsigned int size;
- unsigned int filesize = 0;
- memset(&hdr, 0, sizeof(hdr));
- hdr.type = FW_TYPE_IV;
- hdr.ver = FW_HDR_VER;
- hdr.size = cpu_to_be32(ctx->ivals_count);
- fn_len = strlen(ctx->sect->name) + strlen(cmdargs.initvals_fn_extension ? : "") + 1;
- fn = xmalloc(fn_len);
- snprintf(fn, fn_len, "%s%s", ctx->sect->name, cmdargs.initvals_fn_extension ? : "");
- fd = fopen(fn, "w+");
- if (!fd) {
- fprintf(stderr, "Could not open initval output file \"%s\"\n", fn);
- free(fn);
- exit(1);
- }
- if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
- fprintf(stderr, "Could not write initvals outfile\n");
- exit(1);
- }
- if (IS_VERBOSE_DEBUG)
- fprintf(stderr, "\nInitvals \"%s\":\n", ctx->sect->name);
- list_for_each_entry(iv, &ctx->ivals, list) {
- if (IS_VERBOSE_DEBUG) {
- fprintf(stderr, "%04X %u %08X\n",
- iv->offset,
- iv->size,
- iv->value);
- }
- size = initval_to_raw(ctx, &raw, iv);
- if (fwrite(&raw, size, 1, fd) != 1) {
- fprintf(stderr, "Could not write initvals outfile\n");
- exit(1);
- }
- filesize += size;
- }
- if (cmdargs.print_sizes) {
- printf("%s: %d values (%u bytes)\n",
- fn, ctx->ivals_count, filesize);
- }
- fclose(fd);
- free(fn);
- }
- void assemble_initvals(void)
- {
- struct ivals_context ctx;
- struct initvals_sect *sect;
- list_for_each_entry(sect, &infile.ivals, list) {
- memset(&ctx, 0, sizeof(ctx));
- INIT_LIST_HEAD(&ctx.ivals);
- assemble_ival_section(&ctx, sect);
- emit_ival_section(&ctx);
- }
- }
|