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

1284 lines
23 KiB
C

/*
* Motorola Background Debug Mode Library
* Copyright (C) 1995 W. Eric Norum
* Copyright (C) 1998 Chris Johns
*
* Based on:
* 1. `A Background Debug Mode Driver Package for Motorola's
* 16-bit and 32-Bit Microcontrollers', Scott Howard, Motorola
* Canada, 1993.
* 2. `Linux device driver for public domain BDM Inteface',
* M. Schraut, Technische Universitaet Muenchen, Lehrstuhl
* fuer Prozessrechner, 1995.
*
* 31-11-1999 Chris Johns (ccj@acm.org)
* Extended to support remote operation. See bdmRemote.c for details.
*
* Extended to support the ColdFire BDM interface using the P&E module
* which comes with the EVB. Thanks to David Fiddes who has tested the
* driver with the 5206 (5V), 5206e (3.3V) and 5307 devices.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* W. Eric Norum
* Saskatchewan Accelerator Laboratory
* University of Saskatchewan
* 107 North Road
* Saskatoon, Saskatchewan, CANADA
* S7N 5C6
*
* eric@skatter.usask.ca
*
* Coldfire support by:
* Chris Johns
* Objective Design Systems
*
* ccj@acm.org
*
*/
/*
* If no remote/local directive is supplied, default to the
* existing local only mode.
*/
#if !defined (BDM_DEVICE_REMOTE) && !defined (BDM_DEVICE_LOCAL)
#define BDM_DEVICE_LOCAL
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
/*
* This test should be done by autoconf. Please fix if you
* know how.
*/
#if !defined (__WIN32__) || defined (__CYGWIN__)
#define HAVE_SYSLOG 1
#include <syslog.h>
#endif
#include "BDMlib.h"
#if defined (BDM_DEVICE_REMOTE)
#include "bdmRemote.h"
#endif
/*
* Provide the driver print interface so any debug IO
* does not end up on stdout if the library is embedded
* in a server, ie bdmd.
*/
#define PRINTF bdmPrint
/*
* If on Cygwin assume Windows.
*/
#if defined (__WIN32__) || defined (__CYGWIN__)
#include "../driver/win/win-bdm.c"
#else
/*
* See if this is an ioperm build.
*/
#if defined (BDM_IOPERM)
#include "../driver/ioperm/ioperm.c"
#endif
#endif
/*
* Limit of one BDM per process
*/
static int bdm_fd = -1;
static int cpu = BDM_CPU32;
static int iface = BDM_CPU32_PD;
/*
* The configuration data read from the configuration file.
*/
static char* config;
static size_t config_buffer_size = 0;
#if defined (BDM_DEVICE_REMOTE)
static int bdmRemote = 0;
#endif
/*
* Have to make global to allow the bdmBFD function have
* access.
*/
const char *bdmIO_lastErrorString = "No BDM error (yet!)";
/*
* Debugging
*/
static int debugFlag = 0;
#if HAVE_SYSLOG
static int debug_syslog = 0;
#endif
static const char *const sysregName[BDM_MAX_SYSREG] = {
"RPC", "PCC", "SR", "USP",
"SSP", "SFC", "DFC", "ATEMP",
"FAR", "VBR", "CACR", "ACR0",
"ACR1", "RAMBAR", "MBAR", "CSR",
"AATR", "TDR", "PBR", "PBMR",
"ABHR", "ABLR", "DBR", "DBMR",
};
static const char *const regName[] = {
"D0", "D1", "D2", "D3",
"D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3",
"A4", "A5", "A6", "A7",
};
void
bdmLogSyslog (void)
{
#if HAVE_SYSLOG
debug_syslog = 1;
#endif
}
void
bdmInfo (const char *format, ...)
{
va_list ap;
va_start (ap, format);
#if HAVE_SYSLOG
if (debug_syslog) {
if (debugFlag)
vsyslog (LOG_INFO, format, ap);
} else
#endif
{
vfprintf (stderr, format, ap);
fflush (stderr);
}
va_end (ap);
}
void
bdmPrint (const char *format, ...)
{
va_list ap;
va_start (ap, format);
if (debugFlag) {
#if HAVE_SYSLOG
if (debug_syslog) {
vsyslog (LOG_INFO, format, ap);
} else
#endif
{
fprintf (stderr, "BDM: ");
vfprintf (stderr, format, ap);
fflush (stderr);
}
}
va_end (ap);
}
void
bdmSetDebugFlag (int flag)
{
debugFlag = flag;
}
/*
* Verify that device is open
*/
int
bdmCheck (void)
{
if (bdm_fd < 0) {
bdmIO_lastErrorString = "BDM not open";
return 0;
}
return 1;
}
/*
* Like strerror(), but knows about BDM driver errors, too.
*/
static const char *
bdmStrerror (int error_no)
{
switch (error_no) {
case BDM_FAULT_UNKNOWN: return "Unknown BDM error";
case BDM_FAULT_POWER: return "No power to BDM adapter";
case BDM_FAULT_CABLE: return "BDM cable problem";
case BDM_FAULT_RESPONSE: return "No response to BDM request";
case BDM_FAULT_RESET: return "Target is in RESET state";
case BDM_FAULT_BERR: return "Target Bus Error";
case BDM_FAULT_NVC: return "Invalid target command";
case BDM_FAULT_FORCED_TA: return "Invalid target command - Forced TA";
}
#if defined (BDM_DEVICE_REMOTE)
return bdmRemoteStrerror (error_no);
#else
return strerror (error_no);
#endif
}
/*
* Do an int-argument BDM ioctl
*/
int
bdmIoctlInt (int code, int *var)
{
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
if (bdmRemoteIoctlInt (bdm_fd, code, var) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (ioctl (bdm_fd, code, var) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
return 0;
}
/*
* Do a command (no-argument) BDM ioctl
*/
int
bdmIoctlCommand (int code)
{
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
if (bdmRemoteIoctlCommand (bdm_fd, code) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (ioctl (bdm_fd, code, NULL) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
return 0;
}
/*
* Do a BDMioctl-argument BDM ioctl
*/
int
bdmIoctlIo (int code, struct BDMioctl *ioc)
{
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
if (bdmRemoteIoctlIo (bdm_fd, code, ioc) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (ioctl (bdm_fd, code, ioc) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
return 0;
}
/*
* Do a BDM read
*/
int
bdmRead (unsigned char *cbuf, unsigned long nbytes)
{
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
if (bdmRemoteRead (bdm_fd, cbuf, nbytes) != nbytes) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (read (bdm_fd, (char*) cbuf, nbytes) != nbytes) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
return nbytes;
}
/*
* Do a BDM write
*/
int
bdmWrite (unsigned char *cbuf, unsigned long nbytes)
{
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
if (bdmRemoteWrite (bdm_fd, cbuf, nbytes) != nbytes) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (write (bdm_fd, (char*) cbuf, nbytes) != nbytes) {
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
return nbytes;
}
/*
* Read from the target
*/
static int
readTarget (int command, unsigned long address, unsigned long *lp)
{
struct BDMioctl ioc;
ioc.address = address;
ioc.value = 0;
if (bdmIoctlIo (command, &ioc) < 0)
return -1;
*lp = ioc.value;
return 0;
}
/*
* Write to the target
*/
static int
writeTarget (int command, unsigned long address, unsigned long l)
{
struct BDMioctl ioc;
ioc.address = address;
ioc.value = l;
if (bdmIoctlIo (command, &ioc) < 0)
return -1;
return 0;
}
static int
remoteOpen (const char *name)
{
int fd = -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemoteName (name)) {
bdmRemote = 1;
if ((fd = bdmRemoteOpen (name)) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
bdmRemote = 0;
}
}
#endif
return fd;
}
/*
* Return string describing most recent error
*/
const char *
bdmErrorString (void)
{
return bdmIO_lastErrorString;
}
/*
* Append the configuration data.
*/
static void
bdmAppendConfiguration (const char* fname)
{
FILE* file = fopen (fname, "r");
char line[256];
int count = 0;
if (!file)
return;
if (!config)
{
config = malloc (512);
config_buffer_size = 512;
memset (config, 0, config_buffer_size);
}
while (fgets (line, sizeof (line), file) != NULL)
{
int length;
count++;
length = strlen (line);
if (length)
{
int blank = 1;
int i;
for (i = 0; i < length; i++)
{
if (line[i] == '\r')
{
memmove (line + i, line + i + 1, length - i);
length--;
}
if (line[i] == '#')
{
if (i < (sizeof (line) - 1))
{
line[i] = '\n';
i++;
}
line[i] = '\0';
length = i;
}
}
if (length)
{
if (line[0] == '\n')
continue;
if ((line[length - 1] == '\n') && (line[length - 2] == '\\'))
{
line[length - 2] = '\0';
length -= 2;
}
}
if (!length)
continue;
if (length >= (config_buffer_size - strlen (config)))
{
char* new_config = realloc (config, config_buffer_size + 512);
if (new_config == NULL)
break;
config = new_config;
config_buffer_size += 512;
}
strcat (config, line);
}
}
fclose (file);
}
/*
* Read the configuration file.
*/
void
bdmReadConfiguration ()
{
char* env;
if (config)
return;
/*
* The configuration file is read local first then $HOME
* if $HOME is found or $M68K_BDM_INIT. If not found no
* configuration data is read.
*/
bdmAppendConfiguration (M68K_BDM_INIT_FILE);
env = getenv ("HOME");
if (env && strlen (env))
{
char* fname = malloc (strlen (env) + 1 + strlen (M68K_BDM_INIT_FILE));
if (fname)
{
char last;
strcpy (fname, env);
last = fname[strlen (fname) - 1];
if (last != '/' && last != '\\')
strcat (fname, "/");
strcat (fname, M68K_BDM_INIT_FILE);
bdmAppendConfiguration (fname);
free (fname);
}
}
env = getenv ("M68K_BDM_INIT");
if (env && strlen (env))
bdmAppendConfiguration (M68K_BDM_INIT_FILE);
}
/*
* Skip white space.
*/
const char*
bdmConfigSkipWhiteSpace (const char* text)
{
while (*text != '\n')
{
if (!isblank (*text))
break;
text++;
}
return text;
}
/*
* Find matching lines.
*/
const char*
bdmConfigGet (const char* label, const char* last)
{
const char* next = NULL;
if (config)
{
while (1)
{
if (last)
next = strchr (last, '\n') + 1;
else
next = config;
last = next;
if (*next == '\0')
{
next = NULL;
break;
}
next = bdmConfigSkipWhiteSpace (next);
if (strncmp (next, label, strlen (label)) == 0)
{
next += strlen (label);
break;
}
}
}
return next;
}
/*
* Open the specified BDM device
*/
int
bdmOpen (const char *user_name)
{
#if defined (BDM_LIB_CHECKS_VERSION)
unsigned int ver;
#endif
char* name = NULL;
const char* mapping = NULL;
/*
* Load the configurations.
*/
bdmReadConfiguration ();
/*
* Map the name if a mapping is provided.
*/
while ((mapping = bdmConfigGet ("dev", mapping)))
{
mapping = bdmConfigSkipWhiteSpace (mapping);
if (strncmp (mapping, user_name, strlen (user_name)) == 0)
{
char* lf;
mapping += strlen (user_name);
name = strdup (bdmConfigSkipWhiteSpace (mapping));
lf = strchr (name, '\n');
if (lf)
*lf = '\0';
break;
}
}
if (!name)
name = strdup (user_name);
if (!name)
{
bdmIO_lastErrorString = bdmStrerror (ENOMEM);
return -1;
}
/*
* Open the interface. Name could be an ip:port address
* which results in tring to open a connection to the
* the remote server.
*
* First we try to open a remote connection if remote is
* supported. If this fails we attempt to open the driver.
*/
if (bdm_fd >= 0) {
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote)
bdmRemoteClose (bdm_fd);
#endif
#if defined (BDM_DEVICE_LOCAL)
else
close (bdm_fd);
#endif
}
bdm_fd = -1;
if ((bdm_fd = remoteOpen (name)) < 0) {
#if !defined (BDM_DEVICE_LOCAL)
bdmIO_lastErrorString = bdmStrerror (2);
free (name);
return -1;
#endif
}
#if defined (BDM_DEVICE_LOCAL)
if (bdm_fd < 0) {
if ((bdm_fd = open (name, O_RDWR)) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
free (name);
return -1;
}
}
#endif
free (name);
#if defined (BDM_LIB_CHECKS_VERSION)
/*
* CCJ: This is better done by the user as they produce a better
* error message.
*/
/*
* Check the driver version.
*/
if (bdmGetDrvVersion (&ver) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
bdmClose ();
return -1;
}
if ((ver & 0xff00) != (BDM_DRV_VERSION & 0xff00)) {
bdmIO_lastErrorString = "invalid driver version";
bdmClose ();
return -1;
}
#endif
/*
* Get the processor and interface type
*/
if (bdmGetProcessor (&cpu) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
bdmClose ();
return -1;
}
if (bdmGetInterface (&iface) < 0) {
bdmIO_lastErrorString = bdmStrerror (errno);
bdmClose ();
return -1;
}
return bdm_fd;
}
/*
* Close the specified BDM device
*/
int
bdmClose (void)
{
if (config)
{
free (config);
config = NULL;
config_buffer_size = 0;
}
if (!bdmCheck ())
return -1;
#if defined (BDM_DEVICE_REMOTE)
if (bdmRemote) {
bdmRemote = 0;
if (bdmRemoteClose (bdm_fd) < 0) {
bdm_fd = -1;
return -1;
}
}
else {
#endif
#if defined (BDM_DEVICE_LOCAL)
if (close (bdm_fd) < 0) {
bdm_fd = -1;
bdmIO_lastErrorString = bdmStrerror (errno);
return -1;
}
#endif
#if defined (BDM_DEVICE_REMOTE)
}
#endif
bdm_fd = -1;
return 0;
}
/*
* Tell if interface is open
*/
int
bdmIsOpen (void)
{
return (bdm_fd >= 0);
}
/*
* Return the status of the BDM interface
*/
int
bdmStatus (void)
{
int status = 0;
if (bdmIoctlInt (BDM_GET_STATUS, &status) < 0)
return -1;
PRINTF ("Status %#x\n", status);
return status;
}
/*
* Set the delay time
*/
int
bdmSetDelay (int delay)
{
if (bdmIoctlInt (BDM_SPEED, &delay) < 0)
return -1;
PRINTF ("Set delay %d\n", delay);
return 0;
}
/*
* Set the driver debug flag
*/
int
bdmSetDriverDebugFlag (int debugFlag)
{
if (bdmIoctlInt (BDM_DEBUG, &debugFlag) < 0)
return -1;
PRINTF ("Set driver debug flag %d\n", debugFlag);
return 0;
}
/*
* Get the Coldfire PST enable state.
*/
int
bdmColdfireGetPST (int *pst)
{
if (bdmIoctlInt (BDM_GET_CF_PST, pst) < 0)
return -1;
PRINTF ("Get Coldfire PST state: %d\n", *pst);
return 0;
}
/*
* Set the Coldfire PST enable state.
*/
int
bdmColdfireSetPST (int pst)
{
if (bdmIoctlInt (BDM_SET_CF_PST, &pst) < 0)
return -1;
PRINTF ("Set Coldfire PST state: %d\n", pst);
return 0;
}
/*
* Read a control register
*/
int
bdmReadControlRegister (int code, unsigned long *lp)
{
unsigned long ltmp = 0;
if (readTarget (BDM_READ_CTLREG, code, &ltmp) < 0)
return -1;
PRINTF ("Read control register 0x%04x: %#8lx\n", code, ltmp);
*lp = ltmp;
return 0;
}
/*
* Read a debug register
*/
int
bdmReadDebugRegister (int code, unsigned long *lp)
{
unsigned long ltmp = 0;
if (readTarget (BDM_READ_DBREG, code, &ltmp) < 0)
return -1;
PRINTF ("Read debug register 0x%04x: %#8lx\n", code, ltmp);
*lp = ltmp;
return 0;
}
/*
* Read a system register
*/
int
bdmReadSystemRegister (int code, unsigned long *lp)
{
unsigned long ltmp = 0;
if (readTarget (BDM_READ_SYSREG, code, &ltmp) < 0)
return -1;
PRINTF ("Read system register %s: %#8lx\n", sysregName[code], ltmp);
*lp = ltmp;
return 0;
}
/*
* Read a register
*/
int
bdmReadRegister (int code, unsigned long *lp)
{
unsigned long ltmp = 0;
code &= 0xF;
if (readTarget (BDM_READ_REG, code, &ltmp) < 0)
return -1;
PRINTF ("Read register %s: %#8lx\n", regName[code], ltmp);
*lp = ltmp;
return 0;
}
/*
* Write a control register
*/
int
bdmWriteControlRegister (int code, unsigned long l)
{
if (writeTarget (BDM_WRITE_CTLREG, code, l) < 0)
return -1;
PRINTF ("Write control register 0x%04x: %#8lx\n", code, l);
return 0;
}
/*
* Write a debug register
*/
int
bdmWriteDebugRegister (int code, unsigned long l)
{
if (writeTarget (BDM_WRITE_DBREG, code, l) < 0)
return -1;
PRINTF ("Write debug register 0x%04x: %#8lx\n", code, l);
return 0;
}
/*
* Write a system register
*/
int
bdmWriteSystemRegister (int code, unsigned long l)
{
if (writeTarget (BDM_WRITE_SYSREG, code, l) < 0)
return -1;
PRINTF ("Write system register %s: %#8lx\n",
sysregName[code], l);
return 0;
}
/*
* Write a register
*/
int
bdmWriteRegister (int code, unsigned long l)
{
if (writeTarget (BDM_WRITE_REG, code, l) < 0)
return -1;
PRINTF ("Write register %s: %#8lx\n", regName[code], l);
return 0;
}
/*
* Read a long word
*/
int
bdmReadLongWord (unsigned long address, unsigned long *lp)
{
unsigned long ltmp;
if (readTarget (BDM_READ_LONGWORD, address, &ltmp) < 0)
return -1;
PRINTF ("Read %#8.8lx @ %#8lx\n", ltmp, address);
*lp = ltmp;
return 0;
}
/*
* Read a word
*/
int
bdmReadWord (unsigned long address, unsigned short *sp)
{
unsigned long ltmp;
if (readTarget (BDM_READ_WORD, address, &ltmp) < 0)
return -1;
*sp = ltmp;
PRINTF ("Read %#4.4x @ %#8lx\n", (unsigned short) ltmp, address);
return 0;
}
/*
* Read a byte
*/
int
bdmReadByte (unsigned long address, unsigned char *cp)
{
unsigned long ltmp;
if (readTarget (BDM_READ_BYTE, address, &ltmp) < 0)
return -1;
*cp = ltmp;
PRINTF ("Read %#2.2x @ %#8lx\n", (unsigned char)ltmp, address);
return 0;
}
/*
* Write a long word
*/
int
bdmWriteLongWord (unsigned long address, unsigned long l)
{
PRINTF ("Write %#8.8lx @ %#8lx\n", l, address);
return writeTarget (BDM_WRITE_LONGWORD, address, l);
}
/*
* Write a word
*/
int
bdmWriteWord (unsigned long address, unsigned short s)
{
PRINTF ("Write %#4.4x @ %#8lx\n", s, address);
return writeTarget (BDM_WRITE_WORD, address, s);
}
/*
* Write a byte
*/
int
bdmWriteByte (unsigned long address, unsigned char c)
{
PRINTF ("Write %#2.2x @ %#8lx\n", c, address);
return writeTarget (BDM_WRITE_BYTE, address, c);
}
/*
* Read the Module Base Address Register
*/
int
bdmReadMBAR (unsigned long *lp)
{
return bdmReadSystemRegister (BDM_REG_MBAR, lp);
}
/*
* Write the Module Base Address Register
*/
int
bdmWriteMBAR (unsigned long l)
{
return bdmWriteSystemRegister (BDM_REG_MBAR, l);
}
/*
* Reset the target and disable BDM operation
*/
int
bdmRelease (void)
{
PRINTF ("Release\n");
return bdmIoctlCommand (BDM_RELEASE_CHIP);
}
/*
* Reset the target, enable BDM operation, enter BDM
*/
int
bdmReset (void)
{
PRINTF ("Reset\n");
return bdmIoctlCommand (BDM_RESET_CHIP);
}
/*
* Restart the chip.
*/
int
bdmRestart (void)
{
PRINTF ("Restart\n");
return bdmIoctlCommand (BDM_RESTART_CHIP);
}
/*
* Restart target execution
*/
int
bdmGo (void)
{
PRINTF ("Go\n");
return bdmIoctlCommand (BDM_GO);
}
/*
* Stop the target
*/
int
bdmStop (void)
{
PRINTF ("Stop\n");
return bdmIoctlCommand (BDM_STOP_CHIP);
}
/*
* Single-step the target
*/
int
bdmStep (void)
{
PRINTF ("Step\n");
return bdmIoctlCommand (BDM_STEP_CHIP);
}
/*
* Read target memory
* `cbuf' is in target byte order
*/
int
bdmReadMemory (unsigned long address, unsigned char *cbuf, unsigned long nbytes)
{
if (nbytes == 0)
return 0;
if (!bdmCheck ())
return -1;
/*
* Transfer first part and set up target address pointer
*/
if (((address & 0x3) == 0) && (nbytes >= 4)) {
unsigned long l;
if (bdmReadLongWord (address, &l) < 0)
return -1;
*cbuf++ = l >> 24;
*cbuf++ = l >> 16;
*cbuf++ = l >> 8;
*cbuf++ = l;
address += 4;
nbytes -= 4;
}
else if (((address & 0x1) == 0) && (nbytes >= 2)) {
unsigned short s;
if (bdmReadWord (address, &s) < 0)
return -1;
*cbuf++ = s >> 8;
*cbuf++ = s;
address += 2;
nbytes -= 2;
}
else {
do {
if (bdmReadByte (address, cbuf) < 0)
return -1;
cbuf++;
address++;
nbytes--;
} while (nbytes && (address & 0x3));
}
if (nbytes == 0)
return 0;
if (bdmRead (cbuf, nbytes) < 0)
return -1;
PRINTF ("Read %d byte%s\n", nbytes, nbytes == 1 ? "" : "s");
return 0;
}
/*
* Write target memory
* `cbuf' is in target byte order
*/
int
bdmWriteMemory (unsigned long address, unsigned char *cbuf, unsigned long nbytes)
{
int ret;
if (nbytes == 0)
return 0;
if (!bdmCheck ())
return -1;
/*
* Transfer first part and set up target address pointer
*/
if (((address & 0x3) == 0) && (nbytes >= 4)) {
unsigned long l;
l = (unsigned long)*cbuf++ << 24;
l |= (unsigned long)*cbuf++ << 16;
l |= (unsigned long)*cbuf++ << 8;
l |= (unsigned long)*cbuf++;
if (bdmWriteLongWord (address, l) < 0)
return -1;
address += 4;
nbytes -= 4;
}
else if (((address & 0x1) == 0) && (nbytes >= 2)) {
unsigned short s;
s = (unsigned short)*cbuf++ << 8;
s |= (unsigned short)*cbuf++;
if (bdmWriteWord (address, s) < 0)
return -1;
address += 2;
nbytes -= 2;
}
else {
do {
if (bdmWriteByte (address, *cbuf) < 0)
return -1;
cbuf++;
address++;
nbytes--;
} while (nbytes && (address & 0x3));
}
if (nbytes == 0)
return 0;
ret = bdmWrite (cbuf, nbytes);
if (ret < 0)
return -1;
PRINTF ("Wrote %d byte%s\n", nbytes, nbytes == 1 ? "" : "s");
return 0;
}
/*
* Get Driver version
*/
int
bdmGetDrvVersion (unsigned int *ver)
{
if (bdmIoctlInt (BDM_GET_DRV_VER, (int*) ver) < 0)
return -1;
PRINTF ("Driver version: %d.%d\n", *ver >> 8, *ver & 0xff);
return 0;
}
/*
* Get Processor type
*/
int
bdmGetProcessor (int *processor)
{
if (bdmIoctlInt (BDM_GET_CPU_TYPE, processor) < 0)
return -1;
PRINTF ("CPU type: %d\n", *processor);
return 0;
}
/*
* Get Interface type
*/
int
bdmGetInterface (int *iface)
{
if (bdmIoctlInt (BDM_GET_IF_TYPE, iface) < 0)
return -1;
PRINTF ("Interface type: %d\n", *iface);
return 0;
}