
/*********************************************************************
 *     main.c - a small wrapper for the dsp code.
 *      Copyright (C) 2000 Rui Sousa 
 ********************************************************************* 
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version. 
 * 
 *     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. 
 * 
 *     You should have received a copy of the GNU General Public 
 *     License along with this program; if not, write to the Free 
 *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
 *     USA. 
 ********************************************************************* 
*/

#include <stdio.h>
#include <stdlib.h>
#include "compiler.h"

static void write_header(FILE * fp)
{
	struct list_head *entry, *entry1;
	struct dsp_reg *__gpr;
	struct dsp_gpr_io *__gpr_io;
	struct tram_block *__tramb;
	struct tram_line *__traml;
	__u8 __addr;
	__u32 __addr_val;

	/* patch name */
	fwrite(__patch_name, sizeof(char), PATCH_NAME_SIZE, fp);

	/* io gprs */
	fwrite(&__gpr_io_count, sizeof(__u8), 1, fp);
	list_for_each(entry, &__gpr_io_list) {
		__gpr_io = list_entry(entry, struct dsp_gpr_io, list);

		__addr = __gpr_io->in.address;
		fwrite(&__addr, sizeof(__u8), 1, fp);

		__addr = __gpr_io->out.address;
		fwrite(&__addr, sizeof(__u8), 1, fp);
	}

	/* dynamic gprs */
	fwrite(&__gpr_dynamic_count, sizeof(__u8), 1, fp);
	list_for_each(entry, &__gpr_dynamic_list) {

		__gpr = list_entry(entry, struct dsp_reg, list);

		__addr = __gpr->address - GPR_BASE;
		fwrite(&__addr, sizeof(__u8), 1, fp);	
	}

	/* static gprs */
	fwrite(&__gpr_static_count, sizeof(__u8), 1, fp);
	list_for_each(entry, &__gpr_static_list) {
		__gpr = list_entry(entry, struct dsp_reg, list);

		__addr = __gpr->address - GPR_BASE;
		fwrite(&__addr, sizeof(__u8), 1, fp);
                fwrite(&__gpr->value, sizeof(__s32), 1, fp);
	}

	/* control gprs */
	fwrite(&__gpr_control_count, sizeof(__u8), 1, fp);
	list_for_each(entry, &__gpr_control_list) {
		__gpr = list_entry(entry, struct dsp_reg, list);

		__addr = __gpr->address - GPR_BASE;

		fwrite(&__addr, sizeof(__u8), 1, fp);
                fwrite(&__gpr->value, sizeof(__s32), 1, fp);
                fwrite(&__gpr->min, sizeof(__s32), 1, fp);
                fwrite(&__gpr->max, sizeof(__s32), 1, fp);
                fwrite(__gpr->name, sizeof(char), GPR_NAME_SIZE, fp);
	}

	/* tram tablelookup blocks */
	fwrite(&__tramb_tablelookup_count, sizeof(__u16), 1, fp);	
	list_for_each(entry, &__tramb_tablelookup_list) {
		__tramb = list_entry(entry, struct tram_block, list);
		fwrite(&__tramb->size, sizeof(__u32), 1, fp);

		fwrite(&__tramb->line_read_count, sizeof(__u8), 1, fp);		
	        list_for_each(entry1, &__tramb->line_read_list) {
                	__traml = list_entry(entry1, struct tram_line, list);

			__addr = __traml->data.address - TRAML_DATA_BASE;

			fwrite(&__addr, sizeof(__u8), 1, fp);

			__addr_val = __traml->address.value;

			fwrite(&__addr_val, sizeof(__u32), 1, fp);
		}

		fwrite(&__tramb->line_write_count, sizeof(__u8), 1, fp);
                list_for_each(entry1, &__tramb->line_write_list) {
                        __traml = list_entry(entry1, struct tram_line, list);

                        __addr = __traml->data.address - TRAML_DATA_BASE;

                        fwrite(&__addr, sizeof(__u8), 1, fp);

                        __addr_val = __traml->address.value;

                        fwrite(&__addr_val, sizeof(__u32), 1, fp);
                }
        }


	/* tram delaylines blocks */
        fwrite(&__tramb_delayline_count, sizeof(__u16), 1, fp);
        list_for_each(entry, &__tramb_delayline_list) {
                __tramb = list_entry(entry, struct tram_block, list);
                fwrite(&__tramb->size, sizeof(__u32), 1, fp);

                fwrite(&__tramb->line_read_count, sizeof(__u8), 1, fp);

                list_for_each(entry1, &__tramb->line_read_list) {
                        __traml = list_entry(entry1, struct tram_line, list);

                        __addr = __traml->data.address - TRAML_DATA_BASE;

                        fwrite(&__addr, sizeof(__u8), 1, fp);

                        __addr_val = __traml->address.value;

                        fwrite(&__addr_val, sizeof(__u32), 1, fp);
                }

                fwrite(&__tramb->line_write_count, sizeof(__u8), 1, fp);
                list_for_each(entry1, &__tramb->line_write_list) {
                        __traml = list_entry(entry1, struct tram_line, list);

                        __addr = __traml->data.address - TRAML_DATA_BASE;

                        fwrite(&__addr, sizeof(__u8), 1, fp);

                        __addr_val = __traml->address.value;

                        fwrite(&__addr_val, sizeof(__u32), 1, fp);
                }
        }

	/* code size */
	__ip *= 2;
	fwrite(&__ip, sizeof(__u16), 1, fp);

	__ip /= 2;
	return;
}

void write_code(FILE * fp)
{
#ifdef DEBUG
	int i;

	for (i = 0; i < __ip; i++)
		printf("0x%03x   0x%08x  0x%08x %2d 0x%03x 0x%03x 0x%03x 0x%03x\n", 2 * i,
		       __dsp_code[i * 2 + 1], __dsp_code[i * 2],
			(__dsp_code[i * 2 + 1] >> 20) & 0xf,
			(__dsp_code[i * 2 + 1] >> 10) & 0x3ff, __dsp_code[i * 2 + 1] & 0x3ff,
			(__dsp_code[i * 2] >> 10) & 0x3ff, __dsp_code[i * 2] & 0x3ff);
#endif


	fwrite(__dsp_code, sizeof(__u32), 2 * __ip, fp);

	return;
}

void write_patch(const char *file)
{
	FILE *fp;

	if ((fp = fopen(file, "w")) == NULL) {
		perror(file);
		exit(EXIT_FAILURE);
	}

	write_header(fp);
	write_code(fp);

	fclose(fp);

	return;
}

void init(void)
{
	__arg = 0;
	__ip = 0;
	__line = 0;

	INIT_LIST_HEAD(&__gpr_static_list);
	INIT_LIST_HEAD(&__gpr_dynamic_list);
	INIT_LIST_HEAD(&__gpr_control_list);
	INIT_LIST_HEAD(&__gpr_io_list);

	__gpr_total_count = 0;
	__gpr_static_count = 0;
	__gpr_dynamic_count = 0;
	__gpr_io_count = 0;
	__gpr_control_count = 0;

	INIT_LIST_HEAD(&__tramb_tablelookup_list);
	INIT_LIST_HEAD(&__tramb_delayline_list);

	__tramb_tablelookup_count = 0;
	__tramb_delayline_count = 0;

	__traml_total_count = 0;

	return;
}

int main(int argc, char *argv[])
{

	init();

	{
#ifdef DSP_FILE
#include DSP_FILE
#endif 
	}

	write_patch(argv[1]);

	return 0;
}
