/*
 **********************************************************************
 *     dsp.h -- header file for the dsp patch manager. 
 *     Copyright 2000 Rui Sousa 
 *
 **********************************************************************
 *
 *     Date                 Author          Summary of changes
 *     ----                 ------          ------------------
 *     May 1, 2000          Rui Sousa       initial draft 
 *
 **********************************************************************
 *
 *     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 "list.h"
#include "types.h"

#define NUM_INPUTS 0x20 
#define NUM_OUTPUTS 0x10 
#define NUM_GPRS 0x100 
#define DSP_CODE_SIZE 0x400 

enum {
INPUT = 0,
OUTPUT,
ROUTING
};

/*
An input/output patch consists of:
	m DSP code lines
	1 output line number
	1 input line number
	1 input gpr register
	1 output gpr register
	p automatic gpr registers (the value may be discarded outside the patch) 
	q static gpr registers (the value may not be overwritten by other patches)
	TRAM lines (haven't look into this yet) 

A routing patch consists of:
	m DSP code lines
	n input lines
	o output lines
	n input registers
	o output registers
	p automatic gpr registers (the value may be discarded outside the patch)
	q static gpr registers (the value may not be overwritten by other patches)

Patches are divided into three groups: input, output and routing. The patch
that does the routing will be in the middle and connects each input
to an arbitrary number of outputs. Input patches (Pi_) stay on the input
lines (In_) and output patches (Po_) on the output lines (Out_).
The order of the inputs patches on a given input line is of no importance.
The same for the output patches.

                         
In1---Pi1---Pi2---| Ri1   

In2---------------| Ri2

In3---Pi3---------| Ri2

In4---------------| Ri1

In5---Pi5---------| Ri3


Ro1 |---------------Out1
Ro2 |
Ro3 |

Ro2 |---Po1---Po2---Out2

Ro3 |---------Po3---Out3

Ro1 |---------------Out4
Ro3 |

Ro3 |---------Po4---Out5
                        

A patch should never make direct reference to IN/OUT registers, it should
only use gprs for this purpose. The compiler should build a list of the
gprs used for output/input. The compiler should also build a list of
automatic and static gprs used. If a gpr is not in one of this groups
the patch is illegal.

The program that ask the patch to be loaded must indicate the type of patch
and the line it's going to be placed in. The output line number is ignored for
input patches. For routing patches an array of line numbers maybe be indicated
for the input and output lines. A routing patch can be attached to several input
lines and output lines. To each input line there can only be one routing patch
attached. To each output line there can be an arbitrary number of patches attached.
The patch loader will write some code to mix the various outputs.

Each time a patch is loaded some dsp code maybe moved
in order to insert the patch in the right place.

Each time a patch is unloaded the remaining dsp code maybe moved
in order to keep it in a continuous block.

Also the entire code will be parsed and the input/output gprs
references will be updated to maintain the correctness of the lines in
the above picture. */ 

/* the dsp patch assembler should:
	have an instruction to declare a gpr static or automatic.
	(using a gpr without first declaring it should be illegal).
	have an instruction to declare a gpr to be input/output.
	optimize automatic gpr usage. 
	construct a header suitable to pass this information to the
	patch loader */


struct dsp_patch {
	struct list_head patch;
	struct list_head *in;
	struct list_head *out;

        u32 *code;		/* the binary dsp code for the patch */
	int size;		/* the size of the code (in 4 bytes units) */
	int start;		/* the starting address of the code */

        int *gpr_automatic;	/* automatic gpr's table*/
	int *gpr_static;	/* static gpr's table */
	int *gpr_in;        	/* input gpr's table */
	int *gpr_out;		/* output gpr's table */
	
	int type;		/* input, output, routing */
	int *line_in;
	int *line_out;
};

struct gpr_entry {
	int type;	/* free, automatic, static, input, output */
	int count;
};

struct patch_manager {
	struct list_head line_in[NUM_INPUTS]; /* array of loaded "in patches" */
	struct list_head line_out[NUM_OUTPUTS]; /* array of loaded "out patches" */
	struct list_head routing_in[NUM_INPUTS];	/* routing patches */
	struct list_head routing_out[NUM_OUTPUTS];

	struct list_head patches;

	struct gpr_entry gpr[NUM_GPRS];	/* gpr usage table */
	int free_space;
};

/* loads a dsp patch */
/* returns a pointer to the patch loaded or NULL on error*/
struct dsp_patch *load_dsp_patch(struct dsp_patch *patch);

/* unloads a patch identified by the pointer returned by load_dsp_patch() */
void unload_dsp_patch(struct dsp_patch *patch);
