mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-11-01 22:58:48 -04:00
Add ld10k1 tool
Added ld10k1 tool by Peter Zubaj.
This commit is contained in:
parent
37104ebf62
commit
2df1aa7c20
98 changed files with 19970 additions and 1 deletions
25
ld10k1/src/Makefile.am
Normal file
25
ld10k1/src/Makefile.am
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
bin_PROGRAMS = lo10k1
|
||||
sbin_PROGRAMS = ld10k1 dl10k1
|
||||
ld10k1_SOURCES = ld10k1.c ld10k1_fnc.c ld10k1_fnc1.c ld10k1_debug.c \
|
||||
ld10k1_driver.c comm.c ld10k1_tram.c \
|
||||
ld10k1_dump.c ld10k1_mixer.c\
|
||||
ld10k1.h ld10k1_fnc_int.h ld10k1_fnc1.h ld10k1_debug.h \
|
||||
ld10k1_driver.h bitops.h ld10k1_tram.h \
|
||||
ld10k1_dump.h ld10k1_dump_file.h ld10k1_mixer.h
|
||||
ld10k1_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS)
|
||||
ld10k1_LDADD = $(ALSA_LIBS)
|
||||
|
||||
#liblo10k1_ladir = $(includedir)/lo10k1
|
||||
lib_LTLIBRARIES = liblo10k1.la
|
||||
liblo10k1_la_SOURCES = comm.c liblo10k1.c liblo10k1ef.c liblo10k1lf.c
|
||||
#liblo10k1_la_HEADERS = comm.h liblo10k1.h liblo10k1ef.h ld10k1_error.h ld10k1_fnc.h liblo10k1lf.h
|
||||
|
||||
lo10k1_SOURCES = lo10k1.c
|
||||
lo10k1_CFLAGS = $(ALSA_CFLAGS) -DEFFECTSDIR='"$(effectsdir)"'
|
||||
lo10k1_LDADD = liblo10k1.la
|
||||
|
||||
dl10k1_SOURCES = dl10k1.c ld10k1_dump_file.h
|
||||
dl10k1_CFLAGS = $(ALSA_CFLAGS)
|
||||
dl10k1_LDADD = $(ALSA_LIBS)
|
||||
|
||||
INCLUDES=-I$(top_srcdir)/include
|
||||
50
ld10k1/src/bitops.h
Normal file
50
ld10k1/src/bitops.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef _PZ_GENERIC_BITOPS_H_
|
||||
#define _PZ_GENERIC_BITOPS_H_
|
||||
/* this is from linux kernel header */
|
||||
/*
|
||||
* For the benefit of those who are trying to port Linux to another
|
||||
* architecture, here are some C-language equivalents. You should
|
||||
* recode these in the native assembly language, if at all possible.
|
||||
* To guarantee atomicity, these routines call cli() and sti() to
|
||||
* disable interrupts while they operate. (You have to provide inline
|
||||
* routines to cli() and sti().)
|
||||
*
|
||||
* Also note, these routines assume that you have 32 bit longs.
|
||||
* You will have to change this if you are trying to port Linux to the
|
||||
* Alpha architecture or to a Cray. :-)
|
||||
*
|
||||
* C language equivalents written by Theodore Ts'o, 9/26/92
|
||||
*/
|
||||
|
||||
__inline__ int set_bit(int nr, unsigned long * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
retval = (mask & *addr) != 0;
|
||||
*addr |= mask;
|
||||
return retval;
|
||||
}
|
||||
|
||||
__inline__ int clear_bit(int nr, unsigned long * addr)
|
||||
{
|
||||
int mask, retval;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
retval = (mask & *addr) != 0;
|
||||
*addr &= ~mask;
|
||||
return retval;
|
||||
}
|
||||
|
||||
__inline__ int test_bit(int nr, unsigned long * addr)
|
||||
{
|
||||
int mask;
|
||||
|
||||
addr += nr >> 5;
|
||||
mask = 1 << (nr & 0x1f);
|
||||
return ((mask & *addr) != 0);
|
||||
}
|
||||
|
||||
#endif /* _PZ_GENERIC_BITOPS_H */
|
||||
349
ld10k1/src/comm.c
Normal file
349
ld10k1/src/comm.c
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* EMU10k1 loader lib
|
||||
* Copyright (c) 2003,2004 by Peter Zubaj
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "comm.h"
|
||||
#include "ld10k1_error.h"
|
||||
|
||||
/* taken from glibc example */
|
||||
int setup_comm(comm_param *param)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_un lname;
|
||||
struct sockaddr_in iname;
|
||||
size_t size;
|
||||
|
||||
/* Create the socket. */
|
||||
if (param->type == COMM_TYPE_LOCAL)
|
||||
sock = socket (PF_LOCAL, SOCK_STREAM, 0);
|
||||
else
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
|
||||
if (param->server) {
|
||||
if (param->type == COMM_TYPE_LOCAL) {
|
||||
unlink(param->name);
|
||||
|
||||
/* Bind a name to the socket. */
|
||||
memset(&lname, 0, sizeof(struct sockaddr_un));
|
||||
lname.sun_family = AF_LOCAL;
|
||||
strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
|
||||
lname.sun_path[sizeof (lname.sun_path) - 1] = '\0';
|
||||
|
||||
/* The size of the address is
|
||||
the offset of the start of the filename,
|
||||
plus its length,
|
||||
plus one for the terminating null byte.
|
||||
Alternatively you can just do:
|
||||
size = SUN_LEN (&name);
|
||||
*/
|
||||
size = (offsetof (struct sockaddr_un, sun_path) + strlen (lname.sun_path) + 1);
|
||||
|
||||
if (bind (sock, (struct sockaddr *) &lname, size) < 0)
|
||||
return -1;
|
||||
|
||||
chmod(param->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
} else {
|
||||
/* Give the socket a name. */
|
||||
memset(&iname, 0, sizeof(struct sockaddr_in));
|
||||
iname.sin_family = AF_INET;
|
||||
iname.sin_port = htons (param->port);
|
||||
iname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (bind(sock, (struct sockaddr *) &iname, sizeof (iname)) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int connect_comm(int conn_num, comm_param *param)
|
||||
{
|
||||
struct sockaddr_un lname;
|
||||
struct sockaddr_in iname;
|
||||
struct hostent *hostinfo;
|
||||
size_t size;
|
||||
|
||||
int attempt;
|
||||
int max_attempt;
|
||||
int not_connected;
|
||||
|
||||
attempt = 0;
|
||||
if (param->wfc)
|
||||
max_attempt = param->wfc / 10;
|
||||
else
|
||||
max_attempt = 0;
|
||||
|
||||
if (param->type == COMM_TYPE_LOCAL) {
|
||||
memset(&lname, 0, sizeof(struct sockaddr_un));
|
||||
lname.sun_family = AF_LOCAL;
|
||||
strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
|
||||
lname.sun_path[sizeof(lname.sun_path) - 1] = '\0';
|
||||
|
||||
size = (offsetof(struct sockaddr_un, sun_path)) + strlen(lname.sun_path) + 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
not_connected = connect(conn_num, (struct sockaddr *) &lname, size);
|
||||
if (!not_connected)
|
||||
break;
|
||||
if (attempt >= max_attempt)
|
||||
return -1;
|
||||
attempt++;
|
||||
usleep(10000);
|
||||
}
|
||||
} else {
|
||||
memset(&iname, 0, sizeof(struct sockaddr_in));
|
||||
iname.sin_family = AF_INET;
|
||||
iname.sin_port = htons(param->port);
|
||||
hostinfo = gethostbyname(param->name);
|
||||
if (hostinfo == NULL)
|
||||
return -1;
|
||||
iname.sin_addr = *(struct in_addr *)hostinfo->h_addr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
not_connected = connect(conn_num, (struct sockaddr *) &iname, sizeof(struct sockaddr_in));
|
||||
if (!not_connected)
|
||||
break;
|
||||
if (attempt >= max_attempt)
|
||||
return -1;
|
||||
attempt++;
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int listen_comm(int conn_num)
|
||||
{
|
||||
if (listen(conn_num, 1) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int accept_comm(int conn_num)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
socklen_t addr_len;
|
||||
int sock;
|
||||
|
||||
addr_len = sizeof(addr);
|
||||
|
||||
sock = accept(conn_num, &addr, &addr_len);
|
||||
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int free_comm(int conn_num)
|
||||
{
|
||||
if (shutdown(conn_num, 2))
|
||||
return -1;
|
||||
if (close(conn_num) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_ATEMPT 5
|
||||
|
||||
int read_all(int conn_num, void *data, int data_size)
|
||||
{
|
||||
int offset = 0;
|
||||
int how_much = data_size;
|
||||
int atempt = 0;
|
||||
int readed = 0;
|
||||
|
||||
while (atempt < MAX_ATEMPT && how_much > 0) {
|
||||
readed = read(conn_num, ((char *)data) + offset, how_much);
|
||||
if (readed < 0)
|
||||
return LD10K1_ERR_COMM_READ;
|
||||
offset += readed;
|
||||
how_much -= readed;
|
||||
atempt++;
|
||||
if (how_much > 0)
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
if (how_much > 0)
|
||||
return LD10K1_ERR_COMM_READ;
|
||||
else
|
||||
return data_size;
|
||||
}
|
||||
|
||||
int write_all(int conn_num, void *data, int data_size)
|
||||
{
|
||||
int offset = 0;
|
||||
int how_much = data_size;
|
||||
int atempt = 0;
|
||||
int writed = 0;
|
||||
|
||||
while (atempt < MAX_ATEMPT && how_much > 0) {
|
||||
writed = write(conn_num, ((char *)data) + offset, how_much);
|
||||
if (writed < 0)
|
||||
return LD10K1_ERR_COMM_WRITE;
|
||||
offset += writed;
|
||||
how_much -= writed;
|
||||
atempt++;
|
||||
if (how_much > 0)
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
if (how_much > 0)
|
||||
return LD10K1_ERR_COMM_WRITE;
|
||||
else
|
||||
return data_size;
|
||||
}
|
||||
|
||||
int send_request(int conn_num, int op, void *data, int data_size)
|
||||
{
|
||||
int nbytes;
|
||||
struct msg_req header;
|
||||
|
||||
header.op = op;
|
||||
header.size = data_size;
|
||||
|
||||
/* header */
|
||||
nbytes = write_all(conn_num, &header, sizeof(header));
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
if (data_size > 0) {
|
||||
/* data */
|
||||
nbytes = write_all(conn_num, data, data_size);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_response(int conn_num, int op, int err, void *data, int data_size)
|
||||
{
|
||||
int nbytes;
|
||||
struct msg_resp header;
|
||||
|
||||
header.op = op;
|
||||
header.err = err;
|
||||
header.size = data_size;
|
||||
|
||||
/* header */
|
||||
nbytes = write_all(conn_num, &header, sizeof(header));
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
if (data_size > 0) {
|
||||
/* data */
|
||||
nbytes = write_all(conn_num, data, data_size);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_msg_data(int conn_num, void *data, int data_size)
|
||||
{
|
||||
int nbytes;
|
||||
|
||||
if (data_size > 0) {
|
||||
/* data */
|
||||
nbytes = write_all(conn_num, data, data_size);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_request(int conn_num, int *op, int *data_size)
|
||||
{
|
||||
struct msg_req header;
|
||||
int nbytes;
|
||||
|
||||
nbytes = read_all(conn_num, &header, sizeof(header));
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
if (nbytes == 0) {
|
||||
*op = -1;
|
||||
*data_size = 0;
|
||||
return 0;
|
||||
}
|
||||
*op = header.op;
|
||||
*data_size = header.size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_response(int conn_num, int *op, int *data_size)
|
||||
{
|
||||
struct msg_resp header;
|
||||
int nbytes;
|
||||
|
||||
nbytes = read_all(conn_num, &header, sizeof(header));
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
if (nbytes == 0) {
|
||||
*op = -1;
|
||||
*data_size = 0;
|
||||
return 0;
|
||||
}
|
||||
*op = header.op;
|
||||
*data_size = header.size;
|
||||
if (header.err < 0)
|
||||
return header.err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_msg_data(int conn_num, void *data, int data_size)
|
||||
{
|
||||
int nbytes;
|
||||
nbytes = read_all(conn_num, data, data_size);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *receive_msg_data_malloc(int conn_num, int data_size)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
tmp = malloc(data_size);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
if (receive_msg_data(conn_num, tmp, data_size)) {
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
615
ld10k1/src/dl10k1.c
Normal file
615
ld10k1/src/dl10k1.c
Normal file
|
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* EMU10k1 dump loader
|
||||
*
|
||||
* Copyright (c) 2003,2004 by Peter Zubaj
|
||||
*
|
||||
* Hwdep usage based on sb16_csp
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* TODO - kontrola dat, ktore nahravam */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <alsa/sound/emu10k1.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <bitops.h>
|
||||
|
||||
#include "ld10k1_dump_file.h"
|
||||
|
||||
#define DL10K1_SIGNATURE "DUMP Image (dl10k1)"
|
||||
int card = 0;
|
||||
snd_hwdep_t *handle;
|
||||
const char *card_proc_id;
|
||||
|
||||
void error(const char *fmt,...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
fprintf(stderr, "Error: ");
|
||||
vfprintf(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void help(char *command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-options]\n"
|
||||
"\nAvailable options:\n"
|
||||
" -h, --help this help\n"
|
||||
" -c, --card select card number, default = 0\n"
|
||||
" -d, --dump file with dump\n"
|
||||
, command);
|
||||
}
|
||||
|
||||
int driver_set_tram_size(int tram_size)
|
||||
{
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
|
||||
error("unable to setup tram");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
if (code->gpr_map)
|
||||
free(code->gpr_map);
|
||||
if (code->tram_data_map)
|
||||
free(code->tram_data_map);
|
||||
if (code->tram_addr_map)
|
||||
free(code->tram_addr_map);
|
||||
if (code->code)
|
||||
free(code->code);
|
||||
}
|
||||
|
||||
int alloc_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
/* alloc code structure */
|
||||
code->gpr_map = NULL;
|
||||
code->tram_data_map = NULL;
|
||||
code->tram_addr_map = NULL;
|
||||
code->code = NULL;
|
||||
|
||||
code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
|
||||
if (!code->gpr_map)
|
||||
goto err;
|
||||
memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
|
||||
|
||||
code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_data_map)
|
||||
goto err;
|
||||
memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_addr_map)
|
||||
goto err;
|
||||
memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
|
||||
if (!code->code)
|
||||
goto err;
|
||||
memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
free_code_struct(code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int driver_init_dsp(int audigy)
|
||||
{
|
||||
int i;
|
||||
emu10k1_fx8010_code_t code;
|
||||
emu10k1_fx8010_control_gpr_t *ctrl;
|
||||
emu10k1_ctl_elem_id_t *ids;
|
||||
emu10k1_fx8010_pcm_t ipcm;
|
||||
unsigned int *iptr;
|
||||
|
||||
if (alloc_code_struct(&code) < 0) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get count of controls */
|
||||
code.gpr_list_control_count = 0;
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total);
|
||||
if (!ctrl) {
|
||||
error("no mem");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
code.gpr_list_control_count = code.gpr_list_control_total;
|
||||
code.gpr_list_controls = ctrl;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = 0x0;;
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
free_code_struct(&code);
|
||||
free(ctrl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* new name */
|
||||
strcpy(code.name, DL10K1_SIGNATURE);
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) * 8; i++)
|
||||
code.gpr_map[i] = 0;
|
||||
|
||||
ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total);
|
||||
if (!ids) {
|
||||
free_code_struct(&code);
|
||||
free(ctrl);
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
code.gpr_del_control_count = code.gpr_list_control_total;
|
||||
if (code.gpr_del_control_count) {
|
||||
for (i = 0; i < code.gpr_del_control_count; i++) {
|
||||
memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
|
||||
}
|
||||
}
|
||||
|
||||
free(ctrl);
|
||||
|
||||
code.gpr_del_controls = ids;
|
||||
code.gpr_list_control_count = 0;
|
||||
code.gpr_add_control_count = 0;
|
||||
code.gpr_list_control_count = 0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = ~0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
|
||||
code.tram_addr_map[i] = 0;
|
||||
code.tram_data_map[i] = 0;
|
||||
}
|
||||
|
||||
for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
|
||||
if (audigy) {
|
||||
*iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
*(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
} else {
|
||||
*iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
*(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
}
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
free_code_struct(&code);
|
||||
free(ids);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(ids);
|
||||
|
||||
/* delete tram pcm dsp part */
|
||||
if (!audigy) {
|
||||
for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
|
||||
ipcm.substream = i;
|
||||
ipcm.channels = 0;
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
|
||||
error("unable to poke code");
|
||||
free_code_struct(&code);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dump_load(int audigy, char *file_name)
|
||||
{
|
||||
struct stat dump_stat;
|
||||
void *dump_data, *ptr;
|
||||
FILE *dump_file;
|
||||
emu10k1_fx8010_control_gpr_t *ctrl = NULL;
|
||||
ld10k1_ctl_dump_t *fctrl = NULL;
|
||||
unsigned int *fgpr = NULL;
|
||||
ld10k1_tram_dump_t *ftram = NULL;
|
||||
ld10k1_instr_dump_t *finstr = NULL;
|
||||
int i, j;
|
||||
unsigned int vaddr, addr;
|
||||
int op;
|
||||
|
||||
unsigned int *iptr;
|
||||
|
||||
emu10k1_fx8010_code_t code;
|
||||
|
||||
ld10k1_dump_t *header = NULL;
|
||||
|
||||
/* first load patch to mem */
|
||||
if (stat(file_name, &dump_stat)) {
|
||||
error("unable to load patch %s", file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* minimal dump len is size of header */
|
||||
if (dump_stat.st_size < sizeof(ld10k1_dump_t)) {
|
||||
error("unable to load dump %s (wrong file size)", file_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
dump_data = malloc(dump_stat.st_size);
|
||||
if (!dump_data) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dump_file = fopen(file_name, "r");
|
||||
if (!dump_file) {
|
||||
error("unable to open file %s", file_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (fread(dump_data, dump_stat.st_size, 1, dump_file) != 1) {
|
||||
error("unable to read data from file %s", file_name);
|
||||
goto err;
|
||||
} else
|
||||
fclose(dump_file);
|
||||
|
||||
/* signature check */
|
||||
|
||||
header = (ld10k1_dump_t *)dump_data;
|
||||
if (strncmp(header->signature, "LD10K1 DUMP 001", 16) != 0) {
|
||||
error("wrong dump file %s (wrong signature)", file_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t),
|
||||
header->ctl_count, sizeof(ld10k1_ctl_dump_t),
|
||||
header->gpr_count, sizeof(unsigned int),
|
||||
header->tram_count, sizeof(ld10k1_tram_dump_t),
|
||||
header->instr_count, sizeof(ld10k1_instr_dump_t));*/
|
||||
|
||||
/*check size */
|
||||
if (sizeof(ld10k1_dump_t) +
|
||||
header->ctl_count * sizeof(ld10k1_ctl_dump_t) +
|
||||
header->gpr_count * sizeof(unsigned int) +
|
||||
header->tram_count * sizeof(ld10k1_tram_dump_t) +
|
||||
header->instr_count * sizeof(ld10k1_instr_dump_t) != dump_stat.st_size)
|
||||
goto err;
|
||||
|
||||
/* check dump type */
|
||||
if (header->dump_type == DUMP_TYPE_LIVE && audigy) {
|
||||
error("can't load dump from Live to Audigy");
|
||||
goto err1;
|
||||
} else if ((header->dump_type == DUMP_TYPE_AUDIGY_OLD ||
|
||||
header->dump_type == DUMP_TYPE_AUDIGY) &&
|
||||
!audigy) {
|
||||
error("can't load dump from Audigy to Live");
|
||||
goto err1;
|
||||
} else if (header->dump_type == DUMP_TYPE_AUDIGY_OLD) {
|
||||
error("can't load dump from Audigy (not patched drivers) to Audigy (current drivers)");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ptr = dump_data;
|
||||
ptr += sizeof(ld10k1_dump_t);
|
||||
|
||||
ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
|
||||
if (!ctrl) {
|
||||
error("no mem");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (alloc_code_struct(&code) < 0) {
|
||||
error("no mem");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
strcpy(code.name, DL10K1_SIGNATURE);
|
||||
|
||||
/* copy ctls */
|
||||
fctrl = (ld10k1_ctl_dump_t *)ptr;
|
||||
memset(ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * header->ctl_count);
|
||||
for (i = 0; i < header->ctl_count; i++) {
|
||||
strcpy(ctrl[i].id.name, fctrl[i].name);
|
||||
ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
||||
ctrl[i].id.index = fctrl[i].index;
|
||||
ctrl[i].vcount = fctrl[i].vcount;
|
||||
ctrl[i].count = fctrl[i].count;
|
||||
for (j = 0; j < 32; j++) {
|
||||
ctrl[i].gpr[j] = fctrl[i].gpr_idx[j];
|
||||
ctrl[i].value[j] = fctrl[i].value[j];
|
||||
}
|
||||
ctrl[i].min = fctrl[i].min;
|
||||
ctrl[i].max = fctrl[i].max;
|
||||
ctrl[i].translation = fctrl[i].translation;
|
||||
}
|
||||
code.gpr_add_control_count = header->ctl_count;
|
||||
code.gpr_add_controls = ctrl;
|
||||
|
||||
code.gpr_del_control_count = 0;
|
||||
code.gpr_del_controls = NULL;
|
||||
|
||||
code.gpr_list_control_count = 0;
|
||||
code.gpr_list_controls = NULL;
|
||||
|
||||
/* copy gprs */
|
||||
ptr += sizeof(ld10k1_ctl_dump_t) * header->ctl_count;
|
||||
fgpr = (unsigned int *)ptr;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < header->gpr_count; i++)
|
||||
code.gpr_map[i] = fgpr[i];
|
||||
|
||||
ptr += sizeof(unsigned int) * header->gpr_count;
|
||||
ftram = (ld10k1_tram_dump_t *)ptr;
|
||||
/* tram addr + data */
|
||||
for (i = 0; i < header->tram_count; i++) {
|
||||
addr = ftram[i].addr;
|
||||
vaddr = addr & 0xFFFFF;
|
||||
op = ftram[i].type;
|
||||
|
||||
set_bit(i, code.tram_valid);
|
||||
switch(op) {
|
||||
case DUMP_TRAM_READ:
|
||||
if (audigy)
|
||||
vaddr = vaddr | 0x2 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case DUMP_TRAM_WRITE:
|
||||
if (audigy)
|
||||
vaddr = vaddr | 0x6 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case DUMP_TRAM_NULL:
|
||||
default:
|
||||
vaddr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
code.tram_addr_map[i] = vaddr;
|
||||
code.tram_data_map[i] = ftram[i].data;
|
||||
}
|
||||
|
||||
ptr += sizeof(ld10k1_tram_dump_t) * header->tram_count;
|
||||
finstr = (ld10k1_instr_dump_t *)ptr;
|
||||
for (iptr = code.code, i = 0; i < header->instr_count; i++, iptr += 2) {
|
||||
set_bit(i, code.code_valid);
|
||||
if (finstr[i].used) {
|
||||
if (audigy) {
|
||||
*iptr = ((finstr[i].arg[2] & 0x7ff) << 12) | (finstr[i].arg[3] & 0x7ff);
|
||||
*(iptr + 1) = ((finstr[i].op & 0x0f) << 24) | ((finstr[i].arg[0] & 0x7ff) << 12) | (finstr[i].arg[1] & 0x7ff);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
*iptr = ((finstr[i].arg[2] & 0x3ff) << 10) | (finstr[i].arg[3] & 0x3ff);
|
||||
*(iptr + 1) = ((finstr[i].op & 0x0f) << 20) | ((finstr[i].arg[0] & 0x3ff) << 10) | (finstr[i].arg[1] & 0x3ff);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (audigy) {
|
||||
*iptr = ((0xcf & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
*(iptr + 1) = ((0x0f & 0x0f) << 24) | ((0xc0 & 0x7ff) << 12) | (0xc0 & 0x7ff);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
*iptr = ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
*(iptr + 1) = ((0x06 & 0x0f) << 20) | ((0x40 & 0x3ff) << 10) | (0x40 & 0x3ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header->dump_type != DUMP_TYPE_AUDIGY_OLD &&
|
||||
driver_set_tram_size(header->tram_size))
|
||||
goto err1;
|
||||
|
||||
if (driver_init_dsp(audigy))
|
||||
goto err1;
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (dump_data)
|
||||
free(dump_data);
|
||||
|
||||
if (ctrl)
|
||||
free(ctrl);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
error("wrong dump file format %s", file_name);
|
||||
err1:
|
||||
free_code_struct(&code);
|
||||
if (dump_data)
|
||||
free(dump_data);
|
||||
if (ctrl)
|
||||
free(ctrl);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int dev;
|
||||
int c;
|
||||
int err;
|
||||
int audigy;
|
||||
|
||||
int opt_help = 0;
|
||||
char *opt_dump_file = NULL;
|
||||
|
||||
char card_id[32];
|
||||
snd_ctl_t *ctl_handle;
|
||||
snd_ctl_card_info_t *card_info;
|
||||
snd_hwdep_info_t *hwdep_info;
|
||||
|
||||
char name[16];
|
||||
|
||||
snd_ctl_card_info_alloca(&card_info);
|
||||
snd_hwdep_info_alloca(&hwdep_info);
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
{"card", 1, 0, 'c'},
|
||||
{"dump", 1, 0, 'd'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
while ((c = getopt_long(argc, argv, "hc:d:",
|
||||
long_options, &option_index)) != EOF) {
|
||||
switch (c) {
|
||||
/* case 0: */
|
||||
/* break; */
|
||||
case 'h':
|
||||
opt_help = 1;
|
||||
break;
|
||||
case 'd':
|
||||
opt_dump_file = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
card = snd_card_get_index(optarg);
|
||||
if (card < 0 || card > 31) {
|
||||
error("wrong -c argument '%s'\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_help) {
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!opt_dump_file) {
|
||||
error("dump file not specified");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (getuid() != 0 )
|
||||
{
|
||||
error("You are not running dl10k1 as root.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get control handle for selected card */
|
||||
sprintf(card_id, "hw:%i", card);
|
||||
if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {
|
||||
error("control open (%s): %s", card_id, snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read control hardware info from card */
|
||||
if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {
|
||||
error("control hardware info (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) {
|
||||
error("card id (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) {
|
||||
error("not a EMU10K1/EMU10K2 based card");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 ||
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0)
|
||||
audigy = 1;
|
||||
else
|
||||
audigy = 0;
|
||||
|
||||
/* find EMU10k1 hardware dependant device and execute command */
|
||||
dev = -1;
|
||||
err = 1;
|
||||
while (1) {
|
||||
if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)
|
||||
error("hwdep next device (%s): %s", card_id, snd_strerror(err));
|
||||
if (dev < 0)
|
||||
break;
|
||||
snd_hwdep_info_set_device(hwdep_info, dev);
|
||||
if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {
|
||||
if (err != -ENOENT)
|
||||
error("control hwdep info (%s): %s", card_id, snd_strerror(err));
|
||||
continue;
|
||||
}
|
||||
if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) {
|
||||
sprintf(name, "hw:%i,%i", card, dev);
|
||||
|
||||
/* open EMU10k1 hwdep device */
|
||||
if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) {
|
||||
error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
err = dump_load(audigy, opt_dump_file);
|
||||
|
||||
snd_hwdep_close(handle);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snd_ctl_close(ctl_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
347
ld10k1/src/ld10k1.c
Normal file
347
ld10k1/src/ld10k1.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* EMU10k1 loader
|
||||
*
|
||||
* Copyright (c) 2003,2004 by Peter Zubaj
|
||||
*
|
||||
* Hwdep usage based on sb16_csp
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ld10k1.h"
|
||||
#include "ld10k1_fnc.h"
|
||||
#include "ld10k1_fnc1.h"
|
||||
|
||||
int card = 0;
|
||||
snd_hwdep_t *handle;
|
||||
char comm_pipe[256];
|
||||
FILE *comm;
|
||||
char pidpath[256];
|
||||
FILE *logfile=NULL;
|
||||
|
||||
static void vlog(const char *label, const char *fmt, va_list va)
|
||||
{
|
||||
FILE *out = stderr;
|
||||
|
||||
if (logfile)
|
||||
out = logfile;
|
||||
|
||||
if (logfile) {
|
||||
char timestr[20];
|
||||
time_t tp;
|
||||
|
||||
tp = time(NULL);
|
||||
strftime(timestr, sizeof(timestr), "%b %d %H:%M:%S",
|
||||
localtime(&tp));
|
||||
fprintf(out, "%s %s", timestr, label);
|
||||
} else
|
||||
fprintf(out, label);
|
||||
vfprintf(out, fmt, va);
|
||||
fprintf(out, "\n");
|
||||
fflush(out);
|
||||
}
|
||||
|
||||
void error(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
vlog("Error: ", fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void log(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, fmt);
|
||||
vlog("", fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static void help(char *command)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-options]\n"
|
||||
"\nAvailable options:\n"
|
||||
" -h, --help this help\n"
|
||||
" -c, --card select card number, default = 0\n"
|
||||
" -p, --pipe_name connect to this, default = /tmp/.ld10k1_port\n"
|
||||
" -n, --network listen on port\n"
|
||||
" --port port number, default = 20480\n"
|
||||
" -d --daemon start in background\n"
|
||||
" -i --pidfile print daemon process id to file, default /var/run/ld10k1.pid\n"
|
||||
" -l --logfile \n"
|
||||
" -t, --tram_size initialize tram with given size\n"
|
||||
" 0 - 0 KB\n"
|
||||
" 1 - 16 KB\n"
|
||||
" 2 - 32 KB\n"
|
||||
" 3 - 64 KB\n"
|
||||
" 4 - 128 KB\n"
|
||||
" 5 - 256 KB\n"
|
||||
" 6 - 512 KB\n"
|
||||
" 7 - 1024 KB\n"
|
||||
" 8 - 2048 KB\n"
|
||||
, command);
|
||||
}
|
||||
|
||||
static void cleanup()
|
||||
{
|
||||
if (pidpath[0])
|
||||
unlink(pidpath);
|
||||
log("Exiting daemon");
|
||||
}
|
||||
|
||||
static void term_handler(int i)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int tram_size_table[] = {0, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int dev;
|
||||
int c;
|
||||
int err;
|
||||
int audigy;
|
||||
|
||||
int opt_help = 0;
|
||||
int tram_size = 0;
|
||||
int opt_daemon = 0;
|
||||
unsigned short opt_port = 20480;
|
||||
int uses_pipe = 1;
|
||||
char logpath[255];
|
||||
|
||||
char card_id[32];
|
||||
const char *card_proc_id;
|
||||
|
||||
snd_ctl_t *ctl_handle;
|
||||
snd_ctl_card_info_t *card_info;
|
||||
snd_hwdep_info_t *hwdep_info;
|
||||
|
||||
char name[16];
|
||||
|
||||
comm_param params;
|
||||
|
||||
int option_index;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
{"card", 1, 0, 'c'},
|
||||
{"pipe_name", 1, 0, 'p'},
|
||||
{"network", 0, 0, 'n'},
|
||||
{"port", 1, 0, 0},
|
||||
{"daemon", 0, 0, 'd'},
|
||||
{"tram_size", 1, 0, 't'},
|
||||
{"pidfile", 1, 0, 'i'},
|
||||
{"logfile", 1, 0, 'l'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
snd_ctl_card_info_alloca(&card_info);
|
||||
snd_hwdep_info_alloca(&hwdep_info);
|
||||
|
||||
strcpy(comm_pipe,"/tmp/.ld10k1_port");
|
||||
strcpy(pidpath, "/var/run/ld10k1.pid");
|
||||
memset(logpath, 0, sizeof(logpath));
|
||||
|
||||
option_index = 0;
|
||||
while ((c = getopt_long(argc, argv, "hc:p:t:ndl:i:",
|
||||
long_options, &option_index)) != EOF) {
|
||||
switch (c) {
|
||||
case 0:
|
||||
if (strcmp(long_options[option_index].name, "port") == 0) {
|
||||
opt_port = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
opt_help = 1;
|
||||
break;
|
||||
case 'c':
|
||||
card = snd_card_get_index(optarg);
|
||||
if (card < 0 || card > 31) {
|
||||
error ("wrong -c argument '%s'\n", optarg);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
uses_pipe = 1;
|
||||
strncpy(comm_pipe, optarg, sizeof(comm_pipe) - 1);
|
||||
comm_pipe[sizeof(comm_pipe) - 1] = '\0';
|
||||
break;
|
||||
case 'n':
|
||||
uses_pipe = 0;
|
||||
break;
|
||||
case 'd':
|
||||
opt_daemon = 1;
|
||||
break;
|
||||
case 't':
|
||||
tram_size = atoi(optarg);
|
||||
if (tram_size < 0)
|
||||
tram_size = 0;
|
||||
else if (tram_size > 8)
|
||||
tram_size = 8;
|
||||
tram_size = tram_size_table[tram_size];
|
||||
break;
|
||||
case 'i':
|
||||
strncpy(pidpath, optarg, sizeof(pidpath) - 1);
|
||||
pidpath[sizeof(pidpath) - 1] = '\0';
|
||||
break;
|
||||
case 'l':
|
||||
strncpy(logpath, optarg, sizeof(logpath) - 1);
|
||||
logpath[sizeof(logpath) - 1] = '\0';
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_help) {
|
||||
help(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getuid() != 0 ) {
|
||||
error("You are not running ld10k1 as root.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (logpath[0])
|
||||
logfile = fopen(logpath, "at");
|
||||
|
||||
if (opt_daemon) {
|
||||
FILE *pidfile;
|
||||
|
||||
if (daemon(0, 0) < 0) {
|
||||
error("Unable to run as daemon.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pidfile = fopen(pidpath, "wt");
|
||||
if (!pidfile) {
|
||||
log("%s: pidfile (%s)\n", strerror(errno), pidpath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(pidfile, "%d\n", getpid());
|
||||
fflush(pidfile);
|
||||
fclose(pidfile);
|
||||
|
||||
atexit(cleanup);
|
||||
signal(SIGTERM, term_handler);
|
||||
|
||||
if (logfile) {
|
||||
dup2(fileno(logfile), fileno(stderr));
|
||||
dup2(fileno(logfile), fileno(stdout));
|
||||
}
|
||||
|
||||
log("Starting daemon");
|
||||
}
|
||||
|
||||
params.type = uses_pipe ? COMM_TYPE_LOCAL : COMM_TYPE_IP;
|
||||
params.name = comm_pipe;
|
||||
params.server = 1;
|
||||
params.port = opt_port;
|
||||
params.wfc = 0;
|
||||
|
||||
/* Get control handle for selected card */
|
||||
sprintf(card_id, "hw:%i", card);
|
||||
if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {
|
||||
error("control open (%s): %s", card_id, snd_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read control hardware info from card */
|
||||
if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {
|
||||
error("control hardware info (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!(card_proc_id = snd_ctl_card_info_get_id (card_info))) {
|
||||
error("card id (%s): %s", card_id, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* EMU10k1/EMU10k2 chip is present only on SB Live, Audigy, Audigy 2, E-mu APS cards */
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "EMU10K1") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") != 0 &&
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "E-mu APS") != 0) {
|
||||
error("not a EMU10K1/EMU10K2 based card");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy") == 0 ||
|
||||
strcmp(snd_ctl_card_info_get_driver(card_info), "Audigy2") == 0)
|
||||
audigy = 1;
|
||||
else
|
||||
audigy = 0;
|
||||
|
||||
/* find EMU10k1 hardware dependant device and execute command */
|
||||
dev = -1;
|
||||
err = 1;
|
||||
while (1) {
|
||||
if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)
|
||||
error("hwdep next device (%s): %s", card_id, snd_strerror(err));
|
||||
if (dev < 0)
|
||||
break;
|
||||
snd_hwdep_info_set_device(hwdep_info, dev);
|
||||
if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {
|
||||
if (err != -ENOENT)
|
||||
error("control hwdep info (%s): %s", card_id, snd_strerror(err));
|
||||
continue;
|
||||
}
|
||||
if (snd_hwdep_info_get_iface(hwdep_info) == SND_HWDEP_IFACE_EMU10K1) {
|
||||
sprintf(name, "hw:%i,%i", card, dev);
|
||||
|
||||
/* open EMU10k1 hwdep device */
|
||||
if ((err = snd_hwdep_open(&handle, name, O_WRONLY)) < 0) {
|
||||
error("EMU10k1 open (%i-%i): %s", card, dev, snd_strerror(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (1)
|
||||
if (main_loop(¶ms, audigy, card_proc_id, tram_size, ctl_handle)) {
|
||||
error("error in main loop");
|
||||
break;
|
||||
}
|
||||
|
||||
snd_hwdep_close(handle);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snd_ctl_close(ctl_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
292
ld10k1/src/ld10k1.h
Normal file
292
ld10k1/src/ld10k1.h
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_H
|
||||
#define __LD10K1_H
|
||||
|
||||
#define MAX_CONST_COUNT 0x220
|
||||
#define MAX_GPR_COUNT 0x200
|
||||
#define MAX_TRAM_COUNT 0x100
|
||||
|
||||
/* instructions */
|
||||
typedef struct {
|
||||
unsigned int used: 1,
|
||||
modified: 1;
|
||||
unsigned int op_code;
|
||||
unsigned int arg[4];
|
||||
} ld10k1_instr_t;
|
||||
|
||||
/* tram */
|
||||
typedef struct {
|
||||
unsigned int used: 1,
|
||||
type: 2,
|
||||
req_pos: 2,
|
||||
pos: 2;
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
int acc_count;
|
||||
} ld10k1_tram_grp_t;
|
||||
|
||||
#define TRAM_OP_NULL 0
|
||||
#define TRAM_OP_READ 1
|
||||
#define TRAM_OP_WRITE 2
|
||||
|
||||
typedef struct {
|
||||
unsigned int used: 1,
|
||||
modified: 1;
|
||||
unsigned int op;
|
||||
unsigned int addr_val;
|
||||
unsigned int data_val;
|
||||
} ld10k1_tram_hwacc_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int used: 1,
|
||||
type: 2;
|
||||
unsigned int offset;
|
||||
unsigned int hwacc;
|
||||
unsigned int grp;
|
||||
} ld10k1_tram_acc_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int size;
|
||||
unsigned int max_hwacc;
|
||||
ld10k1_tram_hwacc_t *hwacc;
|
||||
unsigned int used_hwacc;
|
||||
} ld10k1_tram_t;
|
||||
|
||||
#define MAX_CONN_PER_POINT 15
|
||||
#define MAX_INSTR_PER_POINT 7
|
||||
|
||||
#define INSERT_BEFORE_OWNER 0
|
||||
#define INSERT_AFTER_OWNER 1
|
||||
|
||||
typedef struct ld10k1_conn_point_tag
|
||||
{
|
||||
struct ld10k1_conn_point_tag *next;
|
||||
|
||||
int id;
|
||||
int con_count; /* count of io connected to this point */
|
||||
unsigned int con_gpr_idx;
|
||||
int type[MAX_CONN_PER_POINT];
|
||||
struct ld10k1_patch_tag *patch[MAX_CONN_PER_POINT];
|
||||
int io[MAX_CONN_PER_POINT];
|
||||
unsigned int out_gpr_idx[MAX_CONN_PER_POINT];
|
||||
|
||||
int simple;
|
||||
|
||||
int reserved_gpr;
|
||||
int reserved_instr;
|
||||
|
||||
struct ld10k1_patch_tag *owner;
|
||||
int position;
|
||||
|
||||
unsigned int out_instr_offset;
|
||||
ld10k1_instr_t out_instr[MAX_INSTR_PER_POINT];
|
||||
} ld10k1_conn_point_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
ld10k1_conn_point_t *point;
|
||||
} ld10k1_p_in_out_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int gpr_idx;
|
||||
unsigned int const_val;
|
||||
} ld10k1_p_const_sta_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int gpr_idx;
|
||||
} ld10k1_p_dyn_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int reg_idx;
|
||||
unsigned int gpr_idx;
|
||||
} ld10k1_p_hw_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int grp_type;
|
||||
unsigned int grp_size;
|
||||
unsigned int grp_pos;
|
||||
unsigned int grp_idx;
|
||||
} ld10k1_p_tram_grp_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int acc_type;
|
||||
unsigned int acc_offset;
|
||||
unsigned int acc_idx;
|
||||
unsigned int grp;
|
||||
} ld10k1_p_tram_acc_t;
|
||||
|
||||
typedef struct {
|
||||
char name[44];
|
||||
int index;
|
||||
int want_index;
|
||||
unsigned int vcount; /* count of GPR (1..32) */
|
||||
unsigned int count; /* count of GPR (1..32) */
|
||||
unsigned int gpr_idx[32]; /* GPR number(s) */
|
||||
unsigned int value[32];
|
||||
unsigned int min; /* minimum range */
|
||||
unsigned int max; /* maximum range */
|
||||
unsigned int translation; /* typ - 0 - bool, num 1 - enum */
|
||||
} ld10k1_ctl_t;
|
||||
|
||||
typedef struct ld10k1_ctl_list_item_tag {
|
||||
struct ld10k1_ctl_list_item_tag *next;
|
||||
ld10k1_ctl_t ctl;
|
||||
} ld10k1_ctl_list_item_t;
|
||||
|
||||
typedef struct ld10k1_patch_tag {
|
||||
char *patch_name;
|
||||
int order;
|
||||
int id;
|
||||
|
||||
unsigned int in_count;
|
||||
ld10k1_p_in_out_t *ins;
|
||||
|
||||
unsigned int out_count;
|
||||
ld10k1_p_in_out_t *outs;
|
||||
|
||||
unsigned int const_count;
|
||||
ld10k1_p_const_sta_t *consts;
|
||||
|
||||
unsigned int sta_count;
|
||||
ld10k1_p_const_sta_t *stas;
|
||||
|
||||
unsigned int dyn_count;
|
||||
ld10k1_p_dyn_t *dyns;
|
||||
|
||||
unsigned int hw_count;
|
||||
ld10k1_p_hw_t *hws;
|
||||
|
||||
unsigned int tram_count;
|
||||
ld10k1_p_tram_grp_t *tram_grp;
|
||||
|
||||
unsigned int tram_acc_count;
|
||||
ld10k1_p_tram_acc_t *tram_acc;
|
||||
|
||||
unsigned int ctl_count;
|
||||
ld10k1_ctl_t *ctl;
|
||||
|
||||
unsigned int instr_count;
|
||||
unsigned int instr_offset;
|
||||
ld10k1_instr_t *instr;
|
||||
} ld10k1_patch_t;
|
||||
|
||||
#define EMU10K1_PATCH_MAX 128
|
||||
|
||||
typedef struct {
|
||||
unsigned int gpr_idx;
|
||||
unsigned int const_val;
|
||||
unsigned int hw;
|
||||
unsigned int ref;
|
||||
unsigned int used: 1;
|
||||
} ld10k1_dsp_const_t;
|
||||
|
||||
#define GPR_USAGE_NONE 0
|
||||
#define GPR_USAGE_NORMAL 1
|
||||
#define GPR_USAGE_CONST 2
|
||||
#define GPR_USAGE_DYNAMIC 3
|
||||
|
||||
typedef struct {
|
||||
unsigned int gpr_usage;
|
||||
unsigned int val;
|
||||
unsigned int ref;
|
||||
unsigned int modified: 1,
|
||||
used: 1;
|
||||
} ld10k1_dsp_gpr_t;
|
||||
|
||||
/* reserved ctls - for example AC97 */
|
||||
|
||||
typedef struct {
|
||||
char name[44];
|
||||
unsigned int index;
|
||||
} ld10k1_reserved_ctl_t;
|
||||
|
||||
typedef struct ld10k1_reserved_ctl_list_item_tag {
|
||||
struct ld10k1_reserved_ctl_list_item_tag *next;
|
||||
ld10k1_reserved_ctl_t res_ctl;
|
||||
} ld10k1_reserved_ctl_list_item_t;
|
||||
|
||||
typedef struct {
|
||||
int audigy;
|
||||
const char *card_id;
|
||||
|
||||
/* registers */
|
||||
unsigned int fx_count;
|
||||
ld10k1_p_in_out_t fxs[0x40];
|
||||
|
||||
unsigned int in_count;
|
||||
ld10k1_p_in_out_t ins[0x20];
|
||||
|
||||
unsigned int out_count;
|
||||
ld10k1_p_in_out_t outs[0x40];
|
||||
|
||||
unsigned int consts_max_count;
|
||||
ld10k1_dsp_const_t consts[MAX_CONST_COUNT];
|
||||
|
||||
unsigned int regs_max_count;
|
||||
ld10k1_dsp_gpr_t regs[MAX_GPR_COUNT];
|
||||
|
||||
/* instructions */
|
||||
unsigned int instr_count;
|
||||
ld10k1_instr_t instr[1024];
|
||||
|
||||
unsigned int instr_free;
|
||||
|
||||
/* internal tram */
|
||||
ld10k1_tram_t i_tram;
|
||||
|
||||
/* external tram */
|
||||
ld10k1_tram_t e_tram;
|
||||
|
||||
unsigned int max_tram_grp;
|
||||
ld10k1_tram_grp_t tram_grp[MAX_TRAM_COUNT];
|
||||
|
||||
unsigned int max_tram_acc;
|
||||
ld10k1_tram_acc_t tram_acc[MAX_TRAM_COUNT];
|
||||
|
||||
unsigned int max_itram_hwacc;
|
||||
ld10k1_tram_hwacc_t itram_hwacc[0xC0];
|
||||
unsigned int max_etram_hwacc;
|
||||
ld10k1_tram_hwacc_t etram_hwacc[0x40];
|
||||
|
||||
unsigned int patch_count;
|
||||
ld10k1_patch_t *patch_ptr[EMU10K1_PATCH_MAX];
|
||||
unsigned int patch_order[EMU10K1_PATCH_MAX];
|
||||
|
||||
unsigned short patch_id_gens[EMU10K1_PATCH_MAX];
|
||||
|
||||
ld10k1_ctl_list_item_t *add_ctl_list;
|
||||
int add_list_count;
|
||||
|
||||
ld10k1_ctl_list_item_t *del_ctl_list;
|
||||
int del_list_count;
|
||||
|
||||
ld10k1_ctl_list_item_t *ctl_list;
|
||||
int ctl_list_count;
|
||||
|
||||
ld10k1_reserved_ctl_list_item_t *reserved_ctl_list;
|
||||
|
||||
ld10k1_conn_point_t *point_list;
|
||||
} ld10k1_dsp_mgr_t;
|
||||
|
||||
void error(const char *fmt,...);
|
||||
#endif /* __LD10K1_H */
|
||||
667
ld10k1/src/ld10k1_debug.c
Normal file
667
ld10k1/src/ld10k1_debug.c
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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;
|
||||
}
|
||||
30
ld10k1/src/ld10k1_debug.h
Normal file
30
ld10k1/src/ld10k1_debug.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* EMU10k1 loader
|
||||
*
|
||||
* Copyright (c) 2003 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;
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_DEBUG_H
|
||||
#define __LD10K1_DEBUG_H
|
||||
|
||||
typedef struct {
|
||||
int what;
|
||||
} ld10k1_fnc_debug_t;
|
||||
|
||||
int ld10k1_fnc_debug(int data_conn, int op, int size);
|
||||
|
||||
#endif /* __LD10K1_DEBUG_H */
|
||||
541
ld10k1/src/ld10k1_driver.c
Normal file
541
ld10k1/src/ld10k1_driver.c
Normal file
|
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <alsa/sound/emu10k1.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "bitops.h"
|
||||
#include "ld10k1.h"
|
||||
#include "ld10k1_driver.h"
|
||||
#include "ld10k1_error.h"
|
||||
#include "ld10k1_fnc.h"
|
||||
#include "ld10k1_fnc_int.h"
|
||||
|
||||
//#define DEBUG_DRIVER 1
|
||||
|
||||
extern snd_hwdep_t *handle;
|
||||
|
||||
void ld10k1_syntetize_instr(int audigy, int op, int arg1, int arg2, int arg3, int arg4, unsigned int *out)
|
||||
{
|
||||
if (audigy) {
|
||||
*out = ((arg3 & 0x7ff) << 12) | (arg4 & 0x7ff);
|
||||
*(out + 1) = ((op & 0x0f) << 24) | ((arg1 & 0x7ff) << 12) | (arg2 & 0x7ff);
|
||||
} else {
|
||||
*out = ((arg3 & 0x3ff) << 10) | (arg4 & 0x3ff);
|
||||
*(out + 1) = ((op & 0x0f) << 20) | ((arg1 & 0x3ff) << 10) | (arg2 & 0x3ff);
|
||||
}
|
||||
}
|
||||
|
||||
void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
|
||||
void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code);
|
||||
|
||||
/* outputs what must be initialized on audigy */
|
||||
static int audigy_must_init_output[] = {
|
||||
0x68, 0,
|
||||
0x69, 0,
|
||||
0x6a, 0,
|
||||
0x6b, 0,
|
||||
0x6e, 0,
|
||||
0x6f, 0,
|
||||
-1};
|
||||
|
||||
#define LD10K1_SIGNATURE "LD10K1 ver. " VERSION " managed DSP code"
|
||||
|
||||
void ld10k1_free_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
if (code->gpr_map)
|
||||
free(code->gpr_map);
|
||||
if (code->tram_data_map)
|
||||
free(code->tram_data_map);
|
||||
if (code->tram_addr_map)
|
||||
free(code->tram_addr_map);
|
||||
if (code->code)
|
||||
free(code->code);
|
||||
}
|
||||
|
||||
int ld10k1_alloc_code_struct(emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
/* alloc code structure */
|
||||
code->gpr_map = NULL;
|
||||
code->tram_data_map = NULL;
|
||||
code->tram_addr_map = NULL;
|
||||
code->code = NULL;
|
||||
|
||||
code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
|
||||
if (!code->gpr_map)
|
||||
goto err;
|
||||
memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
|
||||
|
||||
code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_data_map)
|
||||
goto err;
|
||||
memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
||||
if (!code->tram_addr_map)
|
||||
goto err;
|
||||
memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
|
||||
|
||||
code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
|
||||
if (!code->code)
|
||||
goto err;
|
||||
memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
ld10k1_free_code_struct(code);
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr)
|
||||
{
|
||||
emu10k1_fx8010_code_t code;
|
||||
emu10k1_fx8010_control_gpr_t *add_ctrl;
|
||||
emu10k1_ctl_elem_id_t *del_ids;
|
||||
|
||||
ld10k1_ctl_list_item_t *item;
|
||||
unsigned int i, j;
|
||||
int max;
|
||||
int modified;
|
||||
unsigned int addr;
|
||||
unsigned int vaddr;
|
||||
unsigned int op;
|
||||
unsigned int idx_offset;
|
||||
unsigned int *iptr;
|
||||
ld10k1_ctl_t gctl;
|
||||
|
||||
int err;
|
||||
|
||||
if ((err = ld10k1_alloc_code_struct(&code)) < 0)
|
||||
return err;
|
||||
|
||||
/* new name */
|
||||
strcpy(code.name, LD10K1_SIGNATURE);
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = 0;
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = 0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = 0;
|
||||
|
||||
/* registers */
|
||||
for (i = 0; i < dsp_mgr->regs_max_count; i++)
|
||||
if (dsp_mgr->regs[i].modified) {
|
||||
set_bit(i, code.gpr_valid);
|
||||
code.gpr_map[i] = dsp_mgr->regs[i].val;
|
||||
}
|
||||
|
||||
/* tram addr + data */
|
||||
for (j = 0; j < 2; j++) {
|
||||
max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
|
||||
for (i = 0; i < max; i++) {
|
||||
modified = (j == 0 ? dsp_mgr->itram_hwacc[i].modified : dsp_mgr->etram_hwacc[i].modified);
|
||||
if (modified) {
|
||||
addr = (j == 0 ? dsp_mgr->itram_hwacc[i].addr_val : dsp_mgr->etram_hwacc[i].addr_val);
|
||||
vaddr = addr & 0xFFFFF;
|
||||
idx_offset = (j == 0 ? 0 : dsp_mgr->max_itram_hwacc);
|
||||
op = (j == 0 ? dsp_mgr->itram_hwacc[i].op : dsp_mgr->etram_hwacc[i].op);
|
||||
|
||||
set_bit(i + idx_offset, code.tram_valid);
|
||||
switch(op) {
|
||||
case TRAM_OP_READ:
|
||||
if (dsp_mgr->audigy)
|
||||
vaddr = vaddr | 0x2 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case TRAM_OP_WRITE:
|
||||
if (dsp_mgr->audigy)
|
||||
vaddr = vaddr | 0x6 << 20;
|
||||
else
|
||||
vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
|
||||
break;
|
||||
case TRAM_OP_NULL:
|
||||
default:
|
||||
vaddr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
code.tram_addr_map[i + idx_offset] = vaddr;
|
||||
code.tram_data_map[i + idx_offset] = (j == 0 ? dsp_mgr->itram_hwacc[i].data_val : dsp_mgr->etram_hwacc[i].data_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* controls to add */
|
||||
if (dsp_mgr->add_list_count > 0) {
|
||||
add_ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count);
|
||||
memset(add_ctrl, 0, sizeof(emu10k1_fx8010_control_gpr_t) * dsp_mgr->add_list_count);
|
||||
for (i = 0, item = dsp_mgr->add_ctl_list; item != NULL; item = item->next, i++) {
|
||||
strcpy(add_ctrl[i].id.name, item->ctl.name);
|
||||
add_ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
||||
add_ctrl[i].id.index = item->ctl.index;
|
||||
add_ctrl[i].vcount = item->ctl.vcount;
|
||||
add_ctrl[i].count = item->ctl.count;
|
||||
for (j = 0; j < 32; j++) {
|
||||
add_ctrl[i].gpr[j] = item->ctl.gpr_idx[j];
|
||||
add_ctrl[i].value[j] = item->ctl.value[j];
|
||||
}
|
||||
add_ctrl[i].min = item->ctl.min;
|
||||
add_ctrl[i].max = item->ctl.max;
|
||||
add_ctrl[i].translation = item->ctl.translation;
|
||||
}
|
||||
} else
|
||||
add_ctrl = NULL;
|
||||
|
||||
code.gpr_add_control_count = dsp_mgr->add_list_count;
|
||||
code.gpr_add_controls = add_ctrl;
|
||||
|
||||
/* controls to del */
|
||||
if (dsp_mgr->del_list_count > 0) {
|
||||
del_ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count);
|
||||
memset(del_ids, 0, sizeof(emu10k1_ctl_elem_id_t) * dsp_mgr->del_list_count);
|
||||
for (i = 0, item = dsp_mgr->del_ctl_list; item != NULL; item = item->next, i++) {
|
||||
strcpy(del_ids[i].name, item->ctl.name);
|
||||
del_ids[i].iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
||||
del_ids[i].index = item->ctl.index;
|
||||
}
|
||||
} else
|
||||
del_ids = NULL;
|
||||
|
||||
code.gpr_del_control_count = dsp_mgr->del_list_count;
|
||||
code.gpr_del_controls = del_ids;
|
||||
|
||||
code.gpr_list_control_count = 0;
|
||||
|
||||
for (iptr = code.code, i = 0; i < dsp_mgr->instr_count; i++, iptr += 2) {
|
||||
if (dsp_mgr->instr[i].modified) {
|
||||
set_bit(i, code.code_valid);
|
||||
if (dsp_mgr->instr[i].used) {
|
||||
if (dsp_mgr->audigy) {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
dsp_mgr->instr[i].op_code,
|
||||
dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
dsp_mgr->instr[i].op_code,
|
||||
dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dsp_mgr->audigy) {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
0x0f,
|
||||
0xc0, 0xc0, 0xcf, 0xc0, iptr);
|
||||
} else {
|
||||
if (i < 0x200) {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
0x06,
|
||||
0x40, 0x40, 0x40, 0x40, iptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check initialization of i2s outputs on audigy */
|
||||
if (dsp_mgr->audigy)
|
||||
ld10k1_check_must_init_output(dsp_mgr, &code);
|
||||
|
||||
|
||||
#ifndef DEBUG_DRIVER
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
ld10k1_free_code_struct(&code);
|
||||
if (add_ctrl)
|
||||
free(add_ctrl);
|
||||
if (del_ids)
|
||||
free(del_ids);
|
||||
return LD10K1_ERR_DRIVER_CODE_POKE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* update state */
|
||||
for (item = dsp_mgr->del_ctl_list; item != NULL; item = item->next) {
|
||||
strcpy(gctl.name, item->ctl.name);
|
||||
ld10k1_del_control_from_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &gctl);
|
||||
}
|
||||
|
||||
ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count);
|
||||
|
||||
for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next)
|
||||
ld10k1_add_control_to_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &(item->ctl));
|
||||
|
||||
ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count);
|
||||
|
||||
for (i = 0; i < dsp_mgr->regs_max_count; i++)
|
||||
dsp_mgr->regs[i].modified = 0;
|
||||
|
||||
for (i = 0; i < dsp_mgr->instr_count; i++)
|
||||
dsp_mgr->instr[i].modified = 0;
|
||||
|
||||
for (j = 0; j < 2; j++) {
|
||||
max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
|
||||
for (i = 0; i < max; i++) {
|
||||
if (j == 0)
|
||||
dsp_mgr->itram_hwacc[i].modified = 0;
|
||||
else
|
||||
dsp_mgr->etram_hwacc[i].modified = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ld10k1_free_code_struct(&code);
|
||||
|
||||
if (add_ctrl)
|
||||
free(add_ctrl);
|
||||
if (del_ids)
|
||||
free(del_ids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size)
|
||||
{
|
||||
emu10k1_fx8010_info_t info;
|
||||
int i;
|
||||
emu10k1_fx8010_code_t code;
|
||||
emu10k1_fx8010_control_gpr_t *ctrl;
|
||||
emu10k1_ctl_elem_id_t *ids;
|
||||
emu10k1_fx8010_pcm_t ipcm;
|
||||
|
||||
unsigned int *iptr;
|
||||
|
||||
int err;
|
||||
|
||||
if ((err = ld10k1_alloc_code_struct(&code)) < 0)
|
||||
return err;
|
||||
|
||||
/* setup tram size */
|
||||
if (tram_size >= 0 && snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
|
||||
error("unable to setup tram");
|
||||
if (dsp_mgr->audigy)
|
||||
error("You are probably user of audigy, audigy 2 and you not aplyed patch to enable tram");
|
||||
/* this is not fatal, but do not use tram */
|
||||
dsp_mgr->i_tram.size = 0;
|
||||
dsp_mgr->e_tram.size = 0;
|
||||
} else {
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_INFO, &info) < 0) {
|
||||
error("unable to get info ");
|
||||
ld10k1_free_code_struct(&code);
|
||||
return LD10K1_ERR_DRIVER_INFO;
|
||||
}
|
||||
|
||||
dsp_mgr->i_tram.size = info.internal_tram_size;
|
||||
dsp_mgr->e_tram.size = info.external_tram_size;
|
||||
}
|
||||
|
||||
/* get count of controls */
|
||||
code.gpr_list_control_count = 0;
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
ld10k1_free_code_struct(&code);
|
||||
return LD10K1_ERR_DRIVER_CODE_PEEK;
|
||||
}
|
||||
|
||||
ctrl = (emu10k1_fx8010_control_gpr_t *)malloc(sizeof(emu10k1_fx8010_control_gpr_t) * code.gpr_list_control_total);
|
||||
if (!ctrl) {
|
||||
ld10k1_free_code_struct(&code);
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
code.gpr_list_control_count = code.gpr_list_control_total;
|
||||
code.gpr_list_controls = ctrl;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = 0x0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = 0x0;;
|
||||
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
||||
error("unable to peek code");
|
||||
ld10k1_free_code_struct(&code);
|
||||
free(ctrl);
|
||||
return LD10K1_ERR_DRIVER_CODE_PEEK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* new name */
|
||||
strcpy(code.name, LD10K1_SIGNATURE);
|
||||
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
||||
code.gpr_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.gpr_valid) * 8; i++) {
|
||||
code.gpr_map[i] = 0;
|
||||
}
|
||||
|
||||
ids = (emu10k1_ctl_elem_id_t *)malloc(sizeof(emu10k1_ctl_elem_id_t) * code.gpr_list_control_total);
|
||||
if (!ids) {
|
||||
ld10k1_free_code_struct(&code);
|
||||
free(ctrl);
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
code.gpr_del_control_count = code.gpr_list_control_total;
|
||||
if (code.gpr_del_control_count) {
|
||||
for (i = 0; i < code.gpr_del_control_count; i++) {
|
||||
memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
|
||||
}
|
||||
}
|
||||
|
||||
free(ctrl);
|
||||
|
||||
code.gpr_del_controls = ids;
|
||||
code.gpr_list_control_count = 0;
|
||||
code.gpr_add_control_count = 0;
|
||||
code.gpr_list_control_count = 0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
||||
code.tram_valid[i] = ~0;
|
||||
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
||||
code.code_valid[i] = ~0;
|
||||
|
||||
for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
|
||||
code.tram_addr_map[i] = 0;
|
||||
code.tram_data_map[i] = 0;
|
||||
}
|
||||
|
||||
for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
|
||||
if (dsp_mgr->audigy) {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
0x0f,
|
||||
0xc0, 0xc0, 0xcf, 0xc0, iptr);
|
||||
} else {
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
0x06,
|
||||
0x40, 0x40, 0x40, 0x40, iptr);
|
||||
}
|
||||
|
||||
/* initialize i2s outputs on audigy */
|
||||
if (dsp_mgr->audigy) {
|
||||
for (iptr = code.code, i = 0; audigy_must_init_output[i] > 0; i += 2, iptr += 2)
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy, 0x00,
|
||||
audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, iptr);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_DRIVER
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
||||
error("unable to poke code");
|
||||
ld10k1_free_code_struct(&code);
|
||||
free(ids);
|
||||
return LD10K1_ERR_DRIVER_CODE_POKE;
|
||||
}
|
||||
#endif
|
||||
|
||||
free(ids);
|
||||
|
||||
/* delete tram pcm dsp part */
|
||||
if (!dsp_mgr->audigy) {
|
||||
for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
|
||||
ipcm.substream = i;
|
||||
ipcm.channels = 0;
|
||||
#ifndef DEBUG_DRIVER
|
||||
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
|
||||
error("unable to poke code");
|
||||
ld10k1_free_code_struct(&code);
|
||||
return LD10K1_ERR_DRIVER_PCM_POKE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ld10k1_free_code_struct(&code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr)
|
||||
{
|
||||
int i;
|
||||
if (dsp_mgr->audigy) {
|
||||
for (i = 0; audigy_must_init_output[i] > 0; i += 2)
|
||||
audigy_must_init_output[i + 1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
|
||||
{
|
||||
int i ;
|
||||
if (dsp_mgr->audigy) {
|
||||
for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
|
||||
if (audigy_must_init_output[i] == reg) {
|
||||
audigy_must_init_output[i + 1] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code)
|
||||
{
|
||||
int j;
|
||||
|
||||
ld10k1_init_must_init_output(dsp_mgr);
|
||||
for (j = 0; j < dsp_mgr->instr_count; j++) {
|
||||
if (dsp_mgr->instr[j].used)
|
||||
ld10k1_set_must_init_output(dsp_mgr, dsp_mgr->instr[j].arg[0]);
|
||||
}
|
||||
|
||||
int i;
|
||||
int l;
|
||||
int ioffset = dsp_mgr->instr_count - 1;
|
||||
if (dsp_mgr->audigy) {
|
||||
for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
|
||||
if (audigy_must_init_output[i + 1]) {
|
||||
/* find free instruction slot */
|
||||
for (;ioffset >= 0; ioffset--) {
|
||||
if (!dsp_mgr->instr[ioffset].used) {
|
||||
ld10k1_instr_t *instr = &(dsp_mgr->instr[ioffset]);
|
||||
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
||||
0x0,
|
||||
audigy_must_init_output[i], 0xc0, 0xc0, 0xc0,
|
||||
code->code + ioffset * 2);
|
||||
instr->op_code = 0;
|
||||
instr->arg[0] = audigy_must_init_output[i];
|
||||
for (l = 1; l < 4; l++)
|
||||
instr->arg[l] = 0xc0;
|
||||
set_bit(ioffset, code->code_valid);
|
||||
dsp_mgr->instr[ioffset].used = 1;
|
||||
ioffset--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioffset < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
ld10k1/src/ld10k1_driver.h
Normal file
28
ld10k1/src/ld10k1_driver.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_DRIVER_H
|
||||
#define __LD10K1_DRIVER_H
|
||||
|
||||
int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size);
|
||||
|
||||
#endif /* __LD10K1_DRIVER_H */
|
||||
153
ld10k1/src/ld10k1_dump.c
Normal file
153
ld10k1/src/ld10k1_dump.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "ld10k1.h"
|
||||
#include "ld10k1_dump_file.h"
|
||||
#include "ld10k1_dump.h"
|
||||
#include "ld10k1_error.h"
|
||||
|
||||
int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size)
|
||||
{
|
||||
int dump_size = 0;
|
||||
void *dump_file = NULL;
|
||||
void *ptr = NULL;
|
||||
ld10k1_dump_t *header = NULL;
|
||||
ld10k1_ctl_dump_t *ctl = NULL;
|
||||
int i, j;
|
||||
ld10k1_ctl_list_item_t *item;
|
||||
unsigned int *ival = NULL;
|
||||
ld10k1_tram_dump_t *tram = NULL;
|
||||
ld10k1_instr_dump_t *instr = NULL;
|
||||
|
||||
dump_size += sizeof(ld10k1_dump_t);
|
||||
dump_size += sizeof(ld10k1_ctl_dump_t) * dsp_mgr->ctl_list_count;
|
||||
dump_size += sizeof(unsigned int) * dsp_mgr->regs_max_count;
|
||||
dump_size += sizeof(ld10k1_tram_dump_t) * (dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc);
|
||||
dump_size += sizeof(ld10k1_instr_dump_t) * dsp_mgr->instr_count;
|
||||
|
||||
dump_file = malloc(dump_size);
|
||||
if (!dump_file)
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
|
||||
ptr = dump_file;
|
||||
header = (ld10k1_dump_t *)ptr;
|
||||
strcpy(header->signature, "LD10K1 DUMP 001");
|
||||
if (!dsp_mgr->audigy)
|
||||
header->dump_type = DUMP_TYPE_LIVE;
|
||||
else
|
||||
header->dump_type = DUMP_TYPE_AUDIGY;
|
||||
|
||||
header->tram_size = dsp_mgr->e_tram.size;
|
||||
header->ctl_count = dsp_mgr->ctl_list_count;
|
||||
header->gpr_count = dsp_mgr->regs_max_count;
|
||||
header->tram_count = dsp_mgr->max_itram_hwacc + dsp_mgr->max_etram_hwacc;
|
||||
header->instr_count = dsp_mgr->instr_count;
|
||||
|
||||
/*printf("Size header%d\n", dump_size);
|
||||
printf("Size header%d\nctc %d %d\ngpr %d %d\ntram %d %d\ninstr %d %d\n", sizeof(ld10k1_dump_t),
|
||||
header->ctl_count, sizeof(ld10k1_ctl_dump_t),
|
||||
header->gpr_count, sizeof(unsigned int),
|
||||
header->tram_count, sizeof(ld10k1_tram_dump_t),
|
||||
header->instr_count, sizeof(ld10k1_instr_dump_t));*/
|
||||
|
||||
ptr += sizeof(ld10k1_dump_t);
|
||||
/* ctls */
|
||||
for (item = dsp_mgr->ctl_list; item != NULL; item = item->next) {
|
||||
ctl = (ld10k1_ctl_dump_t *)ptr;
|
||||
strcpy(ctl->name, item->ctl.name);
|
||||
ctl->index = item->ctl.index;
|
||||
ctl->vcount = item->ctl.vcount;
|
||||
ctl->count = item->ctl.count;
|
||||
for (j = 0; j < 32; j++) {
|
||||
ctl->gpr_idx[j] = item->ctl.gpr_idx[j];
|
||||
ctl->value[j] = item->ctl.value[j];
|
||||
}
|
||||
ctl->min = item->ctl.min;
|
||||
ctl->max = item->ctl.max;
|
||||
ctl->translation = item->ctl.translation;
|
||||
|
||||
ptr += sizeof(ld10k1_ctl_dump_t);
|
||||
}
|
||||
|
||||
/* regs */
|
||||
for (i = 0; i < dsp_mgr->regs_max_count; i++) {
|
||||
ival = (unsigned int *) ptr;
|
||||
*ival = dsp_mgr->regs[i].val;
|
||||
ptr += sizeof(unsigned int);
|
||||
}
|
||||
|
||||
/* tram */
|
||||
for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) {
|
||||
tram = (ld10k1_tram_dump_t *) ptr;
|
||||
if (dsp_mgr->itram_hwacc[i].used) {
|
||||
tram->type = dsp_mgr->itram_hwacc[i].op;
|
||||
tram->addr = dsp_mgr->itram_hwacc[i].addr_val;
|
||||
tram->data = dsp_mgr->itram_hwacc[i].data_val;
|
||||
} else {
|
||||
tram->type = 0;
|
||||
tram->addr = 0;
|
||||
tram->data = 0;
|
||||
}
|
||||
ptr += sizeof(ld10k1_tram_dump_t);
|
||||
}
|
||||
|
||||
for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) {
|
||||
tram = (ld10k1_tram_dump_t *) ptr;
|
||||
if (dsp_mgr->etram_hwacc[i].used) {
|
||||
if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_READ)
|
||||
tram->type = DUMP_TRAM_READ;
|
||||
else if (dsp_mgr->etram_hwacc[i].op == TRAM_OP_WRITE)
|
||||
tram->type = DUMP_TRAM_WRITE;
|
||||
else
|
||||
tram->type = DUMP_TRAM_NULL;
|
||||
tram->addr = dsp_mgr->etram_hwacc[i].addr_val;
|
||||
tram->data = dsp_mgr->etram_hwacc[i].data_val;
|
||||
} else {
|
||||
tram->type = 0;
|
||||
tram->addr = 0;
|
||||
tram->data = 0;
|
||||
}
|
||||
ptr += sizeof(ld10k1_tram_dump_t);
|
||||
}
|
||||
|
||||
/* instr */
|
||||
for (i = 0; i < dsp_mgr->instr_count; i++) {
|
||||
instr = (ld10k1_instr_dump_t *) ptr;
|
||||
instr->used = dsp_mgr->instr[i].used;
|
||||
instr->op = dsp_mgr->instr[i].op_code;
|
||||
instr->arg[0] = dsp_mgr->instr[i].arg[0];
|
||||
instr->arg[1] = dsp_mgr->instr[i].arg[1];
|
||||
instr->arg[2] = dsp_mgr->instr[i].arg[2];
|
||||
instr->arg[3] = dsp_mgr->instr[i].arg[3];
|
||||
ptr += sizeof(ld10k1_instr_dump_t);
|
||||
}
|
||||
|
||||
*dump = dump_file;
|
||||
*size = dump_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
ld10k1/src/ld10k1_dump.h
Normal file
27
ld10k1/src/ld10k1_dump.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_DUMP_H
|
||||
#define __LD10K1_DUMP_H
|
||||
|
||||
int ld10k1_make_dump(ld10k1_dsp_mgr_t *dsp_mgr, void **dump, int *size);
|
||||
|
||||
#endif /* __LD10K1_DUMP_H */
|
||||
67
ld10k1/src/ld10k1_dump_file.h
Normal file
67
ld10k1/src/ld10k1_dump_file.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_DUMP_FILE_H
|
||||
#define __LD10K1_DUMP_FILE_H
|
||||
|
||||
#define DUMP_TYPE_LIVE 0
|
||||
#define DUMP_TYPE_AUDIGY_OLD 1
|
||||
#define DUMP_TYPE_AUDIGY 2
|
||||
|
||||
typedef struct {
|
||||
char signature[16]; /* LD10K1 DUMP 001 */
|
||||
int dump_type;
|
||||
int tram_size;
|
||||
int ctl_count;
|
||||
int gpr_count;
|
||||
int tram_count;
|
||||
int instr_count;
|
||||
} ld10k1_dump_t;
|
||||
|
||||
#define DUMP_TRAM_NULL 0
|
||||
#define DUMP_TRAM_READ 1
|
||||
#define DUMP_TRAM_WRITE 2
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
unsigned int addr;
|
||||
unsigned int data;
|
||||
} ld10k1_tram_dump_t;
|
||||
|
||||
typedef struct {
|
||||
int used;
|
||||
unsigned int op;
|
||||
unsigned int arg[4];
|
||||
} ld10k1_instr_dump_t;
|
||||
|
||||
typedef struct {
|
||||
char name[44];
|
||||
int index;
|
||||
unsigned int vcount; /* count of GPR (1..32) */
|
||||
unsigned int count; /* count of GPR (1..32) */
|
||||
unsigned int gpr_idx[32]; /* GPR number(s) */
|
||||
unsigned int value[32];
|
||||
unsigned int min; /* minimum range */
|
||||
unsigned int max; /* maximum range */
|
||||
unsigned int translation; /* typ - 0 - bool, num 1 - enum */
|
||||
} ld10k1_ctl_dump_t;
|
||||
|
||||
#endif /* __LD10K1_DUMP_FILE_H */
|
||||
2373
ld10k1/src/ld10k1_fnc.c
Normal file
2373
ld10k1/src/ld10k1_fnc.c
Normal file
File diff suppressed because it is too large
Load diff
1507
ld10k1/src/ld10k1_fnc1.c
Normal file
1507
ld10k1/src/ld10k1_fnc1.c
Normal file
File diff suppressed because it is too large
Load diff
35
ld10k1/src/ld10k1_fnc1.h
Normal file
35
ld10k1/src/ld10k1_fnc1.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_FNC1_H
|
||||
#define __LD10K1_FNC1_H
|
||||
|
||||
#include "comm.h"
|
||||
|
||||
extern ld10k1_dsp_mgr_t dsp_mgr;
|
||||
|
||||
int main_loop(comm_param *param, int audigy, const char *card_id, int tram_size, snd_ctl_t *ctlp);
|
||||
|
||||
int send_response_ok(int conn_num);
|
||||
int send_response_err(int conn_num, int err);
|
||||
int send_response_wd(int conn_num, void *data, int data_size);
|
||||
|
||||
#endif /* __LD10K1_FNC1_H */
|
||||
52
ld10k1/src/ld10k1_fnc_int.h
Normal file
52
ld10k1/src/ld10k1_fnc_int.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_FNC_INT_H
|
||||
#define __LD10K1_FNC_INT_H
|
||||
|
||||
int ld10k1_dsp_mgr_init(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
void ld10k1_dsp_mgr_init_id_gen(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
void ld10k1_dsp_mgr_free(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
|
||||
ld10k1_patch_t *ld10k1_dsp_mgr_patch_new(void);
|
||||
void ld10k1_dsp_mgr_patch_free(ld10k1_patch_t *patch);
|
||||
ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_in_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_in_out_t *ld10k1_dsp_mgr_patch_out_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_const_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_const_sta_t *ld10k1_dsp_mgr_patch_sta_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_dyn_t *ld10k1_dsp_mgr_patch_dyn_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_hw_t *ld10k1_dsp_mgr_patch_hw_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_tram_grp_t *ld10k1_dsp_mgr_patch_tram_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_p_tram_acc_t *ld10k1_dsp_mgr_patch_tram_acc_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_instr_t *ld10k1_dsp_mgr_patch_instr_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
ld10k1_ctl_t *ld10k1_dsp_mgr_patch_ctl_new(ld10k1_patch_t *patch, unsigned int count);
|
||||
char *ld10k1_dsp_mgr_name_new(char **where, const char *from);
|
||||
|
||||
int ld10k1_dsp_mgr_patch_load(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, int before, int *loaded);
|
||||
int ld10k1_patch_fnc_check_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *new_patch);
|
||||
int ld10k1_patch_fnc_del(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_patch_del_t *patch_fnc);
|
||||
int ld10k1_connection_fnc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_fnc_connection_t *connection_fnc, int *conn_id);
|
||||
|
||||
void ld10k1_del_control_from_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl);
|
||||
void ld10k1_del_all_controls_from_list(ld10k1_ctl_list_item_t **list, int *count);
|
||||
int ld10k1_add_control_to_list(ld10k1_ctl_list_item_t **list, int *count, ld10k1_ctl_t *gctl);
|
||||
|
||||
#endif /* __LD10K1_FNC_INT_H */
|
||||
97
ld10k1/src/ld10k1_mixer.c
Normal file
97
ld10k1/src/ld10k1_mixer.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "ld10k1.h"
|
||||
#include "ld10k1_mixer.h"
|
||||
#include "ld10k1_error.h"
|
||||
|
||||
int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp)
|
||||
{
|
||||
snd_ctl_elem_list_t *clist;
|
||||
int count;
|
||||
int i;
|
||||
const char *ctl_name;
|
||||
unsigned int ctl_index;
|
||||
|
||||
ld10k1_reserved_ctl_list_item_t *res_ctl;
|
||||
|
||||
dsp_mgr->reserved_ctl_list = NULL;
|
||||
|
||||
snd_ctl_elem_list_alloca(&clist);
|
||||
|
||||
if (snd_ctl_elem_list(ctlp, clist) < 0)
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
|
||||
if ((count = snd_ctl_elem_list_get_count(clist)) < 0)
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
|
||||
snd_ctl_elem_list_set_offset(clist, 0);
|
||||
|
||||
if (snd_ctl_elem_list_alloc_space(clist, count) < 0)
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
|
||||
if (snd_ctl_elem_list(ctlp, clist) < 0) {
|
||||
snd_ctl_elem_list_free_space(clist);
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
snd_ctl_elem_id_t *id;
|
||||
snd_ctl_elem_id_alloca(&id);
|
||||
snd_ctl_elem_list_get_id(clist, i, id);
|
||||
|
||||
ctl_name = snd_ctl_elem_id_get_name(id);
|
||||
ctl_index = snd_ctl_elem_id_get_index(id);
|
||||
|
||||
res_ctl = (ld10k1_reserved_ctl_list_item_t *)malloc(sizeof(ld10k1_reserved_ctl_list_item_t));
|
||||
if (!res_ctl) {
|
||||
snd_ctl_elem_list_free_space(clist);
|
||||
return LD10K1_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
res_ctl->next = dsp_mgr->reserved_ctl_list;
|
||||
dsp_mgr->reserved_ctl_list = res_ctl;
|
||||
strncpy(res_ctl->res_ctl.name, ctl_name, 43);
|
||||
res_ctl->res_ctl.name[43] = '\0';
|
||||
res_ctl->res_ctl.index = ctl_index;
|
||||
}
|
||||
|
||||
snd_ctl_elem_list_free_space(clist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr)
|
||||
{
|
||||
ld10k1_reserved_ctl_list_item_t *item;
|
||||
ld10k1_reserved_ctl_list_item_t *item1;
|
||||
|
||||
for (item = dsp_mgr->reserved_ctl_list; item != NULL;) {
|
||||
item1 = item->next;
|
||||
free(item);
|
||||
item = item1;
|
||||
}
|
||||
|
||||
dsp_mgr->reserved_ctl_list = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
28
ld10k1/src/ld10k1_mixer.h
Normal file
28
ld10k1/src/ld10k1_mixer.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_MIXER_H
|
||||
#define __LD10K1_MIXER_H
|
||||
|
||||
int ld10k1_init_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr, snd_ctl_t *ctlp);
|
||||
int ld10k1_free_reserved_ctls(ld10k1_dsp_mgr_t *dsp_mgr);
|
||||
|
||||
#endif /* __LD10K1_MIXER_H */
|
||||
481
ld10k1/src/ld10k1_tram.c
Normal file
481
ld10k1/src/ld10k1_tram.c
Normal file
|
|
@ -0,0 +1,481 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ld10k1.h"
|
||||
#include "ld10k1_fnc.h"
|
||||
#include "ld10k1_tram.h"
|
||||
#include "ld10k1_error.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res);
|
||||
int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res);
|
||||
|
||||
void ld10k1_tram_init_res(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
res->isize = dsp_mgr->i_tram.size;
|
||||
res->ifree = dsp_mgr->i_tram.size;
|
||||
res->iacc_count = dsp_mgr->i_tram.max_hwacc;
|
||||
res->iacc_free_count = dsp_mgr->i_tram.max_hwacc;
|
||||
|
||||
res->esize = dsp_mgr->e_tram.size;
|
||||
res->efree = dsp_mgr->e_tram.size;
|
||||
res->eacc_count = dsp_mgr->e_tram.max_hwacc;
|
||||
res->eacc_free_count = dsp_mgr->e_tram.max_hwacc;
|
||||
|
||||
res->grp_free = res->iacc_free_count + res->eacc_free_count;
|
||||
|
||||
res->item_count = 0;
|
||||
}
|
||||
|
||||
void ld10k1_tram_init_res_from_dsp_mgr(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
/* throught all groups */
|
||||
int i;
|
||||
for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
|
||||
if (dsp_mgr->tram_grp[i].used) {
|
||||
/* get position */
|
||||
res->grp_free--;
|
||||
switch (dsp_mgr->tram_grp[i].req_pos) {
|
||||
case TRAM_POS_NONE:
|
||||
case TRAM_POS_AUTO:
|
||||
/* add to res */
|
||||
res->items[res->item_count].grp_idx = i;
|
||||
res->items[res->item_count].grp_size = dsp_mgr->tram_grp[i].size;
|
||||
res->items[res->item_count].grp_acc_count = dsp_mgr->tram_grp[i].acc_count;
|
||||
res->items[res->item_count].res_value = 0;
|
||||
res->items[res->item_count].pos = TRAM_POS_NONE;
|
||||
res->item_count++;
|
||||
break;
|
||||
case TRAM_POS_INTERNAL:
|
||||
/* decrease resources */
|
||||
res->ifree -= dsp_mgr->tram_grp[i].size;
|
||||
res->iacc_free_count -= dsp_mgr->tram_grp[i].acc_count;
|
||||
break;
|
||||
case TRAM_POS_EXTERNAL:
|
||||
res->efree -= dsp_mgr->tram_grp[i].size;
|
||||
res->eacc_free_count -= dsp_mgr->tram_grp[i].acc_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ld10k1_tram_acc_count_from_patch(ld10k1_patch_t *patch, int grp)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
for (count = 0, i = 0; i < patch->tram_acc_count; i++)
|
||||
if (patch->tram_acc[i].grp == grp)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int ld10k1_tram_init_res_from_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch)
|
||||
{
|
||||
int i;
|
||||
int acc_count;
|
||||
|
||||
/* through all groups */
|
||||
for (i = 0; i < patch->tram_count; i++) {
|
||||
if (res->grp_free <= 0)
|
||||
return LD10K1_ERR_TRAM_FULL_GRP;
|
||||
/* get acc count */
|
||||
acc_count = ld10k1_tram_acc_count_from_patch(patch, i);
|
||||
if (acc_count <= 0)
|
||||
continue;
|
||||
/* get position */
|
||||
switch (patch->tram_grp[i].grp_pos) {
|
||||
case TRAM_POS_NONE:
|
||||
case TRAM_POS_AUTO:
|
||||
/* add to res */
|
||||
res->items[res->item_count].grp_idx = -i - 1;
|
||||
res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size;
|
||||
res->items[res->item_count].grp_acc_count = acc_count;
|
||||
res->items[res->item_count].res_value = 0;
|
||||
res->items[res->item_count].pos = TRAM_POS_NONE;
|
||||
res->item_count++;
|
||||
break;
|
||||
case TRAM_POS_INTERNAL:
|
||||
/* decrease resources */
|
||||
if (res->ifree < patch->tram_grp[i].grp_size)
|
||||
return LD10K1_ERR_ITRAM_FULL;
|
||||
if (res->iacc_free_count < acc_count)
|
||||
return LD10K1_ERR_ITRAM_FULL_ACC;
|
||||
res->ifree -= patch->tram_grp[i].grp_size;
|
||||
res->iacc_free_count -= acc_count;
|
||||
break;
|
||||
case TRAM_POS_EXTERNAL:
|
||||
/* decrease resources */
|
||||
if (res->efree < patch->tram_grp[i].grp_size)
|
||||
return LD10K1_ERR_ETRAM_FULL;
|
||||
if (res->eacc_free_count < acc_count)
|
||||
return LD10K1_ERR_ETRAM_FULL_ACC;
|
||||
res->efree -= patch->tram_grp[i].grp_size;
|
||||
res->eacc_free_count -= acc_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_init_res_from_patch_copy(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res, ld10k1_patch_t *patch)
|
||||
{
|
||||
/* throught all groups */
|
||||
int i;
|
||||
int acc_count;
|
||||
|
||||
for (i = 0; i < patch->tram_count; i++) {
|
||||
/* get acc count */
|
||||
acc_count = ld10k1_tram_acc_count_from_patch(patch, i);
|
||||
/* get position */
|
||||
if (patch->tram_grp[i].grp_pos == TRAM_POS_INTERNAL ||
|
||||
patch->tram_grp[i].grp_pos == TRAM_POS_EXTERNAL) {
|
||||
|
||||
res->items[res->item_count].grp_idx = -i - 1;
|
||||
res->items[res->item_count].grp_size = patch->tram_grp[i].grp_size;
|
||||
res->items[res->item_count].grp_acc_count = acc_count;
|
||||
res->items[res->item_count].pos = patch->tram_grp[i].grp_pos;
|
||||
res->items[res->item_count].res_value = 0;
|
||||
res->item_count++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_calc_res_value(ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
/* res_value is calculated as grp_size / acc_count */
|
||||
int i;
|
||||
for (i = 0; i < res->item_count; i++)
|
||||
res->items[i].res_value = res->items[i].grp_size / res->items[i].grp_acc_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ld10k1_tram_sort_res_compare(const void *item1, const void *item2)
|
||||
{
|
||||
ld10k1_dsp_tram_resolve_item_t *i1 = (ld10k1_dsp_tram_resolve_item_t *)item1;
|
||||
ld10k1_dsp_tram_resolve_item_t *i2 = (ld10k1_dsp_tram_resolve_item_t *)item2;
|
||||
|
||||
if (i1->res_value == i2->res_value)
|
||||
return 0;
|
||||
else if (i1->res_value > i2->res_value)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ld10k1_tram_sort_res(ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
qsort(res->items, res->item_count, sizeof(ld10k1_dsp_tram_resolve_item_t), ld10k1_tram_sort_res_compare);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_resolve_res(ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < res->item_count; i++) {
|
||||
/* first try internal tram then external tram */
|
||||
if (res->items[i].grp_size <= res->ifree &&
|
||||
res->items[i].grp_acc_count <= res->iacc_free_count) {
|
||||
/* put it into itram */
|
||||
res->ifree -= res->items[i].grp_size;
|
||||
res->iacc_free_count -= res->items[i].grp_acc_count;
|
||||
res->items[i].pos = TRAM_POS_INTERNAL;
|
||||
} else if (res->items[i].grp_size <= res->efree &&
|
||||
res->items[i].grp_acc_count <= res->eacc_free_count) {
|
||||
/* put it into etram */
|
||||
res->efree -= res->items[i].grp_size;
|
||||
res->eacc_free_count -= res->items[i].grp_acc_count;
|
||||
res->items[i].pos = TRAM_POS_EXTERNAL;
|
||||
} else
|
||||
return LD10K1_ERR_TRAM_FULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_grp_alloc(ld10k1_dsp_mgr_t *dsp_mgr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dsp_mgr->max_tram_grp; i++) {
|
||||
if (!dsp_mgr->tram_grp[i].used) {
|
||||
dsp_mgr->tram_grp[i].used = 1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return LD10K1_ERR_TRAM_FULL_GRP;
|
||||
}
|
||||
|
||||
void ld10k1_tram_grp_free(ld10k1_dsp_mgr_t *dsp_mgr, int grp)
|
||||
{
|
||||
dsp_mgr->tram_grp[grp].used = 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_acc_alloc(ld10k1_dsp_mgr_t *dsp_mgr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dsp_mgr->max_tram_acc; i++) {
|
||||
if (!dsp_mgr->tram_acc[i].used) {
|
||||
dsp_mgr->tram_acc[i].used = 1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return LD10K1_ERR_TRAM_FULL_ACC;
|
||||
}
|
||||
|
||||
void ld10k1_tram_acc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc)
|
||||
{
|
||||
dsp_mgr->tram_acc[acc].used = 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
int err;
|
||||
|
||||
ld10k1_tram_init_res(dsp_mgr, res);
|
||||
ld10k1_tram_init_res_from_dsp_mgr(dsp_mgr, res);
|
||||
|
||||
if ((err = ld10k1_tram_init_res_from_patch(dsp_mgr, res, patch)) < 0)
|
||||
return err;
|
||||
|
||||
ld10k1_tram_calc_res_value(res);
|
||||
ld10k1_tram_sort_res(res);
|
||||
|
||||
if ((err = ld10k1_tram_resolve_res(res)) < 0)
|
||||
return err;
|
||||
|
||||
ld10k1_tram_init_res_from_patch_copy(dsp_mgr, res, patch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
int i;
|
||||
int grp;
|
||||
int acc;
|
||||
|
||||
/* allocate tram grp and acc for patch */
|
||||
for (i = 0; i < patch->tram_count; i++) {
|
||||
grp = ld10k1_tram_grp_alloc(dsp_mgr);
|
||||
patch->tram_grp[i].grp_idx = grp;
|
||||
dsp_mgr->tram_grp[grp].type = patch->tram_grp[i].grp_type;
|
||||
dsp_mgr->tram_grp[grp].size = patch->tram_grp[i].grp_size;
|
||||
}
|
||||
|
||||
for (i = 0; i < res->item_count; i++) {
|
||||
if (res->items[i].grp_idx < 0) {
|
||||
res->items[i].grp_idx = patch->tram_grp[-(res->items[i].grp_idx + 1)].grp_idx;
|
||||
dsp_mgr->tram_grp[res->items[i].grp_idx].pos = TRAM_POS_NONE;
|
||||
dsp_mgr->tram_grp[res->items[i].grp_idx].acc_count = res->items[i].grp_acc_count;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < patch->tram_acc_count; i++) {
|
||||
acc = ld10k1_tram_acc_alloc(dsp_mgr);
|
||||
patch->tram_acc[i].acc_idx = acc;
|
||||
dsp_mgr->tram_acc[acc].type = patch->tram_acc[i].acc_type;
|
||||
dsp_mgr->tram_acc[acc].offset = patch->tram_acc[i].acc_offset;
|
||||
dsp_mgr->tram_acc[acc].grp = patch->tram_grp[patch->tram_acc[i].grp].grp_idx;
|
||||
}
|
||||
|
||||
ld10k1_tram_res_alloc_hwacc(dsp_mgr, res);
|
||||
ld10k1_tram_realloc_space(dsp_mgr, res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_hwacc_alloc(ld10k1_dsp_mgr_t *dsp_mgr, int external)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!external) {
|
||||
for (i = 0; i < dsp_mgr->max_itram_hwacc; i++) {
|
||||
if (!dsp_mgr->itram_hwacc[i].used) {
|
||||
dsp_mgr->itram_hwacc[i].used = 1;
|
||||
dsp_mgr->i_tram.used_hwacc++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < dsp_mgr->max_etram_hwacc; i++) {
|
||||
if (!dsp_mgr->etram_hwacc[i].used) {
|
||||
dsp_mgr->etram_hwacc[i].used = 1;
|
||||
dsp_mgr->e_tram.used_hwacc++;
|
||||
return i + dsp_mgr->max_itram_hwacc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return LD10K1_ERR_TRAM_FULL_ACC;
|
||||
}
|
||||
|
||||
void ld10k1_tram_hwacc_free(ld10k1_dsp_mgr_t *dsp_mgr, int acc)
|
||||
{
|
||||
if (acc < dsp_mgr->max_itram_hwacc) {
|
||||
dsp_mgr->itram_hwacc[acc].used = 0;
|
||||
dsp_mgr->itram_hwacc[acc].addr_val = 0;
|
||||
dsp_mgr->itram_hwacc[acc].data_val = 0;
|
||||
dsp_mgr->itram_hwacc[acc].modified = 1;
|
||||
dsp_mgr->i_tram.used_hwacc--;
|
||||
} else {
|
||||
int nacc = acc - dsp_mgr->max_itram_hwacc;
|
||||
dsp_mgr->etram_hwacc[nacc].used = 0;
|
||||
dsp_mgr->etram_hwacc[nacc].used = 0;
|
||||
dsp_mgr->etram_hwacc[nacc].addr_val = 0;
|
||||
dsp_mgr->etram_hwacc[nacc].data_val = 0;
|
||||
dsp_mgr->etram_hwacc[nacc].modified = 1;
|
||||
dsp_mgr->e_tram.used_hwacc--;
|
||||
}
|
||||
}
|
||||
|
||||
void ld10k1_tram_actualize_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int op, unsigned int addr, unsigned int data)
|
||||
{
|
||||
if (acc < dsp_mgr->max_itram_hwacc) {
|
||||
dsp_mgr->itram_hwacc[acc].op = op;
|
||||
dsp_mgr->itram_hwacc[acc].addr_val = addr;
|
||||
dsp_mgr->itram_hwacc[acc].data_val = data;
|
||||
dsp_mgr->itram_hwacc[acc].modified = 1;
|
||||
} else {
|
||||
int nacc = acc - dsp_mgr->max_itram_hwacc;
|
||||
dsp_mgr->etram_hwacc[nacc].op = op;
|
||||
dsp_mgr->etram_hwacc[nacc].addr_val = addr;
|
||||
dsp_mgr->etram_hwacc[nacc].data_val = data;
|
||||
dsp_mgr->etram_hwacc[nacc].modified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data)
|
||||
{
|
||||
int nacc;
|
||||
|
||||
if (acc < dsp_mgr->max_itram_hwacc) {
|
||||
*addr = dsp_mgr->itram_hwacc[acc].addr_val;
|
||||
*data = dsp_mgr->itram_hwacc[acc].data_val;
|
||||
} else {
|
||||
nacc = acc - dsp_mgr->max_itram_hwacc;
|
||||
*addr = dsp_mgr->etram_hwacc[nacc].addr_val;
|
||||
*data = dsp_mgr->etram_hwacc[nacc].data_val;
|
||||
}
|
||||
}
|
||||
|
||||
int ld10k1_tram_res_alloc_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
int i, j;
|
||||
int grp_idx;
|
||||
int hwacc;
|
||||
|
||||
/* free hw acc - where pos changed */
|
||||
for (i = 0; i < res->item_count; i++) {
|
||||
grp_idx = res->items[i].grp_idx;
|
||||
if (dsp_mgr->tram_grp[grp_idx].pos != TRAM_POS_NONE &&
|
||||
dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) {
|
||||
for (j = 0; j < dsp_mgr->max_tram_acc; j++)
|
||||
if (dsp_mgr->tram_acc[j].used &&
|
||||
dsp_mgr->tram_acc[j].grp == grp_idx)
|
||||
ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[j].hwacc);
|
||||
dsp_mgr->tram_grp[grp_idx].pos = TRAM_POS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* now allocate */
|
||||
for (i = 0; i < res->item_count; i++) {
|
||||
grp_idx = res->items[i].grp_idx;
|
||||
if (dsp_mgr->tram_grp[grp_idx].pos == TRAM_POS_NONE &&
|
||||
dsp_mgr->tram_grp[grp_idx].pos != res->items[i].pos) {
|
||||
dsp_mgr->tram_grp[grp_idx].pos = res->items[i].pos;
|
||||
for (j = 0; j < dsp_mgr->max_tram_acc; j++)
|
||||
if (dsp_mgr->tram_acc[j].used &&
|
||||
dsp_mgr->tram_acc[j].grp == grp_idx) {
|
||||
hwacc = ld10k1_tram_hwacc_alloc(dsp_mgr, res->items[i].pos == TRAM_POS_EXTERNAL ? 1 : 0);
|
||||
dsp_mgr->tram_acc[j].hwacc = hwacc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_realloc_space(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_dsp_tram_resolve_t *res)
|
||||
{
|
||||
int itram_size = res->isize;
|
||||
int etram_size = res->esize;
|
||||
int i;
|
||||
|
||||
/* allocate from end */
|
||||
for (i = 0; i < dsp_mgr->max_tram_grp; i++)
|
||||
if (dsp_mgr->tram_grp[i].used) {
|
||||
if (dsp_mgr->tram_grp[i].pos == TRAM_POS_INTERNAL) {
|
||||
itram_size -= dsp_mgr->tram_grp[i].size;
|
||||
dsp_mgr->tram_grp[i].offset = itram_size;
|
||||
} else if (dsp_mgr->tram_grp[i].pos == TRAM_POS_EXTERNAL) {
|
||||
etram_size -= dsp_mgr->tram_grp[i].size;
|
||||
dsp_mgr->tram_grp[i].offset = etram_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
|
||||
{
|
||||
int i;
|
||||
int grp_idx;
|
||||
int acc_idx;
|
||||
int tram_op;
|
||||
|
||||
/* for all patch accs */
|
||||
for (i = 0; i < patch->tram_acc_count; i++) {
|
||||
grp_idx = patch->tram_grp[patch->tram_acc[i].grp].grp_idx;
|
||||
acc_idx = patch->tram_acc[i].acc_idx;
|
||||
tram_op = 0;
|
||||
|
||||
if (dsp_mgr->tram_acc[acc_idx].type == TRAM_ACC_WRITE)
|
||||
tram_op = TRAM_OP_WRITE;
|
||||
else
|
||||
tram_op = TRAM_OP_READ;
|
||||
|
||||
ld10k1_tram_actualize_hwacc(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc,
|
||||
tram_op, dsp_mgr->tram_grp[grp_idx].offset + patch->tram_acc[i].acc_offset, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch)
|
||||
{
|
||||
int i;
|
||||
int acc_idx;
|
||||
int grp_idx;
|
||||
|
||||
/* free all patch accs */
|
||||
for (i = 0; i < patch->tram_acc_count; i++) {
|
||||
acc_idx = patch->tram_acc[i].acc_idx;
|
||||
ld10k1_tram_hwacc_free(dsp_mgr, dsp_mgr->tram_acc[acc_idx].hwacc);
|
||||
ld10k1_tram_acc_free(dsp_mgr, acc_idx);
|
||||
}
|
||||
|
||||
/* free all patch grps */
|
||||
for (i = 0; i < patch->tram_count; i++) {
|
||||
grp_idx = patch->tram_grp[i].grp_idx;
|
||||
ld10k1_tram_grp_free(dsp_mgr, grp_idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
53
ld10k1/src/ld10k1_tram.h
Normal file
53
ld10k1/src/ld10k1_tram.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LD10K1_TRAM_H
|
||||
#define __LD10K1_TRAM_H
|
||||
|
||||
typedef struct {
|
||||
int grp_idx;
|
||||
unsigned int grp_size;
|
||||
unsigned int grp_acc_count;
|
||||
unsigned int res_value;
|
||||
unsigned int pos;
|
||||
} ld10k1_dsp_tram_resolve_item_t;
|
||||
|
||||
typedef struct {
|
||||
int isize;
|
||||
int ifree;
|
||||
int iacc_count;
|
||||
int iacc_free_count;
|
||||
int esize;
|
||||
int efree;
|
||||
int eacc_count;
|
||||
int eacc_free_count;
|
||||
int grp_free;
|
||||
int item_count;
|
||||
ld10k1_dsp_tram_resolve_item_t items[MAX_TRAM_COUNT];
|
||||
} ld10k1_dsp_tram_resolve_t;
|
||||
|
||||
int ld10k1_tram_reserve_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res);
|
||||
int ld10k1_tram_alloc_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch, ld10k1_dsp_tram_resolve_t *res);
|
||||
int ld10k1_tram_actualize_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch);
|
||||
void ld10k1_tram_get_hwacc(ld10k1_dsp_mgr_t *dsp_mgr, int acc, unsigned int *addr, unsigned int *data);
|
||||
int ld10k1_tram_free_tram_for_patch(ld10k1_dsp_mgr_t *dsp_mgr, ld10k1_patch_t *patch);
|
||||
|
||||
#endif /* __LD10K1_TRAM_H */
|
||||
1168
ld10k1/src/liblo10k1.c
Normal file
1168
ld10k1/src/liblo10k1.c
Normal file
File diff suppressed because it is too large
Load diff
1099
ld10k1/src/liblo10k1ef.c
Normal file
1099
ld10k1/src/liblo10k1ef.c
Normal file
File diff suppressed because it is too large
Load diff
1388
ld10k1/src/liblo10k1lf.c
Normal file
1388
ld10k1/src/liblo10k1lf.c
Normal file
File diff suppressed because it is too large
Load diff
1737
ld10k1/src/lo10k1.c
Normal file
1737
ld10k1/src/lo10k1.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue