2 * Copyright (C) 2007 Michael Buesch <mb@bu3sch.de>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
31 struct list_head list;
34 /* The IV in the binary file */
40 } data __attribute__((__packed__));
41 } __attribute__((__packed__));
43 #define FW_IV_OFFSET_MASK 0x7FFF
44 #define FW_IV_32BIT 0x8000
47 struct ivals_context {
48 /* Pointer to the parsed section structure */
49 const struct initvals_sect *sect;
50 /* List of struct initval */
51 struct list_head ivals;
52 /* Number of initvals. */
53 unsigned int ivals_count;
56 #define _msg_helper(type, ctx, msg, x...) do { \
57 fprintf(stderr, "InitVals " type); \
58 fprintf(stderr, " (Section \"%s\")", ctx->sect->name); \
59 fprintf(stderr, ":\n " msg "\n" ,##x); \
62 #define iv_error(ctx, msg, x...) do { \
63 _msg_helper("ERROR", ctx, msg ,##x); \
67 #define iv_warn(ctx, msg, x...) \
68 _msg_helper("warning", ctx, msg ,##x)
70 #define iv_info(ctx, msg, x...) \
71 _msg_helper("info", ctx, msg ,##x)
74 static void assemble_write_mmio(struct ivals_context *ctx,
81 iv = xmalloc(sizeof(struct initval));
85 INIT_LIST_HEAD(&iv->list);
86 list_add_tail(&iv->list, &ctx->ivals);
90 static void assemble_write_phy(struct ivals_context *ctx,
94 assemble_write_mmio(ctx, 0x3FC, SIZE_16BIT, offset);
95 assemble_write_mmio(ctx, 0x3FE, SIZE_16BIT, value);
98 static void assemble_write_radio(struct ivals_context *ctx,
102 assemble_write_mmio(ctx, 0x3F6, SIZE_16BIT, offset);
103 assemble_write_mmio(ctx, 0x3FA, SIZE_16BIT, value);
106 static void shm_control_word(struct ivals_context *ctx,
107 unsigned int routing,
110 unsigned int control;
112 control = (routing & 0xFFFF);
114 control |= (offset & 0xFFFF);
115 assemble_write_mmio(ctx, 0x160, SIZE_32BIT, control);
118 static void shm_write32(struct ivals_context *ctx,
119 unsigned int routing,
123 if ((routing & 0xFF) == 0x01) {
124 /* Is SHM Shared-memory */
125 //TODO assert((offset & 0x0001) == 0);
126 if (offset & 0x0003) {
127 /* Unaligned access */
128 shm_control_word(ctx, routing, offset >> 2);
129 assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
130 (value >> 16) & 0xFFFF);
131 shm_control_word(ctx, routing, (offset >> 2) + 1);
132 assemble_write_mmio(ctx, 0x164, SIZE_16BIT,
138 shm_control_word(ctx, routing, offset);
139 assemble_write_mmio(ctx, 0x164, SIZE_32BIT, value);
142 static void shm_write16(struct ivals_context *ctx,
143 unsigned int routing,
147 if ((routing & 0xFF) == 0x01) {
148 /* Is SHM Shared-memory */
149 //TODO assert((offset & 0x0001) == 0);
150 if (offset & 0x0003) {
151 /* Unaligned access */
152 shm_control_word(ctx, routing, offset >> 2);
153 assemble_write_mmio(ctx, 0x166, SIZE_16BIT,
159 shm_control_word(ctx, routing, offset);
160 assemble_write_mmio(ctx, 0x164, SIZE_16BIT, value);
163 static void assemble_write_shm(struct ivals_context *ctx,
164 unsigned int routing,
169 switch (routing & 0xFF) {
170 case 0: case 1: case 2: case 3: case 4:
181 shm_write16(ctx, routing, offset, value);
184 shm_write32(ctx, routing, offset, value);
187 fprintf(stderr, "Internal assembler BUG. SHMwrite invalid size\n");
192 static void assemble_ival_section(struct ivals_context *ctx,
193 const struct initvals_sect *sect)
195 struct initval_op *op;
198 if (list_empty(§->ops)) {
202 list_for_each_entry(op, §->ops, list) {
205 assemble_write_mmio(ctx, op->args[1],
210 assemble_write_mmio(ctx, op->args[1],
215 assemble_write_phy(ctx, op->args[1],
219 assemble_write_radio(ctx, op->args[1],
223 assemble_write_shm(ctx, op->args[1],
229 assemble_write_shm(ctx, op->args[1],
238 static unsigned int initval_to_raw(struct ivals_context *ctx,
239 struct initval_raw *raw,
240 const struct initval *iv)
244 memset(raw, 0, sizeof(*raw));
245 if (iv->offset & ~FW_IV_OFFSET_MASK) {
246 iv_error(ctx, "Initval offset 0x%04X too big. "
247 "Offset must be <= 0x%04X",
248 iv->offset, FW_IV_OFFSET_MASK);
250 raw->offset_size = cpu_to_be16(iv->offset);
254 raw->data.d16 = cpu_to_be16(iv->value);
255 size = sizeof(be16_t) + sizeof(be16_t);
258 raw->data.d32 = cpu_to_be32(iv->value);
259 raw->offset_size |= cpu_to_be16(FW_IV_32BIT);
260 size = sizeof(be16_t) + sizeof(be32_t);
263 iv_error(ctx, "Internal error. initval_to_raw invalid size.");
270 static void emit_ival_section(struct ivals_context *ctx)
276 struct initval_raw raw;
277 struct fw_header hdr;
279 unsigned int filesize = 0;
281 memset(&hdr, 0, sizeof(hdr));
282 hdr.type = FW_TYPE_IV;
283 hdr.ver = FW_HDR_VER;
284 hdr.size = cpu_to_be32(ctx->ivals_count);
286 fn_len = strlen(ctx->sect->name) + strlen(initvals_fn_extension ? : "") + 1;
287 fn = xmalloc(fn_len);
288 snprintf(fn, fn_len, "%s%s", ctx->sect->name, initvals_fn_extension ? : "");
289 fd = fopen(fn, "w+");
291 fprintf(stderr, "Could not open initval output file \"%s\"\n", fn);
296 if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
297 fprintf(stderr, "Could not write initvals outfile\n");
301 if (IS_VERBOSE_DEBUG)
302 fprintf(stderr, "\nInitvals \"%s\":\n", ctx->sect->name);
303 list_for_each_entry(iv, &ctx->ivals, list) {
304 if (IS_VERBOSE_DEBUG) {
305 fprintf(stderr, "%04X %u %08X\n",
310 size = initval_to_raw(ctx, &raw, iv);
311 if (fwrite(&raw, size, 1, fd) != 1) {
312 fprintf(stderr, "Could not write initvals outfile\n");
318 if (arg_print_sizes) {
319 printf("%s: %d values (%u bytes)\n",
320 fn, ctx->ivals_count, filesize);
327 void assemble_initvals(void)
329 struct ivals_context ctx;
330 struct initvals_sect *sect;
332 list_for_each_entry(sect, &infile.ivals, list) {
333 memset(&ctx, 0, sizeof(ctx));
334 INIT_LIST_HEAD(&ctx.ivals);
336 assemble_ival_section(&ctx, sect);
337 emit_ival_section(&ctx);