initial push
This commit is contained in:
792
m68k/bdmabstraction/bdmops.c
Normal file
792
m68k/bdmabstraction/bdmops.c
Normal file
@@ -0,0 +1,792 @@
|
||||
/* @#Copyright
|
||||
* Copyright (c) 1997, Rolf Fiedler.
|
||||
* Copyright (c) 1999-2000, Brett Wuth.
|
||||
*/
|
||||
/* @#License:
|
||||
* 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, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* File: bdmops.c (BDM Operations)
|
||||
* Purpose:
|
||||
* Author: Rolf Fiedler
|
||||
* Created:
|
||||
*
|
||||
* Initials:
|
||||
* BCW - Brett Wuth
|
||||
* @#[ContactWuth:
|
||||
* Phone: +1 403 627-2460
|
||||
* E-mail: support@castrov.cuug.ab.ca, wuth@acm.org]
|
||||
*
|
||||
* this is an abstraction layer to have a general target programming interface
|
||||
* so the programmer doesn't have to bother with motorola's bdm commands.
|
||||
*
|
||||
* applications only include bdmops.h and call the functions below
|
||||
*
|
||||
* HISTORY:
|
||||
* $Log: bdmops.c,v $
|
||||
* Revision 1.2 2005/10/24 01:37:25 cjohns
|
||||
* Fixed includes for building in Windows with MinGW.
|
||||
*
|
||||
* Revision 1.1 2003/12/29 22:18:49 codewiz
|
||||
* Move tools/bdm_abstraction to m68k/bdmabstraction and autoconfiscate.
|
||||
*
|
||||
* Revision 1.2 2003/07/04 22:33:01 codewiz
|
||||
* Applied SST block-erase patch.
|
||||
*
|
||||
* Revision 1.1 2003/06/03 15:42:04 codewiz
|
||||
* Import userland tools from bdm-fiedler
|
||||
*
|
||||
* Revision 1.6 2000/09/19 00:28:29 wuth
|
||||
* cleanly use Fiedler's bdm driver; bdm_mon detects flash errors
|
||||
*
|
||||
* Revision 1.5 2000/07/25 13:51:09 wuth
|
||||
* Working sector erase. Better error reports.
|
||||
*
|
||||
* Revision 1.4 2000/04/20 04:56:23 wuth
|
||||
* GPL. Abstract flash interface.
|
||||
*
|
||||
* Revision 1.3 2000/03/28 20:24:41 wuth
|
||||
* Break out flash code into separate executable. Make run under Chris Johns BDM driver.
|
||||
*
|
||||
* Revision 1.2 1999/07/05 22:09:50 wuth
|
||||
* Abort if can't sync BDM. Work with Am29F800 flash.
|
||||
* @#[BasedOnTemplate: template.c version 2]
|
||||
*/
|
||||
|
||||
#define _COMPILING_
|
||||
# include "bdmops.h"
|
||||
#undef _COMPILING_
|
||||
|
||||
#include <assert.h>
|
||||
#include "BDMDriver.h"
|
||||
#include "Debug.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined (__WIN32__) && !defined (__CYGWIN__)
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* query status
|
||||
*/
|
||||
static unsigned long target_status=0;
|
||||
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
static int fd;
|
||||
|
||||
static void bdm_update_status(unsigned long x)
|
||||
{
|
||||
x &= CSR_FOF | CSR_TRG | CSR_HALT | CSR_BKPT; /* these bits ain't sticky */
|
||||
target_status |= x;
|
||||
}
|
||||
|
||||
static int bdm_read_status(void)
|
||||
{
|
||||
unsigned long x;
|
||||
|
||||
if(bdm_read_reg(REG_CSR, &x)) return -1;
|
||||
bdm_update_status(x);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* general file handling
|
||||
*/
|
||||
/* open bdm-driver */
|
||||
int /* <0 if error, BDMHandle otherwise */
|
||||
bdm_init(const char *path)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
unsigned long tdr, csr;
|
||||
|
||||
#ifdef USERMODE
|
||||
fd=path[strlen(path)-1]-'0'; /* this is so ugly! works with /dev/bdm[0-9]*/
|
||||
if(fd>3 || fd<0) return -1;
|
||||
fd=bdm_open(fd, O_RDWR);
|
||||
if(fd<0) return fd;
|
||||
#else
|
||||
fd=bdm_open(path, O_RDWR);
|
||||
if(fd<0) return fd;
|
||||
#endif
|
||||
bdm_clear_status();
|
||||
tdr = BDM_TDR_TRC_HALT; /* trigger response is halt */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
csr = BDM_CSR_UHE; /* user halt enable */
|
||||
if(bdm_write_reg(REG_CSR, &csr)) return -1;
|
||||
return fd;
|
||||
#else
|
||||
int fd=bdmOpen( path );
|
||||
return (fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* close driver */
|
||||
void bdm_release(int port)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_close(fd);
|
||||
#else
|
||||
bdmClose();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* bdm control functions
|
||||
*/
|
||||
/* bring chip to running state */
|
||||
void bdm_run(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_ioctl(fd, BDM_RUN_CHIP_IOC, 0);
|
||||
bdm_clear_status();
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* bring chip to stopped state */
|
||||
void bdm_stop(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_ioctl(fd, BDM_STOP_CHIP_IOC, 0);
|
||||
bdm_read_status();
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* step chip on instruction */
|
||||
void bdm_step(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_ioctl(fd, BDM_STEP_CHIP_IOC, 0);
|
||||
bdm_read_status();
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* reset chip and hold in reset state */
|
||||
void bdm_reset(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_ioctl(fd, BDM_RESET_CHIP_IOC, 0);
|
||||
bdm_clear_status();
|
||||
bdm_read_status();
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* restart from reset to running state */
|
||||
void bdm_restart(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
bdm_ioctl(fd, BDM_RESTART_CHIP_IOC, 0);
|
||||
bdm_read_status();
|
||||
#else
|
||||
/* not implemented */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* data transfer to/from target
|
||||
*/
|
||||
int regs_log2phys(CF_REGS which)
|
||||
{
|
||||
int i;
|
||||
struct regs {
|
||||
int logical;
|
||||
int physical;
|
||||
} regs[]= {
|
||||
{REG_D0, BDM_REG_D0},
|
||||
{REG_D1, BDM_REG_D1},
|
||||
{REG_D2, BDM_REG_D2},
|
||||
{REG_D3, BDM_REG_D3},
|
||||
{REG_D4, BDM_REG_D4},
|
||||
{REG_D5, BDM_REG_D5},
|
||||
{REG_D6, BDM_REG_D6},
|
||||
{REG_D7, BDM_REG_D7},
|
||||
{REG_A0, BDM_REG_A0},
|
||||
{REG_A1, BDM_REG_A1},
|
||||
{REG_A2, BDM_REG_A2},
|
||||
{REG_A3, BDM_REG_A3},
|
||||
{REG_A4, BDM_REG_A4},
|
||||
{REG_A5, BDM_REG_A5},
|
||||
{REG_A6, BDM_REG_A6},
|
||||
{REG_A7, BDM_REG_A7},
|
||||
/* debug registers */
|
||||
{REG_CSR, BDM_REG_CSR},
|
||||
{REG_AATR, BDM_REG_AATR},
|
||||
{REG_TDR, BDM_REG_TDR},
|
||||
{REG_PBR, BDM_REG_PBR},
|
||||
{REG_PBMR, BDM_REG_PBMR},
|
||||
{REG_ABHR, BDM_REG_ABHR},
|
||||
{REG_ABLR, BDM_REG_ABLR},
|
||||
{REG_DBR, BDM_REG_DBR},
|
||||
{REG_DBMR, BDM_REG_DBMR},
|
||||
/* configuration registers */
|
||||
{REG_CACR, BDM_REG_CACR},
|
||||
{REG_ACR0, BDM_REG_ACR0},
|
||||
{REG_ACR1, BDM_REG_ACR1},
|
||||
{REG_VBR, BDM_REG_VBR},
|
||||
{REG_SR, BDM_REG_SR},
|
||||
{REG_RPC, BDM_REG_RPC},
|
||||
{REG_RAMBAR, BDM_REG_RAMBAR},
|
||||
{REG_MBAR, BDM_REG_MBAR},
|
||||
{0xffff,0}
|
||||
};
|
||||
for(i=0; regs[i].logical!=0xffff; i++) {
|
||||
if(regs[i].logical == which) return regs[i].physical;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* read a register from the chip */
|
||||
int bdm_read_reg(CF_REGS which, unsigned long *value)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
int i;
|
||||
|
||||
if(which <= MAX_USER_REGS) {
|
||||
unsigned long word[3];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_RREG_CMD | which;
|
||||
word[1]=BDM_NOP_CMD;
|
||||
word[2]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[1]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
*value = ((word[1] & 0xffff) << 16) | (word[2] & 0xffff);
|
||||
return 0;
|
||||
}
|
||||
if(which <= MAX_CONFIG_REGS) {
|
||||
unsigned long word[5];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_RCREG_CMD;
|
||||
word[1]=0;
|
||||
word[2]=which;
|
||||
word[3]=BDM_NOP_CMD;
|
||||
word[4]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[4]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
word[0]=word[4];
|
||||
while(word[0]==BDM_NOTREADY) {
|
||||
unsigned long poll = BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(poll==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*value = ((word[3] & 0xffff) << 16) | (word[4] & 0xffff);
|
||||
return 0;
|
||||
}
|
||||
if(which <= MAX_DEBUG_REGS) {
|
||||
unsigned long word[3];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_RDMREG_CMD | which;
|
||||
word[1]=BDM_NOP_CMD;
|
||||
word[2]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[1]==BDM_ILLEGAL)
|
||||
return -1;
|
||||
*value = ((word[1] & 0xffff) << 16) | (word[2] & 0xffff);
|
||||
if(which == REG_CSR) {
|
||||
bdm_update_status(*value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* write a register in the chip */
|
||||
int bdm_write_reg(CF_REGS which, unsigned long *value)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
int i;
|
||||
|
||||
if(which <= MAX_USER_REGS) {
|
||||
unsigned long word[4];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_WREG_CMD | which;
|
||||
word[1]=(*value >> 16) & 0xffff;
|
||||
word[2]=*value & 0xffff;
|
||||
word[3]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[1]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(which <= MAX_CONFIG_REGS) {
|
||||
unsigned long word[6];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_WCREG_CMD;
|
||||
word[1]=0;
|
||||
word[2]=which;
|
||||
word[3]=(*value >> 16) & 0xffff;
|
||||
word[4]=*value & 0xffff;
|
||||
word[5]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[5]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
word[0]=word[5];
|
||||
while(word[0]==BDM_NOTREADY) {
|
||||
unsigned long poll = BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(poll==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(which <= MAX_DEBUG_REGS) {
|
||||
unsigned long word[4];
|
||||
which=regs_log2phys(which);
|
||||
word[0]=BDM_WDMREG_CMD | which;
|
||||
word[1]=(*value >> 16) & 0xffff;
|
||||
word[2]=*value & 0xffff;
|
||||
word[3]=BDM_NOP_CMD;
|
||||
i=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(i<0)
|
||||
return i;
|
||||
if(word[1]==BDM_ILLEGAL)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* read a block of memory, alignment doesn't matter anymore */
|
||||
int bdm_read_mem(unsigned int addr, unsigned char *mem, int count)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
unsigned long word[4], poll;
|
||||
int read_bytes=0, ret;
|
||||
int i;
|
||||
|
||||
if(!count) return 0;
|
||||
|
||||
/* align to long word boundary from target's point of view */
|
||||
i=4-(addr&3);
|
||||
for(; i>0 && count>0; i--) {
|
||||
word[0]=BDM_READ_CMD | BDM_SIZE_BYTE;
|
||||
word[1]=(addr>>16) & 0xffff;
|
||||
word[2]=addr & 0xffff;
|
||||
word[3]=BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
if(word[3]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
if(word[3]==BDM_ILLEGAL)
|
||||
return BDM_FAULT_NVC;
|
||||
poll=word[3];
|
||||
while(poll==BDM_NOTREADY) {
|
||||
poll = BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
if(poll==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
if(poll==BDM_ILLEGAL)
|
||||
return BDM_FAULT_NVC;
|
||||
}
|
||||
read_bytes++;
|
||||
count--;
|
||||
addr++;
|
||||
*mem++=(unsigned char)(0xff & poll);
|
||||
}
|
||||
if(count>4) {
|
||||
ret = bdm_read(fd, mem, count & ~3);
|
||||
}
|
||||
if(ret < 0) return ret;
|
||||
read_bytes+=ret;
|
||||
count-=ret;
|
||||
addr+=ret;
|
||||
mem+=ret;
|
||||
|
||||
while(count>0) {
|
||||
word[0]=BDM_READ_CMD | BDM_SIZE_BYTE;
|
||||
word[1]=(addr>>16) & 0xffff;
|
||||
word[2]=addr & 0xffff;
|
||||
word[3]=BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
if(word[3]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
if(word[3]==BDM_ILLEGAL)
|
||||
return BDM_FAULT_NVC;
|
||||
poll=word[3];
|
||||
while(poll==BDM_NOTREADY) {
|
||||
poll = BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
if(ret<0)
|
||||
return ret;
|
||||
if(poll==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
unsigned long poll;
|
||||
poll = BDM_NOP_CMD;
|
||||
bdm_ioctl(fd, BDM_XCHG_DATA_IOC(poll), (unsigned long)&poll);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
if(poll==BDM_ILLEGAL)
|
||||
return BDM_FAULT_NVC;
|
||||
}
|
||||
read_bytes++;
|
||||
count--;
|
||||
addr++;
|
||||
*mem++=(unsigned char)(0xff & poll);
|
||||
}
|
||||
return read_bytes;
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
static int perform_byte_write(int fd, unsigned int addr, unsigned char *mem)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
unsigned long word[5];
|
||||
int ret;
|
||||
|
||||
word[0]=BDM_WRITE_CMD | BDM_SIZE_BYTE;
|
||||
word[1]=(addr>>16) & 0xffff;
|
||||
word[2]=addr & 0xffff;
|
||||
word[3]=*mem;
|
||||
word[4]=BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word), (unsigned long)&word);
|
||||
if(ret<0) {
|
||||
PRINTD("error in bdm_ioctl (0x%08x): %d\n", addr, ret);
|
||||
return ret;
|
||||
}
|
||||
if(word[4]==BDM_BERR) {
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
PRINTD("bus error in bdm_ioctl (0x%08x): %d\n", addr, ret);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
if(word[4]==BDM_ILLEGAL) {
|
||||
/* get BDM_NOT_READY after ILLEGAL */
|
||||
PRINTD("illegal cmd in bdm_ioctl (0x%08x): %d\n", addr, ret);
|
||||
return BDM_FAULT_NVC;
|
||||
}
|
||||
while(1) {
|
||||
word[4] = BDM_NOP_CMD;
|
||||
ret=bdm_ioctl(fd, BDM_XCHG_DATA_IOC(word[4]), (unsigned long)&word[4]);
|
||||
if(ret<0) {
|
||||
PRINTD("error in bdm_ioctl poll (0x%08x): %d\n", addr, ret);
|
||||
return ret;
|
||||
}
|
||||
switch(word[4]) {
|
||||
case BDM_BERR:
|
||||
/* get BDM_NOT_READY after BERR */
|
||||
PRINTD("bus error in bdm_ioctl poll (0x%08x): %d\n", addr, ret);
|
||||
return BDM_FAULT_BERR;
|
||||
case BDM_ILLEGAL:
|
||||
PRINTD("illegal cmd in bdm_ioctl poll (0x%08x): %d\n", addr, ret);
|
||||
return BDM_FAULT_NVC;
|
||||
case BDM_COMPLETE:
|
||||
return 0; /* we've done it ! */
|
||||
case BDM_NOTREADY:
|
||||
break;
|
||||
default:
|
||||
PRINTD("undefined reponse from target (0x%08x): %d\n", addr, ret);
|
||||
return BDM_FAULT_BERR;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* write a block of memory, alignment doesn't matter anymore */
|
||||
int bdm_write_mem(unsigned int addr, unsigned char *mem, int count)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
int written=0, ret;
|
||||
int i;
|
||||
|
||||
if(!count) return 0;
|
||||
|
||||
PRINTD("entering write_mem...");
|
||||
/* align to long word boundary from target's point of view */
|
||||
i=4-(addr&3); /* perform at least one write to set address */
|
||||
for(; i && count; i--) {
|
||||
PRINTD("alignment loop and AATR setup: %d\n", i);
|
||||
ret=perform_byte_write(fd, addr, mem);
|
||||
if(ret<0) return ret;
|
||||
mem++;
|
||||
written++;
|
||||
count--;
|
||||
addr++;
|
||||
}
|
||||
if(count>4) {
|
||||
ret = bdm_write(fd, mem, count & ~3);
|
||||
}
|
||||
if(ret < 0) {
|
||||
PRINTD("error in bdm_write: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
written+=ret;
|
||||
count-=ret;
|
||||
addr+=ret;
|
||||
mem+=ret;
|
||||
PRINTD("write syscall wrote %d (%x) bytes.\n", ret, ret);
|
||||
|
||||
while(count>0) {
|
||||
ret=perform_byte_write(fd, addr, mem);
|
||||
if(ret<0) return ret;
|
||||
mem++;
|
||||
written++;
|
||||
count--;
|
||||
addr++;
|
||||
}
|
||||
PRINTD("bdm_write_mem finished, %d bytes written\n", written);
|
||||
return written;
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bdm_clear_status(void)
|
||||
{
|
||||
target_status = 0;
|
||||
}
|
||||
|
||||
int bdm_query_status(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
unsigned long x, y /* , z */;
|
||||
|
||||
y=0;
|
||||
x = bdm_ioctl(fd, BDM_GET_STATUS_IOC, 0);
|
||||
if(x & BDM_TARGETRESET) y |= BDM_STAT_RESET;
|
||||
if(x & BDM_TARGETHALT) y |= BDM_STAT_PSTHALT;
|
||||
if(x & BDM_TARGETSTOPPED);
|
||||
if(x & BDM_TARGETPOWER) return BDM_STAT_NOPWR;
|
||||
if(x & BDM_TARGETNC) return BDM_STAT_NC;
|
||||
|
||||
if(bdm_read_reg(REG_CSR, &x)) return -1;
|
||||
printf("CSR=%08lx\n", x);
|
||||
/* z = x & 0x10; USER HALT ENABLE */
|
||||
/* y = x >> 28; it's better to translate */
|
||||
x |= target_status;
|
||||
if(x & CSR_BKPT) y |= BDM_STAT_BKPT;
|
||||
if(x & CSR_HALT) y |= BDM_STAT_HALT;
|
||||
if(x & CSR_TRG) y |= BDM_STAT_TRG;
|
||||
if(x & CSR_FOF) y |= BDM_STAT_FOF;
|
||||
if(x & CSR_SSM) y |= BDM_STAT_SSM;
|
||||
switch(x>>28) {
|
||||
case CSR_STAT_WAIT1:
|
||||
y |= BDM_STAT_WAIT1;
|
||||
break;
|
||||
case CSR_STAT_TRIG1:
|
||||
y |= BDM_STAT_TRIG1;
|
||||
break;
|
||||
case CSR_STAT_WAIT2:
|
||||
y |= BDM_STAT_WAIT2;
|
||||
break;
|
||||
case CSR_STAT_TRIG2:
|
||||
y |= BDM_STAT_TRIG2;
|
||||
break;
|
||||
}
|
||||
return y;
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* wait for stopped target
|
||||
*/
|
||||
int bdm_wait(void)
|
||||
{
|
||||
#if BDMDriverVersion_M == BDMDriverFiedler_M
|
||||
unsigned long x;
|
||||
|
||||
while(1) {
|
||||
usleep(100000);
|
||||
x = bdm_ioctl(fd, BDM_GET_STATUS_IOC, 0);
|
||||
if(x & BDM_TARGETRESET) return BDM_STAT_RESET;
|
||||
if(x & BDM_TARGETHALT) return BDM_STAT_PSTHALT;
|
||||
if(x & BDM_TARGETSTOPPED) return BDM_STAT_HALT;
|
||||
if(x & BDM_TARGETPOWER) return BDM_STAT_NOPWR;
|
||||
if(x & BDM_TARGETNC) return BDM_STAT_NC;
|
||||
}
|
||||
#else
|
||||
/* not implemented */
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static unsigned long tdr = 0; /* shadow trigger definition register */
|
||||
/*
|
||||
* breakpoint control
|
||||
*/
|
||||
int bdm_set_pc_bp(unsigned long addr, unsigned long mask)
|
||||
{
|
||||
bdm_stop();
|
||||
if(bdm_write_reg(REG_PBR, &addr)) return -1;
|
||||
if(bdm_write_reg(REG_PBMR, &mask)) return -1;
|
||||
tdr = (1 << 30) | (~(3<<30) & tdr); /* trigger response is halt */
|
||||
tdr |= 1 << 29; /* enable second level trigger breakpoints */
|
||||
tdr |= 1 << 13; /* enable first level trigger breakpoints */
|
||||
tdr |= 1 << 1; /* enable PC breakpoint */
|
||||
tdr &= ~1; /* clear PC breakpoint invert */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdm_clear_pc_bp(void)
|
||||
{
|
||||
bdm_stop();
|
||||
tdr &= ~(1 << 1); /* disable PC breakpoint */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdm_set_addr_bp(unsigned long from_addr, unsigned long to_addr)
|
||||
{
|
||||
unsigned long tmp=0xff05;
|
||||
|
||||
bdm_stop();
|
||||
if(bdm_write_reg(REG_ABLR, &from_addr)) return -1;
|
||||
if(bdm_write_reg(REG_ABHR, &to_addr)) return -1;
|
||||
if(bdm_write_reg(REG_AATR, &tmp)) return -1; /* match everything */
|
||||
tdr = (1 << 30) | (~(3<<30) & tdr); /* trigger response is halt */
|
||||
tdr &= ~(1 << 29); /* disable second level trigger breakpoints */
|
||||
tdr |= 1 << 13; /* enable first level trigger breakpoints */
|
||||
tdr = (tdr & ~(7<<2)) | (2 << 2);
|
||||
/* enable address range breakpoint */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int bdm_clear_addr_bp(void)
|
||||
{
|
||||
bdm_stop();
|
||||
tdr = (tdr & ~(7<<2)) | (0 << 2);
|
||||
/* disable address range breakpoint */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdm_set_data_bp(unsigned long value, unsigned long mask)
|
||||
{
|
||||
bdm_stop();
|
||||
bdm_write_reg(REG_DBR, &value);
|
||||
bdm_write_reg(REG_DBMR, &mask);
|
||||
tdr = (1 << 30) | (~(3<<30) & tdr); /* trigger response is halt */
|
||||
tdr &= ~(1 << 29); /* disable second level trigger breakpoints */
|
||||
tdr |= 1 << 13; /* enable first level trigger breakpoints */
|
||||
tdr = (tdr & ~(0xff<<5)) | (0x80 << 5);
|
||||
/* enable data breakpoint for long word */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdm_clear_data_bp(void)
|
||||
{
|
||||
bdm_stop();
|
||||
tdr = (tdr & ~(0xff<<5)) | (0x00 << 5);
|
||||
/* disable data breakpoint */
|
||||
if(bdm_write_reg(REG_TDR, &tdr)) return -1;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user