/*
* EMU10k1 loader
*
* Copyright (c) 2003,2004 by Peter Zubaj
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <alsa/asoundlib.h>
#include "ld10k1.h"
#include "ld10k1_fnc.h"
#include "ld10k1_fnc1.h"
#include "ld10k1_debug.h"
#include "ld10k1_error.h"
#include "ld10k1_tram.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static char *usage_str[] = {
"NONE",
"NORMAL",
"CONST",
"DYNAMIC"
};
char debug_line[1000];
int send_debug_line(int data_conn)
{
return send_response(data_conn, FNC_CONTINUE, 0, debug_line, strlen(debug_line) + 1);
}
int ld10k1_debug_new_gpr_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx)
{
int usage;
int value;
int ref_count;
int modified;
modified = dsp_mgr->regs[idx].modified;
usage = dsp_mgr->regs[idx].gpr_usage;
value = dsp_mgr->regs[idx].val;
ref_count = dsp_mgr->regs[idx].ref;
sprintf(debug_line, "%c 0x%03x : %-12s 0x%08x %3d\n",
modified ? '*' : ' ',
idx,
usage_str[usage],
value,
ref_count);
return send_debug_line(data_conn);
}
int ld10k1_debug_new_gpr_read_hdr(int data_conn)
{
sprintf(debug_line, "M Idx Usage Value Ref\n");
return send_debug_line(data_conn);
}
static int ld10k1_debug_new_gpr_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
sprintf(debug_line, "FX8010 GPR List\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
if ((err = ld10k1_debug_new_gpr_read_hdr(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->regs_max_count; i++)
if (dsp_mgr->regs[i].used)
if ((err = ld10k1_debug_new_gpr_read_one(data_conn, dsp_mgr, i)) < 0)
return err;
return 0;
}
static int ld10k1_debug_new_fx_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
sprintf(debug_line, "FX8010 FX List\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->fx_count; i++) {
sprintf(debug_line, "%03x : %-20s\n",
i,
dsp_mgr->fxs[i].name ? dsp_mgr->fxs[i].name : "");
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
return 0;
}
static int ld10k1_debug_new_in_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
sprintf(debug_line, "FX8010 IN List\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->in_count; i++) {
sprintf(debug_line, "%03x : %-20s\n",
i,
dsp_mgr->ins[i].name ? dsp_mgr->ins[i].name : "");
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
return 0;
}
static int ld10k1_debug_new_out_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
sprintf(debug_line, "FX8010 OUT List\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->out_count; i++) {
sprintf(debug_line, "%03x : %-20s\n",
i,
dsp_mgr->outs[i].name ? dsp_mgr->outs[i].name : "");
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
return 0;
}
int ld10k1_debug_new_const_read_one(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, unsigned int idx)
{
int hw;
int value;
int ref_count;
hw = dsp_mgr->consts[idx].hw;
value = dsp_mgr->consts[idx].const_val;
ref_count = dsp_mgr->consts[idx].ref;
sprintf(debug_line, "0x%03x : 0x%08x %c %3d\n",
idx,
value,
hw ? '*' : ' ',
ref_count);
return send_debug_line(data_conn);
}
int ld10k1_debug_new_const_read_hdr(int data_conn)
{
sprintf(debug_line, "Idx Value HW Ref\n");
return send_debug_line(data_conn);
}
static int ld10k1_debug_new_const_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
sprintf(debug_line, "CONST List\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
if ((err = ld10k1_debug_new_const_read_hdr(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->consts_max_count; i++)
if (dsp_mgr->consts[i].used)
if ((err = ld10k1_debug_new_const_read_one(data_conn, dsp_mgr, i)) < 0)
return err;
return 0;
}
char *instr_name[] = {
"MACS",
"MACS1",
"MACW",
"MACW1",
"MACINTS",
"MACINTW",
"ACC3",
"MACMV",
"ANDXOR",
"TSTNEG",
"LIMIT",
"LIMIT1",
"LOG",
"EXP",
"INTERP",
"SKIP",
};
static void ld10k1_debug_decode_preg_idx(char *type, unsigned int reg)
{
switch ((reg & EMU10K1_PREG_TYPE_MASK) >> 28) {
case EMU10K1_PREG_TYPE_IN:
sprintf(type, "IN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_OUT:
sprintf(type, "OUT(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_CONST:
sprintf(type, "CON(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_STA:
sprintf(type, "STA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_DYN:
sprintf(type, "DYN(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_HW:
sprintf(type, "HW(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_CTL:
sprintf(type, "CTL(%03d, %03d)", (reg & ~EMU10K1_PREG_TYPE_MASK) >> 8, reg & ~EMU10K1_PREG_TYPE_MASK & 0xFF);
break;
case EMU10K1_PREG_TYPE_TRAM_DATA:
sprintf(type, "TD(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
case EMU10K1_PREG_TYPE_TRAM_ADDR:
sprintf(type, "TA(%03d)", reg & ~EMU10K1_PREG_TYPE_MASK);
break;
default:
sprintf(type, "??? 0x%08x", reg);
}
}
int ld10k1_debug_new_code_read_one(int data_conn, int preg, ld10k1_instr_t *instr, unsigned int idx)
{
char type1[100];
char type2[100];
char type3[100];
char type4[100];
if (instr->used) {
if (preg) {
ld10k1_debug_decode_preg_idx(type1, instr->arg[0]);
ld10k1_debug_decode_preg_idx(type2, instr->arg[1]);
ld10k1_debug_decode_preg_idx(type3, instr->arg[2]);
ld10k1_debug_decode_preg_idx(type4, instr->arg[3]);
sprintf(debug_line, "%c 0x%03x : %-10s %s, %s, %s, %s\n",
instr->modified ? '*' : ' ',
idx,
instr_name[instr->op_code],
type1,
type2,
type3,
type4);
} else {
sprintf(debug_line, "%c 0x%03x : %-10s 0x%03x, 0x%03x, 0x%03x, 0x%03x\n",
instr->modified ? '*' : ' ',
idx,
instr_name[instr->op_code],
instr->arg[0],
instr->arg[1],
instr->arg[2],
instr->arg[3]);
}
return send_debug_line(data_conn);
} else {
sprintf(debug_line, "%c 0x%03x : NOT USED\n",
instr->modified ? '*' : ' ',
idx);
return send_debug_line(data_conn);
}
}
int ld10k1_debug_new_code_read_hdr(int data_conn)
{
sprintf(debug_line, "M Idx OPCODE\n");
return send_debug_line(data_conn);
}
static int ld10k1_debug_new_code_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
int err;
ld10k1_instr_t *instr;
sprintf(debug_line, "FX8010 Code\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->instr_count; i++) {
instr = &(dsp_mgr->instr[i]);
if (instr->used)
if ((err = ld10k1_debug_new_code_read_one(data_conn, 0, instr, i)) < 0)
return err;
}
return 0;
}
static int ld10k1_debug_new_tram_info_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i, j;
int err;
char *req_pos_str;
char *pos_str;
ld10k1_tram_acc_t *tram_acc;
unsigned int data, addr;
int ifree = dsp_mgr->i_tram.size;
int efree = dsp_mgr->e_tram.size;
sprintf(debug_line, "TRAM\n\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, "Internal tram size: 0x%08x\n", dsp_mgr->i_tram.size);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, "External tram size: 0x%08x\n", dsp_mgr->e_tram.size);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, "\nTram groups:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
if (dsp_mgr->tram_grp[i].used) {
sprintf(debug_line, "%03d %10s ", i, dsp_mgr->tram_grp[i].type == TRAM_GRP_DELAY ? "DELAY" : "TABLE");
if ((err = send_debug_line(data_conn)) < 0)
return err;
req_pos_str = "NONE";
if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_AUTO)
req_pos_str = "AUTO";
else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_INTERNAL)
req_pos_str = "INTERNAL";
else if (dsp_mgr->tram_grp[i].req_pos == TRAM_POS_EXTERNAL)
req_pos_str = "EXTERNAL";
pos_str = "NONE";
if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) {
pos_str = "INTERNAL";
ifree -= dsp_mgr->tram_grp[i].size;
} else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) {
pos_str = "EXTERNAL";
efree -= dsp_mgr->tram_grp[i].size;
}
sprintf(debug_line, "%10s %10s %08x %08x %03d\n", req_pos_str, pos_str,
dsp_mgr->tram_grp[i].size, dsp_mgr->tram_grp[i].offset, dsp_mgr->tram_grp[i].acc_count);
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (j = 0; j < dsp_mgr->max_tram_acc; j++) {
tram_acc = &(dsp_mgr->tram_acc[j]);
ld10k1_tram_get_hwacc(dsp_mgr, tram_acc->hwacc, &addr, &data);
if ((tram_acc->used) && (tram_acc->grp == i)) {
sprintf(debug_line, " %c%c%c Off:0x%08x HWacc:%03d ADDR:0x%08x DATA:0x%08x\n",
(tram_acc->type & TRAM_ACC_READ) ? 'R' : '-',
(tram_acc->type & TRAM_ACC_WRITE) ? 'W' : '-',
(tram_acc->type & TRAM_ACC_ZERO) ? 'Z' : '-',
tram_acc->offset,
tram_acc->hwacc,
addr,
data);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
}
}
}
return 0;
}
int ld10k1_debug_new_patch_read1(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
{
int i, j;
int err;
ld10k1_conn_point_t *point;
sprintf(debug_line, "Patch name: %s\n\n", patch->patch_name);
if ((err = send_debug_line(data_conn)) < 0)
return err;
/* in list */
sprintf(debug_line, "IN registers:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->in_count; i++) {
sprintf(debug_line, "%03d %s -> 0x%08x\n", i,
patch->ins[i].name ? patch->ins[i].name : "",
patch->ins[i].point ? patch->ins[i].point->con_gpr_idx : 0);
if ((err = send_debug_line(data_conn)) < 0)
return err;
point = patch->ins[i].point;
if (point != NULL)
for (j = 0; j < MAX_CONN_PER_POINT; j++) {
if (point->out_gpr_idx[j] != 0) {
sprintf(debug_line, " +0x%08x\n", point->out_gpr_idx[j]);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
}
}
/* out list */
sprintf(debug_line, "OUT registers:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->out_count; i++) {
sprintf(debug_line, "%03d %s -> 0x%08x\n", i,
patch->outs[i].name ? patch->outs[i].name : "",
patch->outs[i].point ? patch->outs[i].point->con_gpr_idx : 0);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* const list */
sprintf(debug_line, "CONST registers:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->const_count; i++) {
sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i,
patch->consts[i].const_val,
patch->consts[i].gpr_idx);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* sta list */
sprintf(debug_line, "STA registers:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->sta_count; i++) {
sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i,
patch->stas[i].const_val,
patch->stas[i].gpr_idx);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* hw list */
sprintf(debug_line, "HW registers:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->hw_count; i++) {
sprintf(debug_line, "%03d 0x%08x -> 0x%08x\n", i,
patch->hws[i].reg_idx,
patch->hws[i].gpr_idx);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* tram list */
sprintf(debug_line, "\nUsed tram groups:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->tram_count; i++) {
sprintf(debug_line, "%03d 0x%01x 0x%08x 0x%01x -> %03d\n", i,
patch->tram_grp[i].grp_type,
patch->tram_grp[i].grp_size,
patch->tram_grp[i].grp_pos,
patch->tram_grp[i].grp_idx);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* tram acc list */
sprintf(debug_line, "\nUsed tram acc:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->tram_acc_count; i++) {
sprintf(debug_line, "%03d 0x%01x 0x%08x 0x%03x -> 0x%03x\n", i,
patch->tram_acc[i].acc_type,
patch->tram_acc[i].acc_offset,
patch->tram_acc[i].grp,
patch->tram_acc[i].acc_idx);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
/* cotrol list */
sprintf(debug_line, "\nUsed controls:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < patch->ctl_count; i++) {
sprintf(debug_line, "%03d\n", i);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, " Name:%s\n", patch->ctl[i].name);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, " Min: 0x%08x\n", patch->ctl[i].min);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, " Max: 0x%08x\n", patch->ctl[i].max);
if ((err = send_debug_line(data_conn)) < 0)
return err;
sprintf(debug_line, " GPRS:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (j = 0; j < patch->ctl[i].count; j++) {
sprintf(debug_line, " %03d 0x%08x -> 0x%08x %c\n", j,
patch->ctl[i].value[j],
patch->ctl[i].gpr_idx[j],
j < patch->ctl[i].vcount ? 'v' : ' ');
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
}
/* instruction list */
sprintf(debug_line, "\nCode:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
if ((err = ld10k1_debug_new_code_read_hdr(data_conn)) < 0)
return err;
for (i = 0; i < patch->instr_count; i++) {
ld10k1_instr_t *instr;
instr = &(patch->instr[i]);
if ((err = ld10k1_debug_new_code_read_one(data_conn, 1, instr, i)) < 0)
return err;
}
return 0;
}
static int ld10k1_debug_new_patch_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr, int idx)
{
ld10k1_patch_t *patch;
patch = dsp_mgr->patch_ptr[idx];
if (!patch)
return LD10K1_ERR_UNKNOWN_PATCH_NUM;
return ld10k1_debug_new_patch_read1(data_conn, dsp_mgr, patch);
}
static int ld10k1_debug_new_patch_list_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i;
ld10k1_patch_t *patch;
int err;
sprintf(debug_line, "\nPatch List:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < EMU10K1_PATCH_MAX; i++) {
patch = dsp_mgr->patch_ptr[i];
if (patch) {
sprintf(debug_line, "%03d %s\n\n", i, patch->patch_name);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
}
return 0;
}
static int ld10k1_debug_new_patch_order_read(int data_conn, ld10k1_dsp_mgr_t *dsp_mgr)
{
int i, idx;
ld10k1_patch_t *patch;
int err;
sprintf(debug_line, "\nPatch order:\n");
if ((err = send_debug_line(data_conn)) < 0)
return err;
for (i = 0; i < dsp_mgr->patch_count; i++) {
idx = dsp_mgr->patch_order[i];
patch = dsp_mgr->patch_ptr[idx];
if (patch) {
sprintf(debug_line, "%03d %03d %s\n\n", i, idx, patch->patch_name);
if ((err = send_debug_line(data_conn)) < 0)
return err;
}
}
return 0;
}
int ld10k1_fnc_debug(int data_conn, int op, int size)
{
ld10k1_fnc_debug_t debug_info;
int err;
if (size != sizeof(ld10k1_fnc_debug_t))
return LD10K1_ERR_PROTOCOL;
if ((err = receive_msg_data(data_conn, &debug_info, sizeof(ld10k1_fnc_debug_t))))
return err;
if (debug_info.what >= 100 && debug_info.what <= 100 + EMU10K1_PATCH_MAX) {
if ((err = ld10k1_debug_new_patch_read(data_conn, &dsp_mgr, debug_info.what - 100)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 1) {
/* registers */
if ((err = ld10k1_debug_new_gpr_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 2) {
/* registers */
if ((err = ld10k1_debug_new_const_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 3) {
/* instruction */
if ((err = ld10k1_debug_new_code_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 4) {
/* tram */
if ((err = ld10k1_debug_new_tram_info_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 5) {
if ((err = ld10k1_debug_new_patch_list_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 6) {
if ((err = ld10k1_debug_new_patch_order_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 7) {
/* fx */
if ((err = ld10k1_debug_new_fx_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 8) {
/* in */
if ((err = ld10k1_debug_new_in_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else if (debug_info.what == 9) {
/* out */
if ((err = ld10k1_debug_new_out_read(data_conn, &dsp_mgr)) < 0)
return err;
if ((err = send_response_ok(data_conn)) < 0)
return err;
} else
if ((err = send_response_ok(data_conn)) < 0)
return err;
return 0;
}