missing commit in generator.h
[galan.git] / plugins / emu10k1-lib / file.c
blobba966868a48764a2594b43a14fd1c040afb8d288
1 /*********************************************************************
2 * file.c - dsp patch manager library - patch file reading functions
3 *
4 * Copyright (C) 2000 Rui Sousa
5 *********************************************************************
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
19 * USA.
20 *********************************************************************
23 #include <stdio.h>
24 #include "../emu10k1-include/dsp.h"
25 #include "../emu10k1-include/list.h"
26 #include <stdlib.h>
27 #include "../emu10k1-include/internal.h"
29 extern __u32 addr_change[0x400];
32 #define FILE_HEAD "emu10k1-dsp-file"
33 #define FILE_FORMAT_VERSION 1
35 /* gives an increasing id to patches with the same name */
36 static int set_patch_id(struct dsp_patch_manager *mgr, struct dsp_patch *patch)
38 struct dsp_patch *patch1;
39 struct list_head *entry;
40 int table[255];
42 patch->id = 0;
45 list_for_each(entry, &mgr->ipatch_list) {
46 patch1 = list_entry(entry, struct dsp_patch, list);
48 if (!strcmp(patch1->name, patch->name)) {
49 table[patch1->id] = 1;
50 while (table[patch->id] == 1) {
51 patch->id++;
52 if (patch->id == 255)
53 return -1;
59 list_for_each(entry, &mgr->opatch_list) {
60 patch1 = list_entry(entry, struct dsp_patch, list);
62 if (!strcmp(patch1->name, patch->name)) {
63 table[patch1->id] = 1;
64 while (table[patch->id] == 1) {
65 patch->id++;
66 if (patch->id == 255)
67 return -1;
72 return 0;
74 static int read_patch_code(struct dsp_patch *patch, FILE * fp)
76 patch->code = (__u32 *) malloc(patch->code_size * sizeof(__u32));
78 if (patch->code == NULL) {
79 fprintf(stderr, "read_patch_code(): no memory available\n");
80 return -1;
83 fread(patch->code, sizeof(__u32), patch->code_size, fp);
85 return 0;
88 /* FIXME */
89 /* Still missing the ALIGN and CLEAR bits */
90 static inline void read_tram_lines(__u32 tramb_start, __u32 * traml_addr,
91 __u8 * traml_size, __u16 base, __u32 type, FILE * fp)
93 int i;
94 __u8 lines;
95 __u8 data_addr;
96 __u32 addr_val;
98 fread(&lines, sizeof(__u8), 1, fp);
99 for (i = 0; i < lines; i++) {
100 fread(&data_addr, sizeof(__u8), 1, fp);
102 addr_change[TRAML_IDATA_BASE - GPR_BASE + data_addr] = base + *traml_size;
104 addr_change[TRAML_IADDR_BASE - GPR_BASE + data_addr] =
105 base + (TRAML_IADDR_BASE - TRAML_IDATA_BASE) + *traml_size;
107 fread(&addr_val, sizeof(__u32), 1, fp);
109 traml_addr[*traml_size] = ((tramb_start + addr_val) & 0xfffff) | (type << 20);
110 (*traml_size)++;
114 /* FIXME restore tramb_?start on failure */
115 static int read_tram_block(struct dsp_patch_manager *mgr, struct dsp_patch *patch, __u32 * traml_iaddr,
116 __u32 * traml_eaddr, FILE * fp)
118 int i;
119 __u8 blocks;
120 __u32 size;
121 __u8 tmp;
122 __u32 type;
123 /* tram blocks and lines */
124 fread(&blocks, sizeof(__u8), 1, fp);
125 for (i = 0; i < blocks; i++) {
126 fread(&size, sizeof(__u32), 1, fp);
128 type = 0x30000000 & size;
129 size &= 0x001fffff;
131 if (size == 0) {
132 fprintf(stderr, "tram block of 0 size\n");
133 return -1;
136 if ( (size <= TRAMB_ISIZE - mgr->tramb_ifree_start ) && (type!=TRAM_EXTERNAL)) {
137 tmp = patch->traml_isize;
139 /* write lines */
141 read_tram_lines(patch->tramb_isize,
142 traml_iaddr, &patch->traml_isize, TRAML_IDATA_BASE, TRAML_TYPE_WRITE, fp);
144 /* read lines */
145 read_tram_lines(patch->tramb_isize,
146 traml_iaddr, &patch->traml_isize, TRAML_IDATA_BASE, TRAML_TYPE_READ, fp);
148 /* a block with no tram lines */
149 if (tmp == patch->traml_isize) {
150 fprintf(stderr, "tram block with no tram lines\n");
151 return -1;
154 /* no free tram space */
155 if (mgr->traml_ifree_start + patch->traml_isize > TRAML_ISIZE) {
156 fprintf(stderr, "no free internal tram lines\n");
157 return -1;
160 patch->tramb_isize += size;
161 mgr->tramb_ifree_start += size;
163 } else if ((size <= TRAMB_ESIZE - mgr->tramb_efree_start)&&(type!=TRAM_INTERNAL)) {
164 tmp = patch->traml_esize;
166 /* write lines */
168 read_tram_lines(patch->tramb_esize, traml_eaddr,
169 &patch->traml_esize, TRAML_EDATA_BASE, TRAML_TYPE_WRITE, fp);
171 /* read lines */
173 read_tram_lines(patch->tramb_esize, traml_eaddr,
174 &patch->traml_esize, TRAML_EDATA_BASE, TRAML_TYPE_READ, fp);
176 /* a block with no tram lines */
177 if (tmp == patch->traml_esize) {
178 fprintf(stderr, "tram block with no tram lines\n");
179 return -1;
182 /* no free tram space */
183 if (mgr->traml_efree_start + patch->traml_esize > TRAML_ESIZE) {
184 fprintf(stderr, "no free external tram lines\n");
185 return -1;
187 patch->tramb_esize += size;
188 mgr->tramb_efree_start += size;
190 } else {
191 fprintf(stderr, "no free tram blocks\n");
192 return -1;
196 mgr->traml_ifree_start += patch->traml_isize;
197 mgr->traml_efree_start += patch->traml_esize;
199 return 0;
202 /* FIXME */
203 /* only single input patches supported */
204 static int read_patch_header(struct dsp_patch_manager *mgr, struct dsp_patch *patch, FILE * fp, char *name, int num_in, int num_out)
206 char tmp[sizeof(FILE_HEAD)];
207 __u8 count, addr;
208 __u32 traml_iaddr[TRAML_ISIZE];
209 __u32 traml_eaddr[TRAML_ESIZE];
210 int ret, i, j;
211 __u8 input[DSP_NUM_INPUTS],output[DSP_NUM_OUTPUTS];
214 //Read file format info:
215 fread(tmp, sizeof(char), sizeof(FILE_HEAD), fp);
216 if(strcmp(tmp,FILE_HEAD)){
217 fprintf(stderr,"Error: File is not a proper dsp file\n" );
218 return -1;
220 //Read format version
221 i=0;
222 fread(&i, sizeof(__u16),1 , fp);
224 if( i < FILE_FORMAT_VERSION)
225 fprintf(stderr,"Warning: file was created with a newer version of the emu-tools\n");
229 /* patch name */
230 fread(patch->name, sizeof(char), DSP_PATCH_NAME_SIZE, fp);
232 //If user specifies a different patch name, we change it now:
233 if(name[0]!='\0'){
234 strncpy(patch->name,name, DSP_LINE_NAME_SIZE);
235 patch->name[DSP_LINE_NAME_SIZE - 1] = '\0';
236 }else
237 //we copy back the name in the patch
238 strncpy(name, patch->name, DSP_LINE_NAME_SIZE);
240 /* input/output gprs */
241 fread(&count, sizeof(__u8), 1, fp);
243 // FIXME:
244 // We'll need to change the file format to support non-symetric I/O
245 if(num_in!=count){
246 fprintf(stderr,"Patch requires %d inputs, %d were specified\n",count,num_in);
247 goto err0;
251 for (i = 0; i < count; i++) {
252 fread(&(input[i]), sizeof(__u8), 1, fp);
253 fread(&(output[i]), sizeof(__u8), 1, fp);
256 j=0;
257 for(i=0;i<DSP_NUM_INPUTS;i++){
258 if(patch_uses_input(patch,i)){
259 addr_change[input[j]] = get_io_gpr(mgr, i , GPR_INPUT, patch->gpr_used, patch->gpr_input);
260 j++;
264 j=0;
265 for(i=0;i<DSP_NUM_OUTPUTS;i++){
266 if(patch_uses_output(patch,i)){
267 addr_change[output[j]] = get_io_gpr(mgr, i , GPR_OUTPUT, patch->gpr_used, patch->gpr_input);
268 j++;
272 /* dynamic gprs */
273 fread(&count, sizeof(__u8), 1, fp);
274 for (i = 0; i < count; i++) {
275 fread(&addr, sizeof(__u8), 1, fp);
276 addr_change[addr] = get_dynamic_gpr(mgr, patch->gpr_used);
279 /* static gprs */
280 fread(&count, sizeof(__u8), 1, fp);
281 for (i = 0; i < count; i++) {
282 __s32 value;
283 fread(&addr, sizeof(__u8), 1, fp);
284 fread(&value, sizeof(__s32), 1, fp);
285 addr_change[addr] = get_static_gpr(mgr, value, patch->gpr_used);
288 /* control gprs */
289 fread(&count, sizeof(__u8), 1, fp);
290 for (i = 0; i < count; i++) {
291 __s32 value, min, max;
292 char name[DSP_GPR_NAME_SIZE];
294 fread(&addr, sizeof(__u8), 1, fp);
295 fread(&value, sizeof(__s32), 1, fp);
296 fread(&min, sizeof(__s32), 1, fp);
297 fread(&max, sizeof(__s32), 1, fp);
299 if (min >= max) {
300 fprintf(stderr, "invalid range for control gpr %x %x\n", min, max);
301 return -1;
304 if (value > max)
305 value = max;
306 else if (value < min)
307 value = min;
309 fread(name, sizeof(char), DSP_GPR_NAME_SIZE, fp);
311 addr_change[addr] = get_control_gpr(mgr, value, min, max, name, patch->gpr_used, patch->name);
314 /* constant gprs */
315 fread(&count, sizeof(__u8), 1, fp);
316 for (i = 0; i < count; i++) {
317 __s32 value;
319 fread(&addr, sizeof(__u8), 1, fp);
320 fread(&value, sizeof(__s32), 1, fp);
321 addr_change[addr] = get_constant_gpr(mgr, value, patch->gpr_used);
323 /* here lines and blocks, internal and external, all start from 0 */
324 /* this is fixed later on in set_tram_addr() */
326 patch->tramb_istart = 0;
327 patch->tramb_isize = 0;
328 patch->tramb_estart = 0;
329 patch->tramb_esize = 0;
331 patch->traml_istart = 0;
332 patch->traml_isize = 0;
334 patch->traml_estart = 0;
335 patch->traml_esize = 0;
337 /* tram tablelookup blocks and lines */
338 ret = read_tram_block(mgr, patch, traml_iaddr, traml_eaddr, fp);
339 if (ret < 0)
340 return ret;
342 /* tram delaylines blocks and lines */
343 ret = read_tram_block(mgr, patch, traml_iaddr, traml_eaddr, fp);
344 if (ret < 0)
345 return ret;
347 if (patch->traml_isize != 0) {
348 patch->traml_iaddr = (__u32 *) malloc(patch->traml_isize * sizeof(__u32));
349 if (patch->traml_iaddr == NULL) {
350 fprintf(stderr, "read_patch_header(): no memory available\n");
351 return -1;
353 memcpy(patch->traml_iaddr, traml_iaddr, patch->traml_isize * sizeof(__u32));
356 if (patch->traml_esize != 0) {
357 patch->traml_eaddr = (__u32 *) malloc(patch->traml_esize * sizeof(__u32));
358 if (patch->traml_eaddr == NULL) {
359 fprintf(stderr, "read_patch_header(): no memory available\n");
360 goto err0;
362 memcpy(patch->traml_eaddr, traml_eaddr, patch->traml_esize * sizeof(__u32));
365 fread(&patch->code_size, sizeof(__u16), 1, fp);
367 if (patch->code_size == 0) {
368 fprintf(stderr, "patch with zero code size\n");
369 goto err1;
372 mgr->code_free_start += patch->code_size;
374 if (mgr->code_free_start > DSP_CODE_SIZE) {
375 fprintf(stderr, "no free dsp code memory\n");
376 goto err2;
379 return 0;
381 err2:
382 mgr->code_free_start -= patch->code_size;
384 err1:
385 if (patch->traml_esize != 0)
386 free(patch->traml_eaddr);
388 err0:
389 if (patch->traml_isize != 0)
390 free(patch->traml_iaddr);
392 return -1;
395 /* FIXME */
396 /* support precise patch positioning in a line (patches in general don't commute) */
398 int dsp_read_patch(struct dsp_patch_manager *mgr, const char *file, int input[DSP_NUM_INPUTS],
399 int output[DSP_NUM_OUTPUTS], int num_in, int num_out, int io, char *name, int placement)
401 struct dsp_patch *patch;
402 struct list_head *list;
403 FILE *fp;
404 int i, j;
406 if(num_in!=num_out)
407 fprintf(stderr,"Error: Patches with an unequal number of ins and outs are not yet supported\n");
409 if (!mgr->init)
410 dsp_init(mgr);
412 patch = (struct dsp_patch *) malloc(sizeof(struct dsp_patch));
413 if (patch == NULL) {
414 perror("patch");
415 goto err0;
417 memset(patch, 0, sizeof(struct dsp_patch));
420 if ((fp = fopen(file, "r")) == NULL) {
423 perror(file);
424 goto err1;
427 if(io==1){
428 list= &mgr->ipatch_list;
429 /* only load a patch if there is a route connecting it */
430 for(i=0;i<num_in;i++){
431 set_bit(input[i], &patch->input);
432 set_bit(output[i], &patch->output);
434 for (j = 0; j < DSP_NUM_OUTPUTS; j++)
435 if ( test_bit(input[i], &mgr->rpatch.route_v[j]) || test_bit(input[i], &mgr->rpatch.route[j]) )
436 goto match1;
437 goto err2;
438 match1:
440 goto match;
441 }else{
442 list=&mgr->opatch_list;
443 /* only load a patch if there is a route connecting it */
444 for(i=0;i<num_out;i++){
445 set_bit(input[i], &patch->input);
446 set_bit(output[i], &patch->output);
447 if ( !( mgr->rpatch.route_v[input[i]] || mgr->rpatch.route[input[i]]))
448 goto err2;
453 goto match;
458 err2:
459 fclose(fp);
460 err1:
461 free(patch);
462 err0:
463 return -1;
465 match:
467 if (read_patch_header(mgr, patch, fp, name, num_in, num_out) < 0)
468 goto err2;
470 read_patch_code(patch, fp);
471 search_and_replace(patch->code, patch->code_size, addr_change, GPR_BASE, TRAML_EADDR_BASE + TRAML_ESIZE);
473 set_patch_id(mgr, patch);
474 determine_io(mgr, patch);
476 if(placement==0)
477 list_add(&patch->list, list);
478 else
479 list_add_tail(&patch->list, list);
482 fclose(fp);
483 return 0;