Files
m68k-bdm/m683xx/bdm-load/bdmlib.c
Bernd Mueller adfd70813f initial push
2026-06-17 13:44:30 +02:00

1702 lines
39 KiB
C

/*
* $Id: bdmlib.c,v 1.5 2005/11/04 14:33:54 ppisa Exp $
*
* Remote debugging interface for 683xx via Background Debug Mode
* needs a driver, which controls the BDM interface.
* written by G.Magin
* (C) 1996 Technische Universitaet Muenchen, Lehrstuhl fuer Prozessrechner
* (C) 1997 G. Magin
*
* Modified by Pavel Pisa pisa@cmp.felk.cvut.cz 1998
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, 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; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/*
* NOTE:
* This file is assumed to be runnable only on Linux/i386 because of
* HW-restrictions: the driver is currently only available on i386-Linux
* So byte-swapping and alignment is handled directly, violating the
* GNU-coding standards. However, the "dirty spots" are restricted in this
* file. The accompanying application backend file (e.g. remote-bdm.c for
* gdb) is not affected by this restriction.
*
* If anybody wants to port to e.g. Sparc, byte-sex has to be handled in
* a more general way.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <ansidecl.h>
/* #define SUPPORT_RAMINIT 0 */ /* force ram_init to be loaded */
#define RAMINIT_FILENAME "ram_init"
#define RESETINIT_FILENAME "cpu32init"
#define END_MACRO 0
#define BEGIN_MACRO 1
#define NO_SUFFIX_MACRO 2
#define BDMLIB_REQUIRED_DRIVER_VERSION 2
/*
* version 1 (cannot be accessed by ioctl): release 3/95
* version 2 (includes SENSE ioctl + ICD): release 7/96
*/
#ifdef BDMLIB_FORGDB
#include "defs.h"
#endif
#ifndef PROTO
/* this is missing in current ansidecl.h - remove it later gm */
#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4))
#define PROTO(type, name, arglist) type name arglist
#define PARAMS(paramlist) paramlist
#define ANSI_PROTOTYPES 1
#else /* Not ANSI C. */
#define PROTO(type, name, arglist) type name ()
#define PARAMS(paramlist) ()
#endif /* ANSI C. */
#endif
#include <bfd.h>
#include "bdmlib.h"
#include "bdm.h"
static int bdm_fd;
/* default delay for interface */
#define BDM_DEFAULT_DELAY 75
static int bdm_delay=-1;
#define BDM_DODPRINTF (1<<0)
#define BDM_GOTEXCEPTION (1<<1)
#define BDM_DEBUG_NAME "bdm-dbg.log"
static int bdm_flags = 0;
static int mbar_used = 0;
static u_long mbar_default_val = 0;
extern char hashmark;
extern int bdm_autoreset;
extern int bdm_ttcu;
static void dbprintf(const char *format, ...);
#if !defined BDMLIB_FORGDB
/*
* this is borrowed from gdb utils.c
*/
static void
error(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
va_end(args);
}
static void
fprintf_filtered(FILE *fp, const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(fp, format, args);
fprintf(fp, "\n");
va_end(args);
}
#define printf_filtered printf
#define xmalloc malloc
#define gdb_stderr stderr
#endif
void
bdmlib_setdebug(int switch_on)
{
if (switch_on)
bdm_flags |= BDM_DODPRINTF;
else
bdm_flags &= ~BDM_DODPRINTF;
dbprintf("Setting Debug to %d\n", switch_on);
}
int
bdmlib_querydebug(void)
{
return (bdm_flags & BDM_DODPRINTF);
}
/* startofcleanup */
int
bdmlib_isopen(void)
{
return (bdm_fd != 0);
}
/* filter to put out bdm specific status messages */
char *
bdmlib_getstatus_str(bdmstatus status)
{
int st;
static char put_buffer[128];
*put_buffer = '\0';
st = (int) status;
if (st < 0) {
return bdmlib_geterror_str(status);
}
if (status & BDM_TARGETNC) {
strcat(put_buffer, "NotConnected ");
return put_buffer;
}
strcat(put_buffer, "Connected ");
if (status & BDM_TARGETPOWER) {
strcat(put_buffer, "PowerFail ");
return put_buffer;
}
strcat(put_buffer, "PowerOK ");
if (status & BDM_TARGETSTOPPED)
strcat(put_buffer, "Frozen ");
else
strcat(put_buffer, "Running ");
if (status & BDM_TARGETRESET)
strcat(put_buffer, "Reset ");
return put_buffer;
}
static struct _err_messages {
int err_num;
char *err_msg;
}
err_messages[] = {
{ BDM_FAULT_UNKNOWN, "bdm driver recognized unknown fault" } ,
{ BDM_FAULT_POWER, "target power failed" } ,
{ BDM_FAULT_CABLE, "cable disconnected" } ,
{ BDM_FAULT_RESPONSE, "no response from target via bdm" } ,
{ BDM_FAULT_RESET, "target got a reset" } ,
{ BDM_FAULT_PORT, "wrong bdm port" } ,
{ BDM_FAULT_BERR, "bus error occured on access via bdm" } ,
{ BDM_FAULT_NVC, "bdm internal error: no valid command to bdm" } ,
{ BDM_NO_ERROR, "No error" } ,
{ BDM_ERR_NOT_OPEN, "bdm device is not open" } ,
{ BDM_ERR_ILL_IOCTL, "ioctl code does not match library ioctl type" } ,
{ BDM_ERR_WRITE_FAIL, "write to processor failed" } ,
{ BDM_ERR_READ_FAIL, "read from processor failed" } ,
{ BDM_ERR_ILL_SIZE, "illegal variable size" } ,
{ BDM_ERR_OPEN, "open error" } ,
{ BDM_ERR_LOAD, "error on loading binary file" } ,
{ BDM_ERR_MACROFILE, "error on loading macro" } ,
{ BDM_ERR_SECTION, "error on loading section" } ,
{ BDM_ERR_VERSION, "driver version conflict" } ,
};
static int err_msg_len = sizeof(err_messages) / sizeof(struct _err_messages);
/* filter to pick out bdm specific error messages */
char *
bdmlib_geterror_str(int err)
{
int i;
static char put_buffer[128];
for (i = 0; i < err_msg_len; i++) {
if (err == err_messages[i].err_num)
return err_messages[i].err_msg;
}
strncpy(put_buffer, strerror(-err), 128);
return put_buffer;
}
#define do_case(x) case x: ret = #x; break;
static char *
bdmlib_getioctlname(int ioctl)
{
char *ret;
switch (ioctl) {
do_case(BDM_INIT);
do_case(BDM_DEINIT);
do_case(BDM_RESET_CHIP);
do_case(BDM_RESTART_CHIP);
do_case(BDM_STOP_CHIP);
do_case(BDM_STEP_CHIP);
do_case(BDM_GET_STATUS);
do_case(BDM_SPEED);
do_case(BDM_RELEASE_CHIP);
do_case(BDM_DEBUG_LEVEL);
do_case(BDM_GET_VERSION);
do_case(BDM_SENSECABLE);
default:
ret = "Unknown ioctl";
}
return ret;
}
int
bdmlib_setioctl(u_int code, u_int val)
{
if (bdmlib_isopen()) {
switch (code) {
case BDM_SENSECABLE:
case BDM_DEBUG_LEVEL:
break;
case BDM_SPEED:
bdm_delay = val; break;
default:
return BDM_ERR_ILL_IOCTL;
}
return ioctl(bdm_fd, code, (u_long) val);
} else {
return BDM_ERR_NOT_OPEN;
}
}
int
bdmlib_ioctl(u_int code)
{
int ret;
if (bdmlib_isopen()) {
switch (code) {
case BDM_INIT:
case BDM_RESET_CHIP:
case BDM_STOP_CHIP:
case BDM_RESTART_CHIP:
case BDM_RELEASE_CHIP:
case BDM_STEP_CHIP:
if ((ret = ioctl(bdm_fd, code, (u_long) NULL)) == -1) {
dbprintf("bdmlib_ioctl %s failed; error %d %s\n",
bdmlib_getioctlname(code), errno,
bdmlib_geterror_str(errno));
return -errno;
} else {
return BDM_NO_ERROR;
}
break;
default:
return BDM_ERR_ILL_IOCTL;
}
} else {
return BDM_ERR_NOT_OPEN;
}
}
/*
* get status of interface
*/
bdmstatus
bdmlib_getstatus(void)
{
if (bdmlib_isopen()) {
return ioctl(bdm_fd, BDM_GET_STATUS, NULL);
} else {
return BDM_ERR_NOT_OPEN;
}
}
int
bdmlib_go(void)
{
u_short buf;
int ret;
dbprintf("bdmlib_go\n");
#if MORE_DEBUGGING
bdmlib_showpc();
#endif /* MORE_DEBUGGING */
if (bdmlib_isopen()) {
buf = BDM_GO_CMD;
ret = write(bdm_fd, &buf, 2);
if ((ret < 0) || (ret != 2)) {
dbprintf("bdm_go: write_error %d\n", errno);
return -errno;
}
} else {
return BDM_ERR_NOT_OPEN;
}
return BDM_NO_ERROR;
}
int
bdmlib_set_mbar(u_long mbar_val)
{
int ret;
bdmlib_set_sys_reg(BDM_REG_DFC, 7);
bdmlib_set_sys_reg(BDM_REG_SFC, 7);
ret = bdmlib_write_var((caddr_t)0x3ff00, BDM_SIZE_LONG, mbar_val);
if(ret >= 0){
mbar_used = 1;
mbar_default_val = mbar_val;
}
bdmlib_set_sys_reg(BDM_REG_DFC, 5);
bdmlib_set_sys_reg(BDM_REG_SFC, 5);
return ret;
}
int
bdmlib_reset(void)
{
#if SUPPORT_RAMINIT
u_long dummy;
#endif
int ret;
dbprintf("bdmlib_reset ttcu %d\n", bdm_ttcu);
if ((ret = bdmlib_ioctl(BDM_RESTART_CHIP))) {
return ret;
}
#if MORE_DEBUGGING
printf("bdmlib_reset: RESTART_CHIP replies %d %s\n",
ret, bdmlib_geterror_str(ret));
printf("status: %s\n", bdmlib_getstatus_str(bdmlib_getstatus()));
#endif /* MORE_DEBUGGING */
/*
* it cannot break anything to set right SFC and DFC
* adress space for memory accesses
*/
bdmlib_set_sys_reg(BDM_REG_DFC, 5);
bdmlib_set_sys_reg(BDM_REG_SFC, 5);
/*
* The 68360 targets requires setup of MBAR to enable access
* to integrated modules and system configuration registers
*/
if(mbar_used) {
bdmlib_set_mbar(mbar_default_val);
}
/*
* in case we have a monitor in place, we might want to let him do
* the basic setup, let it come to the prompt...
*/
if (bdm_ttcu) {
if ((ret = bdmlib_go())) /* let the monitor come up.... */
return ret;
usleep(bdm_ttcu);
ret = bdmlib_ioctl(BDM_STOP_CHIP);
}
#if SUPPORT_RAMINIT
if ((ret = bdmlib_do_load_binary(RAMINIT_FILENAME, &dummy)) < 0) {
fprintf_filtered(gdb_stderr, "Warning: %s for file `%s'\n",
bdmlib_geterror_str(ret),
RAMINIT_FILENAME);
}
#endif /* SUPPORT_RAMINIT */
bdmlib_do_load_macro(RESETINIT_FILENAME, NO_SUFFIX_MACRO);
fprintf(stdout, "\r"); fflush(stdout);
return ret;
}
#define swaps(x) \
((u_short)((((u_short)(x) & 0x00ff) << 8) | \
(((u_short)(x) & 0xff00) >> 8)))
#define swapl(x) \
((u_int)((((u_int)(x) & 0x000000ffU) << 24) | \
(((u_int)(x) & 0x0000ff00U) << 8) | \
(((u_int)(x) & 0x00ff0000U) >> 8) | \
(((u_int)(x) & 0xff000000U) >> 24)))
static u_short *
bdmlib_conv_short_to_buf(u_short * buf, u_short val, int endianness)
{
if (endianness) {
*buf++ = swaps(val);
} else {
*buf++ = val;
}
return buf;
}
/* conv long in host format (little endian) to buf (target format = big e) */
static u_short *
bdmlib_conv_long_to_buf(u_short * buf, u_long val, int endianness)
{
if (endianness) {
*buf++ = swaps(val & 0xffff);
*buf++ = swaps(val >> 16);
} else {
*buf++ = val >> 16;
*buf++ = val & 0xffff;
}
return buf;
}
/* buf representation to a single short */
static u_short *
bdmlib_conv_buf_to_short(u_short * buf, u_short * val, int endianness)
{
if (endianness) {
*val = *buf++;
} else {
*val = swaps(*buf);
buf++;
}
return buf;
}
/* buf representation to a single long */
static u_short *
bdmlib_conv_buf_to_long(u_short * buf, u_long * val, int endianness)
{
if (endianness) {
*val = (buf[0] << 16) | buf[1];
} else {
*val = (swaps(buf[1]) << 16) | swaps(buf[0]);
}
buf += 2;
return buf;
}
/*
* put a char stream of 4 bytes into a long;
* endianness=0: interprete char as little end
* else interprete char as big endian
*/
static u_char *
bdmlib_conv_char_to_long(u_char * buf, u_long * val, int endianness)
{
int i;
union {
u_long l;
u_char c[4];
} u;
if (endianness) {
for (i = 3; i >= 0; i--)
u.c[i] = *buf++;
} else {
for (i = 0; i < 4; i++)
u.c[i] = *buf++;
}
*val = u.l;
return buf;
}
/* put a char stream of 2 bytes into a short */
static u_char *
bdmlib_conv_char_to_short(u_char * buf, u_short * val, int endianness)
{
int i;
union {
u_short s;
u_char c[2];
} u;
if (endianness) {
for (i = 1; i >= 0; i--)
u.c[i] = *buf++;
} else {
for (i = 0; i < 2; i++)
u.c[i] = *buf++;
}
*val = u.s;
return buf;
}
/* put a long to a char stream */
static u_char *
bdmlib_conv_long_to_char(u_char * buf, u_long val, int endianness)
{
int i;
union {
u_long l;
u_char c[4];
} u;
u.l = val;
if (endianness) {
for (i = 3; i >= 0; i--)
*buf++ = u.c[i];
} else {
for (i = 0; i < 4; i++)
*buf++ = u.c[i];
}
return buf;
}
/* put a short to a char stream */
static u_char *
bdmlib_conv_short_to_char(u_char * buf, u_short val, int endianness)
{
int i;
union {
u_short s;
u_char c[2];
} u;
u.s = val;
if (endianness) {
for (i = 1; i >= 0; i--)
*buf++ = u.c[i];
} else {
for (i = 0; i < 2; i++)
*buf++ = u.c[i];
}
return buf;
}
int
bdmlib_get_sys_reg(u_int reg, u_int * ret_val)
{
u_short send;
u_short recv[2];
int ret;
send = BDM_RSREG_CMD | (reg & 0xf);
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
ret = write(bdm_fd, &send, 2);
if (ret == 2) {
ret = read(bdm_fd, recv, 4);
} else {
dbprintf("bdmlib_get_sys_reg error on send: errno %d\n", errno);
return -errno;
}
bdmlib_conv_buf_to_long(recv, (u_long *) ret_val, 0);
return (ret == 4) ? BDM_NO_ERROR : -errno;
}
int
bdmlib_set_sys_reg(u_int reg, u_int cont)
{
u_short send[3];
int ret;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
send[0] = BDM_WSREG_CMD | (reg & 0xf);
bdmlib_conv_long_to_buf(&send[1], cont, 0);
if ((ret = write(bdm_fd, send, 6)) != 6) {
dbprintf("bdmlib_set_sys_reg error: reg %#x cont %#x error %d\n",
reg, cont, errno);
return -errno;
}
return BDM_NO_ERROR;
}
int
bdmlib_get_reg(u_int reg, u_int * ret_val)
{
u_short send;
u_short recv[2];
int ret;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
send = BDM_RREG_CMD | (reg & 0xf);
ret = write(bdm_fd, &send, 2);
if (ret == 2) {
ret = read(bdm_fd, recv, 4);
} else {
dbprintf("bdmlib_get_reg: error on send ret %d\n", errno);
return -errno;
}
/* get target format, as conversion will be done in higher levels */
bdmlib_conv_buf_to_long(recv, (u_long *) ret_val, 0);
return (ret == 4) ? BDM_NO_ERROR : -errno;
}
int
bdmlib_set_reg(u_int reg, u_int cont)
{
u_short send[3];
int ret;
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
send[0] = BDM_WREG_CMD | (reg & 0xf);
bdmlib_conv_long_to_buf(&send[1], cont, 0);
if ((ret = write(bdm_fd, send, 6)) != 6) {
dbprintf("bdmlib_set_reg error: reg %#x to cont %#x error %#d\n",
reg, cont, errno);
return -errno;
}
return BDM_NO_ERROR;
}
int
bdmlib_write_var(caddr_t adr, u_short size, u_int val)
{
u_short buf[6], *b_ptr = buf;
int w_buf_len, r_buf_len;
int written;
dbprintf("bdmlib_write_var: addr %#x cont %#x\n", adr, val);
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
size &= 0x00c0;
*b_ptr++ = (BDM_WRITE_CMD | size);
/* no need for byte swapping, as adr is already a valid long; so use 0 */
b_ptr = bdmlib_conv_long_to_buf(b_ptr, (u_long) adr, 0);
switch (size) {
case BDM_SIZE_LONG:
b_ptr = bdmlib_conv_long_to_buf(b_ptr, val, 0);
w_buf_len = 5;
break;
case BDM_SIZE_WORD:
b_ptr = bdmlib_conv_short_to_buf(b_ptr, val, 0);
w_buf_len = 4;
break;
case BDM_SIZE_BYTE:
*b_ptr++ = (u_short) (val & 0xff);
w_buf_len = 4;
break;
default:
w_buf_len = 0;
dbprintf("error! bdmlib_write_var: unknown size %#x\n", size);
return BDM_ERR_ILL_SIZE;
}
if ((written = write(bdm_fd, buf, w_buf_len * 2)) != w_buf_len * 2) {
dbprintf("error! bdmlib_write_var: write returns %d errno %d\n",
written, errno);
written = errno;
}
if ((r_buf_len = read(bdm_fd, buf, 2)) != 2) {
dbprintf(
"bdmlib_write_var: verify read return val expected 2 is %d errno %d\n",
r_buf_len, errno);
return -errno;
}
if (written == (w_buf_len*2)) {
return BDM_NO_ERROR;
} else {
return -written;
}
}
#if 1
/* slower but reliable method for writting, main solved problem is
waiting for ready after memory access achieved by read
in bdm_write_var */
int
bdmlib_write_block(caddr_t in_adr, u_int size, u_char * bl_ptr)
{
u_short buf[8];
int fills, got_size = 0;
u_long ul;
u_short us;
u_char uc;
u_int first_acc;
dbprintf("bdmlib_write_block size %#x to adr %#x ", size, in_adr);
first_acc = 4 - ((u_long) in_adr & 0x3);
if (size < first_acc) {
switch (size) {
case 0: return 0;
case 1: first_acc = 1; break;
case 2:
case 3: first_acc = first_acc&1? 1: 2; break;
}
}
switch (first_acc) {
case 4:
bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1);
if (bdmlib_write_var(in_adr, BDM_SIZE_LONG, ul) < 0) {
return got_size;
}
got_size += 4;
break;
case 3:
uc = *bl_ptr++;
if (bdmlib_write_var(in_adr, BDM_SIZE_BYTE, uc) < 0) {
return got_size;
}
in_adr += 1;
got_size += 1;
/* fall through to 'word' */
case 2:
bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1);
if (bdmlib_write_var(in_adr, BDM_SIZE_WORD, us) < 0) {
return got_size;
}
got_size += 2;
break;
case 1:
uc = *bl_ptr++;
if (bdmlib_write_var(in_adr, BDM_SIZE_BYTE, uc) < 0) {
return got_size;
}
got_size += 1;
break;
default: ;
/* cannot happen */
}
buf[0] = BDM_FILL_CMD | BDM_SIZE_LONG;
fills = (size - got_size) / 4;
while (fills--) {
bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1);
bdmlib_conv_long_to_buf(&buf[1], ul, 0);
if (write(bdm_fd, &buf[0], 6) !=6) {
return got_size;
}
if (read(bdm_fd, &buf[1], 2) != 2) {
return got_size;
}
got_size += 4;
}
if (size - got_size >= 2) {
buf[0] = (BDM_FILL_CMD | BDM_SIZE_WORD);
bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1);
bdmlib_conv_short_to_buf(&buf[1], us, 0);
if(write(bdm_fd, &buf[0], 4)!=4) return got_size;
if (read(bdm_fd, &buf[0], 2) != 2) return got_size;
got_size += 2;
}
if (size - got_size) {
buf[0] = (BDM_FILL_CMD | BDM_SIZE_BYTE);
buf[1] = *bl_ptr++;
if(write(bdm_fd, &buf[0], 4)!=4) return got_size;
if (read(bdm_fd, &buf[0], 2) != 2) return got_size;
got_size += 1;
}
if (size - got_size) { /* cannot happen */
error("internal error: bdmlib_write_block - cannot happen");
}
return got_size;
}
#else
int
bdmlib_write_block(caddr_t in_adr, u_int size, u_char * block)
{
u_short *buf, *buf_ptr;
int buf_len = 0; /* valid len of buf to writecmd in shorts */
u_char *bl_ptr;
u_int adr;
int fills, put_size;
u_long ul;
u_short us;
u_int first_acc;
dbprintf("bdmlib_write_block size %#x to adr %#x\n", size, in_adr);
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
first_acc = 4 - ((u_long) in_adr & 0x3);
if (size < first_acc) {
switch (size) {
case 0: return 0;
case 1: first_acc = 1; break;
case 2:
case 3: first_acc = first_acc&1? 1: 2; break;
}
}
put_size = size;
adr = (u_int) in_adr;
bl_ptr = block;
buf_ptr = buf = xmalloc((size / 4 + 5) * 6);
/*
* per 4 bytes 3 shorts for fill-long-cmd
* + 3 short for initial write-long-cmd + addr
* = 1 * 3 shorts
* + worst case both a write-byte and write-short on begin & end
* = 4 * 3 shorts
*/
switch (first_acc) {
case 4:
*buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_LONG);
*buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */
*buf_ptr++ = (adr & 0x0000ffff); /* l-Address */
bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1);
buf_ptr = bdmlib_conv_long_to_buf(buf_ptr, ul, 0);
adr += 4;
size -= 4;
buf_len = 5;
break;
case 3:
*buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_BYTE);
*buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */
*buf_ptr++ = (adr & 0x0000ffff); /* l-Address */
*buf_ptr++ = *bl_ptr++;
adr += 1;
size -= 1;
buf_len = 4;
/* fall through to 'word' */
case 2:
*buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_WORD);
*buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */
*buf_ptr++ = (adr & 0x0000ffff); /* l-Address */
bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1);
buf_ptr = bdmlib_conv_short_to_buf(buf_ptr, us, 0);
adr += 2;
size -= 2;
buf_len += 4;
break;
case 1:
*buf_ptr++ = (BDM_WRITE_CMD | BDM_SIZE_BYTE);
*buf_ptr++ = (adr & 0xffff0000) >> 16; /* h-Address */
*buf_ptr++ = (adr & 0x0000ffff); /* l-Address */
*buf_ptr++ = *bl_ptr++;
adr += 1;
size -= 1;
buf_len = 4;
break;
default:
/* cannot happen */
}
fills = size / 4;
size -= fills * 4;
buf_len += (fills * 3);
while (fills--) {
*buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_LONG);
bl_ptr = bdmlib_conv_char_to_long(bl_ptr, &ul, 1);
buf_ptr = bdmlib_conv_long_to_buf(buf_ptr, ul, 0);
}
if(size>=2){
*buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_WORD);
bl_ptr = bdmlib_conv_char_to_short(bl_ptr, &us, 1);
buf_ptr = bdmlib_conv_short_to_buf(buf_ptr, us, 0);
buf_len += 2;
size -= 2;
}
if(size>=1){
*buf_ptr++ = (BDM_FILL_CMD | BDM_SIZE_BYTE);
*buf_ptr++ = *bl_ptr;
buf_len += 2;
size--;
}
if(size){
error("internal error: bdmlib_write_block: size=%d!=0",size);
}
/* now we have a whole buf we can send in one chunk to 'write' */
buf_len *= 2; /* now buflen in bytes */
if ((size = write(bdm_fd, buf, buf_len)) != buf_len) {
dbprintf("error! bdmlib_write_block: write %d returns %d errno %d %s\n",
buf_len, size, errno, bdmlib_geterror_str(-errno));
put_size = 0;
}
/*
* FIXME: needs more persistence on trying to write; analyze reason
* for not writing, and if possible, try again with rest of the buf
* give up on detected bus-err
*/
free(buf);
return put_size;
}
#endif
/* return format in *val is target byte ordering */
int
bdmlib_read_var(caddr_t adr, u_short size, void *val)
{
u_short buf[6], *b_ptr = buf;
int count;
/* u_char *cptr; u_short *sptr; u_long *lptr; */
dbprintf("bdmlib_read_var size %#x from adr %#x ", size, adr);
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
size &= 0x00c0;
*b_ptr++ = (BDM_READ_CMD | size);
/* no need for byte swapping, as adr is already a valid long; so use 0 */
b_ptr = bdmlib_conv_long_to_buf(b_ptr, (u_long) adr, 0);
if ((count = write(bdm_fd, buf, 6)) != 6) {
dbprintf("bdmlib_read_var error: write returns %d\n", count);
return BDM_ERR_WRITE_FAIL;
}
switch (size) {
case BDM_SIZE_LONG:
if ((count = read(bdm_fd, buf, 4)) == 4) {
*(u_long *) val = (buf[0] << 16) | buf[1];
}
break;
case BDM_SIZE_WORD:
if ((count = read(bdm_fd, buf, 2)) == 2) {
*(u_short *) val = (u_short) buf[0];
/* sptr = (u_short*) val; *sptr = (u_short) buf[0]; */
}
break;
case BDM_SIZE_BYTE:
if ((count = read(bdm_fd, buf, 2)) == 2) {
count = 1;
*(u_char *) val = (u_char) (buf[0] & 0xff);
/* cptr = (u_char*)val; *cptr = (u_char) (buf[0] & 0xff); */
}
break;
default:
dbprintf("\n\terror! bdmlib_read_var: unknown size %#x\n", size);
}
if (count < 0) {
dbprintf("\nerror %d (%s)\n", errno, bdmlib_geterror_str(errno));
return -errno;
}
/* val = (u_int*) ((u_long)val & ~3); */
dbprintf(" cont %#x\n", *(u_long *) ((long) val & ~3));
return count; /* _must_ return count */
}
int
bdmlib_read_block(caddr_t in_adr, u_int size, u_char * bl_ptr)
{
u_short buf[8];
u_short dump_cmd;
int dumps, got_size = 0;
u_long ul;
u_short us;
u_char uc;
u_int first_acc;
dbprintf("bdmlib_read_block size %#x from adr %#x ", size, in_adr);
first_acc = 4 - ((u_long) in_adr & 0x3);
if (size < first_acc) {
switch (size) {
case 0: return 0;
case 1: first_acc = 1; break;
case 2:
case 3: first_acc = first_acc&1? 1: 2; break;
}
}
switch (first_acc) {
case 4:
if (bdmlib_read_var(in_adr, BDM_SIZE_LONG, &ul) != 4) {
return got_size;
}
bl_ptr = bdmlib_conv_long_to_char(bl_ptr, ul, 1);
got_size += 4;
break;
case 3:
if (bdmlib_read_var(in_adr, BDM_SIZE_BYTE, &uc) != 1) {
return got_size;
}
*bl_ptr++ = uc;
got_size += 1;
in_adr += 1;
/* fall through to 'word' */
case 2:
if (bdmlib_read_var(in_adr, BDM_SIZE_WORD, &us) != 2) {
return got_size;
}
bl_ptr = bdmlib_conv_short_to_char(bl_ptr, us, 1);
got_size += 2;
break;
case 1:
if (bdmlib_read_var(in_adr, BDM_SIZE_BYTE, &uc) != 1) {
return got_size;
}
*bl_ptr++ = uc;
got_size += 1;
break;
default: ;
/* cannot happen */
}
dump_cmd = BDM_DUMP_CMD | BDM_SIZE_LONG;
dumps = (size - got_size) / 4;
while (dumps--) {
write(bdm_fd, &dump_cmd, 2);
if (read(bdm_fd, &buf, 4) != 4) {
return got_size;
}
bdmlib_conv_buf_to_long(buf, &ul, 1);
bl_ptr = bdmlib_conv_long_to_char(bl_ptr, ul, 1);
got_size += 4;
}
if (size - got_size >= 2) {
dump_cmd = BDM_DUMP_CMD | BDM_SIZE_WORD;
write(bdm_fd, &dump_cmd, 2);
if (read(bdm_fd, &buf, 2) != 2) {
return got_size;
}
bdmlib_conv_buf_to_short(buf, &us, 1);
bl_ptr = bdmlib_conv_short_to_char(bl_ptr, us, 1);
got_size += 2;
}
if (size - got_size) {
dump_cmd = BDM_DUMP_CMD | BDM_SIZE_BYTE;
write(bdm_fd, &dump_cmd, 2);
if (read(bdm_fd, &buf, 2) != 2) {
return got_size;
}
*bl_ptr++ = *buf & 0xff;
got_size += 1;
}
if (size - got_size) { /* cannot happen */
error("internal error: bdmlib_read_block - cannot happen");
}
return got_size;
}
void
bdmlib_propeller(u_long addr, FILE * fp)
{
static char *str = "\\|/-";
static int index;
if (!hashmark) return;
fprintf(fp, "%c 0x%08lx\b\b\b\b\b\b\b\b\b\b\b\b", str[index++], addr);
fflush(fp);
index %= 4;
}
/*
* Open a connection the target via bdm
* name is the devicename of bdm and the filename to be used
* used for communication.
*/
int
bdmlib_open(char *name)
{
int ret;
int version;
if (bdmlib_isopen()) {
dbprintf("bdmlib_open: tried to open twice\n");
return BDM_ERR_OPEN;
}
if ((bdm_fd = open(name, O_RDWR)) < 0) {
dbprintf(
"bdmlib_open: Warning trouble on opening %s: reply %d errno %d\n",
name, bdm_fd, errno);
fprintf(stderr, "Warning: trouble on opening %s: %s\n", name,
bdmlib_geterror_str(-errno));
bdm_fd = 0; /* mark unused */
return BDM_FAULT_PORT;
}
bdmlib_ioctl(BDM_INIT);
if (bdm_delay>=0) {
/* delay has been set before */
bdmlib_setioctl(BDM_SPEED, bdm_delay);
} else {
bdmlib_setioctl(BDM_SPEED, BDM_DEFAULT_DELAY);
}
if (((ret = ioctl(bdm_fd, BDM_GET_VERSION, (u_long) &version)) < 0) ||
(version < BDMLIB_REQUIRED_DRIVER_VERSION)) {
if (ret < 0) version = 1;
fprintf(stderr, "Error:\tBDM device driver version conflict.\n");
fprintf(stderr,
"\tyou need at least version %d, currently installed is version %d.\n",
BDMLIB_REQUIRED_DRIVER_VERSION, version);
fprintf(stderr, "\tAborting operation\n");
close(bdm_fd);
return BDM_ERR_VERSION;
}
return BDM_NO_ERROR;
}
int
bdmlib_close(quitting)
int quitting;
{
dbprintf("bdmlib_close: quitting %d\n", quitting);
if (quitting) {
bdmlib_reset();
bdmlib_ioctl(BDM_RELEASE_CHIP);
}
close(bdm_fd);
bdm_fd = 0;
return BDM_NO_ERROR;
}
#define swap_l(x) (x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | ((x&0xff)<<24)
void
bdmlib_showpc(void)
{
u_int sr, usp, ssp, vbr;
u_int pcc, rpc, a7;
bdmlib_get_sys_reg(BDM_REG_SR, &sr);
bdmlib_get_sys_reg(BDM_REG_USP, &usp);
bdmlib_get_reg(BDM_REG_A7, &a7);
bdmlib_get_sys_reg(BDM_REG_SSP, &ssp);
printf(" SR: %9x USP: %9x A7: %9x SSP: %9x\n",
swap_l(sr), swap_l(usp), swap_l(a7), swap_l(ssp));
bdmlib_get_sys_reg(BDM_REG_PCC, &pcc);
bdmlib_get_sys_reg(BDM_REG_RPC, &rpc);
bdmlib_get_sys_reg(BDM_REG_VBR, &vbr);
printf("PCC: %9x RPC: %9x VBR: %9x\n",
swap_l(pcc), swap_l(rpc), swap_l(vbr));
}
#define LINE_LEN 256
static char *
get_line(FILE * f, int *line_nr)
{
static char line_buf[LINE_LEN];
while (!feof(f)) {
fgets(line_buf, LINE_LEN, f);
(*line_nr)++;
if (line_buf[0] == '#')
continue;
if (line_buf[0] == '\n')
continue;
if (line_buf[0] == '\0')
continue;
return line_buf;
}
return NULL;
}
/*
* retval is just if we found the macro file, no errors!
*/
int
bdmlib_do_load_macro(char *file_name, int which_suffix)
{
char m_name[256];
FILE *m_file;
char *lptr;
char cmd;
int line_nr, ret, size;
bfd_vma addr1, addr2;
short size_tag;
u_char *buf;
int errorcount = 0;
char * begin_suffix = ".bdmmb", *end_suffix = ".bdmme", *no_suffix = "";
char * suffix;
dbprintf("bdmlib_do_load_macro %s suffix %d\n", file_name, which_suffix);
strcpy(m_name, file_name);
if ((lptr = rindex(m_name, '.')) != 0) {
*lptr = '\0';
}
switch (which_suffix) {
case BEGIN_MACRO: suffix = begin_suffix; break;
case END_MACRO: suffix = end_suffix; break;
case NO_SUFFIX_MACRO: suffix = no_suffix; break;
default: suffix = no_suffix;
}
strcat(m_name, suffix);
if ((m_file = fopen(m_name, "r")) == NULL) {
dbprintf("\tno macro file found\n");
return BDM_ERR_MACROFILE; /* no macro file available, quit silently */
}
if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED)) {
dbprintf("\twarning: chip needs stopping\n");
bdmlib_ioctl(BDM_STOP_CHIP);
}
line_nr = 0;
while ((lptr = get_line(m_file, &line_nr))) {
cmd = *lptr++;
addr1 = strtoul (lptr, &lptr, 0);
addr2 = strtoul (lptr, &lptr, 0);
size = strtol (lptr, &lptr, 0);
bdmlib_propeller(addr1, stdout);
switch (toupper(cmd)) {
case 'W':
dbprintf("\twrite to addr %#x cont %#x size %d\n",
addr1, addr2, size);
switch (size) {
case 1:
size_tag = BDM_SIZE_BYTE;
size = 8;
break;
case 2:
size_tag = BDM_SIZE_WORD;
size = 8;
break;
case 4:
size_tag = BDM_SIZE_LONG;
size = 10;
break;
default:
error("\
Error in processing macro %s line %d 'W' command:\n\t\
size must be either 1,2,4 bytes, '%d' is not allowed",
m_name, line_nr, size);
continue;
}
if ((ret = bdmlib_write_var((caddr_t) addr1, size_tag, (u_int) addr2)) < 0) {
errorcount++;
dbprintf("\
Error in processing macro %s line %d 'W' command:\n\t\
bdm_write size mismatch: send %d returned %d errno %d",
m_name, line_nr, size, ret, errno);
}
break;
case 'C':
dbprintf("\tcopy from %#x to %#x size %d\n",
addr1, addr2, size);
buf = xmalloc(size);
if ((ret = bdmlib_read_block((caddr_t) addr1, size, buf)) != size) {
errorcount++;
error("\
Error in processing macro %s line %d 'C' command:\n\t\
bdm_copy size mismatch on read from %#x: wanted %d got %d",
m_name, line_nr, addr1, size, ret);
} else {
{
int i;
for (i = 0; i < size; i++) {
if (!(i % 16))
printf("\n0x%08X: ", (unsigned int) addr1 + i);
printf("0x%02X ", buf[i]);
}
printf("\n");
}
if ((ret = bdmlib_write_block((caddr_t) addr2, size, buf)) != size) {
errorcount++;
error("\
Error in processing macro %s line %d 'C' command:\n\t\
bdm_copy size mismatch on write to %#x: wanted %d got %d",
m_name, line_nr, addr2, size, ret);
}
}
free(buf);
break;
case 'Z':
dbprintf("\tzero from %#x with %#x size %#x\n",
addr1, addr2 & 0xff, size);
buf = xmalloc(size);
memset(buf, addr2, size);
if ((ret = bdmlib_write_block((caddr_t) addr1, size, buf)) != size) {
errorcount++;
error("\
Error in processing macro %s line %d 'Z' command:\n\t\
bdm_set size mismatch on write to %#x: wanted %d got %d",
m_name, line_nr, addr1, size, ret);
}
free(buf);
break;
case 'M':
dbprintf("\tMBAR setup to %#x\n", addr1);
if ((ret = bdmlib_set_mbar((u_long) addr1))) {
errorcount++;
error("\
Error in processing macro %s line %d 'M' command:\n\t\
MBAR set returned %d",
m_name, line_nr, ret);
}
break;
#if DEBUGGING_MACROS
case 'T':
{
int i;
buf = xmalloc(size);
for (i = 0; i < size; i++)
buf[i] = i;
bdmlib_write_block(addr1, size, buf);
free(buf);
}
break;
#endif /* DEBUGGING_MACROS */
default:
dbprintf("\tcmd %c unknown\n", cmd);
}
}
if (hashmark) {
printf(" \b\b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
}
if(m_file) fclose(m_file);
dbprintf("\tfinished macro. errorcount %d\n", errorcount);
return 0;
/*
* dont give back errorcount, errors will show up on binary
* download also.
*/
}
bdmlib_bfilt_t * bdmlib_bfilt=NULL;
int
bdmlib_wrb_filt(bdmlib_bfilt_t * filt, caddr_t in_adr,
u_int size, u_char * bl_ptr)
{
int ret, part_ret;
u_int part_size;
if (!size) return 0;
while (filt) {
if((in_adr<=filt->end_adr)&&
(in_adr+size-1>=filt->begin_adr)) {
ret = 0;
if(in_adr<filt->begin_adr) {
part_size=filt->begin_adr-in_adr;
part_ret=bdmlib_wrb_filt(filt->next,in_adr,part_size,bl_ptr);
ret+=part_ret;
if(part_ret!=part_size) return ret;
in_adr+=part_size;
bl_ptr+=part_size;
size-=part_size;
}
part_size=filt->end_adr-in_adr+1;
if (part_size>=size) {
part_size=size;
size=0;
} else size-=part_size;
part_ret=filt->wrb_filt(filt,in_adr,part_size,bl_ptr);
ret+=part_ret;
if(part_ret!=part_size) {
dbprintf("write error on filt write, address 0x%lx size %d acknowledged %d errno %d\n",
(long)in_adr, part_size, part_ret, errno);
return ret;
}
in_adr+=part_size;
bl_ptr+=part_size;
if(!size) return ret;
ret+=bdmlib_wrb_filt(filt->next,in_adr,size,bl_ptr);
return ret;
}
filt=filt->next;
}
/* regular memory block write */
if ((ret = bdmlib_write_block(in_adr, size, bl_ptr)) != size) {
dbprintf("write error on block write, written %d acknowledged %d errno %d\n",
size, ret, errno);
return ret;
}
return ret;
}
int bdmlib_load_use_lma=0;
static int load_section_error;
static void
bdmlib_load_section(bfd * abfd, sec_ptr sec, PTR ignore)
{
u_long addr;
u_long dfc;
u_long load_bytes;
file_ptr offset;
int ret, cnt;
char cbuf[512];
dbprintf("bdmlib_load_section:\n\tsection %s index %d\n",
sec->name, sec->index);
dbprintf("\tflags %#x raw_size 0x%08lx cooked_size 0x%08lx\n",
sec->flags, (long)bfd_get_section_limit(abfd, sec), (long)bfd_get_section_size(sec));
dbprintf("\tvma %#x lma %#x output_offset %#x\n",
sec->vma, sec->lma, sec->output_offset);
if ((load_section_error < 0) ||
((bfd_get_section_flags(abfd, sec) & SEC_LOAD) == 0)) {
return;
}
if (bfd_get_section_flags(abfd, sec) & SEC_CODE)
dfc = 0x6; /* Supervisor program space */
else
dfc = 0x5; /* Supervisor data space */
if ((ret = bdmlib_set_sys_reg(BDM_REG_DFC, dfc)) < 0) {
load_section_error = ret;
return;
}
if(!bdmlib_load_use_lma)
addr = bfd_section_vma(abfd, sec);
else
addr = bfd_section_lma(abfd, sec);
/* there used to be bfd_get_section_size_before_reloc() */
if ((load_bytes = bfd_section_size(abfd,sec)) == 0)
return;
offset = 0;
while (load_bytes) {
if (load_bytes > sizeof(cbuf)) {
cnt = sizeof(cbuf);
} else {
cnt = load_bytes;
}
if (!bfd_get_section_contents(abfd, sec, cbuf, offset, cnt)) {
dbprintf("read error section %s\n", sec->name);
load_section_error = BDM_ERR_LOAD;
return;
}
if ((ret = bdmlib_wrb_filt(bdmlib_bfilt,(caddr_t) addr, cnt, cbuf)) != cnt) {
dbprintf("write error on block write, written %d acknowledged %d errno %d\n",
cnt, ret, errno);
load_section_error = BDM_ERR_LOAD;
return;
}
load_bytes -= cnt;
addr += cnt;
offset += cnt;
bdmlib_propeller(addr, stdout);
}
}
static int bfd_initialized;
static bfd * prepare_binary(char *file_name)
{
bfd *abfd;
if (!bfd_initialized) {
bfd_init();
bfd_initialized = 1;
}
abfd = bfd_openr(file_name, 0);
if (!abfd) {
dbprintf("Unable to open file %s\n", file_name);
return NULL;
}
if (bfd_check_format(abfd, bfd_object) == 0) {
dbprintf("File %s is not an object file\n", file_name);
bfd_close(abfd);
return NULL;
}
return abfd;
}
/*
* load a binary file, returns error codes
*/
int
bdmlib_do_load_binary(char *file_name, char *entry_name, u_long *entry_pt)
{
bfd *abfd;
int ret;
u_long entry_addr = 0;
if ((abfd = prepare_binary(file_name)) == NULL)
return BDM_ERR_OPEN;
if (entry_name)
while (isspace(*entry_name))
entry_name++;
if (entry_name && isdigit(*entry_name)) {
entry_addr = strtoul (entry_name, NULL, 0);
} else if (entry_name) {
long i, symcnt;
asymbol **symtab;
if ((i=bfd_get_symtab_upper_bound(abfd))<=0 || !(symtab=malloc(i)))
return BDM_ERR_OPEN;
if ((symcnt = bfd_canonicalize_symtab (abfd, symtab))<0)
return BDM_ERR_OPEN;
for (i=0; i<symcnt; i++) {
if (!strcmp (entry_name, symtab[i]->name)) {
entry_addr = symtab[i]->section->vma + symtab[i]->value;
break;
}
}
} else {
entry_addr = bfd_get_start_address(abfd);
}
if(entry_pt) *entry_pt = entry_addr;
load_section_error = BDM_NO_ERROR;
if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED) &&
((ret = bdmlib_ioctl(BDM_STOP_CHIP)))) {
dbprintf("bdmlib_do_load_binary: %d %s\n",
errno, bdmlib_geterror_str(-errno));
return -errno;
}
bfd_map_over_sections(abfd, bdmlib_load_section, NULL);
if (hashmark) {
printf(" . \b\b\b\b\b\b\b\b\b\b\b\b");
fflush(stdout);
}
bfd_close(abfd);
return load_section_error;
}
int
bdmlib_do_load_binary_section(char *file_name, char *section_name)
{
bfd *abfd;
asection *sec;
int ret;
if ((abfd = prepare_binary(file_name)) == NULL)
return BDM_ERR_OPEN;
if ((sec = bfd_get_section_by_name(abfd, section_name)) == NULL)
return BDM_ERR_SECTION;
load_section_error = BDM_NO_ERROR;
if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED) &&
((ret = bdmlib_ioctl(BDM_STOP_CHIP)))) {
dbprintf("bdmlib_do_load_binary: %d %s\n",
errno, bdmlib_geterror_str(-errno));
return -errno;
}
if (hashmark) {
printf(" "); fflush(stdout);
}
bdmlib_load_section(abfd, sec, NULL);
if (hashmark) {
printf("\r \r");
fflush(stdout);
}
bfd_close(abfd);
return load_section_error;
}
/*
* Load a file.
* This is supposed to be coff here, but bfd should handle other formats...
*
* use a macro for target specific manipulations, eg. setting
* chipselect, switching memory banks, etc.
*/
int
bdmlib_load(char *file, char *entry_name, u_long * entry_pt)
{
int ret = 0;
u_int sfc, dfc;
int we_have_macro_files = 0;
#if SUPPORT_RAMINIT
u_long dummy;
#endif
if (!bdmlib_isopen())
return BDM_ERR_NOT_OPEN;
dbprintf("bdmlib_load: program name %s\n", file);
if (bdm_autoreset) bdmlib_reset();
if (!(bdmlib_getstatus() & BDM_TARGETSTOPPED))
if ((ret = bdmlib_ioctl(BDM_STOP_CHIP))) {
fprintf_filtered(gdb_stderr, "%s", bdmlib_geterror_str(ret));
error("Download failed\n");
return ret; /* this is for non-gdb applications */
}
bdmlib_set_sys_reg(BDM_REG_DFC, 5);
if ((ret = bdmlib_set_sys_reg(BDM_REG_SFC, 5)) < 0) {
return ret;
}
bdmlib_get_sys_reg(BDM_REG_DFC, &dfc);
bdmlib_get_sys_reg(BDM_REG_SFC, &sfc);
dbprintf("\tDFC %x SFC %x\n", dfc, sfc);
we_have_macro_files = !bdmlib_do_load_macro(file, BEGIN_MACRO);
#if SUPPORT_RAMINIT
if ((ret = bdmlib_do_load_binary(RAMINIT_FILENAME, &dummy)) < 0) {
error("ram_init load error.\n");
}
#endif /* SUPPORT_RAMINIT */
if ((ret = bdmlib_do_load_binary(file, entry_name, entry_pt)) < 0) {
error("Download failed.");
return ret;
}
if (we_have_macro_files)
bdmlib_do_load_macro(file, END_MACRO);
return BDM_NO_ERROR;
}
static FILE *debug_fp;
static int
open_debug(void)
{
if ((debug_fp = fopen(BDM_DEBUG_NAME, "w")) == NULL) {
perror("bdm-dbprintf");
fprintf_filtered(gdb_stderr, "bdm: opening debug %s\n",
BDM_DEBUG_NAME);
return -1;
}
return 0;
}
/* debug printf for Log-file */
void
dbprintf(const char *format, ...)
{
va_list ap;
if (bdm_flags & BDM_DODPRINTF) {
if ((!debug_fp) && open_debug()) return;
va_start(ap, format);
vfprintf(debug_fp, format, ap); fflush(debug_fp);
va_end(ap);
} else if (debug_fp) {
fclose(debug_fp);
debug_fp = NULL;
}
}
void
bdmlib_log(const char *format, ...)
{
va_list ap;
/*
* this would normally call dbprintf(); however it seems not possible
* to do nested varargs calls....
*/
if (bdm_flags & BDM_DODPRINTF) {
if ((!debug_fp) && open_debug()) return;
va_start(ap, format);
fprintf(debug_fp, "%s: ",
#if defined BDMLIB_FORGDB
"GDB"
#elif defined BDMLIB_FORFLT
"FLT"
#else
"???"
#endif
);
vfprintf(debug_fp, format, ap); fflush(debug_fp);
va_end(ap);
} else if (debug_fp) {
fclose(debug_fp);
debug_fp = NULL;
}
}