diff -urN gdb-5.2.1/gdb/Makefile.in gdb-5.2.1-mpcbdm/gdb/Makefile.in --- gdb-5.2.1/gdb/Makefile.in Fri Jul 19 14:22:06 2002 +++ gdb-5.2.1-mpcbdm/gdb/Makefile.in Mon Jan 27 21:22:56 2003 @@ -1772,6 +1772,12 @@ $(inferior_h) $(target_h) $(serial_h) $(terminal_h) $(gdb_string_h) \ $(regcache_h) +mpcbdm.o: mpcbdm.c mpcbdm.h defs.h gdbcore.h target.h $(wait_h) $(bfd_h) \ + $(unistd_h) $(stdlib_h) $(errno_h) $(signal_h) $(string_h) $(stdio_h) \ + $(fcntl_h) $(ctype_h) $(sys/types_h) $(sys/ioctl_h) command.h \ + inferior.h value.h breakpoint.h gdb_string.h frame.h symfile.h \ + gdbcmd.h objfiles.h dcache.h serial.h + Onindy.o: nindy-share/Onindy.c gdb_wait.h nindy-share/block_io.h \ nindy-share/env.h $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/Onindy.c diff -urN gdb-5.2.1/gdb/config/powerpc/linux.mt gdb-5.2.1-mpcbdm/gdb/config/powerpc/linux.mt --- gdb-5.2.1/gdb/config/powerpc/linux.mt Fri Oct 19 20:16:44 2001 +++ gdb-5.2.1-mpcbdm/gdb/config/powerpc/linux.mt Mon Jan 27 21:20:37 2003 @@ -1,5 +1,5 @@ # Target: Motorola PPC on Linux -TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o solib.o solib-svr4.o solib-legacy.o +TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o mpcbdm.o solib.o solib-svr4.o solib-legacy.o TM_FILE= tm-linux.h SIM_OBS = remote-sim.o diff -urN gdb-5.2.1/gdb/mpcbdm.c gdb-5.2.1-mpcbdm/gdb/mpcbdm.c --- gdb-5.2.1/gdb/mpcbdm.c Wed Dec 31 19:00:00 1969 +++ gdb-5.2.1-mpcbdm/gdb/mpcbdm.c Mon Jan 27 22:39:37 2003 @@ -0,0 +1,5384 @@ +/****************************************************************** +* * +* File: mpcbdm.c * +* Project: MPCBDM * +* Version: 1.2.3 * +* Date: 2001/10/25 * +* FirstDate: 1999/12/07 * +* Author: FP * +* Copyright: (c) 1999,2000,2001 VAS-EntwicklungsgesellschaftmbH* +* Description: gdb remote target for Motorola's MPC * +* via parallel port interface * +* * +******************************************************************/ + +/****************************************************************** +* Includes * +******************************************************************/ + +#include "mpcbdm.h" + +#include "defs.h" +#include "gdbcore.h" +#include "target.h" +#include "wait.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "command.h" +#include "inferior.h" +#include "value.h" +#include "breakpoint.h" + +#include "gdb_string.h" +#include "frame.h" +#include "symfile.h" +#include "gdbcmd.h" +#include "objfiles.h" +#include "gdb-stabs.h" +#include "dcache.h" +#include "serial.h" /*?*/ +#include "regcache.h" + +#define MQ_REGNUM 70 /* Multiply/quotient register */ + + +/****************************************************************** +* macros * +******************************************************************/ + +/****************************************************************** +* prototypes * +******************************************************************/ + +u_int bdm_getspr(int reg); +static void mpcbdm_dcache_flush(u_int Adr, int bAll); +void print_spr_info(int num,u_int val, int bName, int bDef, int bVal, int bPretty); + +/****************************************************************** +* global variables * +******************************************************************/ + +static char sVersion[] = "1.2.3 / 2001/10/25"; + +static uid_t nEuid = -1; /* effective user id */ +static int LastICR; /*save last returned interrupt cause*/ +static int LastDER; /*save previous Debug Enable Register value*/ +static u_int LastMSR; /*copy of srr1, MSR before exception*/ + +static unsigned int mpcbdm_delay = 0; /* delay port output */ +static unsigned int mpcbdm_verbose = 0; /* set verbosity level to quiet */ +static int mpcbdm_mmu = 1; /*allow table walks*/ +static int mpcbdm_reattach = 0; /* resume without command to MPC */ +/*use with unplug-plug then c to wait for FRZ*/ +static unsigned long int mpcbdm_sleep = 250000; /* sleep 0.25 seconds between FRZ polls*/ +static int mpcbdm_hwbrk = 1; /*use hardware breakpoints*/ +static int mpcbdm_maxhwbrk = MAX_HWBRK; /*use cmp register a..d*/ +static unsigned int mpcbdm_wait = 40; /* toggle maximum 40 times DSCK to wait for target CPU clear DSDO */ +static unsigned int mpcbdm_toggle = 4000000; /* flash toggle or poll loop maximum values for timeout*/ +static int mpcbdm_fflash = 1; /*use fast flash programming routine */ +static int mpcbdm_dflush = 0; /*use automatic data cache flushing when returning into mpcbdm */ +static int mpcbdm_relaxed = 0; /* relax timing on bdm port */ +static unsigned int mpcbdm_kbase = 0xc0000000; /* kernel base address */ +static unsigned int mpcbdm_pgdir = 0; /* used to debug kernel routines from user process for linux 2.4*/ +static unsigned int mpcbdm_pram = 0; /* pointer to where to load ppc subroutine */ +static unsigned int mpcbdm_fbuf = 0xfff02000; /* pointer to target buffer, default mpc860 DPRAM */ +static unsigned int mpcbdm_fsizebuf = 4096; /* size of target buffer, default mpc860 DPRAM size */ +static int mpcbdm_fquery = 1; /* query for confirm when erase/write flash */ + +static unsigned int RegBuffer[36]; +static unsigned int membuf[MAXBUFFERLEN]; /*temporary buffer*/ +static unsigned int pramlen = 0; /* store length of actual subroutine */ + +static char break_insn[] = BDM_BREAKPOINT; /* use software emulation for breakpoint*/ + +static int hwbrk_used[MAX_HWBRK]; /* flag for usage of hardware registers */ +static unsigned int hwbrk_adr[MAX_HWBRK]; /* addresses in use for breakpoints*/ + +static int ctrlc; /*Counter for occurance of -c*/ + +static u_int mpcbdm_stat; /* ready and stat values from DSDO protocol */ +static u_int mpcbdm_freeze; /* freeze value from DSDO protocol, one means frozen */ +static u_int mpcbdm_dpi; /* dpi value from DSDO protocol, zero means active! */ +static u_int mpcbdm_icr_or; /* counter for core interrupts during BDM */ + +static int mpcbdm_kill_kludge; /* Workaraound:If nonzero, ignore the next kill. */ + +static struct target_ops *current_ops = NULL; +struct target_ops mpcbdm_ops ; + +static int bdm_regmap[] = {BDM_REGMAP}; + +extern struct cmd_list_element *cmdlist; /*gdb command list*/ + +static FlashBank FB[MAXFLASHBANKS]; /* stores informatins about configured FLASH banks*/ +static int FBank; /* selected FLASH bank */ +static int FSec; /* actual sector in selected FLASH bank */ +static FlashBank * pFB; /* pointer to selected FB */ +static int mpcbdm_nBank = 0; /* number of configured FLASH banks */ +static char * mpcbdm_flashdev; /* string pointer for flash configuration file path */ +static FILE * f; +static char FileBuffer[MAXBUFFERLEN]; +static char * pParse; + +/*************************************************************** +* low level port routines * +****************************************************************/ + +static Port PP; + +static short portadr[] = +{ + 0x378, /* lpt0 */ + 0x278, /* lpt1 */ + 0x3bc, /* lpt2 */ +}; + +/* use 'set mpcbdm_adapter 1|2' to force adapter version. */ +static unsigned int mpcbdm_adapter = 0; /* adapter identification */ +/* use 'set mpcbdm_power 1' to turn on powering from parallel port*/ +static int mpcbdm_power = 0; /* default :do not use power from parallel port*/ + +#define INB(x,port) asm volatile("inb %1, %0" : "=a" (x) : "d" (port)) +#define OUTB(x,port) asm volatile("outb %0, %1" : : "a" (x), "d" (port)) +/* in case of asm trouble (red hat 7.0?) try the code below and compile with -O option */ +/*#include +#define INB(x,port) x = inb(port) +#define OUTB(x,port) outb(x,port)*/ + +/* slow down host for not overrunning target */ +void bdm_delay(int counter) +{ + unsigned char dummy; + + while (counter--) + { +/* since usleep and sisters are to slow (10-20msec minimum) + , and nop's depend on CPU speed + we try I/O port reads for a delay of round about 1usec */ +// asm volatile ("nop"); + INB(dummy,PP.STATAddr); + } +} + +int PortRead(void) +{ + INB(PP.STAT,PP.STATAddr); + return PP.STAT; +} + +void PortStatus(void) +{ + INB(PP.DATA, PP.DATAAddr); + INB(PP.STAT, PP.STATAddr); + INB(PP.CTRL, PP.CTRLAddr); + printf_filtered("PortStatus : DATA=0x%02X STAT=0x%02X CTRL=0x%02X\n",PP.DATA,PP.STAT,PP.CTRL); +} + +void PortPowerV1(unsigned char Power) +{ + if (Power) /* turn power on? */ + { + PP.POWER = 0xff; /* V1 uses D0-D7 */ + OUTB(PP.POWER, PP.DATAAddr); + } + else /* turn power off */ + { + PP.POWER = 0x00; + OUTB(0x00, PP.DATAAddr); + } +} + +void PortWriteV1(unsigned char Data) +{ + PP.CTRL = PP.CTRL & PP.CTRLMask | (Data & PP.DSDI) | ~(Data & PP.DSCK)&PP.DSCK; + OUTB(PP.CTRL, PP.CTRLAddr); + bdm_delay(mpcbdm_delay); +} + +void PortResetV1(unsigned char Data) +{ + PP.CTRL = PP.CTRL & PP.DATAMask | (~(Data & PP.CTRLMask))&PP.CTRLMask; + OUTB(PP.CTRL, PP.CTRLAddr); +} + +void PortStatusV1(void) +{ + int i; + int l; + + INB(PP.DATA, PP.DATAAddr); + INB(PP.STAT, PP.STATAddr); + INB(PP.CTRL, PP.CTRLAddr); + + printf_filtered("PortStatusV1: DATA=0x%02X STAT=0x%02X CTRL=0x%02X\n",PP.DATA,PP.STAT,PP.CTRL); + + i = 0; + if (PP.DATA & PP.POWER) + { + sprintf(&(PP.sStatus[i]),"POWER %n",&l); + i += l; + } + if (PP.STAT & PP.VFLS0) + { + sprintf(&(PP.sStatus[i]),"VFLS0 %n",&l); + i += l; + } + if (PP.STAT & PP.VDD1) + { + sprintf(&(PP.sStatus[i]),"VDD1 %n",&l); + i += l; + } + if (PP.STAT & PP.DSDO) + { + sprintf(&(PP.sStatus[i]),"DSD0 %n",&l); + i += l; + } + if (!(PP.CTRL & PP.DSCK)) + { + sprintf(&(PP.sStatus[i]),"DSCK %n",&l); + i += l; + } + if (PP.CTRL & PP.DSDI) + { + sprintf(&(PP.sStatus[i]),"DSDI %n",&l); + i += l; + } + if (!(PP.CTRL & PP.HRESET)) + { + sprintf(&(PP.sStatus[i]),"HRESET %n",&l); + i += l; + } + if (!(PP.CTRL & PP.SRESET)) + { + sprintf(&(PP.sStatus[i]),"SRESET %n",&l); + i += l; + } + printf_filtered("Port active lines: '%s'\n",PP.sStatus); +} + +void PortPowerV2(unsigned char Power) +{ + if (Power) /* turn power on? */ + { + PP.POWER = 0xf8; /* set mask for power lines */ + OUTB((PP.DATA | PP.POWER), PP.DATAAddr); + } + else /* turn power off */ + { + PP.POWER = 0x00; /* reset mask for power lines */ + PP.DATA=PP.DATA&(~0xf8); + OUTB(PP.DATA, PP.DATAAddr); + } +} + +void PortWriteV2(unsigned char Data) +{ + PP.DATA = Data; + OUTB((Data | PP.POWER), PP.DATAAddr); + bdm_delay(mpcbdm_delay); + if (mpcbdm_verbose&VERBOSE_BDM) + { + printf_filtered("Write: "); + PP.Status(); + } +} + +void PortResetV2(unsigned char Data) +{ + PP.CTRL = Data; + OUTB(Data, PP.CTRLAddr); + if (mpcbdm_verbose&VERBOSE_BDM) + { + printf_filtered("Reset: "); + PP.Status(); + } +} + +void PortStatusV2(void) +{ + int i; + int l; + + INB(PP.DATA, PP.DATAAddr); + INB(PP.STAT, PP.STATAddr); + INB(PP.CTRL, PP.CTRLAddr); + + i = 0; + + if (!(mpcbdm_verbose&VERBOSE_BDM)) /* called from user via port command */ + printf_filtered("PortStatusV2: DATA=0x%02X STAT=0x%02X CTRL=0x%02X\n",PP.DATA,PP.STAT,PP.CTRL); + + sprintf(&(PP.sStatus[i]),"out: %n",&l); + i += l; + if (PP.CTRL & PP.HRESET) + { + sprintf(&(PP.sStatus[i]),"HRESET %n",&l); + i += l; + } + if (PP.CTRL & PP.SRESET) + { + sprintf(&(PP.sStatus[i]),"SRESET %n",&l); + i += l; + } + if (PP.CTRL & PP.TRST) + { + sprintf(&(PP.sStatus[i]),"TRST %n",&l); + i += l; + } + if (PP.DATA & PP.DSCK) + { + sprintf(&(PP.sStatus[i]),"DSCK %n",&l); + i += l; + } + if (PP.DATA & PP.DSDI) + { + sprintf(&(PP.sStatus[i]),"DSDI %n",&l); + i += l; + } + if (PP.DATA & PP.TMS) + { + sprintf(&(PP.sStatus[i]),"TMS %n",&l); + i += l; + } + if (PP.DATA & PP.POWER) + { + sprintf(&(PP.sStatus[i]),"POWER %n",&l); + i += l; + } + sprintf(&(PP.sStatus[i]),"\tin: %n",&l); + i += l; + if (PP.STAT & PP.VFLS0) + { + sprintf(&(PP.sStatus[i]),"VFLS0 %n",&l); + i += l; + } + if (PP.STAT & PP.VFLS1) + { + sprintf(&(PP.sStatus[i]),"VFLS1 %n",&l); + i += l; + } + if (PP.STAT & PP.VDD1) + { + sprintf(&(PP.sStatus[i]),"VDD1 %n",&l); + i += l; + } + if (PP.STAT & PP.VDD2) + { + sprintf(&(PP.sStatus[i]),"VDD2 %n",&l); + i += l; + } + if (PP.STAT & PP.DSDO) + { + sprintf(&(PP.sStatus[i]),"DSD0 %n",&l); + i += l; + } + if (mpcbdm_verbose&VERBOSE_BDM) /* debug BDM protocol: be a little more compact */ + printf_filtered("%s\n",PP.sStatus); + else /* or called from user via port command */ + printf_filtered("Port active lines: %s\n",PP.sStatus); +} + +void PortError(unsigned char Data) +{ + if (mpcbdm_verbose&VERBOSE_BDM) + { + printf_filtered("PortError: called uninitialized port function\n"); + } + else + { + printf_filtered("P!"); + } +} +void PortErrorV(void) +{ + if (mpcbdm_verbose&VERBOSE_BDM) + { + printf_filtered("PortError: called uninitialized port function\n"); + } + else + { + printf_filtered("P!"); + } +} + +/* setup port parameters, try version 2 for default */ +int PortInit(int Port) +{ + int nResult; + int nLast; + + PP.port = -1; + + PP.DATAAddr = 0; + PP.STATAddr = 0; + PP.CTRLAddr = 0; + PP.DATA = 0; + PP.STAT = 0; + PP.CTRL = 0; + PP.POWER = 0x00; + + if ((Port <0) || (Port > 2)) + { + printf_filtered("invalid printer port %d. Use 0..2\n",Port); + return RETURN_FAIL; + } + PP.DATAAddr = portadr[Port]; + PP.STATAddr = PP.DATAAddr + 1; + PP.CTRLAddr = PP.DATAAddr + 2; + + if (nEuid == -1) + { + nEuid = geteuid(); + } + else + { + nResult = seteuid(nEuid); + + if (nResult == -1) + { + printf_filtered("unable to change process effective user ID\n"); + PP.DATAAddr = 0; + PP.STATAddr = 0; + PP.CTRLAddr = 0; + return RETURN_FAIL; + } + } + + nResult = ioperm(PP.DATAAddr,3,1); + + seteuid(getuid()); + + if (nResult == -1) + { + printf_filtered("unable to get access rights for printer port %d addr 0x%3X..0x%3X\n",Port,PP.DATAAddr,PP.CTRLAddr); + PP.DATAAddr = 0; + PP.STATAddr = 0; + PP.CTRLAddr = 0; + return RETURN_FAIL; + } + printf_filtered("got access rights for printer port %d addr 0x%3X..0x%3X\n",Port,PP.DATAAddr,PP.CTRLAddr); + PP.port = Port; /* remember port number */ + + OUTB(0x00,PP.DATAAddr); /* reset all data lines -> disable power from port */ + OUTB(0xC0,PP.CTRLAddr); /* set data lines for output */ + printf_filtered("disabled power at port %d\n",PP.port); + usleep(mpcbdm_sleep); /* allow changes on port lines */ + +/* Removed the buggy auto detection, default is adapter version 2. + The very rare adapter 1 users have to explicitly 'set mpcbdm_adapter 1' + before initializing the 'target' */ + if (!mpcbdm_adapter) + mpcbdm_adapter=2; /* use adpater version 2, if no other is specified */ + + switch (mpcbdm_adapter) /* initialize version dependencies */ + { + case 1: + PP.Read = PortRead; + PP.Status = PortStatusV1; + PP.Power = PortPowerV1; + PP.Write = PortWriteV1; + PP.Reset = PortResetV1; + + PP.DSCK = 0x01; + PP.DSDI = 0x04; + PP.VFLS0 = 0x08; + PP.DSDO = 0x20; + PP.VDD1 = 0x40; + PP.SRESET = 0x02; + PP.HRESET = 0x08; + + PP.FREEZE = PP.VFLS0; /* bug of v1 adapter, only VFLS0 connected */ + + PP.CTRLMask = PP.HRESET | PP.SRESET; + PP.DATAMask = PP.DSDI | PP.DSCK; + + nResult = PP.Read(); /* plausibility check for adapter v1 */ + if (nResult & 0x80) /* STAT[7] is NC on v1 -> always low (because of invert)*/ + { + printf_filtered("adapter v1 specified, but STAT[7] !=0\n"); + PortStatus(); + return RETURN_FAIL; + } + + break; + case 2: + PP.Read = PortRead; + PP.Power = PortPowerV2; + PP.Write = PortWriteV2; + PP.Reset = PortResetV2; + PP.Status = PortStatusV2; + + PP.DSCK = 0x01; + PP.DSDI = 0x02; + PP.TMS = 0x04; + PP.VFLS0 = 0x08; + PP.VDD2 = 0x10; + PP.DSDO = 0x20; + PP.VDD1 = 0x40; + PP.VFLS1 = 0x80; + PP.TRST = 0x01; + PP.SRESET = 0x02; + PP.HRESET = 0x08; + + PP.FREEZE = PP.VFLS0 | PP.VFLS1; + break; + default: + printf_filtered("invalid adapter version %d specified\n",mpcbdm_adapter); + return RETURN_FAIL; + break; + } + + if (mpcbdm_power) + { + PP.Power(1); /* enable power if requested */ + printf_filtered("turned on powering from port %d\n",PP.port); + } + + PP.Write(0x00); /* DSDI and DSCK low*/ + + printf_filtered("adapter version %d initialized\n",mpcbdm_adapter); + + nResult = PP.Read(); + if (!(nResult & PP.VDD1)) + { + printf_filtered("please turn on power at target\n"); + } + while (!(nResult & PP.VDD1)) /* until target powered up */ + { + nLast = nResult; + nResult = PP.Read(); + if (nResult != nLast) + { + PP.Status(); + } + usleep(mpcbdm_sleep); + } + return RETURN_OK; +} + +static void mpcbdm_port(char *args, int from_tty) +{ + if (!mpcbdm_adapter) + { + printf("unknow port adapter\n"); + return; + } + printf("port: adapter version %d at port %d ioaddr from 0x%03X to 0x%03X, FREEZE=0x%02X\n",mpcbdm_adapter,PP.port,PP.DATAAddr,PP.CTRLAddr,PP.FREEZE); + if (mpcbdm_power) + { + printf("powering adapter from port, POWER=0x%02X\n",PP.POWER); + } + PP.Status(); +} + +/*************************************************************** +* low level, serial BDM routines * +****************************************************************/ + +static void WaitFreeze(void) +{ + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("WaitFreeze:\n"); + } + while(!(PP.Read() & PP.FREEZE)) + { + usleep(mpcbdm_sleep); + } +} + + +/* keep DSDI low and toggle DSCK until DSDO goes low */ + +static void ser_wait_ready(void) +{ + unsigned int i = 0; + if (!mpcbdm_reattach) + { + if ((mpcbdm_verbose&VERBOSE_SER) && (mpcbdm_verbose&VERBOSE_BDM)) + { + printf_filtered("ser_wait_ready: start\n"); + } + do + { + if (mpcbdm_relaxed) + { + PP.Write(0x00); /* relaxed BDM port timing */ + } + PP.Write(PP.DSCK); + PP.Write(0x00); + i++; + if (i > mpcbdm_wait) + { + printf_filtered("target CPU does not clear DSDO. No connection?\n"); + mpcbdm_reattach = 1; + printf_filtered("-> forced 'set mpcbdm_reattach on' \n"); + return; + } + bdm_delay(1); /* assure host independent timing */ + } while(PP.Read() & PP.DSDO); + + if (mpcbdm_verbose&VERBOSE_SER) + { + printf_filtered("ser_wait_ready: waited %d cycles\n",i); + } + } +}; + +static void ser_clkpref(u_int word) +{ + int n; + + u_int bit; + + mpcbdm_stat = 0; /* begin new sequence, clear values */ + mpcbdm_freeze = 0; + mpcbdm_dpi=0; + + /* if target processor is frozen, get BDM ready */ + if (PP.Read() & PP.FREEZE) + { + ser_wait_ready(); + } + + for(n = 0; n < 3; ++n) + { + + mpcbdm_stat <<= 1; + if (PP.Read() & PP.DSDO) mpcbdm_stat |= 1; + /* test if target is signaling READY, this should always happen, (stat == 0) + as we just checked ser_wait_ready, waiting for DSDO going low */ + if ((n == 0) && (mpcbdm_stat)) + { + if (mpcbdm_verbose&VERBOSE_SER) + { + printf_filtered("ser_clkpref: target not ready?\n"); + } + else + { + printf_filtered("R!"); + } + } + bit = (word & 4) ? PP.DSDI : 0; + if (mpcbdm_relaxed) + { + PP.Write(bit); /* relaxed BDM port timing */ + } + PP.Write(bit | PP.DSCK); /* clock DSCK High after setting data bit on DSDI*/ + PP.Write(bit); /*clock DSCK low for reading DSDO next */ + word <<= 1; + } +} + +static void ser_clk(u_int word, int len, u_int *data) +{ + int n; + int reslen = 0; + u_int mask = 1 << (len-1); + + if(data) *data = 0; /* if pointer to receive data buffer given, clear buffer */ + + switch(mpcbdm_stat) + { + case DSDO_CORE_DATA: + mpcbdm_dpi = 1; /* this bit is not transmitted, but normal data is in progress */ + reslen = 32; + break; + case DSDO_SEQ_ERROR: /* debug command while target not in debug mode */ + if (mpcbdm_verbose&VERBOSE_SER) + printf_filtered("BDM sequence error: stat %d word 0x%08x len %d data 0x%08x\n", mpcbdm_stat, word, len, data); + else + printf_filtered("E!"); + reslen = 7; + break; + case DSDO_CORE_INTERRUPT: /* interrupt occurred, have to read ICR to clear */ + if (mpcbdm_verbose&VERBOSE_SER) + printf_filtered("BDM core interrupt: stat %d word 0x%08x len %d data 0x%08x\n", mpcbdm_stat, word, len, data); + else + printf_filtered("I!"); + mpcbdm_icr_or++; + reslen = 7; + break; + case DSDO_NULL: + reslen = 7; + break; + default: + if (mpcbdm_verbose&VERBOSE_SER) + printf_filtered("BDM bad stat: stat %d word 0x%08x len %d data 0x%08x\n", mpcbdm_stat, word, len, data); + else + printf_filtered("S!"); + break; + } + for(n = 0; n < len; ++n) + { + int bit; + + if(data) *data <<= 1; + if(PP.Read() & PP.DSDO) + { + if (data) *data |= 1; + if (mpcbdm_stat != 0) + { + if (n == 0) + mpcbdm_freeze = 1; + else if (n == 1) + mpcbdm_dpi = 1; + } + } + bit = (word & mask) ? PP.DSDI : 0; + if (mpcbdm_relaxed) + { + PP.Write(bit); /* relaxed BDM port timing */ + } + PP.Write(bit | PP.DSCK); /* output bit with high clock*/ + PP.Write(bit); /*clock DSCK low for reading DSDO*/ + word <<= 1; + } + for(;n < reslen;) /* clock rest of data in with writing zeros*/ + { + if(data) *data <<= 1; + if (PP.Read() & PP.DSDO) + { + if(data) *data |= 1; + } + if (mpcbdm_relaxed) + { + PP.Write(0x00); /* relaxed BDM port timing */ + } + PP.Write(PP.DSCK); /*clock DSCK high*/ + n++; + if (n == reslen) break; + PP.Write(0x00);/* clock DSCK low */ + } + PP.Write(0x00); /* reset data bit on DSDI */ +} + + +static void ser_clkinstr(u_int word, u_int *data) +{ + if (!mpcbdm_reattach) + { + if ((mpcbdm_verbose&VERBOSE_SER) && (mpcbdm_verbose&VERBOSE_BDM)) + printf_filtered("ser_clkinstr: start word=0x%08x ,data=0x%08x\n",word,data); + ser_clkpref(DSDI_PREF3_CORE_INSTRUCTION); + ser_clk(word, 32, data); + + if (mpcbdm_verbose&VERBOSE_SER) + { + if (data) + { + printf_filtered("ser_clkinstr: word=0x%08x ,*data=0x%08x -> stat %d freeze %d dpi %d\n",word,*data,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + else + { + printf_filtered("ser_clkinstr: word=0x%08x ,data=Null -> stat %d freeze %d dpi %d\n",word,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + } + } +} + +static void ser_clkdata(u_int word, u_int *data) +{ + if (!mpcbdm_reattach) + { + if ((mpcbdm_verbose&VERBOSE_SER) && (mpcbdm_verbose&VERBOSE_BDM)) + printf_filtered("ser_clkidata: start word=0x%08x ,data=0x%08x\n",word,data); + + ser_clkpref(DSDI_PREF3_CORE_DATA); + ser_clk(word, 32, data); + + if (mpcbdm_verbose&VERBOSE_SER) + { + if (data) + { + printf_filtered("ser_clkdata: word=0x%08x ,*data=0x%08x -> stat %d freeze %d dpi %d\n",word,*data,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + else + { + printf_filtered("ser_clkdata: word=0x%08x ,data=Null) -> stat %d freeze %d dpi %d\n",word,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + } + } +} + +static void ser_clkdpc(u_int word, u_int *data) +{ + if (!mpcbdm_reattach) + { + if ((mpcbdm_verbose&VERBOSE_SER) && (mpcbdm_verbose&VERBOSE_BDM)) + printf_filtered("ser_clkdpc: start word=0x%08x ,data=0x%08x\n",word,data); + + ser_clkpref(DSDI_PREF3_DPC); + ser_clk(word, 7, data); + + if (mpcbdm_verbose&VERBOSE_SER) + { + if (data) + { + printf_filtered("ser_clkdpc: word=0x%08x ,*data=0x%08x -> stat %d freeze %d dpi %d\n",word,*data,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + else + { + printf_filtered("ser_clkdpc: word=0x%08x ,data=Null) -> stat %d freeze %d dpi %d\n",word,mpcbdm_stat,mpcbdm_freeze,mpcbdm_dpi); + } + } + } +} + +/*************************************************************** +* BDM routines, using low level routines * +****************************************************************/ + +static u_int bdm_getreg(int reg) +{ + u_int data; + u_int com; + + reg &= ~GPR_REG_MASK; +/*DPDR = SPR 630 = /t 10011 10110*/ +/*spr field in instruction is split field = SPR[5-9] || SPR[0-4]*/ +/*-> spr = /t 10110 10011 = 723*/ + com = (31 << 26) | (reg << 21) | (723 << 11) | (467 << 1); /*mtspr DPDR,rreg*/ + ser_clkinstr(com, 0); /*copy reg to debug port data register*/ + ser_clkinstr(DSDI_COM_NOP, &data); /*get data*/ + + return data; +} + +static void bdm_setreg(int reg, u_int word) +{ + u_int data; + u_int com; + + reg &= ~GPR_REG_MASK; + com = (31 << 26) | (reg << 21) | (723 << 11) | (339 << 1); /*mfspr rreg,DPDR*/ + ser_clkinstr(com, 0); /*copy debug port register to reg*/ + ser_clkdata(word, &data); /*put data to execute instruction*/ +} + +static u_int bdm_getmsr(void) +{ + u_int r0; + u_int spr; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + com = (31 << 26) | (83 << 1); /*mfmsr r0*/ + ser_clkinstr(com, 0); /*copy msr to r0*/ + spr = bdm_getreg(0); /*get r0*/ + bdm_setreg(0, r0); /*restore r0*/ + + return spr; +} + +static void bdm_setmsr(u_int word) +{ + u_int data; + u_int r0; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + com = (31 << 26) | (723 << 11) | (339 << 1); /*mfspr r0,DPDR*/ + ser_clkinstr(com, 0); /*get data from debug port*/ + ser_clkdata(word, &data); /*place data to debug port*/ + com = (31 << 26) | (146 << 1); /*mtmsr r0*/ + ser_clkinstr(com, 0); /*copy r0 to msr*/ + bdm_setreg(0, r0); /*restore r0*/ +} + + +static u_int bdm_getcr(void) +{ + u_int r0; + u_int spr; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + com = (31 << 26) | (19 << 1); /*mfcr r0*/ + ser_clkinstr(com, 0); /*copy cr to r0*/ + spr = bdm_getreg(0); /*get r0*/ + bdm_setreg(0, r0); /*restore r0*/ + + return spr; +} + +static void bdm_setcr(u_int word) +{ + u_int data; + u_int r0; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + com = (31 << 26) | (723 << 11) | (339 << 1); /*mfspr r0,DPDR*/ + ser_clkinstr(com, 0); /*get data from debug port*/ + ser_clkdata(word, &data); /*place data*/ + com = (31 << 26) | (0xFF << 12) | (144 << 1); /*mtcrf 0xff,r0*/ + ser_clkinstr(com, 0); /*copy r0 to cr*/ + bdm_setreg(0, r0); /*restore r0*/ +} + + + +static u_int bdm_getspri(int reg) +{ + u_int immr; + u_int r0; + u_int r1; + u_int n; + u_int com; + + immr = bdm_getspr(SPR_IMMR); /*get offset for memory mapped sprs*/ + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1,(immr&0xFFFF0000) + reg); /*load r1 with adr for spri*/ + com = (32 << 26) | (1 << 16); /*lwz r0,0(r1)*/ + ser_clkinstr(com, 0); /*copy spri to r0*/ + n = bdm_getreg(0); /*get spri value from r0*/ + bdm_setreg(1,r1); /*restore r1*/ + bdm_setreg(0,r0); /*restore r0*/ + + return n; +} + +static void bdm_setspri(int reg, u_int word) +{ + u_int immr; + u_int r0; + u_int r1; + u_int com; + + immr = bdm_getspr(SPR_IMMR); /*get offset for memory mapped sprs*/ + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1,(immr&0xFFFF0000) + reg); /*load r1 with adr for spr*/ + bdm_setreg(0, word); /*set r0 with value*/ + com = (36 << 26) | (1 << 16); /*stw r0,0(r1)*/ + ser_clkinstr(com, 0); /*store value to spr*/ + bdm_setreg(1,r1); /*restore r1*/ + bdm_setreg(0,r0); /*restore r0*/ +} + +static void bdm_setsprihw(int reg, u_int word) +{ + u_int immr; + u_int r0; + u_int r1; + u_int com; + + immr = bdm_getspr(SPR_IMMR); /*get offset for memory mapped sprs*/ + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + + bdm_setreg(1,(immr&0xFFFF0000) + reg); /*load r1 with adr for spr*/ + bdm_setreg(0, word); /*set r0 with data*/ + com = (44 << 26) | (1 << 16); /*sth r0,0(r1)*/ + ser_clkinstr(com, 0); /*copy data to spr*/ + bdm_setreg(1,r1); /*restore r1*/ + bdm_setreg(0,r0); /*restore r0*/ +} + + + +u_int bdm_getspr(int reg) +{ + u_int r0; + u_int spr; + u_int com; + + if(reg == SPR_MSR) return bdm_getmsr(); /*special for msr*/ + if(reg == SPR_CR) return bdm_getcr(); /*special for cr*/ + if(reg & SPRI_MASK) return bdm_getspri(reg & ~SPRI_MASK); /*memory mapped sprs*/ + r0 = bdm_getreg(0); /*save r0*/ +/*mfspr r0,SPRreg*/ + com = (31 << 26) | ((((reg&0x1f) << 5) | ((reg >> 5)&0x1f)) << 11) | (339 << 1); + ser_clkinstr(com, 0); /*copy spr to r0*/ + spr = bdm_getreg(0); /*read r0*/ + bdm_setreg(0, r0); /*restore r0*/ + + return spr; +} + +void bdm_setspr(int reg, u_int word) +{ + u_int data; + u_int r0; + u_int com; + + if(reg == SPR_MSR) return bdm_setmsr(word); /*special for msr*/ + if(reg == SPR_CR) return bdm_setcr(word); /*special for cr*/ + if(reg & SPRI_MASK) return bdm_setspri(reg & ~SPRI_MASK, word); /*memory mapped sprs*/ + r0 = bdm_getreg(0); /*save r0*/ + com = (31 << 26) | (723 << 11) | (339 << 1); /*mfspr r0,DPDR*/ + ser_clkinstr(com, 0); /*copy data to r0*/ + ser_clkdata(word, &data); /*provide data to r0*/ +/*mtspr SPRreg,r0*/ + com = (31 << 26) | ((((reg&0x1f) << 5) | ((reg >> 5)&0x1f)) << 11) | (467 << 1); + ser_clkinstr(com, 0); + bdm_setreg(0, r0); /*restore r0*/ +} + + +u_int ppc_read_bdm_register(int reg) +{ + u_int val; + + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("ppc_read_bdm_register: reg=0x%08x\n",reg); + } + if(reg & GPR_REG_MASK) val = bdm_getreg(reg); + else val = bdm_getspr(reg); + val = extract_unsigned_integer(&val, sizeof(val)); + return val; +} + +void ppc_write_bdm_register(int reg, u_int word) +{ + u_int val = extract_unsigned_integer(&word, sizeof(word)); + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("ppc_write_bdm_register: reg=0x%08x\n",reg); + } + if(reg & GPR_REG_MASK) return bdm_setreg(reg, val); + return bdm_setspr(reg, val); +} + +u_int ppc_bdm_getword(u_int addr) +{ + u_int r0; + u_int r1; + u_int val; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*set addr to r1*/ + com = (32 << 26) | (1 << 16); /*lwz r0,0(r1)*/ + ser_clkinstr(com, 0); /*load r0 with data from mem*/ + val = bdm_getreg(0); /*get data from r0*/ + bdm_setreg(0, r0); /*restore data*/ + bdm_setreg(1, r1); /*restore data*/ + + return val; +} + +void ppc_bdm_setword(u_int addr, u_int val) +{ + u_int r0; + u_int r1; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*put addr in r1*/ + bdm_setreg(0, val); /*put data in r0*/ + com = (36 << 26) | (1 << 16); /*stw r0,0(r1)*/ + ser_clkinstr(com, 0); /*store data into mem*/ + bdm_setreg(0, r0); /*restore r0*/ + bdm_setreg(1, r1); /*restore r1*/ +} + +u_int ppc_bdm_gethalfword(u_int addr) +{ + u_int r0; + u_int r1; + u_int val; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*set addr to r1*/ + com = (40 << 26) | (1 << 16); /*lhz r0,0(r1)*/ + ser_clkinstr(com, 0); /*load r0 with data from mem*/ + val = bdm_getreg(0); /*get data from r0*/ + bdm_setreg(0, r0); /*restore data*/ + bdm_setreg(1, r1); /*restore data*/ + + return val; +} + +void ppc_bdm_sethalfword(u_int addr, u_int val) +{ + u_int r0; + u_int r1; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*put addr in r1*/ + bdm_setreg(0, val); /*put data in r0*/ + com = (44 << 26) | (1 << 16); /*sth r0,0(r1)*/ + ser_clkinstr(com, 0); /*store data into mem*/ + bdm_setreg(0, r0); /*restore r0*/ + bdm_setreg(1, r1); /*restore r1*/ +} + +u_int ppc_bdm_getbyte(u_int addr) +{ + u_int r0; + u_int r1; + u_int val; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*set addr to r1*/ + com = (34 << 26) | (1 << 16); /*lbz r0,0(r1)*/ + ser_clkinstr(com, 0); /*load r0 with data from mem*/ + val = bdm_getreg(0); /*get data from r0*/ + bdm_setreg(0, r0); /*restore data*/ + bdm_setreg(1, r1); /*restore data*/ + + return val; +} + +void ppc_bdm_setbyte(u_int addr, u_int val) +{ + u_int r0; + u_int r1; + u_int com; + + r0 = bdm_getreg(0); /*save r0*/ + r1 = bdm_getreg(1); /*save r1*/ + bdm_setreg(1, addr); /*put addr in r1*/ + bdm_setreg(0, val); /*put data in r0*/ + com = (38 << 26) | (1 << 16); /*stb r0,0(r1)*/ + ser_clkinstr(com, 0); /*store data into mem*/ + bdm_setreg(0, r0); /*restore r0*/ + bdm_setreg(1, r1); /*restore r1*/ +} + + +u_int ppc_bdm_tablewalk(u_int vAddr) +{ + u_int EPN; + u_int TWC; + u_int Level1; + u_int Level2; + u_int Level2Desc; + u_int pAddr; + +/* return value in case of mmu problems : */ +/* emergency solution for second stage loader */ + pAddr = vAddr - mpcbdm_kbase; /* =-0xc0000000 */ + + EPN = bdm_getspr(SPR_MD_EPN); /* save EPN register */ + TWC = bdm_getspr(SPR_MD_TWC); /* save TWC register */ + + bdm_setspr(SPR_MD_EPN,vAddr); /* set effective addr to virtual addr*/ + Level1 = bdm_getspr(SPR_M_TWB); /* do table walk level 1*/ + if (Level1 == 0) + { + if (mpcbdm_verbose&VERBOSE_MMU) + { + printf("ppc_bdm_tablewalk: invalid level one descriptor for vAddr 0x%08x\n",vAddr); + } + else + { + printf("M!"); + } + return pAddr; + } + if ((Level1 & 0x0800)&&(mpcbdm_pgdir != 0)) /* kernel function? */ + { + Level1 = ((mpcbdm_pgdir & 0x3ffff000) | (Level1&0x00000fff)); + if (mpcbdm_verbose&VERBOSE_MMU) + { + printf("ppc_bdm_tablewalk: pgdir -> Level1 = 0x%08x for vAddr 0x%08x\n",Level1,vAddr); + } + } + Level2 = ppc_bdm_getword(Level1); + Level2 &= (u_int)0xfffff000; + if (Level2 == 0) + { + if (mpcbdm_verbose&VERBOSE_MMU) + { + printf("ppc_bdm_tablewalk: invalid level two base for vAddr 0x%08x and level one = 0x%08x\n",vAddr,Level1); + } + else + { + printf("M!"); + } + return pAddr; + } + Level2 -=mpcbdm_kbase; /* tophys, like table miss does, default=-0xc0000000 */ + Level2 |=0x000000001; /* set valid bit in physical L2 page */ + + bdm_setspr(SPR_MD_TWC,Level2); + Level2Desc= bdm_getspr(SPR_MD_TWC); /* perform table walk level 2*/ + if (Level2Desc == 0) + { + if (mpcbdm_verbose&VERBOSE_MMU) + { + printf("ppc_bdm_tablewalk: invalid level two descriptor for vAddr 0x%08x, level one 0x%08x, level two 0x%08x\n",vAddr,Level1,Level2); + } + else + { + printf("M!"); + } + return pAddr; + } + pAddr = ppc_bdm_getword(Level2Desc); /*get physical page addr*/ + pAddr = (pAddr & (u_int)0xfffff000) | (vAddr & (u_int)0xfff); /*calc physical addr*/ + + if (mpcbdm_verbose&VERBOSE_MMU) + { + printf("ppc_bdm_tablewalk: MMU translates virtual 0x%08x to physical 0x%08x\n",vAddr,pAddr); + } + + bdm_setspr(SPR_MD_TWC,TWC); /* restore TWC register */ + bdm_setspr(SPR_MD_EPN,EPN); /* restore EPN register */ + + return pAddr; +} + +void ppc_bdm_read_block(u_int from, char *to, int len) +{ + int n; + int val; + u_int r0 = bdm_getreg(0); /*save r0*/ + u_int r1 = bdm_getreg(1); /*save r1*/ + + if ((LastMSR & MSR_IR)&&(mpcbdm_mmu)) /*mmu on and option activated*/ + { + from = ppc_bdm_tablewalk(from); + } + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("ppc_bdm_read_block: from=0x%08x, len=%d\n",from,len); + } + + if(len > 0) + while((from & 3) || len < 4) /*no word aligned start adr?*/ + { + bdm_setreg(1, (int)from); + from += 1; + ser_clkinstr(0x88010000, 0); /* lbz r0,0(r1) */ + val = bdm_getreg(0); /* read byte*/ + *(u_char*)to = val & 0xFF; /* store byte*/ + to += 1; + if(!--len) break; + } + + if(len > 0 ) bdm_setreg(1, from - 4); + for(len; len > 3; len -= 4) /* loop for aligned words*/ + { + ser_clkinstr(0x84010004, 0); /* lwzu r0,4(r1) */ + val = bdm_getreg(0); /* read word*/ + val = extract_unsigned_integer(&val, sizeof(val)); + memcpy(to, &val, 4); /* store word */ + to += 4; + from +=4; /* FP: this one was missing ! */ + } + while(len > 0 && len < 4) /*misaligned bytes to read at end?*/ + { + bdm_setreg(1, from); + from += 1; + ser_clkinstr(0x88010000, 0); /* lbz r0,0(r1) */ + val = bdm_getreg(0); /*read byte*/ + *(u_char*)to = val & 0xFF; /*store byte*/ + to += 1; + --len; + } + + bdm_setreg(0, r0); /* restore r0*/ + bdm_setreg(1, r1); /* restore r1*/ +} + +void ppc_bdm_write_block(u_int mem, u_char *ozu, int len) +{ + u_int val; + u_int r30 = bdm_getreg(30); + u_int r31 = bdm_getreg(31); + + if ((LastMSR & MSR_IR)&&(mpcbdm_mmu)) /*mmu on and option activated*/ + { + mem = ppc_bdm_tablewalk(mem); + } + + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("ppc_bdm_write_block: mem=0x%08x, len=%d\n",mem,len); + } + + if(len > 0) + while((mem & 3) || len < 4) + { + bdm_setreg(30, (int)mem); mem += 1; + val = *(u_char*)ozu; ozu += 1; + bdm_setreg(31, val); + ser_clkinstr(0x9BFE0000, 0); /* stb r31,0(r30) */ + if(!--len) break; + } + + if(len > 3 ) /*for aligned words use BDM download feature*/ + { + bdm_setreg(30, mem - 4); + ser_clkdpc(DSDI_DPC_START_DOWNLOAD, 0); + for(; len > 3; len -= 4) + { + memcpy(&val, ozu, 4); ozu += 4; + val = extract_unsigned_integer(&val, sizeof(val)); + ser_clkdata(val, 0); + mem += 4; + } + ser_clkdpc(DSDI_DPC_END_DOWNLOAD, 0); + ser_clkdata(val, 0); + } + + while(len > 0) + { + bdm_setreg(30, (int)mem); mem += 1; + val = *(u_char*)ozu; ozu += 1; + bdm_setreg(31, val); + ser_clkinstr(0x9BFE0000, 0); /* stb r31,0(r30) */ + --len; + } + + bdm_setreg(30, r30); + bdm_setreg(31, r31); +} + + +/*************************************************************** +* MPCBDM target operations * +****************************************************************/ + +static void show_regs(void) +{ + int n; + int data; + + for(n = 0; n < 32; ++n) + { + data = bdm_getreg(n); + printf("R%02d=0x%08X ", n, data); + if(!((n + 1) % 4)) printf("\n"); + } + printf("\n"); +} + + +void ppc_bdm_stop(void) +{ +/* Reset and set DSCK and /DSDI for immediate Debug Mode, asynchronously clocked */ + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf_filtered("ppc_bdm_stop: assert Reset for immediate debug mode, asynchronous clocked\n"); + } + PP.Write(PP.DSCK); /* set DSCK and /DSDI, implicite wait in Write */ +/* assert /HRESET and /SRESET, hold DSCK and /DSDI : Debug Mode enable */ +/* Note: I added HRESET here, because sometimes only SRESET + didn't bring the processor in a stable state. So I completely removed + ppc_bdm_reset. But I'm not shure I broke something here...*/ + PP.Reset(PP.HRESET|PP.SRESET); +/* hold reset for some while, since here occured some problems with fast CPUs*/ + usleep(mpcbdm_sleep); +/* release H&SRESET, hold DSCK, /DSDI: immediate Debug Mode, asynchr. clocked*/ + PP.Reset(0x00); +/* we have to hold DSDI low for at least eight MPC cycles*/ + usleep(mpcbdm_sleep); + WaitFreeze(); + LastMSR = bdm_getspr(SPR_SRR1); + if (mpcbdm_verbose&VERBOSE_SRR1) + { + printf_filtered("ppc_bdm_stop: "); + print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); + printf_filtered("\n"); + } +} + +/*FIXME: remove?*/ +void ppc_bdm_reset(void) +{ + printf("assert HRESET\n"); + PP.Write(PP.DSCK); + PP.Reset(PP.HRESET); /*FP: assert HRESET with DSCK : Debug Mode enable */ +/* hold reset for some while, since here occured some problems with fast CPUs*/ + usleep(mpcbdm_sleep); + PP.Reset(0x00); /* release HRESET with DSCK, /DSDI: immediately debug, asynchr. clocked*/ +} + + +void ppc_bdm_resume() +{ + if (mpcbdm_reattach) + { + printf("*** Resume without communicating with the MPC (mpcbdm_reattach)\n"); + mpcbdm_reattach = 0; + ctrlc = 0; + return; + } + printf("*** Resume\n"); + ctrlc = 0; + bdm_getspr(SPR_ICR); /*read ICR to clear pending interrupts*/ + bdm_setspr(SPR_IC_CST, 0x0C000000); /*invalidate instruction cache*/ + /*tell PPC to exit from Debug Port Interrupt*/ + ser_clkinstr(DSDI_COM_RFI, 0); /*return from interrupt*/ +} + + +static void ppc_bdm_interrupt (int signo) +{ + signal(signo, ppc_bdm_interrupt); + + printf("CTRL-C catched - %d\n", ++ctrlc); + if(ctrlc >= 5) + { + printf("\n caught five times CTRL-C: BDM port is not responding.\nQuitting gdb\n"); + exit(-1); + } + ser_clkdpc(DSDI_DPC_ASSERT_NMASK_BREAK,0); /*signal debug port interrupt*/ + printf("Sending Debug Port Interrupt Request to PPC...\n"); +} + + +int ppc_bdm_wait(void) +{ + int icr = 0; + void (*ofunc)(); + + ofunc = signal (SIGINT, ppc_bdm_interrupt); /*install our handler*/ + printf("*** wait freeze\n"); + WaitFreeze(); /*wait for ppc to come into debug mode*/ + /*or interrupt ppc with ctrl-c with our handler*/ + signal (SIGINT, ofunc); /*restore old handler*/ + icr = bdm_getspr(SPR_ICR); /*interrupt cause register*/ + LastICR = icr; /*save interupt cause*/ +/*get srr1, contents of MSR before debug exception*/ + LastMSR = bdm_getspr(SPR_SRR1); + if (mpcbdm_verbose&VERBOSE_SRR1) + { + printf_filtered("ppc_bdm_wait: "); + print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); + printf_filtered("\n"); + } + + ser_clkdpc(DSDI_DPC_NEGATE_NMASK_BREAK,0); /*negate debug port interrupt request*/ +// ser_clkinstr(0x7C0004AC, 0); /* sync */ +// ser_clkinstr(0x4C00012C, 0); /* isync */ + if (mpcbdm_dflush) + { +/* flush all data cache blocks to see valid data, but this is slow*/ + mpcbdm_dcache_flush(0,1); + } + bdm_setspr(SPR_IC_CST, 0x0C000000); /*invalidate instruction cache*/ + + if(icr & PPC_BIT(17)) icr = 1; /* ICR[SEI] -> INT */ + else icr = 0; /* else TRAP */ + return icr; +} + + +void ppc_bdm_step(void) +{ + if (mpcbdm_reattach) + { + printf("*** step without communicating with the MPC (mpcbdm_reattach)\n"); + } + else + { + printf("*** step\n"); + LastDER = bdm_getspr(SPR_DER); /*save previous Debug Enable Register value*/ + bdm_setspr(SPR_DER, LastDER | PPC_BIT(14)); /* force TRE for single step*/ +/* set single step trace enable in next MSR */ + bdm_setspr(SPR_SRR1, bdm_getspr(SPR_SRR1) | PPC_BIT(21)); + } + ppc_bdm_resume(); /*execute one step*/ +} + + +void ppc_bdm_run(void) +{ + if (mpcbdm_reattach) + { + printf("*** run without communicating with the MPC (mpcbdm_reattach)\n"); + } + else + { + printf("*** run\n"); + LastDER = bdm_getspr(SPR_DER); /*save previous Debug Enable Register value*/ +/* disable single step trace enable (SE) */ + bdm_setspr(SPR_SRR1, bdm_getspr(SPR_SRR1) & ~(PPC_BIT(21))); + } + ppc_bdm_resume(); +} + +void ppc_bdm_init(void) +{ + int i; + int n; + u_int pvr; + u_int partmask; + u_int revnum; + u_int word; + u_int partnum; + u_int masknum; + + if (mpcbdm_reattach) + { + return; + } + + printf_filtered("*** init\n"); + +/* try to identify processor */ + pvr = bdm_getspr(SPR_PVR); /* get processor version register */ + partmask = 0x0000ffff & bdm_getspr(SPR_IMMR); /* get IMMR */ + partnum = (partmask & 0x0000ff00) >> 8; + masknum = partmask & 0x000000ff; + word = bdm_getspri(SPRI_REV_NUM); /* get REV_NUM */ + revnum = (word & 0xffff0000) >> 16; + printf_filtered("Target cpu PVR=0x%08X PARTNUM=0x%02X MASKNUM=0x%02X REV_NUM=0x%04X\n", + pvr,partnum,masknum,revnum); + + for (i=0; CPU[i].name; i++) + { + if ((pvr == CPU[i].pvr) && (partmask == CPU[i].partmask) && (revnum == CPU[i].revnum)) + { + printf_filtered("Target cpu is a '%s'\n",CPU[i].name); + if (CPU[i].regfile) + { + printf_filtered("Reading CPU register description file '%s'\n",CPU[i].regfile); + } + break; + } + } + if (!(CPU[i].name)) + { + printf_filtered("warning: unknown CPU. Using default register description\n"); + } + +/*initial value for Debug Enable Register*/ +/* SEIE for soft breakpoint recognition (illegal opcode) needed */ + bdm_setspr(SPR_DER, 0x7002400F); /*RSTE,CHSTPE,MCIE,TRE,SEIE,LBRKE,IBRKE,EBRKE,DPIE*/ + bdm_setspr(SPRI_PLPRCR, bdm_getspr(SPRI_PLPRCR) | PPC_BIT(24)); /*CSE, CheckStopEnable*/ + bdm_setsprihw(SPRI_SWSR, 0x556C); /*trigger software watch dog*/ + bdm_setsprihw(SPRI_SWSR, 0xAA39); + LastMSR = bdm_getspr(SPR_SRR1); + if (mpcbdm_verbose&VERBOSE_SRR1) + { + printf_filtered("ppc_bdm_init: "); + print_spr_info(SPR_SRR1, LastMSR, 1, 1, 1, 1); + printf_filtered("\n"); + } + printf("\007BDM initialized\n"); +} + +/*********************************************************** +* routines from ocd.c * +***********************************************************/ + +/* Return nonzero if the thread TH is still alive on the remote system. */ + +int mpcbdm_thread_alive (ptid_t pid_t) +{ + return 1; +} + +/* Clean up connection to a remote debugger. */ + +/* ARGSUSED */ +void mpcbdm_close (int quitting) +{ + /* if (mpcbdm_desc) + SERIAL_CLOSE (mpcbdm_desc); + mpcbdm_desc = NULL; */ +} + +/* Stub for catch_errors. */ + +static int mpcbdm_start_remote (PTR dummy) +{ + int nResult; + int port; + + if (!dummy) + { + if (PP.port == -1) + { + printf_filtered("port number is required\n"); + return 0; + } + else + { + port = PP.port; /* preveously used port*/ + } + } + else /* port number specified */ + { + PP.port = -1; + port = (int)strtoul((char*) dummy,0,0); /* read port number */ + } + + immediate_quit = 1; /* Allow user to interrupt it */ + + nResult = PortInit(port); + if (nResult == RETURN_FAIL) + { + printf_filtered("error on opening printer port %d\n",port); + return 0; + } + + mpcbdm_icr_or = 0; /* init core interrupt counter */ + +/* setup processor vor debugging */ + ppc_bdm_stop(); + ppc_bdm_init(); + + immediate_quit = 0; + +/* This is really the job of start_remote however, that makes an assumption + that the target is about to print out a status message of some sort. That + doesn't happen here (in fact, it may not be possible to get the monitor to + send the appropriate packet). */ + + flush_cached_frames (); + registers_changed (); + stop_pc = read_pc (); + set_current_frame (create_new_frame (read_fp (), stop_pc)); + select_frame (get_current_frame (), 0); + print_stack_frame (selected_frame, -1, 1); + + return 1; +} + +/* Open a connection to a remote debugger. + NAME is the filename used for communication. */ + +/* static DCACHE *mpcbdm_dcache; */ + +void mpcbdm_open (char *name, int from_tty) +{ + unsigned char buf[10], *p; + int status; + + target_preopen (from_tty); + + current_ops = &mpcbdm_ops; + + unpush_target (current_ops); + + /* mpcbdm_dcache = dcache_init (mpcbdm_read_bytes, mpcbdm_write_bytes); */ + + // printf("FP_REGNUM=%d\n", FP_REGNUM); + + printf_filtered("MPCBDM version %s\n",sVersion); +/* + if (from_tty) + { + puts_filtered ("Remote target MPCBDM connected to parallel port "); + puts_filtered (name); + puts_filtered ("\n"); + } +*/ + + push_target (current_ops); /* Switch to using remote target now */ + + /* Without this, some commands which require an active target (such as kill) + won't work. This variable serves (at least) double duty as both the pid + of the target process (if it has such), and as a flag indicating that a + target is active. These functions should be split out into seperate + variables, especially since GDB will someday have a notion of debugging + several processes. */ + + inferior_ptid.pid = 42000; + /* Start the remote connection; if error (0), discard this target. + In particular, if the user quits, be sure to discard it + (we'd be in an inconsistent state otherwise). */ + + + if (!catch_errors (mpcbdm_start_remote, name, + "Couldn't establish connection to remote target\n", + RETURN_MASK_ALL)) + { + pop_target(); + error("Failed to connect to target 'mpcbdm'"); + } +} + +/* This takes a program previously attached to and detaches it. After + this is done, GDB can be used to debug some other program. We + better not have left any breakpoints in the target program or it'll + die when it hits one. */ + +void mpcbdm_detach (char *args, int from_tty) +{ + if (args) + error ("Argument given to \"detach\" when remotely debugging."); + + pop_target (); + if (from_tty) + puts_filtered ("Ending remote debugging.\n"); +} + +/* Tell the remote machine to resume. */ + +void mpcbdm_resume (ptid_t pid_t, int step, enum target_signal siggnal) +{ + int pid = pid_t.pid; + + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("mpcbdm_resume %s\n", step?"step":"run"); + } + /* dcache_flush (mpcbdm_dcache); */ + if(step) ppc_bdm_step(); + else ppc_bdm_run(); +} + +/* Wait until the remote machine stops, then return, + storing status in STATUS just as `wait' would. + Returns "pid" (though it's not clear what, if anything, that + means in the case of this target). */ + +void mpcbdm_prepare_to_store (void) +{ +} + + +/* Read or write LEN bytes from inferior memory at MEMADDR, transferring + to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is + nonzero. Returns length of data written or read; 0 for error. */ + +int mpcbdm_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, + int should_write, struct target_ops *target) +{ + u_int val; + u_int n; + u_int mem = memaddr; + + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("mpcbdm_xfer_memory: memaddr 0x%08x myaddr 0x%08x len %d write %d\n",memaddr,myaddr,len,should_write); + } + + if(should_write) + { + ppc_bdm_write_block(mem, myaddr, len); + } + else + { + ppc_bdm_read_block(mem, myaddr, len); + } + return len; +} + +void mpcbdm_files_info (struct target_ops *ignore) +{ + puts_filtered ("Debugging a MPC target through the BDM interface over a parallel port.\n"); +} + + +void mpcbdm_kill (void) +{ + /* For some mysterious reason, wait_for_inferior calls kill instead of + mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ + if (mpcbdm_kill_kludge) + { + mpcbdm_kill_kludge = 0; + target_mourn_inferior (); + return; + } + +/* Don't wait for it to die. I'm not really sure it matters whether + we do or not. */ + target_mourn_inferior (); +} + +void mpcbdm_mourn (void) +{ + unpush_target (current_ops); + generic_mourn_inferior (); +} + +/* All we actually do is set the PC to the start address of exec_bfd, and start + the program at that point. */ + +void mpcbdm_create_inferior (char *exec_file, char *args, char **env) +{ + if (args && *args) + error ("Args are not supported by BDM."); + + clear_proceed_status (); + proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0); +} + +void mpcbdm_load (char *args, int from_tty) +{ + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("mpcbdm_load: args %s from_tty %d\n",args,from_tty); + } + + generic_load (args, from_tty); + +/*FP inferior_ptid = 0;*/ + +/* This is necessary because many things were based on the PC at the time that + we attached to the monitor, which is no longer valid now that we have loaded + new code (and just changed the PC). Another way to do this might be to call + normal_stop, except that the stack may not be valid, and things would get + horribly confused... */ + + clear_symtab_users (); +} + +/* This should be defined for each target */ +/* But we want to be able to compile this file for some configurations + not yet supported fully */ + +int mpcbdm_insert_breakpoint (CORE_ADDR addr, char *contents_cache) +{ + int i; + unsigned int ictrl; + unsigned int hwmask; + + if (mpcbdm_hwbrk) /*use MPC hardware registers?*/ + { + for (i = 0; i < mpcbdm_maxhwbrk; i++) + { + if (!hwbrk_used[i]) + break; + } + if (i >= mpcbdm_maxhwbrk) + { + printf("too many hardware breakpoints: only %d supported\n",mpcbdm_maxhwbrk); + return 1; + } + + ictrl = bdm_getspr(SPR_ICTRL); + + /*mask for ictrl: CTx = 100 | IWx = 10 | SIWxEN = 1*/ + hwmask = (1<<(31-i*3)) | (1<<(19-i*2)) | (1<<(11-i)); + if (mpcbdm_verbose&VERBOSE_BRK) + printf("enable hardware breakpoint %d : addr 0x%08x ICTRL mask = 0x%08x\n",i,addr,hwmask); + + ictrl |= hwmask; /*enable CMPx*/ + bdm_setspr(SPR_ICTRL,ictrl); + bdm_setspr(SPR_CMPA+i, (unsigned int) addr); + + hwbrk_used[i] = 1; /* remember break point and addr*/ + hwbrk_adr[i] = (unsigned int) addr; + + return 0; + } + + /* use illegal opcodes for software emulation exception*/ + + target_read_memory (addr, contents_cache, sizeof (break_insn)); + target_write_memory (addr, break_insn, sizeof (break_insn)); + return 0; +} + +int mpcbdm_remove_breakpoint (CORE_ADDR addr, char *contents_cache) +{ + int i; + unsigned int ictrl; + unsigned int hwmask; + + if (mpcbdm_hwbrk) /*use MPC hardware registers?*/ + { + for (i = 0; i < mpcbdm_maxhwbrk; i++) + { + if (hwbrk_used[i] && (hwbrk_adr[i] == (unsigned int) addr)) /* brkp found?*/ + break; + } + if (i >= mpcbdm_maxhwbrk) + { + printf("no matching hardware breakpoint found\n"); + return 1; + } + ictrl = bdm_getspr(SPR_ICTRL); + hwmask = (1<<(31-i*3)) | (1<<(19-i*2)) | (1<<(11-i)); + if (mpcbdm_verbose&VERBOSE_BRK) + printf("disable hardware breakpoint %d : addr 0x%08x ICTRL mask = 0x%08x\n",i,addr,hwmask); + ictrl &= ~hwmask; /*disable CMPx*/ + bdm_setspr(SPR_ICTRL,ictrl); + + hwbrk_used[i] = 0; + + return 0; + } + + /* use illegal opcodes for software emulation exception*/ + + target_write_memory (addr, contents_cache, sizeof (break_insn)); + + return 0; +} + +static void bdm_command (char *args, int from_tty) +{ + error ("try 'help mpcbdm' for target specific commands"); +} + +static void mpcbdm_reset_command (char *args, int from_tty) +{ + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("mpcbdm_reset_command: args %s from_tty %d\n",args,from_tty); + } + ppc_bdm_stop(); +} + +static void mpcbdm_restart_command (char *args, int from_tty) +{ + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("mpcbdm_restart_command: args %s from_tty %d\n",args,from_tty); + } + mpcbdm_start_remote(args); +} + +/* Temporary replacement for target_store_registers(). This prevents + generic_load from trying to set the PC. */ + +static void noop_store_registers (int regno) +{ +} + +static int findsprnum(char *pch) +{ + int n; + char *p; + + for(p = pch; *p ; ++p) *p = toupper(*p); + + for(n = 0; sprnames[n].name; ++n) + { + if(!strcmp(sprnames[n].name, pch)) return sprnames[n].num; + } + + return -1; +} + +void print_spr_info(int num,u_int val, int bName, int bDef, int bVal, int bPretty) +{ + int i; + int index; + int startbit,bit; + int len; + int bFirstPrinted; + int bSPRI; + u_int bitmask; + u_int bitfieldmask; + u_int bitfieldval; + char *pFormat; + char *pFieldName; + char *pFieldNameEnd; + char FieldName[255]; + + index = -1; + for(i = 0; sprnames[i].name ; ++i) + { + if(sprnames[i].num == num) + { + index = i; + break; + } + } + + bSPRI = (num & SPRI_MASK); + num &= (GPR_REG_MASK-1); /*remove register markings*/ + + if (index < 0) /*not in sprnames*/ + { + if (bName) + { + if (bSPRI) + printf("SPRI 0x%x", num); + else + printf("SPR %d", num); + } + if (bVal) + { + printf(" = 0x%08x", val); + } + return; + } + + pFormat = sprnames[i].Namefield; + if (!pFormat) /*no bitfield description available?*/ + { + if (bDef) + { + if (bSPRI) + { + printf("IMMR + 0x%x",num); + } + else + { + printf("SPR %d",num); + } + if ((bName) && (sprnames[i].name)) + printf(" : %s", sprnames[i].name); + } + else if ((bName) && (sprnames[i].name)) + printf("%s", sprnames[i].name); + + if (bVal) + printf(" = 0x%08x", val); + if (bDef) + { + if (sprnames[i].Longname) printf(" , %s", sprnames[i].Longname); + if (sprnames[i].Reference) printf(" , %s", sprnames[i].Reference); + if ((sprnames[i].Longname) || (sprnames[i].Reference)) printf("\n"); + } + return; /*for no Format description, we are finished here */ + } + +/*start of pretty print*/ + if (bDef) /* print name and format description field?*/ + { + printf("%s := (%s)\n",sprnames[index].name,sprnames[index].Namefield); + if (bSPRI) + printf("IMMR + 0x%x:",num); + else + printf("SPR %d:",num); + if (sprnames[i].Longname) + { + printf("%s", sprnames[i].Longname); + if (sprnames[i].Reference) printf(", "); + } + if (sprnames[i].Reference) printf("%s", sprnames[i].Reference); + printf("\n"); + } + if (bName) + { + if (sprnames[i].name) printf("%s", sprnames[i].name); + else + { + if (bSPRI) + printf("IMMR + 0x%x",num); + else + printf("SPR %d",num); + } + } + if (bVal) + { + printf(" = 0x%08x", val); + } + if (bPretty) + { + startbit = 0; + bFirstPrinted = 0; + if (isdigit(*pFormat)) /*extra case first field starting not at bit zero*/ + { + i = sscanf(pFormat,"%d",&startbit); + if ((startbit<0) || (startbit >PPC_BITS)|| (i!=1)) + { + printf("\nerror in bitfield description string %s\n",sprnames[index].Namefield); + printf(" wrong bit position %d at %s\n",startbit, pFormat); + return; + } + do + { + pFormat++; + } while (isdigit(*pFormat)); + } + while ((*pFormat)) + { + pFieldName = pFormat; + pFormat = strchr(pFormat,'|'); + if (!pFormat) /*last entry*/ + { + bit = PPC_BITS; /*reached last bit*/ + len = strlen(pFieldName); + } + else + { + len = pFormat-pFieldName; + pFormat++; /*skip |*/ + if (isdigit(*pFormat)) /*bitfield or single bit*/ + { + i = sscanf(pFormat,"%d",&bit); + if ((bit<0) || (bit >PPC_BITS) ||(bit <=startbit) || (i!=1)) + { + printf("error in bitfield description string %s\n",sprnames[index].Namefield); + printf(" wrong bit position %d at %s\n",bit,pFormat); + return; + } + do + { + pFormat++; + } while (isdigit(*pFormat)); + } + else bit = startbit + 1; + } + strncpy(FieldName,pFieldName,len); + FieldName[len]= 0; + + bitmask = PPC_BIT(startbit); + bitfieldval = 0; + for (i = startbit; i> 1; + } + if (len != 0) /*name, no spare bit field?*/ + { + if (bit-startbit >1) /*multi bitfield*/ + { + if (!bFirstPrinted) + { + bFirstPrinted = 1; + printf(" = ("); + } + else printf("|"); + printf("%s=0x%x",FieldName,bitfieldval); + } + else if (bitfieldval) /*single bit*/ + { + if (!bFirstPrinted) + { + bFirstPrinted = 1; + printf(" = ("); + } + else printf("|"); + printf("%s",FieldName); + } + } + if (bit >= PPC_BITS) + { + break; + } + startbit = bit; + } + if (bFirstPrinted) printf(")"); + } +} + + +static void mpcbdm_spr_command (char *args, int from_tty) +{ + int reg; + u_int val; + char *name; + char *svalue = 0; + char *pch; + int i; + int num; + + if (!args) + { + printf_filtered("List of supported SPRs:\n"); + for(i = 0; sprnames[i].name ; ++i) + { + printf_filtered("%s",sprnames[i].name); + num = sprnames[i].num; + if (num & SPRI_MASK) + printf_filtered("\tIMMR + 0x%x",num & ~SPRI_MASK); + else if (num & SPR_MASK) + printf_filtered("\t"); + else + printf_filtered("\tSPR %d ",num); + if (sprnames[i].Longname) + { + printf_filtered("\t%s", sprnames[i].Longname); + } + printf_filtered("\n"); + } + return; + } + + if (mpcbdm_reattach) + { + printf_filtered("!C\n"); + return; + } + + if (pch = strchr(args,'=')) /*set command ?*/ + { + svalue = pch+1; + while(*svalue <= 040) ++svalue; /*read spaces*/ + *pch-- = 0; + while(*pch <= 040) *pch-- = 0; + } + if (isdigit(*args)) /*spr by number?*/ + { + reg = strtol(args,0,0); + } + else /*by name?*/ + { + reg = findsprnum(args); + } + + if (reg < 0) + { + printf_filtered("Invalid SPR\n"); + return; + } + + if (svalue) /*set command?*/ + { + val = strtoul(svalue,0,0); + bdm_setspr(reg,val); /*set value*/ + } + else /* show register */ + { + if (reg == SPR_ICR) /* reading ICR clears bits, so show old values */ + { + val = LastICR; + } + else val = bdm_getspr(reg); + + print_spr_info(reg,val,1,1,1,1); /* show register name, def, val and pretty */ + printf_filtered("\n"); + } +} + + +/*********************************************************** +* routines from ppc-bdm.c * +***********************************************************/ + +/* Wait until the remote machine stops, then return, + storing status in STATUS just as `wait' would. + Returns "pid" (though it's not clear what, if anything, that + means in the case of this target). */ + +static ptid_t bdm_ppc_wait (ptid_t pid_t, struct target_waitstatus *target_status) +{ + int pid = pid_t.pid; + int stop_reason; + + if (mpcbdm_verbose&VERBOSE_SER) + { + printf("bdm_ppc_wait:\n"); + } + target_status->kind = TARGET_WAITKIND_STOPPED; + + stop_reason = ppc_bdm_wait(); + + if (stop_reason) + { + target_status->value.sig = TARGET_SIGNAL_INT; + return inferior_ptid; + } + + target_status->value.sig = TARGET_SIGNAL_TRAP; /* XXX for now */ + return inferior_ptid; +} + +/* Read the remote registers into regs. + Fetch register REGNO, or all registers if REGNO == -1 + + */ + +static void bdm_ppc_fetch_registers (int regno) +{ + int i; + int first; + int last; + int val; + + if (mpcbdm_verbose&VERBOSE_SER) + { + printf("bdm_ppc_fetch_registers: regno %d",regno); + } + if(regno == -1) + { + first = 0; + last = NUM_REGS-1; + } + else + { + first = last = regno; + } + + for (i = first; i <= last; i++) + { + if(i == MQ_REGNUM || (i >= FP0_REGNUM && i <= FPLAST_REGNUM)) + { + supply_register(i, 0); + continue; + } + val = ppc_read_bdm_register(bdm_regmap[i]); + supply_register(i, (char*)&val); + } +} + +/* Store register REGNO, or all registers if REGNO == -1, from the contents + of REGISTERS. FIXME: ignores errors. */ + +static void bdm_ppc_store_registers (int regno) +{ + int i; + int first; + int last; + int val; + + if (mpcbdm_verbose&VERBOSE_TAR) + { + printf("bdm_ppc_store_registers: regno %d",regno); + } + if(regno == -1) + { + first = 0; + last = NUM_REGS-1; + } + else + { + first = last = regno; + } + + for (i = first; i <= last; i++) + { + if(i == MQ_REGNUM || (i >= FP0_REGNUM && i <= FPLAST_REGNUM)) + continue; + memcpy (&val , ®isters[REGISTER_BYTE (i)], REGISTER_RAW_SIZE (i)); + ppc_write_bdm_register(bdm_regmap[i], val); + } +} + +/* Define the target subroutine names */ +static void init_mpcbdm_ops(void) +{ + mpcbdm_ops.to_shortname = "mpcbdm"; + mpcbdm_ops.to_longname = "Background Debug Mode Interface for Motorola MPC-Family"; + mpcbdm_ops.to_doc = "Use On-Chip Debugging on MPC's via parallel port BDM interface" ; /* to_doc */ + mpcbdm_ops.to_open = mpcbdm_open; + mpcbdm_ops.to_close = mpcbdm_close; + mpcbdm_ops.to_attach = NULL; + mpcbdm_ops.to_post_attach = NULL; + mpcbdm_ops.to_require_attach = NULL; + mpcbdm_ops.to_detach = mpcbdm_detach; + mpcbdm_ops.to_require_detach = NULL; + mpcbdm_ops.to_resume = mpcbdm_resume; + mpcbdm_ops.to_wait = bdm_ppc_wait; + mpcbdm_ops.to_post_wait = NULL; + mpcbdm_ops.to_fetch_registers = bdm_ppc_fetch_registers; + mpcbdm_ops.to_store_registers = bdm_ppc_store_registers; + mpcbdm_ops.to_prepare_to_store = mpcbdm_prepare_to_store; + mpcbdm_ops.to_xfer_memory = mpcbdm_xfer_memory; + mpcbdm_ops.to_files_info = mpcbdm_files_info; + mpcbdm_ops.to_insert_breakpoint = mpcbdm_insert_breakpoint; + mpcbdm_ops.to_remove_breakpoint = mpcbdm_remove_breakpoint; + mpcbdm_ops.to_terminal_init = NULL; + mpcbdm_ops.to_terminal_inferior = NULL; + mpcbdm_ops.to_terminal_ours_for_output = NULL; + mpcbdm_ops.to_terminal_ours = NULL; + mpcbdm_ops.to_terminal_info = NULL; + mpcbdm_ops.to_kill = mpcbdm_kill; + mpcbdm_ops.to_load = mpcbdm_load; + mpcbdm_ops.to_lookup_symbol = NULL; + mpcbdm_ops.to_create_inferior = mpcbdm_create_inferior; + mpcbdm_ops.to_post_startup_inferior = NULL; + mpcbdm_ops.to_acknowledge_created_inferior = NULL; + mpcbdm_ops.to_clone_and_follow_inferior = NULL; + mpcbdm_ops.to_post_follow_inferior_by_clone = NULL; + mpcbdm_ops.to_insert_fork_catchpoint = NULL; + mpcbdm_ops.to_remove_fork_catchpoint = NULL; + mpcbdm_ops.to_insert_vfork_catchpoint = NULL; + mpcbdm_ops.to_remove_vfork_catchpoint = NULL; + mpcbdm_ops.to_has_forked = NULL; + mpcbdm_ops.to_has_vforked = NULL; + mpcbdm_ops.to_can_follow_vfork_prior_to_exec = NULL; + mpcbdm_ops.to_post_follow_vfork = NULL; + mpcbdm_ops.to_insert_exec_catchpoint = NULL; + mpcbdm_ops.to_remove_exec_catchpoint = NULL; + mpcbdm_ops.to_has_execd = NULL; + mpcbdm_ops.to_reported_exec_events_per_exec_call = NULL; + mpcbdm_ops.to_has_exited = NULL; + mpcbdm_ops.to_mourn_inferior = mpcbdm_mourn; + mpcbdm_ops.to_can_run = 0; + mpcbdm_ops.to_notice_signals = 0; + mpcbdm_ops.to_thread_alive = mpcbdm_thread_alive; + mpcbdm_ops.to_stop = ppc_bdm_stop; + mpcbdm_ops.to_pid_to_exec_file = NULL; + mpcbdm_ops.to_stratum = process_stratum; + mpcbdm_ops.DONT_USE = NULL; + mpcbdm_ops.to_has_all_memory = 1; + mpcbdm_ops.to_has_memory = 1; + mpcbdm_ops.to_has_stack = 1; + mpcbdm_ops.to_has_registers = 1; + mpcbdm_ops.to_has_execution = 1; + mpcbdm_ops.to_sections = NULL; + mpcbdm_ops.to_sections_end = NULL; + mpcbdm_ops.to_magic = OPS_MAGIC; +} /* init_mpcbdm_ops */ + +/*********************************************************** +* mpcbdm obscure routines * +***********************************************************/ + +static void mpcbdm_obscure_upms(char *args, int from_tty) +{ + int n; + + printf("============\n"); + for(n = 0; n < 64; ++n) + { + bdm_setspr(SPRI_MCR, (01 << 30) | n); + printf("MDR%02d=0x%08x ", n, bdm_getspr(SPRI_MDR)); + if(!((n+1) % 4)) printf("\n"); + } + printf("============\n"); + + printf("BR0=0x%08x\n", bdm_getspr(SPRI_BRx(0))); + printf("OR0=0x%08x\n", bdm_getspr(SPRI_ORx(0))); + printf("BR1=0x%08x\n", bdm_getspr(SPRI_BRx(1))); + printf("OR1=0x%08x\n", bdm_getspr(SPRI_ORx(1))); + printf("BR2=0x%08x\n", bdm_getspr(SPRI_BRx(2))); + printf("OR2=0x%08x\n", bdm_getspr(SPRI_ORx(2))); + + printf("MAMR=0x%08x\n", bdm_getspr(SPRI_MAMR)); + printf("MAR=0x%08x\n", bdm_getspr(SPRI_MAR)); + printf("MDR=0x%08x\n", bdm_getspr(SPRI_MDR)); + printf("MCR=0x%08x\n", bdm_getspr(SPRI_MCR)); + printf("MSTAT=0x%08x\n", bdm_getspr(SPRI_MSTAT)); +} + +static void show_spr(char *args, int from_tty) +{ + int i; + u_int val; + + int RegList[] = + { + SPR_SRR0, + SPR_SRR1, + SPR_MSR, + SPR_BAR, + SPR_DAR, + SPR_DSISR, + SPR_DER, + SPR_ICR, + SPR_ICTRL, + SPRI_PLPRCR, + SPRI_RSR, + SPRI_SCCR, + SPRI_SYPCR, + SPRI_SIUMCR, + 0 + }; + + for (i = 0; RegList[i]; i++) + { + val = bdm_getspr(RegList[i]); + print_spr_info(RegList[i], val,1,0,0,0); /* show name*/ + printf_filtered("\t"); + print_spr_info(RegList[i], val,0,0,1,1); /* val and pretty */ + printf_filtered("\n"); + } +} + +/***************************************************************** +* memory dump routines * +*****************************************************************/ +static char * parse_filename(char** sArgs) +{ + char *fq; + char *lq; + + if (!sArgs) return NULL; + if (!(*sArgs)) return NULL; + + fq = strchr(*sArgs,'\"'); /* get first double quote */ + if (!fq) return NULL; + + lq = strrchr(*sArgs,'\"'); /* get last double quote */ + if ((!lq) || (lq <= fq)) return NULL; + + (*lq) = 0; /* set end of filename string FIXME: better copy name, instead of messing arround?*/ + + (*sArgs) = lq + 1; /* adjust argument pointer */ + + return fq + 1; /*return pointer to beginning of filename*/ +} + +/*****************************************************************/ +static void mem_load(char * sFilename, u_int start, u_int len) +{ + FILE * f; + u_int nTotal; + u_int nBuffer; + u_int nLeft; + int nResult; + + printf_filtered("mem load \"%s\" to 0x%08x len %d\n", sFilename, start, len); + + if (!sFilename) + { + error("parameter syntax error."); + return; + } + + f = fopen(sFilename, "rb"); + + if(!f) + { + error("failed to open input file."); + return; + } + + if (!len) + { + nResult = fseek(f, 0, SEEK_END); + if (nResult) + { + error("fseek error."); + if (f) fclose(f); + return; + } + len = ftell(f); + printf_filtered(" len = 0x%08x, total file length\n", len); + rewind(f); + } + + for (nTotal = 0, nLeft = len; nLeft > 0; nTotal += nBuffer, nLeft -= nBuffer) + { + if(nLeft > MAXBUFFERLEN) + { + nBuffer = MAXBUFFERLEN; + } + else + { + nBuffer = nLeft; + } + nResult = fread(FileBuffer, 1, nBuffer, f); + if (nResult != nBuffer) + { + error("read error."); + break; + } + + ppc_bdm_write_block(start + nTotal, FileBuffer, nBuffer); + + } + if (f) fclose(f); +} + +/*****************************************************************/ + +static void mem_save(char * sFilename, u_int start, u_int len) +{ + FILE * f; + u_int nTotal; + u_int nBuffer; + u_int nLeft; + int nResult; + + printf_filtered("mem save \"%s\" from 0x%08x len %d\n", sFilename, start, len); + + if ((!sFilename) || (!len)) + { + error("parameter syntax error."); + return; + } + + f = fopen(sFilename, "wb"); + + if(!f) + { + error("failed to open output file."); + return; + } + + for (nTotal = 0, nLeft = len; nLeft > 0; nTotal += nBuffer, nLeft -= nBuffer) + { + if(nLeft > MAXBUFFERLEN) + { + nBuffer = MAXBUFFERLEN; + } + else + { + nBuffer = nLeft; + } + ppc_bdm_read_block(start + nTotal, FileBuffer, nBuffer); + + nResult = fwrite(FileBuffer, 1, nBuffer, f); + + if (nResult != nBuffer) + { + error("write error."); + break; + } + } + if (f) fclose(f); +} + +/*****************************************************************/ +static void mpcbdm_mem(char *args, int from_tty) +{ + u_int MemStart,MemEnd,MemLen; /* memory range */ + char *sParse; + char *sFilename; + + if (args != 0) /* arguments ?*/ + { + sParse = args; + if (strncmp(sParse,"load ",5) == 0) + { + sParse +=5; + + sFilename = parse_filename(&sParse); + if (!sFilename) + { + printf_filtered("error while parsing filename\n"); + return; + } + + MemStart = strtoul(sParse,&sParse,0); /*for testing destination ADDR*/ + MemLen = strtoul(sParse,&sParse,0); /*for testing len */ + + mem_load(sFilename, MemStart, MemLen); + return; + } + else if (strncmp(sParse,"save ",5) == 0) + { + sParse +=5; + + sFilename = parse_filename(&sParse); + if (!sFilename) + { + printf_filtered("error while parsing filename\n"); + return; + } + + MemStart = strtoul(sParse,&sParse,0); /*for testing destination ADDR*/ + MemLen = strtoul(sParse,&sParse,0); /*for testing len */ + + mem_save(sFilename, MemStart, MemLen); + return; + } + } + + printf_filtered("try 'help mpcbdm mem' for a list of supported commands\n"); +} + +/***************************************************************** +* Cache routines * +/*****************************************************************/ +static void mpcbdm_icache(char *args, int from_tty) +{ + u_int CacheAdr; /* IC_ADR value for reading cache content */ + u_int CacheDat; /* IC_DAT value for reading cache content */ + u_int OldICacheAdr; /* IC_ADR value for restoring */ + u_int IC_CST; /* IC_CST value*/ + u_int adr; /* cached adr */ + u_int LRU; /* Last Recently Used Code: 1 bit for 860, 6 bit for 860P/DP instruction cache */ + + int set; + int way; + + if (args == 0) /* no arguments ?*/ + { + IC_CST = bdm_getspr(SPR_IC_CST); + printf_filtered("icache:"); + if (IC_CST & MPC_IC_CST_IEN) + { + printf_filtered(" enabled"); + } + else + { + printf_filtered(" disabled"); + } + printf_filtered("\n"); + OldICacheAdr = bdm_getspr(SPR_IC_ADR); + for (set=0; set < MPC_ICACHE_SETS; set++) + { + printf_filtered("set0x%02x: ",set); + for (way=0; way < MPC_ICACHE_WAYS; way++) + { +/* read tags */ + CacheAdr = (way<<(31-19)) | (set << (31-27)); + bdm_setspr(SPR_IC_ADR, CacheAdr); + CacheDat = bdm_getspr(SPR_IC_DAT); + adr = (CacheDat & MPC_IC_DAT_TAG) | (set << (31-27)); + + if (way == 0) /* first output ?*/ + { + LRU = (CacheDat & MPC_IC_DAT_LRU) >> MPC_IC_DAT_LRU_SHIFT; + printf_filtered("LRU=0x%1x ",LRU); + } + else /* not first way, print separator */ + { + printf_filtered(", "); + } + + printf_filtered("way%1x:0x%08x..%1x",way,adr,MPC_ICACHE_SIZE-1); + if (CacheDat & MPC_IC_DAT_VALID) + printf_filtered(" val"); + else + printf_filtered(" "); + if (CacheDat & MPC_IC_DAT_LOCKED) + printf_filtered(" lck"); + else + printf_filtered(" "); + } + printf_filtered("\n"); + } + bdm_setspr(SPR_IC_ADR,OldICacheAdr); + } + else + { + printf_filtered("no args supported for 'mpcbdm icache'\n"); + } +} + +/*****************************************************************/ +static void mpcbdm_dcache_flush(u_int Adr, int bAll) +{ + u_int CacheAdr; /* DC_ADR value for reading cache content */ + u_int CacheDat; /* DC_DAT value for reading cache content */ + u_int OldDCacheAdr; /* DC_ADR value for restoring */ + u_int DC_CST; /* DC_CST value*/ + u_int adr; /* cached adr */ + u_int pAddr; /* cached physical address */ + u_int ValMod; /* helper variable for valid modified entry test */ + + int set; + int way; + + if (bAll) + { +/* if verbose on data cache ops, be informative, */ +/* but allow flushing in all cases, even if unnecessary */ + if (mpcbdm_verbose&VERBOSE_DCA) + { + DC_CST = bdm_getspr(SPR_DC_CST); + + if (!(DC_CST & MPC_DC_CST_DEN)) /* data cache enabled? */ + { + printf_filtered("mpcbdm_dcache_flush: data cache not enabled\n"); + } + if (DC_CST & MPC_DC_CST_DFWT) /* data cache forced write through enable? */ + { + printf_filtered("mpcbdm_dcache_flush: data cache DFWT enabled\n"); + } + } + set = 0; + } + else /* specific address */ + { + if ((LastMSR & MSR_DR)&&(mpcbdm_mmu)) /* data mmu on and option activated*/ + { + Adr = ppc_bdm_tablewalk(Adr); + } + set = ((Adr & MPC_DCACHE_SETMASK) >> MPC_DCACHE_SETSHIFT); + } + + OldDCacheAdr = bdm_getspr(SPR_DC_ADR); /* save DC_ADR */ + + for (; set < MPC_DCACHE_SETS; set++) + { + for (way=0; way < MPC_DCACHE_WAYS; way++) + { +/* address format for reading cache flags AND for flushing blocks */ +/* flushing blocks need this format, not physical address as stated in 860UM.pdf */ + CacheAdr = ((way<<(31-19)) | (set << (31-27))); + bdm_setspr(SPR_DC_ADR, CacheAdr); + CacheDat = bdm_getspr(SPR_DC_DAT); + pAddr = ((CacheDat & MPC_DC_DAT_TAG) | (set << (31-27))); +/* If flushing all command */ +/* only flush modified valid (the necessary) cache lines for speed up. */ + ValMod = (CacheDat & (MPC_DC_DAT_VALID | MPC_DC_DAT_MOD)); + if (((bAll) && (ValMod == (MPC_DC_DAT_VALID | MPC_DC_DAT_MOD))) + || ((!bAll) && (pAddr == (Adr & (~(MPC_DCACHE_SIZE-1)))))) + { +/* replaced call to low level data cache flush block stuff, for speed up */ + if (CacheDat & MPC_DC_DAT_LOCKED) + { + if (mpcbdm_verbose&VERBOSE_DCA) + { + printf_filtered("mpcbdm_dcache_flush: unlocking set 0x%02x way 0x%1x for physical adr 0x%08x\n",set,way,pAddr); + } + bdm_setspr(SPR_DC_ADR, pAddr); /* set physical address of cached line */ + bdm_setspr(SPR_DC_CST, MPC_DC_CST_UNLOCK); /* unlock block */ + } + if (mpcbdm_verbose&VERBOSE_DCA) + { + printf_filtered("mpcbdm_dcache_flush: flushing set 0x%02x way 0x%1x for physical adr 0x%08x\n",set,way,pAddr); + } +/* FIXME: this took me half an day: ADR has to be in DC_DAT reading format for CMD=FLUSH?*/ +/* and not given as physical address as stated in the manuals!!!*/ + bdm_setspr(SPR_DC_ADR, CacheAdr); /* set address of cache block */ + bdm_setspr(SPR_DC_CST, MPC_DC_CST_FLUSH); /* flush block to get modified cache content into memory */ + if (CacheDat & MPC_DC_DAT_LOCKED) + { + if (mpcbdm_verbose&VERBOSE_DCA) + { + printf_filtered("mpcbdm_dcache_flush: relocking set 0x%02x way 0x%1x for physical adr 0x%08x\n",set,way,pAddr); + } + bdm_setspr(SPR_DC_ADR, pAddr); /* set physical address of cached line */ + bdm_setspr(SPR_DC_CST, MPC_DC_CST_LOCK); /* load and lock block again for restauration */ + } + if (!bAll) + break; /* only one way entry can be valid, so leave way loop*/ + } + } + if (!bAll) + break; /* finish set loop, if only flushing one entry */ + } + bdm_setspr(SPR_DC_ADR,OldDCacheAdr); /* restore DC_ADR */ +} + +/*****************************************************************/ +static void mpcbdm_dcache_info(u_int Adr, int bAll) +{ + u_int CacheAdr; /* DC_ADR value for reading cache content */ + u_int CacheDat; /* DC_DAT value for reading cache content */ + u_int OldDCacheAdr; /* DC_ADR value for restoring */ + u_int DC_CST; /* DC_CST value*/ + u_int adr; /* cached adr */ + u_int LRU; /* Last Recently Used Code: 1 bit for 860 data cache*/ + + int set; + int way; + + OldDCacheAdr = bdm_getspr(SPR_DC_ADR); /* for restauration */ + + if (bAll) /* total dcache info */ + { + DC_CST = bdm_getspr(SPR_DC_CST); + printf_filtered("dcache: "); + if (DC_CST & MPC_DC_CST_DEN) + { + printf_filtered(" enabled"); + } + else + { + printf_filtered("disabled"); + } + if (DC_CST & MPC_DC_CST_DFWT) + { + printf_filtered(", DFWT"); + } + if (DC_CST & MPC_DC_CST_LES) + { + printf_filtered(", LES"); + } + if (DC_CST & MPC_DC_CST_CCER1) + { + printf_filtered(", CCER1"); + } + if (DC_CST & MPC_DC_CST_CCER2) + { + printf_filtered(", CCER2"); + } + if (DC_CST & MPC_DC_CST_CCER3) + { + printf_filtered(", CCER3"); + } + printf_filtered(", data MMU: MSR[DR]"); + if (LastMSR & MSR_DR) /* data mmu on*/ + printf_filtered(" enabled"); + else + { + printf_filtered(" disabled"); + } + printf_filtered("\n"); + + CacheAdr = (1<<(31-18)) | (4 << (31-27)); /* read last copy back address */ + bdm_setspr(SPR_DC_ADR, CacheAdr); + CacheDat = bdm_getspr(SPR_DC_DAT); + printf_filtered("last copyback adr=0x%08x:",CacheDat); + + for (set=0; set < MPC_DCACHE_SIZE/4; set++) + { + CacheAdr = (1<<(31-18)) | (set << (31-27)); /* read last copy back buffer */ + bdm_setspr(SPR_DC_ADR, CacheAdr); + CacheDat = bdm_getspr(SPR_DC_DAT); + printf_filtered(" 0x%08x",CacheDat); + } + printf_filtered("\n"); + + set = 0; + } + else /* specific address */ + { + if ((LastMSR & MSR_DR)&&(mpcbdm_mmu)) /*mmu on and option activated*/ + { + Adr = ppc_bdm_tablewalk(Adr); + } + Adr = (Adr & (~(MPC_DCACHE_SIZE-1))); /* align to cache block start */ + set = (Adr & MPC_DCACHE_SETMASK) >> MPC_DCACHE_SETSHIFT; + } + + + for (; set < MPC_DCACHE_SETS; set++) + { + for (way=0; way < MPC_DCACHE_WAYS; way++) + { +/* read tags */ + CacheAdr = (way<<(31-19)) | (set << (31-27)); + bdm_setspr(SPR_DC_ADR, CacheAdr); + CacheDat = bdm_getspr(SPR_DC_DAT); + adr = (CacheDat & MPC_DC_DAT_TAG) | (set << (31-27)); + + if ((!bAll) && (adr != (Adr & (~(MPC_DCACHE_SIZE-1))))) + continue; /* skip not matching entry */ + + if ((!bAll) || (way == 0)) /* show LRU code only once */ + { + LRU = (CacheDat & MPC_DC_DAT_LRU) >> MPC_DC_DAT_LRU_SHIFT; + printf_filtered("set0x%02x: LRU=0x%1x ",set,LRU); + } + + if (bAll) + { + if (way) /* need separator ?*/ + printf_filtered(", "); + printf_filtered("way%1x:0x%08x..%1x",way,adr,MPC_DCACHE_SIZE-1); + } + else /* show only specified way */ + { + printf_filtered("way%1x:0x%08x..%1x",way,Adr,MPC_DCACHE_SIZE-1); + } + if (CacheDat & MPC_DC_DAT_VALID) + { + printf_filtered(" val"); + } + else + { + printf_filtered(" "); + } + if (CacheDat & MPC_DC_DAT_LOCKED) + { + printf_filtered(" lck"); + } + else + { + printf_filtered(" "); + } + if (CacheDat & MPC_DC_DAT_MOD) + { + printf_filtered(" mod"); + } + else + { + printf_filtered(" "); + } + + if (!bAll) + { + printf_filtered("\n"); + break; + } + } + if (!bAll) break; + printf_filtered("\n"); + } + bdm_setspr(SPR_DC_ADR,OldDCacheAdr); +} + +/*****************************************************************/ +static void mpcbdm_dcache(char *args, int from_tty) +{ + u_int adr; /* cached adr */ + + int bAll; + + char * OsParse; + char * sParse; + + sParse = args; + if (sParse == 0) /* no arguments ?*/ + { + mpcbdm_dcache_info(0,1); /* display all data cache contents */ + } + else if (strncmp(sParse,"flush",5) == 0) + { + sParse +=5; + adr = strtoul(sParse,&OsParse,0); + if (sParse != OsParse) /* digits found? */ + { + bAll = 0; + } + else + { + bAll = 1; + } + mpcbdm_dcache_flush(adr,bAll); + } + else + { + adr = strtoul(sParse,&OsParse,0); + if (sParse != OsParse) /* digits found? */ + { + mpcbdm_dcache_info(adr,0); /* display only specific data cache entry */ + } + else + { + printf_filtered("try 'help mpcbdm dcache' for a list of supported commands\n"); + } + } +} + +/***************************************************************** +* MMU routines * +*****************************************************************/ +static void mpcbdm_cmd_mmu(char *args, int from_tty) +{ + u_int vAddr; + u_int pAddr; + + u_int Mx_CTR; + + char * OsParse; + char * sParse; + + int i; + + sParse = args; + if (sParse == 0) /* no arguments ?*/ + { + printf_filtered("IMMU:"); + if (LastMSR & MSR_IR) /* instruction mmu activated? */ + { + printf_filtered(" enabled"); + } + else + { + printf_filtered(" disabled"); + } + + printf_filtered(", DMMU:"); + if (LastMSR & MSR_DR) /* data mmu activated? */ + { + printf_filtered(" enabled"); + } + else + { + printf_filtered(" disabled"); + } + + printf_filtered(", mpcbdm_mmu tablewalk:"); + if (mpcbdm_mmu) /*mmu option activated*/ + { + printf_filtered(" enabled"); + } + else + { + printf_filtered(" disabled"); + } + printf_filtered("\n"); + } + else if (strncmp(sParse,"on",2) == 0) + { + mpcbdm_mmu = 1; + } + else if (strncmp(sParse,"off",3) == 0) + { + mpcbdm_mmu = 0; + } + else if (strncmp(sParse,"inst",4) == 0) + { + Mx_CTR = bdm_getspr(SPR_MI_CTR); + print_spr_info(SPR_MI_CTR, Mx_CTR,1,0,0,1); + printf_filtered("\n"); + for (i = 0; i < MPC_IMMU_ENTRIES; i++) + { + bdm_setspr(SPR_MI_CTR, ((Mx_CTR & MPC_MI_CTR_MASK) | (i << MPC_MI_CTR_SHIFT)) ); + bdm_setspr(SPR_MI_CAM, 0); /* perform mtspr CAM for CAM,RAM0,RAM1 update */ + printf_filtered("IMMU%2d:",i); + print_spr_info(SPR_MI_CAM,bdm_getspr(SPR_MI_CAM),1,0,0,1); + printf_filtered("\n "); + print_spr_info(SPR_MI_RAM0,bdm_getspr(SPR_MI_RAM0),1,0,0,1); + printf_filtered("\n "); + print_spr_info(SPR_MI_RAM1,bdm_getspr(SPR_MI_RAM1),1,0,0,1); + printf_filtered("\n"); + } + bdm_setspr(SPR_MI_CTR,Mx_CTR); /* restore */ + } + else if (strncmp(sParse,"data",4) == 0) + { + Mx_CTR = bdm_getspr(SPR_MD_CTR); + print_spr_info(SPR_MD_CTR, Mx_CTR,1,0,0,1); + printf_filtered("\n"); + for (i = 0; i < MPC_DMMU_ENTRIES; i++) + { + bdm_setspr(SPR_MD_CTR, ((Mx_CTR & MPC_MD_CTR_MASK) | (i << MPC_MD_CTR_SHIFT)) ); + bdm_setspr(SPR_MD_CAM, 0); /* perform mtspr CAM for CAM,RAM0,RAM1 update */ + printf_filtered("DMMU%2d:",i); + print_spr_info(SPR_MD_CAM,bdm_getspr(SPR_MD_CAM),1,0,0,1); + printf_filtered("\n "); + print_spr_info(SPR_MD_RAM0,bdm_getspr(SPR_MD_RAM0),1,0,0,1); + printf_filtered("\n "); + print_spr_info(SPR_MD_RAM1,bdm_getspr(SPR_MD_RAM1),1,0,0,1); + printf_filtered("\n"); + } + bdm_setspr(SPR_MD_CTR,Mx_CTR); /* restore */ + } + else if (strncmp(sParse,"kbase",5) == 0) + { + sParse +=5; + vAddr = strtoul(sParse,&OsParse,0); + if (sParse != OsParse) /* digits found? */ + { + mpcbdm_kbase = vAddr; + } + else + { + printf_filtered("mmu kbase = 0x%08x\n",mpcbdm_kbase); + } + } + else if (strncmp(sParse,"pgdir",5) == 0) + { + sParse +=5; + vAddr = strtoul(sParse,&OsParse,0); + if (sParse != OsParse) /* digits found? */ + { + mpcbdm_pgdir = vAddr; + } + else + { + printf_filtered("mmu pgdir = 0x%08x\n",mpcbdm_pgdir); + } + } + else + { + vAddr = strtoul(sParse,&OsParse,0); + if (sParse != OsParse) /* digits found? */ + { + if (LastMSR & MSR_IR) /* instruction mmu activated? */ + { + pAddr = ppc_bdm_tablewalk(vAddr); /* FIXME: necessary to check if enabled?*/ + printf_filtered("MMU translates virtual 0x%08x to physical 0x%08x\n",vAddr,pAddr); + } + else + { + printf_filtered("MMU disabled virtual = physical 0x%08x\n",vAddr); + } + } + else + { + printf_filtered("try 'help mpcbdm mmu' for a list of supported commands\n"); + } + } +} +/***************************************************************** +* remote target execution helpers * +*****************************************************************/ +unsigned int remote_restore(void) +{ + unsigned int temp; + int i; + + for (i = 0; i < 32; i++) + { + if (pramlen != 0) + temp = bdm_getreg(i); /* save registers */ + bdm_setreg(i, RegBuffer[i]); /* restore GPR0..31 */ + if (pramlen != 0) + RegBuffer[i] = temp; /* store into register buffers for return values */ + } + + if (pramlen != 0) + { +/* restore original control registers content, if any program loaded before */ + temp = bdm_getspr(SPR_CTR); /*save CTR*/ + bdm_setspr(SPR_CTR, RegBuffer[i]); /*restore CTR*/ + RegBuffer[i++] = temp; + temp = bdm_getspr(SPR_SRR0); /*save srr0*/ + bdm_setspr(SPR_SRR0, RegBuffer[i++]); /*restore srr0*/ + RegBuffer[i++] = temp; + temp = bdm_getspr(SPR_SRR1); /*save srr1*/ + bdm_setspr(SPR_SRR1, RegBuffer[i++]); /*restore srr1*/ + RegBuffer[i++] = temp; + temp = bdm_getspr(SPR_DER); /*save DER*/ + bdm_setspr(SPR_DER, RegBuffer[i++]); /*restore DER*/ + RegBuffer[i++] = temp; + +/* restore original memory content, if any program loaded before */ + for (i = 0; i< pramlen; i++) + { + ppc_bdm_setword(mpcbdm_pram+i*4,membuf[i]); + } + pramlen = 0; /* program removed from target */ + + } + + return RegBuffer[0]; /* default return value is r0 */ +} + +/*****************************************************************/ +unsigned int remote_execute(void) +{ + if (pramlen == 0) + { + printf_filtered("remote_execute: pramlen == 0, no program loaded\n"); + return 0; + } + ppc_bdm_resume(); /* start remote target NIP = preloaded SRR0 = mpxbdm_pram */ + ppc_bdm_wait(); /* wait until remote target reaches 0x0 -> SEI */ + + return remote_restore(); +} + +/*****************************************************************/ +unsigned int remote_prepare(unsigned int * pPrg, int nPrg) +{ + int i; + + for (i = 0; i < 32; i++) + { + RegBuffer[i] = bdm_getreg(i); /* save GPR0..31 */ + } + + RegBuffer[i++] = bdm_getspr(SPR_CTR); /*save CTR*/ + RegBuffer[i++] = bdm_getspr(SPR_SRR0); /*save srr0*/ + RegBuffer[i++] = bdm_getspr(SPR_SRR1); /*save srr1*/ + RegBuffer[i++] = bdm_getspr(SPR_DER); /*save DER*/ + +/*copy ram content into buffer, and remote program into ram, if any*/ + for (i = 0; i< nPrg; i++) + { + membuf[i] = ppc_bdm_getword(mpcbdm_pram+i*4); + ppc_bdm_setword(mpcbdm_pram+i*4,pPrg[i]); + } + pramlen = i; + +/*verify, that ram holds program, if any */ + for (i = 0; i< pramlen; i++) + { + if (ppc_bdm_getword(mpcbdm_pram+i*4) != pPrg[i]) + { + printf_filtered("remote_execute_init: RAM doesn't hold prg at addr 0x%08x\n",mpcbdm_pram+i*4); + pramlen = 0; + remote_restore(); /* at least restore registers */ + return pramlen; + } + } + +/* setup processor for program, if any */ + if (pramlen) + { + bdm_setspr(SPR_SRR0,mpcbdm_pram); /*start address*/ + bdm_setspr(SPR_SRR1,0x1000); /* new MSR:enable only ME*/ + bdm_setspr(SPR_DER,0x7002400f); /* allow SEIE, to return to gdb*/ + } + +/* target processor is now ready to execute program with remote_execute() */ + + return pramlen; /* return len of program, 0 for fail */ +} + +/***************************************************************** +* FLASH routines * +*****************************************************************/ +unsigned int flash_addr(unsigned int Addr) +{ + unsigned int Val; + + if (!pFB) return 0; /* no bank selected */ + + Val = (Addr << pFB->shift) + pFB->start; + return Val; +} + +/*****************************************************************/ +unsigned int flash_data(unsigned int Data) +{ + unsigned int Val; + int i; + + if (!pFB) return 0; /* no bank selected */ + + Val = pFB->mask & Data; + for (i = 1; i < pFB->devices; i++) /* copy data for all parallel devices */ + { + Val |= (Val<bits); + } + return Val; +} + +/*****************************************************************/ +int flash_erase(unsigned int Addr) +{ + int i; + int nResult; + + flash_find_bank(Addr,1); + if (!pFB) return; + +/*check if sector is protected*/ +/* Data = FBS.getword(flash_addr((FBS.pDevice->ADDR_VERIFYPROTECT)+((secID)<Sector[FSec].Start, pFB->Sector[FSec].End); + if (i != 1) return 0; + } + else + { + printf_filtered("erasing FLASH bank %d sector %d [0x%08x,0x%08x]\n", FBank, FSec, pFB->Sector[FSec].Start, pFB->Sector[FSec].End); + } + + remote_prepare(NULL,0); /*save GPRs*/ + flash_load_sequence(pFB->cErase,Addr,0,1); + nResult = flash_execute_sequence(pFB->cErase,Addr,0); + remote_restore(); /*restore GPRs*/ + + return nResult; +} +/*****************************************************************/ +int flash_clear(unsigned int Addr) +{ + int i; + int nResult; + + flash_find_bank(Addr,1); + if (!pFB) return; + + if (mpcbdm_fquery) + { + i = query("clear FLASH bank %d [0x%08x,0x%08x] ?", FBank, pFB->start, pFB->end); + if (i != 1) return 0; + } + else + { + printf_filtered("clearing FLASH bank %d [0x%08x,0x%08x]\n", FBank, pFB->start, pFB->end); + } + + remote_prepare(NULL,0); /*save GPRs*/ + flash_load_sequence(pFB->cClear,Addr,0,1); + nResult = flash_execute_sequence(pFB->cClear,Addr,0); + remote_restore(); /*restore GPRs*/ + + return nResult; +} +/*****************************************************************/ +int flash_write_word(unsigned int Addr, unsigned int Word, int bLoadSeq) +{ +/* have to be check for zero to ones before, destroys target register content */ + int nResult; + int i; + + flash_find_bank(Addr,0); + if (!pFB) return 0; /* no valid bank configuration found */ + + for (i = pFB->EWA-1; i >=0; i--) /* loop elementar accesses for one 32 word, turn endianess */ + { + nResult = flash_load_sequence(pFB->cWrite,Addr+(i<shift),Word & pFB->mask,(i == pFB->EWA-1)&&(bLoadSeq)); + if (!nResult) break; + nResult = flash_execute_sequence(pFB->cWrite,Addr+(i<shift),Word & pFB->mask); + if (!nResult) break; + Word = Word >> pFB->width; + } + if (!nResult) /* write reset commando, if errors occured */ + { + flash_load_sequence(pFB->cReset,Addr,Word,1); + flash_execute_sequence(pFB->cReset,Addr,Word); + } + return nResult; +} + +/*****************************************************************/ +int flash_write(unsigned int Addr, unsigned int Word) +{ + int nResult; + int i; + unsigned int Data; + unsigned int hData; + + flash_find_bank(Addr,1); + if (!pFB) return 0; /* no valid bank configuration found */ + + if (mpcbdm_fquery) + { + i = query("write 0x%08x to FLASH at 0x%08x (bank %d sector %d [0x%08x,0x%08x]) ?", Word, Addr, FBank, FSec, pFB->Sector[FSec].Start, pFB->Sector[FSec].End); + if (i != 1) return 0; + } + else + { + printf_filtered("writing 0x%08x to FLASH at 0x%08x (bank %d sector %d [0x%08x,0x%08x])\n", Word, Addr, FBank, FSec, pFB->Sector[FSec].Start, pFB->Sector[FSec].End); + } + + Data = ppc_bdm_getword(Addr); /*Word found in FLASH*/ + hData = Word & ~Data; /* find ones to be written into zeros*/ + if (hData) + { + printf_filtered("0x%08x: unable to write 0->1 : need to erase sector\n",Addr); + return 0; /* failure */ + } + + remote_prepare(NULL,0); /*save GPRs*/ + nResult = flash_write_word(Addr,Word,1); + remote_restore(); /*restore GPRs*/ + if (!nResult) + { + printf_filtered("0x%08x: flash_write: failed to write 0x%08x to 0x%08x\n",Word,Addr); + } + return nResult; +} +/*****************************************************************/ +int flash_check_zeros_host(unsigned int *Buffer, unsigned int len, unsigned int Destination, unsigned int * Adr) +{ + int i; + int nResult; + unsigned int r0; + unsigned int r1; + unsigned int Data; + unsigned int hData; + unsigned int Word; + int wlen; + + nResult = 0; + + r0 = bdm_getreg(0); /* save scratch registers */ + r1 = bdm_getreg(1); + + bdm_setreg(1,Destination-4); + wlen = (len + 3)>>2; /* word len */ + if ((wlen << 2) != len) + { + printf_filtered("flash_check_zeros_host: assert warning: len not divisible by 4"); + } + + *Adr = Destination; + for (i=0; i0; i--) + { + ser_clkinstr(prg[0], 0); + ser_clkinstr(prg[1], 0); + ser_clkinstr(prg[2], 0); + h = bdm_getreg(0); + if (h) + { + *Adr = bdm_getreg(2); + break; + } + } + remote_restore(); /* restore GPRs*/ + return h; +} + +/*****************************************************************/ +unsigned int flash_fast_program( + unsigned int SourceStart, + unsigned int SourceEnd, + unsigned int Destination, + unsigned int *Adr) +{ + int i; + int nResult; + unsigned int h,len; + + flash_find_bank(Destination,1); + + if (!pFB) return -1; /* no bank found for destination address */ + + if ((!pFB->fflash) || (pFB->nfflash<=0)) return -2; /* no fast routine configured */ + + h = remote_prepare(pFB->fflash,pFB->nfflash); + if (h != pFB->nfflash) return -3; + +/* preload registers for fast cycle */ + nResult = flash_load_sequence(pFB->cFast,Destination,0,1); + +/*parameters for program*/ + bdm_setreg(28,SourceStart-pFB->align); + bdm_setreg(29,Destination-pFB->align); + len = (SourceEnd-SourceStart+pFB->align)/pFB->align; + bdm_setspr(SPR_CTR,len); /*len*/ + + remote_execute(); /* implicite remote_restore() */ + + (*Adr) = RegBuffer[29]; /*last written to FLASH adr*/ + h = RegBuffer[32]; /* in case of no error, CTR should be equal to 0 */ + + return h; +} + +/*****************************************************************/ +int flash_copy(unsigned int SourceStart, unsigned int SourceEnd, unsigned int Destination) +{ + int i; + int K,L; + unsigned int Source,Dest,len; + unsigned int nResult, Adr; + unsigned int Pos; + u_int Word,Data,hData ; /*for read operations*/ + + if (SourceStart > SourceEnd) + { + printf_filtered("error: source start > source end\n"); + return 0; /* failure */ + } + len = SourceEnd - SourceStart; + + flash_find_bank(Destination,1); + if (!pFB) return 0; /* no bank found for address */ + + if (pFB->end < Destination+len) + { + printf_filtered("error: destination range [0x%08x,0x%08x] exceeds bank range [0x%08x,0x%08x]\n", + Destination, Destination+len, pFB->start, pFB->end); + return 0; + } + if (((Destination>=SourceStart) && (Destination <=SourceEnd))|| + ((Destination+len>=SourceStart) && (Destination+len <=SourceEnd))) + { + printf_filtered("error: destination range [0x%08x,0x%08x] within source range [0x%08x,0x%08x]\n", + Destination, Destination+len, SourceStart, SourceEnd); + return 0; + } + if (SourceStart%pFB->align !=0) + { + printf_filtered("error: start address has to be %d bytes aligned\n",pFB->align); + return 0; + } + if (Destination%pFB->align !=0) + { + printf_filtered("error: destination address has to be %d bytes aligned\n",pFB->align); + return 0; + } + + printf_filtered(" checking, if data can be written without erasing FLASH...\n"); + + for (Pos = 0; Pos <= SourceEnd-SourceStart;) + { + /*search for zeros to be written to ones: sector needs erasure*/ + nResult = flash_check_zeros(SourceStart+Pos,SourceEnd,Destination+Pos,&Adr); + if (nResult == 0) break; /*ok to write data to flash*/ + + if (Adr == 0) /* flash_check_zeros failed to setup remote*/ + { + printf_filtered(" range not copied\n"); + return 0; + } + printf_filtered("0x%08x: need to erase sector\n",Adr); + i = flash_erase(Adr); /*try to erase sector*/ + if (i == 0) + { + printf_filtered(" range not copied\n"); + return 0; + } + Pos = Adr - Destination; /* retry checking at last position */ + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_copy Pos = 0x%08x\n",Pos); + } + } + if (Pos > SourceEnd-SourceStart) + { + printf_filtered("assert warning: flash_copy Pos > SourceEnd-SourceStart 0x%08x\n",Pos); + } + printf_filtered("\nFLASH checked successfully!\n"); + + if (mpcbdm_fquery) + { + i = query("Copy memory [0x%08x,0x%08x] to FLASH at [0x%08x,0x%08x] ?", SourceStart, SourceEnd, Destination, Destination +len); + if (i!=1) return 0; + } + else + { + printf_filtered("Copying memory [0x%08x,0x%08x] to FLASH at [0x%08x,0x%08x]\n", SourceStart, SourceEnd, Destination, Destination +len); + } + +/* use fast flash ppc subroutines? */ + if ((mpcbdm_fflash) && (pFB->fflash) && (pFB->nfflash>0) && (pFB->cFast)) + { + nResult = flash_fast_program(SourceStart,SourceEnd,Destination,&Adr); + if (nResult !=0) + { + printf_filtered("error: FLASH failure at 0x%08x: nResult=0x%08x\n",Adr,nResult); + return 0; /* failure */ + } + return 1; /* success*/ + } + if (mpcbdm_fflash) + { + if ((!(pFB->fflash)) || (pFB->nfflash<=0)) + { + printf_filtered("no fast flash routine configured, using slow host routine\n"); + } + else if (!(pFB->cFast)) + { + printf_filtered("no fast flash routine register preload (cfast) configured, using slow host routine\n"); + } + } +/* use host controlled flash routine, very slow! */ + remote_prepare(NULL,0); /*save GPRs*/ + bdm_setreg(28,SourceStart-4); /**/ + len = 0; + K = 0; + L = 0; + for (Source = SourceStart; Source <= SourceEnd; Destination+=4,Source+=4) + { + ser_clkinstr(0x877c0004, 0);// lwzu r27,4(r28) + Word = bdm_getreg(27); + + i = flash_write_word(Destination,Word,(Source==SourceStart)); + if (!i) + { + remote_restore(); /*restore GPRs*/ + return 0;/*stop if failed writing data to FLASH*/ + } + len+=4; + K+=4; /*count bytes*/ + if (K >= 4096) /*4KByte*/ + { + printf_unfiltered("."); + gdb_flush (gdb_stdout); + K-=4096; + L++; + if (L == 32) /*32*4K = 128KByte*/ + { + printf_unfiltered("%dK\n",len/1024); + gdb_flush (gdb_stdout); + L = 0; + } + } + } + remote_restore(); /*restore GPRs*/ + printf_filtered("\n copying finished.\n"); + return 1; /* success */ +} + +/*****************************************************************/ +void flash_info(void) +{ + int i; + int bank; + int nResult; + + for(bank=0; bank < mpcbdm_nBank; bank++) /*for all configured flash banks*/ + { + flash_find_bank(FB[bank].start,1); + if (!pFB) continue; /* misconfigured, should never happen*/ + + printf_filtered("FLASH bank %d %dx %d bit %s: %x-%x, adr align %d\n", + bank,pFB->devices,pFB->bits,pFB->sName, + pFB->start, pFB->end, pFB->align); + nResult = flash_ident(pFB->start); /* test if device is responding */ + +/* for (i = 0; i< FBS.pDevice->nSectors; i++) + { + Data = FBS.getword(flash_addr((FBS.pDevice->ADDR_VERIFYPROTECT) + +((FBS.pDevice->Sector[i].ID)<Sector[i].Start)); + printf_filtered(" End:%08x\n",flash_addr(FBS.pDevice->Sector[i].End)+(FBS.width)/8-1); + } +*/ + } +} + +/*****************************************************************/ +int flash_find_bank(unsigned int Addr, int bVerbose) +{ + int nResult; + + for (FBank = 0; FBank < mpcbdm_nBank; FBank++) + { + if ((FB[FBank].start <= Addr) && (FB[FBank].end >= Addr)) + break; /*found bank for addr*/ + } + if (FBank >= mpcbdm_nBank) + { + if (bVerbose) + { + printf_filtered("no FLASH bank found for Addr:0x%08x\n",Addr); + } + pFB = NULL; + return 0; + } + if (pFB == &(FB[FBank])) + { + nResult = 1; /* same bank selected previously */ + } + else + { + nResult = 0; /* new bank selected */ + pFB = &(FB[FBank]); + } + + for (FSec = 0; FSec < pFB->nSectors; FSec++) + { + if ((pFB->Sector[FSec].Start <= Addr) && (pFB->Sector[FSec].End >= Addr)) + break; /*found sector for addr*/ + } + if (FSec >= pFB->nSectors) + { + if (bVerbose) + { + printf_filtered("no FLASH sector found for Addr:0x%08x in bank %d\n",Addr,FBank); + } + pFB = NULL; + return 0; + } + return nResult; +} +/*****************************************************************/ +int flash_load_sequence(FlashCycle *pCycle,unsigned int Addr,unsigned int Data,int bFirstTime) +{ + int bAdr; + int bData; + int bID; + int cyc; + + if ((!pCycle) || (!pFB)) return 0; + + cyc = 0; + bAdr = 0; /* actual address used at least once, loaded into r31*/ + bData = 0; /* actual data used at least once, loaded into r0 */ + bID = 0; /* actual id used at least once, loaded into r30 */ + + while ((cyc < MAXFLASHCYCLES) && (pCycle[cyc].cType != 0)) + { + switch (pCycle[cyc].cAdrType) + { + case 'a': + if (!bAdr) + { + bdm_setreg(31,Addr); + bAdr = 1; + } + pCycle[cyc].Adr = Addr; /* for debugging, insert actual address */ + break; + case 'i': + if (!bID) + { + bdm_setreg(30,flash_addr(pFB->Sector[FSec].ID<IDshift)); + bID = 1; + } + pCycle[cyc].Adr = flash_addr(pFB->Sector[FSec].ID<IDshift); /* for debugging, insert actual id address */ + break; + default: + if (bFirstTime) /* load immediate data only once */ + { + bdm_setreg((cyc<<1)+1,pCycle[cyc].Adr); + } + break; + } +/* only for write cycles data has to be placed into registers*/ +/* the rest is to load actual cycle data for debug purposes*/ + switch (pCycle[cyc].cDataType) + { + case 'd': + if (pCycle[cyc].cType == 'w') + { + if (!bData) + { + bdm_setreg(0,Data); + bData = 1; + } + } + pCycle[cyc].Data = Data; /* for debugging, insert actual Data */ + break; + case 'i': + if (pCycle[cyc].cType == 'w') + { + if (!bID) + { + bdm_setreg(30,flash_data(pFB->Sector[FSec].ID<IDshift)); + bID = 1; + } + } + /* for debugging, insert actual Data */ + pCycle[cyc].Data = flash_data(pFB->Sector[FSec].ID<IDshift); + break; + default: + if (pCycle[cyc].cType == 'w') + { + if (bFirstTime) /* load immediate data only once */ + { + bdm_setreg((cyc<<1)+2,pCycle[cyc].Data); + } + } + break; + } + cyc++; + } + return 1; +} +/*****************************************************************/ +int flash_execute_sequence(FlashCycle *pCycle, unsigned int Addr, unsigned int Data) +{ + int cyc; + u_int val; + u_int com; + u_int comload; + u_int comstore; + u_int rD; /* number of register holding data for cycle */ + u_int rA; /* number of register holding address for cycle */ + u_int comp = 0; /* for load related cycles value to compare with */ + u_int dgbRA; /* for debug printouts*/ + u_int dgbRD; + unsigned int i; + + if ((!pCycle) || (!pFB)) return 0; + + switch (pFB->width) + { +/* com = (OP << 26) | (rD << 21) | (rA << 16) | d;*/ /* l/s w/h/b z rD,d(rA)*/ + case 8: + comload = (34 << 26); /*lbz rD,d(rA)*/ + comstore =(38 << 26); /*stb rS,d(rA)*/ + break; + case 16: + comload = (40 << 26); /*lhz rD,d(rA)*/ + comstore =(44 << 26); /*sth rS,d(rA)*/ + break; + case 32: + comload = (32 << 26); /*lwz rD,d(rA)*/ + comstore =(36 << 26); /*stw rS,d(rA)*/ + break; + default: + printf_filtered("flash_execute_sequence: config error bank %d width %d\n",FBank,pFB->width); + return 0; + break; + } + + cyc = 0; + + while ((cyc < MAXFLASHCYCLES) && (pCycle[cyc].cType != 0)) + { + switch (pCycle[cyc].cAdrType) + { + case 'a': + rA = 31; + break; + case 'i': + rA = 30; + break; + default: + rA = (cyc<<1)+1; + break; + } + + if (pCycle[cyc].cType == 'w') + { + switch (pCycle[cyc].cDataType) + { + case 'd': + rD = 0; + break; + case 'i': + rD = 30; + break; + default: + rD = (cyc<<1)+2; + break; + } + } + else /* for read related cycles store data in cycle data reg */ + { + rD = (cyc<<1)+2; + + switch (pCycle[cyc].cDataType) + { + case 'd': + comp = Data; + break; + case 'i': + comp = flash_data(pFB->Sector[FSec].ID<IDshift); + break; + default: + comp = pCycle[cyc].Data; + break; + } + } + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_execute_sequence: Cyc%d %c%c 0x%x:%c 0x%x\n", + cyc,pCycle[cyc].cType,pCycle[cyc].cAdrType, + pCycle[cyc].Adr,pCycle[cyc].cDataType,pCycle[cyc].Data); + } + + switch (pCycle[cyc].cType) + { + case 'w': + com = comstore | (rD << 21) | (rA << 16); /*st[width] rS,0(rA)*/ + ser_clkinstr(com, 0); + break; + case 'r': + com = comload | (rD << 21) | (rA << 16); /*l[width]w rD,0(rA)*/ + ser_clkinstr(com, 0); + val = bdm_getreg(rD); + if (comp != val) + { + printf_filtered("flash_execute_cycle: read 0x%x got 0x%x\n",comp,val); + } + break; + case 'c': + com = comload | (rD << 21) | (rA << 16); /*l[width]z rD,0(rA)*/ + ser_clkinstr(com, 0); + val = bdm_getreg(rD); + if (comp != val) + { + printf_filtered("flash_execute_cycle: compare 0x%x got 0x%x\n",comp,val); + return 0; + } + break; + case 'p': + com = comload | (rD << 21) | (rA << 16); /*l[width]z rD,0(rA)*/ + for (i = 0; i < mpcbdm_toggle; i++) + { + ser_clkinstr(com, 0); + val = bdm_getreg(rD) & pCycle[cyc].Data; /*poll only valid with immediate data*/ + if (!val) break; + } + if (i == mpcbdm_toggle) + { + printf_filtered("flash_execute_cycle: poll timed out\n"); + return 0; + } + break; + case 't': + com = comload | (rD << 21) | (rA << 16); /*l[width]z rD,0(rA)*/ + ser_clkinstr(com, 0); + val = bdm_getreg(rD) & pCycle[cyc].Data; /* toggle only valid with immediate data*/ + for (i = 0; i < mpcbdm_toggle; i++) + { + ser_clkinstr(com, 0); + comp = bdm_getreg(rD) & pCycle[cyc].Data; + if (!(val ^ comp)) break; /* toggling stopped?*/ + val = comp; + } + if (i == mpcbdm_toggle) + { + printf_filtered("flash_execute_cycle: toggle timed out\n"); + return 0; + } + break; + default: + break; + } + cyc++; + } + return 1; /* success */ +} +/*****************************************************************/ +int flash_file_skipspace(FILE *f,char cChar, unsigned int * Start) +{ + int nResult; + + while (!feof(f) && !ferror(f)) + { + nResult = fgetc(f); + if (nResult == cChar) + { + if (Start!=0) *Start = ftell(f); + return 1; + } + if (! isspace(nResult)) + { + ungetc(nResult,f); + return 0; + } + } + if (ferror(f)) + { + printf_filtered("file error while skipping whitespace for '%c'\n",cChar); + } + return 0; +} +/*****************************************************************/ +int flash_file_find(FILE *f,char * sString,unsigned int * Start) +{ + int pos; + int len; + int nResult; + + pos = 0; + len = strlen(sString); + while (!feof(f) && !ferror(f)) + { + nResult = fgetc(f); + if (nResult != sString[pos]) + { + pos = 0; + continue; + } + pos++; + if (pos == len) + { + if (Start!=0) *Start = ftell(f); + return 1; + } + } + if (ferror(f)) + { + printf_filtered("file error while searching for '%s'\n",sString); + } + return 0; +} +/*****************************************************************/ +int flash_file_node(FILE *f,char * sString,unsigned int * Start) +{ + int nResult; + + do + { + nResult = flash_file_find(f,sString,Start); + if (!nResult) + { + printf_filtered("error: '%s' not found inside '%s'.\n",sString,mpcbdm_flashdev); + return 0; + } + nResult = flash_file_skipspace(f,'{',Start); + } while (!nResult && !feof(f) && ! ferror(f)); + if (feof(f) || ferror(f)) return 0; + return 1; +} +/*****************************************************************/ +void flash_free_bank() +{ + if ((mpcbdm_nBank >= 0) && (mpcbdm_nBank < MAXFLASHBANKS)) + { + if (FB[mpcbdm_nBank].sName) + { + free(FB[mpcbdm_nBank].sName); + FB[mpcbdm_nBank].sName=NULL; + } + if (FB[mpcbdm_nBank].Sector) + { + free(FB[mpcbdm_nBank].Sector); + FB[mpcbdm_nBank].Sector=NULL; + } + if (FB[mpcbdm_nBank].cReset) + { + free(FB[mpcbdm_nBank].cReset); + FB[mpcbdm_nBank].cReset=NULL; + } + if (FB[mpcbdm_nBank].cIdent) + { + free(FB[mpcbdm_nBank].cIdent); + FB[mpcbdm_nBank].cIdent=NULL; + } + if (FB[mpcbdm_nBank].cWrite) + { + free(FB[mpcbdm_nBank].cWrite); + FB[mpcbdm_nBank].cWrite=NULL; + } + if (FB[mpcbdm_nBank].cErase) + { + free(FB[mpcbdm_nBank].cErase); + FB[mpcbdm_nBank].cErase=NULL; + } + if (FB[mpcbdm_nBank].cClear) + { + free(FB[mpcbdm_nBank].cClear); + FB[mpcbdm_nBank].cClear=NULL; + } + if (FB[mpcbdm_nBank].cFast) + { + free(FB[mpcbdm_nBank].cFast); + FB[mpcbdm_nBank].cFast=NULL; + } + if (FB[mpcbdm_nBank].fflash) + { + free(FB[mpcbdm_nBank].fflash); + FB[mpcbdm_nBank].fflash=NULL; + FB[mpcbdm_nBank].nfflash=0; + } + } +} +/*****************************************************************/ +int flash_parse_cycle(FlashCycle **pCycle) +{ + int len; + int i; + int j; + int p; + int cyc; + int data; + unsigned int val; + char cType; + + *pCycle = malloc(sizeof(FlashCycle)*MAXFLASHCYCLES); + if (!*pCycle) + { + printf_filtered("flash_parse_cycle:unable to allocate mem\n"); + return 0; + } + + for(cyc = 0; cyc < MAXFLASHCYCLES; cyc++) + { + len = strlen(pParse); + for(i = 0;(i= len) return 0; + + cType = tolower(pParse[i]); + switch(cType) + { + case 'w': + case 'r': + case 'c': + case 't': + case 'p': + break; + default: + printf_filtered("flash_parse_cycle: incorrect cycle #%d '%s'\n",cyc,pParse); + return 0; + break; + } + (*pCycle)[cyc].cType = cType; + if ((i+1=len) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, missing adr '%s'\n",cyc,pParse); + return 0; + } + cType = tolower(pParse[i+2]); + switch(cType) + { + case 'a': + break; + case 'i': + break; + default: + printf_filtered("flash_parse_cycle: incorrect cycle #%d, special adr '%s'\n",cyc,pParse); + return 0; + break; + } + (*pCycle)[cyc].cAdrType = cType; + i+=3; + } + else + { + (*pCycle)[cyc].cAdrType = ' '; + sscanf(pParse+i+1,"%i%n",&data,&p); + if (p==0) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, adr '%s'\n",cyc,pParse); + return 0; + } + (*pCycle)[cyc].Adr = (((unsigned int)data)<= len) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, missing ':' '%s'\n",cyc,pParse); + return 0; + } + if (pParse[i] != ':') + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, missing ':' '%s'\n",cyc,pParse); + return 0; + } + i++; + if (i >= len) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, missing data '%s'\n",cyc,pParse); + return 0; + } + if (pParse[i]=='%') /* special DATA? */ + { + if (i+1>=len) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, missing data '%s'\n",cyc,pParse); + return 0; + } + cType = tolower(pParse[i+1]); + switch(cType) + { + case 'd': + break; + case 'i': + break; + default: + printf_filtered("flash_parse_cycle: incorrect cycle #%d, special data '%s'\n",cyc,pParse); + return 0; + break; + } + (*pCycle)[cyc].cDataType = cType; + i+=2; + } + else + { + (*pCycle)[cyc].cDataType = ' '; + sscanf(pParse+i,"%i%n",&data,&p); + if (p==0) + { + printf_filtered("flash_parse_cycle: incorrect cycle #%d, data '%s'\n",cyc,pParse); + return 0; + } + val = FB[mpcbdm_nBank].mask & (unsigned int)data; + for (j = 1; j < FB[mpcbdm_nBank].devices; j++) /* copy data for all parallel devices */ + { + val |= (val<= len) /* end of line, no ',' -> end of cycles */ + { + cyc++; + break; + } + if (pParse[i] == ',') + { + pParse++; + } + len = strlen(pParse); + for(i = 0;(i= len) /* ',' + eol -> read next line */ + { + fgets(FileBuffer,MAXBUFFERLEN,f); + pParse = FileBuffer; + } + } + if (cyc < MAXFLASHCYCLES) + { + (*pCycle)[cyc].cType = 0; /* mark end of cycles */ + } + return 1; /* successfully parsed cycles */ +} +/*****************************************************************/ +void flash_configure(u_int Addr,u_int Num,char * sDevice) +{ + char Buffer[MAXBUFFERLEN]; + char sSector[MAXBUFFERLEN]; + char sAlgo[MAXBUFFERLEN]; + char sFast[MAXBUFFERLEN]; + int len; + int i; + int nResult; + int nComma = 0; + u_int nStart; + u_int adr; + u_int prg; + + sFast[0]=0; + + if (mpcbdm_nBank >= MAXFLASHBANKS) + { + printf_filtered("unable to configure bank: too many banks %d\n",mpcbdm_nBank); + return; + } + + flash_find_bank(Addr,0); + if (pFB) + { + printf_filtered("bank %d already defined for 0x%08x\n",FBank,Addr); + return; + } + + for(;isspace(*sDevice);sDevice++); + len = strlen(sDevice); + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("configuring bank %d 0x%08x as %u * %s\n",mpcbdm_nBank,Addr,Num,sDevice); + } + + if (!mpcbdm_flashdev) + { + error("no flash configuration file path given: set mpcbdm_flashdev."); + return; + } + + FB[mpcbdm_nBank].sName = malloc(len+1); + if (!FB[mpcbdm_nBank].sName) + { + printf_filtered("flash_configure:unable to allocate mem for Name\n"); + flash_free_bank(); + return; + } + + strncpy(FB[mpcbdm_nBank].sName,sDevice,len+1); + FB[mpcbdm_nBank].start = Addr; + FB[mpcbdm_nBank].devices = Num; + + f = fopen(mpcbdm_flashdev, "rb"); + + if(!f) + { + error("failed to open flash configuration file."); + return; + } + + sprintf(Buffer,".device %s",sDevice); + nResult = flash_file_node(f,Buffer,&nStart); + + if (!nResult) + { + flash_free_bank(); + if (f) fclose(f); + return; + } + do + { + nResult = flash_file_skipspace(f,'}',NULL); + if (nResult) + { + break; + } + nResult = flash_file_skipspace(f,'.',NULL); + if (nResult) + { + fgets(Buffer,sizeof(Buffer),f); + pParse=Buffer; + if (strncmp(pParse,"size",4) == 0) + { + pParse+=4; + FB[mpcbdm_nBank].size = strtoul(pParse,&pParse,0); + if (pParse[0]== 'M') + { + FB[mpcbdm_nBank].size *= 1048576; + } + else if (pParse[0]== 'K') + { + FB[mpcbdm_nBank].size *= 1024; + } + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.size %u\n",FB[mpcbdm_nBank].sName,FB[mpcbdm_nBank].size); + } + } + else if (strncmp(pParse,"width",5) == 0) + { + pParse+=5; + FB[mpcbdm_nBank].bits = strtoul(pParse,&pParse,0); + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.width %u\n",FB[mpcbdm_nBank].sName,FB[mpcbdm_nBank].bits); + } + } + else if (strncmp(pParse,"sector",6) == 0) + { + pParse+=6; + sscanf(pParse,"%s",sSector); + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.sector %s\n",FB[mpcbdm_nBank].sName,sSector); + } + } + else if (strncmp(pParse,"idoffset",8) == 0) + { + pParse+=8; + FB[mpcbdm_nBank].IDshift = strtoul(pParse,&pParse,0); + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.idoffset %u\n",FB[mpcbdm_nBank].sName,FB[mpcbdm_nBank].IDshift); + } + } + else if (strncmp(pParse,"algorithm",9) == 0) + { + pParse+=9; + sscanf(pParse,"%s",sAlgo); + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.algorithm %s\n",FB[mpcbdm_nBank].sName,sAlgo); + } + } + else + { + printf_filtered("wrong syntax: %s",Buffer); + } + } + } while (!feof(f) && !ferror(f)); + if (ferror(f)) + { + printf_filtered("file error while parsing .device %s",mpcbdm_flashdev); + flash_free_bank(); + if (f) fclose(f); + return; + } + + FB[mpcbdm_nBank].width = FB[mpcbdm_nBank].devices * FB[mpcbdm_nBank].bits; + FB[mpcbdm_nBank].EWA = 32 / FB[mpcbdm_nBank].width; /* number of elementar accesses needed for a 32 bit word */ + FB[mpcbdm_nBank].fflash = NULL; + FB[mpcbdm_nBank].nfflash = 0; + + switch (FB[mpcbdm_nBank].width) + { + case 8: + FB[mpcbdm_nBank].mask = 0xff; + FB[mpcbdm_nBank].align = 1; + FB[mpcbdm_nBank].shift = 0; + FB[mpcbdm_nBank].getword = ppc_bdm_getbyte; + FB[mpcbdm_nBank].setword = ppc_bdm_setbyte; + break; + case 16: + FB[mpcbdm_nBank].mask = 0xffff; + FB[mpcbdm_nBank].align = 2; + FB[mpcbdm_nBank].shift = 1; + FB[mpcbdm_nBank].getword = ppc_bdm_gethalfword; + FB[mpcbdm_nBank].setword = ppc_bdm_sethalfword; + break; + case 32: + FB[mpcbdm_nBank].mask = 0xffffffff; + FB[mpcbdm_nBank].align = 4; + FB[mpcbdm_nBank].shift = 2; + FB[mpcbdm_nBank].getword = ppc_bdm_getword; /* set default routines to 32 bit */ + FB[mpcbdm_nBank].setword = ppc_bdm_setword; /* set default routines to 32 bit */ + break; + default: + printf_filtered("FLASH bank %d misconfigured: found width %d for Addr:0x%08x\n",mpcbdm_nBank,FB[mpcbdm_nBank].width,Addr); + flash_free_bank(); + if (f) fclose(f); + return; + break; + } + + FB[mpcbdm_nBank].end = FB[mpcbdm_nBank].start + FB[mpcbdm_nBank].devices * FB[mpcbdm_nBank].size -1; + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.end 0x%08x\n",FB[mpcbdm_nBank].sName,FB[mpcbdm_nBank].end); + } + + sprintf(Buffer,".sector %s",sSector); + nResult = flash_file_node(f,Buffer,&nStart); + if (!nResult) + { + flash_free_bank(); + if (f) fclose(f); + return; + } + + FB[mpcbdm_nBank].Sector = malloc(sizeof(FlashSector)*MAXFLASHSECTORS); + if (!FB[mpcbdm_nBank].Sector) + { + printf_filtered("flash_configure:unable to allocate mem for sectors\n"); + flash_free_bank(); + if (f) fclose(f); + return; + } + + FB[mpcbdm_nBank].nSectors = 0; + for (i = 0; (i < MAXFLASHSECTORS)&&(!feof(f) && !ferror(f)); i++) + { + nResult = flash_file_skipspace(f,'}',NULL); + if (nResult) + { + if (nComma) + { + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: unnecessary ',' in .sector %s\n",sSector); + } + } + break; + } + if ((i !=0 ) && (!nComma)) + { + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: missing ',' in .sector %s entry %d\n",sSector,i); + } + break; + } + + nResult = fscanf(f,"%i",&adr); + if (nResult != 1) break; + FB[mpcbdm_nBank].Sector[i].ID = adr; + nResult = flash_file_skipspace(f,',',NULL); + if (nResult != 1) break; + nResult = fscanf(f,"%i",&adr); + if (nResult != 1) break; + FB[mpcbdm_nBank].Sector[i].Start = (adr<0) && (FB[mpcbdm_nBank].Sector[i-1].End != FB[mpcbdm_nBank].end) ) + { + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("end of last sector not equal to end of bank?\n"); + } + } + + sprintf(Buffer,".algorithm %s",sAlgo); + nResult = flash_file_node(f,Buffer,&nStart); + + if (!nResult) + { + flash_free_bank(); + if (f) fclose(f); + return; + } + do + { + nResult = flash_file_skipspace(f,'}',NULL); + if (nResult) + { + break; + } + nResult = flash_file_find(f,".",NULL); + if (nResult) + { + fgets(FileBuffer,sizeof(FileBuffer),f); + pParse=FileBuffer; + if (strncmp(pParse,"reset",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.reset\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cReset); + if (!nResult) + { + printf_filtered("error in .algorithm %s .reset\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"ident",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.ident\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cIdent); + if (!nResult) + { + printf_filtered("error in .algorithm %s .ident\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"write",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.write\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cWrite); + if (!nResult) + { + printf_filtered("error in .algorithm %s .write\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"erase",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.erase\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cErase); + if (!nResult) + { + printf_filtered("error in .algorithm %s .erase\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"clear",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.clear\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cClear); + if (!nResult) + { + printf_filtered("error in .algorithm %s .clear\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"cfast",5) == 0) + { + pParse+=5; + + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: %s.cfast\n",FB[mpcbdm_nBank].sName); + } + + nResult = flash_parse_cycle(&FB[mpcbdm_nBank].cFast); + if (!nResult) + { + printf_filtered("error in .algorithm %s .cfast\n",sAlgo); + flash_free_bank(); + if (f) fclose(f); + return; + } + } + else if (strncmp(pParse,"fast",4) == 0) + { + pParse+=4; + sscanf(pParse,"%s",sFast); + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("%s.fast%d %s\n",FB[mpcbdm_nBank].sName,FB[mpcbdm_nBank].width,sFast); + } + } + else + { + printf_filtered("wrong syntax: %s",FileBuffer); + } + } + } while (!feof(f) && !ferror(f)); + + if (ferror(f)) + { + printf_filtered("file error while parsing .device %s",mpcbdm_flashdev); + flash_free_bank(); + if (f) fclose(f); + return; + } + + if (sFast[0]!= 0) + { + sprintf(Buffer,".fast%d %s",FB[mpcbdm_nBank].width,sFast); + nResult = flash_file_node(f,Buffer,&nStart); + + if (!nResult) + { + flash_free_bank(); + if (f) fclose(f); + return; + } + + FB[mpcbdm_nBank].fflash = malloc(sizeof(unsigned int)*MAXFLASHPRG); + if (!FB[mpcbdm_nBank].fflash) + { + printf_filtered("flash_configure:unable to allocate mem for fast flash routine\n"); + flash_free_bank(); + if (f) fclose(f); + return; + } + + nComma = 0; + i = 0; + do + { + nResult = flash_file_skipspace(f,'}',NULL); + if (nResult) + { + if (nComma) + { + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: unnecessary comma...\n"); + } + } + break; + } + nResult = flash_file_skipspace(f,'/',NULL); /* comment sign?*/ + if (!nResult) + { + nResult = fscanf(f,"%x",&prg); + if (!nResult) + { + printf_filtered("flash_configure: %s expected instruction\n",Buffer); + flash_free_bank(); + if (f) fclose(f); + return; + } + if (i >= MAXFLASHPRG) + { + printf_filtered("flash_configure: %s too many instructions\n",Buffer); + flash_free_bank(); + if (f) fclose(f); + return; + } + FB[mpcbdm_nBank].fflash[i] = prg; + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash_configure: fflash[%d] =0x%08x\n",i,FB[mpcbdm_nBank].fflash[i]); + } + i++; + nComma=flash_file_skipspace(f,',',NULL); + } + else /* comment, skip end of row */ + { + fgets(FileBuffer,sizeof(FileBuffer),f); + } + + } while (!feof(f) && !ferror(f)); + if (ferror(f)) + { + printf_filtered("file error while parsing .device %s\n",mpcbdm_flashdev); + flash_free_bank(); + if (f) fclose(f); + return; + } + FB[mpcbdm_nBank].nfflash = i; + } + mpcbdm_nBank++; + if (mpcbdm_verbose&VERBOSE_FLS) + { + printf_filtered("flash bank %d configured.\n",mpcbdm_nBank); + } + + if (f) fclose(f); +} +/*****************************************************************/ +void flash_bank_reset(u_int Adr) +{ + int nResult; + + flash_find_bank(Adr,1); + if (!pFB) return; /* no valid bank configuration found */ + remote_prepare(NULL,0); + flash_load_sequence(pFB->cReset,Adr,0,1); + flash_execute_sequence(pFB->cReset,Adr,0); + remote_restore(); +} + +/*****************************************************************/ +int flash_ident(u_int Adr) +{ + int nResult; + + flash_find_bank(Adr,1); + if (!pFB) return 0; /* no valid bank configuration found */ + remote_prepare(NULL,0); + flash_load_sequence(pFB->cIdent,Adr,0,1); + nResult = flash_execute_sequence(pFB->cIdent,Adr,0); + remote_restore(); + if (nResult) + { + printf_filtered("Ident Sequence: Ok!\n"); + } + else + { + printf_filtered("Ident Sequence: failure?\n"); + } + return nResult; +} +/*****************************************************************/ +void flash_program_file(char* sFilename,unsigned int destaddr) +{ + int i; + unsigned int len; + FILE * pf; + int nResult; + int bUseFast; + unsigned int Adr; + unsigned int Data; + + unsigned int nTotal; + unsigned int nBuffer; + unsigned int nLeft; + + u_char * buffer = NULL; + u_char * rbuffer = NULL; + + nResult = flash_find_bank(destaddr,0); + if (!pFB) return; + + if (mpcbdm_fbuf % 4) + { + printf_filtered("mpcbdm_fbuf must be divisible by 4.\n"); + return; + } + if (mpcbdm_fsizebuf % 4) + { + printf_filtered("mpcbdm_fsizebuf must be divisible by 4.\n"); + return; + } + + if (destaddr%pFB->align !=0) + { + printf_filtered("error: destination address has to be %d bytes aligned\n",pFB->align); + return; /* failure */ + } + + buffer = (u_char*)malloc(mpcbdm_fsizebuf); + if (!buffer) + { + printf_filtered("flash_program_file: unable to alloc host mem for buffer\n"); + return; + } + +/* can we use fast flash ppc subroutines? */ + bUseFast = 0; + if ((mpcbdm_fflash) && (pFB->fflash) && (pFB->nfflash>0) && (pFB->cFast)) + { +/* so it's faster to copy bufferwise into target and execute remote flashing per buffer */ +/* this mode seems only usefull, if using DPRAM and no other properly configured RAM is available*/ +/* else using 'mem load' and then 'flash copy' is more efficient */ + rbuffer = (u_char*)malloc(mpcbdm_fsizebuf); + if (rbuffer) + { +/* save target buffer content*/ + ppc_bdm_read_block(mpcbdm_fbuf, rbuffer, mpcbdm_fsizebuf); + bUseFast = 1; + printf_filtered("Copying to flash with remote routines using buffer[0x%08x,0x%08x]...\n",mpcbdm_fbuf,mpcbdm_fbuf+mpcbdm_fsizebuf-1); + } + else + { + printf_filtered("flash_program_file: unable to alloc host mem for rbuffer\n"); + } + } + else if (mpcbdm_fflash) + { + if ((!(pFB->fflash)) || (pFB->nfflash<=0)) + { + printf_filtered("no fast flash routine configured\n"); + } + else if (!(pFB->cFast)) + { + printf_filtered("no fflash register preload (cfast) configured\n"); + } + } + + do /* for freeing resources on error, break */ + { + pf=fopen(sFilename,"rb"); + if(pf==NULL) /* could not open the file */ + { + printf_filtered("Could not open the file\"%s\"\n",sFilename); + break; + } + + nResult = fseek(pf, 0, SEEK_END); + if (nResult) + { + error("fseek error."); + break; + } + len = (unsigned int)ftell(pf); + rewind(pf); + + if (destaddr+len > pFB->end) + { + printf_filtered("error: destination end 0x%08x exceeds bank border 0x%08x\n",destaddr+len,pFB->end); + break; /* failure */ + } + + i = query("Copy file \"%s\" len 0x%08x to FLASH at [0x%08x,0x%08x] ?",sFilename, len, destaddr, destaddr+len-1); + if (i!=1) break; + +/* checking if we have to erase */ + for (nTotal = 0, nLeft = len; nLeft > 0; nTotal += nBuffer, nLeft -= nBuffer) + { + if(nLeft > mpcbdm_fsizebuf) + { + nBuffer = mpcbdm_fsizebuf; + } + else + { + nBuffer = nLeft; + } + nResult = fread(buffer, 1, nBuffer, pf); + if (nResult != nBuffer) + { + error("read error."); + nResult = 0; + break; + } +/* check buffer for zero writing to ones */ + printf_filtered("checking FLASH [0x%08x,0x%08x]...\n",destaddr+nTotal,destaddr+nTotal+nBuffer-1); + if (bUseFast) + { + ppc_bdm_write_block(mpcbdm_fbuf, buffer, nBuffer); + nResult = flash_check_zeros(mpcbdm_fbuf,mpcbdm_fbuf+nBuffer-1, destaddr+nTotal, &Adr); + } + else + { + nResult = flash_check_zeros_host((unsigned int *)buffer, nBuffer, destaddr + nTotal,&Adr); + } + if (nResult) + { + printf_filtered("need to erase sector for 0x%08x\n",Adr); + nResult = flash_erase(Adr); /*try to erase sector*/ + if (!nResult) + { + printf_filtered(" range not copied\n"); + break; /* failure, exit for loop */ + } + } + else /* no need to erase sector belonging to this buffer*/ + { + nResult = 1; /* success for this buffer, set nResult not to break, if last sector */ + } + } + if (!nResult) break; /* for loop failure */ + + rewind(pf); + + if (bUseFast) + { + printf_filtered("Copying to Flash using remote routines...\n"); + } + else + { + printf_filtered("Copying to Flash using host routines...\n"); + remote_prepare(NULL,0); /*save GPRs*/ + } + for (nTotal = 0, nLeft = len; nLeft > 0; nTotal += nBuffer, nLeft -= nBuffer) + { + if(nLeft > mpcbdm_fsizebuf) + { + nBuffer = mpcbdm_fsizebuf; + } + else + { + nBuffer = nLeft; + } + nResult = fread(buffer, 1, nBuffer, pf); + if (nResult != nBuffer) + { + error("read error."); + nResult = 0; + break; + } + printf_filtered("writing FLASH [0x%08x,0x%08x]...\n",destaddr+nTotal,destaddr+nTotal+nBuffer-1); + if (bUseFast) + { + ppc_bdm_write_block(mpcbdm_fbuf, buffer, nBuffer); + nResult = flash_fast_program(mpcbdm_fbuf,mpcbdm_fbuf+nBuffer-1, destaddr+nTotal, &Adr); + if (nResult !=0) + { + printf_filtered("error: FLASH failure at 0x%08x: nResult=0x%08x\n",Adr,nResult); + nResult = 0; /* failure */ + break; + } + else + { + nResult = 1; /* we have to invert nResult since flash_fast_program uses 0 for success*/ + } + } + else + { + for (i = 0; i < nBuffer; i+=4) + { + if (i+3 >= nBuffer) + { + printf_filtered("buffer len not divisible by 4, ommiting last subword\n"); + nResult = 0; + break; + } +/* we have to correct endianess here:*/ + Data = extract_unsigned_integer(buffer+i, sizeof(Data)); +// Data = *(unsigned int *)&(buffer[i]); + nResult = flash_write_word(destaddr+nTotal+i,Data,(nTotal == 0)&&(i == 0)); + if (!nResult) + { + printf_filtered("error: FLASH failure at 0x%08x: nResult=0x%08x\n",Adr,nResult); + break; + } + } + } + if (!nResult) break; + } + if (!bUseFast) + { + remote_restore(); /*restore GPRs*/ + } + break; + } while (1); /* for freeing resources on error, break */ + + if (rbuffer) + { +/* restore target buffer content, if any */ + ppc_bdm_write_block(mpcbdm_fbuf, rbuffer, mpcbdm_fsizebuf); + free(rbuffer); + rbuffer = NULL; + } + + if (buffer) + { + free(buffer); + buffer = NULL; + } + if (nResult) + { + printf_filtered("FLASH writing completed\n"); + } + + if (ferror(pf)) + { + printf_filtered(" file error while reading \"%s\" \n",sFilename); + } + if (pf) + { + fclose(pf); + pf = NULL; + } +} +/*****************************************************************/ +static void mpcbdm_flash(char *args, int from_tty) +{ + u_int Data,Addr; /* for single word write */ + u_int Num; + u_int SourceStart,Source,SourceEnd,Destination; /* copy range and destination*/ + char *sParse; + char *sFilename; + + if (args == 0) /*no arguments, print info*/ + { + flash_info(); + } + else /* parsing conf, write, copy and erase */ + { + sParse = args; + if (strncmp(sParse,"conf ",5) == 0) + { + sParse +=5; + + if (strncmp(sParse,"clear",5) == 0) + { + for (;mpcbdm_nBank > 0;) + { + mpcbdm_nBank--; + flash_free_bank(); + } + printf_filtered("flash config cleared\n"); + return; + } + Addr = strtoul(sParse,&sParse,0); /* start ADDR of bank */ + Num = strtoul(sParse,&sParse,0); /* number of devices in parallel */ + flash_configure(Addr,Num,sParse); + } + else if (strncmp(sParse,"ident",5) == 0) + { + sParse +=5; + + Addr = strtoul(sParse,&sParse,0); /* ADDR of bank */ + flash_ident(Addr); + } + else if (strncmp(sParse,"reset",5) == 0) + { + sParse +=5; + + Addr = strtoul(sParse,&sParse,0); /* ADDR of bank */ + flash_bank_reset(Addr); + } + else if (strncmp(sParse,"write ",6) == 0) + { + sParse +=6; + + Addr = strtoul(sParse,&sParse,0); /*for testing Write ADDR*/ + Data = strtoul(sParse,&sParse,0); /*for testing write DATA*/ + + flash_write(Addr,Data); + } + else if (strncmp(sParse,"copy ",5) == 0) + { + sParse +=5; + + SourceStart = strtoul(sParse,&sParse,0); /*source start addr*/ + SourceEnd = strtoul(sParse,&sParse,0); /*source end addr*/ + Destination = strtoul(sParse,&sParse,0); /*for testing write DATA*/ + + flash_copy(SourceStart, SourceEnd, Destination); + } + else if (strncmp(sParse,"erase ",6) == 0) + { + sParse +=6; + + Addr = strtoul(sParse,&sParse,0); + + flash_erase(Addr); + } + else if (strncmp(sParse,"clear ",6) == 0) + { + sParse +=6; + + Addr = strtoul(sParse,&sParse,0); + + flash_clear(Addr); + } + else if(strncmp(sParse,"file ",5)==0) + { + sParse+=5; + + sFilename = parse_filename(&sParse); + if (!sFilename) + { + printf_filtered("error while parsing filename\n"); + return; + } + if (*sParse=='\0') //no flash destination + { + printf_filtered("try 'help mpcbdm flash' for a list of supported commands\n"); + return; + } + Destination = strtoul(sParse,&sParse,0); + + flash_program_file(sFilename,Destination); + + } + else + { + printf_filtered("try 'help mpcbdm flash' for a list of supported commands\n"); + } + } +} + +/*************************************************************** +* Automatic initialization from init.c to add target to gdb. * +* IMPORTANT: '_initialize_mpcbdm' have to be at the beginning * +* of the line, therefore the 'void' one line above. If not, * +* the target will not be initialized. So DO NOT touch the * +* following four lines !!! * +****************************************************************/ +void +_initialize_mpcbdm (void) +{ + static struct cmd_list_element *mpcbdm_cmd_list = NULL; + + init_mpcbdm_ops() ; /*init target operation structure*/ + add_target (&mpcbdm_ops); /*add target to gdb*/ + + mpcbdm_flashdev = malloc(MAXBUFFERLEN); + if (mpcbdm_flashdev) strncpy(mpcbdm_flashdev,"Flash.dev",MAXBUFFERLEN); + +/* customizing target by adding obscure commands*/ + + add_show_from_set (add_set_cmd ("mpcbdm_adapter", no_class, + var_zinteger, (char *)&mpcbdm_adapter, + "Set adapter version.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_delay", no_class, + var_zinteger, (char *)&mpcbdm_delay, + "Set delay value for mpcbdm signals.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_power", no_class, + var_boolean, (char *)&mpcbdm_power, + "Set powering adapter from port.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_verbose", no_class, + var_zinteger, (char *)&mpcbdm_verbose, + "Set mask of verbosity for mpcbdm.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_mmu", no_class, + var_boolean, (char *)&mpcbdm_mmu, + "Set translating virtual addresses over mpcbdm.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_reattach", no_class, + var_boolean, (char *)&mpcbdm_reattach, + "Set reattach mode for resume.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_hwbrk", no_class, + var_boolean, (char *)&mpcbdm_hwbrk, + "Set using hardware registers for breakpoints.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_fflash", no_class, + var_boolean, (char *)&mpcbdm_fflash, + "Set using fast flashing routines.\n", &setlist), + &showlist); + + + add_show_from_set (add_set_cmd ("mpcbdm_flashdev", no_class, + var_filename, (char *)&mpcbdm_flashdev, + "Set flash device description file.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_dflush", no_class, + var_boolean, (char *)&mpcbdm_dflush, + "Set automatic data cache flushing on returning into mpcbdm .\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_relaxed", no_class, + var_boolean, (char *)&mpcbdm_relaxed, + "Set relaxed BDM port timing.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_wait", no_class, + var_zinteger, (char *)&mpcbdm_wait, + "Set number of wait-for-DSDO-goes-low cycles.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_toggle", no_class, + var_zinteger, (char *)&mpcbdm_toggle, + "Set number of wait-FLASH-toggle cycles.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_fquery", no_class, + var_boolean, (char *)&mpcbdm_fquery, + "Set confirm query for erases and writes to flash.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_fbuf", no_class, + var_zinteger, (char *)&mpcbdm_fbuf, + "Set address of buffer for FLASH file.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_fsizebuf", no_class, + var_zinteger, (char *)&mpcbdm_fsizebuf, + "Set size of buffer for FLASH file.\n", &setlist), + &showlist); + + add_show_from_set (add_set_cmd ("mpcbdm_pram", no_class, + var_zinteger, (char *)&mpcbdm_pram, + "Set pointer to RAM where to load the fast remote routines to.\n", &setlist), + &showlist); + + add_prefix_cmd ("mpcbdm", class_obscure, bdm_command, + "Use On-Chip Debugging on MPC's via parallel port BDM interface", + &mpcbdm_cmd_list, "mpcbdm ", 0, &cmdlist); + + add_cmd ("reset", class_obscure, mpcbdm_reset_command, + "send /HRESET signal to MPC", &mpcbdm_cmd_list); + + add_cmd ("restart", class_obscure, mpcbdm_restart_command, + "resetting and stopping target MPC", &mpcbdm_cmd_list); + + add_cmd ("spr", class_obscure, mpcbdm_spr_command, + "show or set value of MPC's spr, give number or name", &mpcbdm_cmd_list); + + add_cmd ("sprs", class_obscure, show_spr, + "show important sprs", &mpcbdm_cmd_list); + + add_cmd ("upms", class_obscure, mpcbdm_obscure_upms, + "show settings of upms", &mpcbdm_cmd_list); + + add_cmd ("flash", class_obscure, mpcbdm_flash, + "program and erase flash memory\n\ +without arguments to get info about banks\n\ +'conf ADR NUM NAME' to configure next bank from ADR, NUM devices of type NAME\n\ +'conf clear' to empty all flash configurations\n\ +'ident ADR' to run an ident cycle on FLASH\n\ +'reset ADR' to run an reset cycle on FLASH\n\ +'write ADR DATA' to write single word to FLASH\n\ +'copy SOURCESTART SOURCEEND DESTINATION' for writing to FLASH\n\ +'erase ADR' to erase FLASH sector containing address\n\ +'clear ADR' to clear FLASH bank containing address\n\ +'file \"FILE\" DESTINATION' to write a file to FLASH\n "\ +, &mpcbdm_cmd_list); + + add_cmd ("port", class_obscure, mpcbdm_port, + "show settings of adapter port", &mpcbdm_cmd_list); + + add_cmd ("mem", class_obscure, mpcbdm_mem, + "load/save memory contents from/to file\n\ +'load \"FILE\" DESTINATION [LEN]'\n\ +'save \"FILE\" SOURCE LEN'\n"\ +, &mpcbdm_cmd_list); + + add_cmd ("icache", class_obscure, mpcbdm_icache, + "show instruction cache entries\n"\ +, &mpcbdm_cmd_list); + + add_cmd ("dcache", class_obscure, mpcbdm_dcache, + "data cache commands\n\ +'[ADR]' without subcommand display whole data cache, or specific [ADR] entry\n\ +'flush [ADR]' to flush all or selected blocks\n"\ +, &mpcbdm_cmd_list); + + add_cmd ("mmu", class_obscure, mpcbdm_cmd_mmu, + "mmu commands\n\ +without subcommand display mmu status and mpcbdm mmu settings\n\ +'ADR' display address translation if mmu is enabled\n\ +'data' display dmmu register contents\n\ +'inst' display immu register contents\n\ +'kbase [ADR]' display [or set] kernel base address\n\ +'pgdir [ADR]' display [or set] kernel swapper_pg_dir address\n\ +'on|off' enable|disable mpcbdm tablewalk\n"\ +, &mpcbdm_cmd_list); + + PP.Power = PortError; + PP.Write = PortError; + PP.Reset = PortError; + PP.Status = PortErrorV; + PP.port = -1; +} diff -urN gdb-5.2.1/gdb/mpcbdm.h gdb-5.2.1-mpcbdm/gdb/mpcbdm.h --- gdb-5.2.1/gdb/mpcbdm.h Wed Dec 31 19:00:00 1969 +++ gdb-5.2.1-mpcbdm/gdb/mpcbdm.h Mon Jan 27 21:15:33 2003 @@ -0,0 +1,578 @@ + +#ifndef _MPCBDM_H_ +#define _MPCBDM_H_ + +#define MAXBUFFERLEN 256 /* needs to be at least word aligned!*/ +#define MAXFLASHBANKS 4 +#define MAXFLASHSECTORS 1024 +#define MAXFLASHCYCLES 10 /* using maximum 2*10 ppc registers for flash preload*/ +#define MAXFLASHPRG 100 + +#define PPC_BITS 32 +#define PPC_BIT(x) (1 << (PPC_BITS-1-(x))) + +// Commands of Development Port Shift Register + +#define DSDI_PREF3_CORE_INSTRUCTION 0x4 // +32 bits +#define DSDI_PREF3_CORE_DATA 0x5 // +32 bits +#define DSDI_PREF3_TECR 0x6 // +7 bits +#define DSDI_PREF3_DPC 0x7 // +7 bits + +#define DSDI_DPC_NOP 0 +#define DSDI_DPC_HRESET 0x1 +#define DSDI_DPC_SRESET 0x2 +#define DSDI_DPC_END_DOWNLOAD 0x43 +#define DSDI_DPC_START_DOWNLOAD 0x63 +#define DSDI_DPC_NEGATE_MASK_BREAK 0x1f +#define DSDI_DPC_ASSERT_MASK_BREAK 0x3f +#define DSDI_DPC_NEGATE_NMASK_BREAK 0x1f +#define DSDI_DPC_ASSERT_NMASK_BREAK 0x7f + +#define DSDO_CORE_DATA 0x0 // +32 bits +#define DSDO_SEQ_ERROR 0x1 // +2 bits + xx +#define DSDO_CORE_INTERRUPT 0x2 // +2 bits + xx +#define DSDO_NULL 0x3 // +2 bits + xx + + +#define DSDI_COM_NOP 0x60000000 +#define DSDI_COM_RFI 0x4C000064 +#define DSDI_COM_ICR 0x7C1422A6 +#define DSDI_COM_DER 0x7C1522A6 +#define DSDI_COM_MFMSR 0x7C0000A6 +#define DSDI_COM_MTSPR 0x7C169BA6 + +#define GPR_REG_MASK 0x2000 + +#define SPR_XER 1 +#define SPR_LR 8 +#define SPR_CTR 9 +#define SPR_TBLR 268 +#define SPR_TBUR 269 +#define SPR_DSISR 18 +#define SPR_DAR 19 +#define SPR_DEC 22 +#define SPR_SRR0 26 +#define SPR_SRR1 27 +#define SPR_SPRG0 272 +#define SPR_SPRG1 273 +#define SPR_SPRG2 274 +#define SPR_SPRG3 275 +#define SPR_TBLW 284 +#define SPR_TBUW 285 +#define SPR_PVR 287 +#define SPR_EIE 80 +#define SPR_EID 81 +#define SPR_NRI 82 +#define SPR_DPIR 631 +#define SPR_IMMR 638 +#define SPR_IC_CST 560 +#define SPR_IC_ADR 561 +#define SPR_IC_DAT 562 +#define SPR_DC_CST 568 +#define SPR_DC_ADR 569 +#define SPR_DC_DAT 570 +#define SPR_MI_CTR 784 +#define SPR_MI_AP 786 +#define SPR_MI_EPN 787 +#define SPR_MI_TWC 789 +#define SPR_MI_RPN 790 +#define SPR_MI_CAM 816 +#define SPR_MI_RAM0 817 +#define SPR_MI_RAM1 818 +#define SPR_MD_CTR 792 +#define SPR_M_CASID 793 +#define SPR_MD_AP 794 +#define SPR_MD_EPN 795 +#define SPR_M_TWB 796 +#define SPR_MD_TWC 797 +#define SPR_MD_RPN 798 +#define SPR_M_TW 799 +#define SPR_MD_CAM 824 +#define SPR_MD_RAM0 825 +#define SPR_MD_RAM1 826 +#define SPR_CMPA 144 +#define SPR_CMPB 145 +#define SPR_CMPC 146 +#define SPR_CMPD 147 +#define SPR_ICR 148 +#define SPR_DER 149 +#define SPR_COUNTA 150 +#define SPR_COUNTB 151 +#define SPR_CMPE 152 +#define SPR_CMPF 153 +#define SPR_CMPG 154 +#define SPR_CMPH 155 +#define SPR_LCTRL1 156 +#define SPR_LCTRL2 157 +#define SPR_ICTRL 158 +#define SPR_BAR 159 +#define SPR_DPDR 630 + +#define SPRI_REV_NUM 0x3cb0 + +#define SPRI_MASK 0x10000 +#define SPRI_SIUMCR (SPRI_MASK | 0x000) +#define SPRI_SYPCR (SPRI_MASK | 0x004) +#define SPRI_SWSR (SPRI_MASK | 0x00E) /* 16 bit 556C AA39 */ +#define SPRI_SCCR (SPRI_MASK | 0x280) +#define SPRI_PLPRCR (SPRI_MASK | 0x284) +#define SPRI_RSR (SPRI_MASK | 0x288) +#define SPRI_BRx(x) (SPRI_MASK | (0x100 + (x)*8)) +#define SPRI_ORx(x) (SPRI_MASK | (0x104 + (x)*8)) +#define SPRI_MAMR (SPRI_MASK | 0x170) +#define SPRI_MBMR (SPRI_MASK | 0x174) +#define SPRI_MCR (SPRI_MASK | 0x168) +#define SPRI_MAR (SPRI_MASK | 0x164) +#define SPRI_MDR (SPRI_MASK | 0x17C) +#define SPRI_MSTAT (SPRI_MASK | 0x178) /* MSTAT MPTPR */ + +#define SPR_MASK 0x20000 + +#define SPR_MSR (SPR_MASK | 0x1) +#define SPR_CR (SPR_MASK | 0x2) + + +#define PPC_I_R0R1 0x90010000 /* stw 0,0(1) # mov r0,@r1 */ +#define PPC_I_R0R1hw 0xB0010000 /* stw 0,0(1) # movh r0,@r1 */ +#define PPC_I_R1R0 0x80010000 /* lwz 0,0(1) # mov @r1,r0 */ + +/* from ppc_sprnames.h*/ + +typedef struct +{ + char *name; /*motorola name for spr*/ + int num; /*spr number*/ + char *Namefield; /*(Na|Nb..|Ne) Acronyms of bitfield plus start and end*/ + char *Longname; /*no acronym*/ + char *Reference; /*where to find documentation*/ +} SPRNAME; + +SPRNAME sprnames[] = +{ +{"XER", 1 ,"SO|OV|CA||25BCNT","","UM141"}, +{"LR", 8 ,"","Link Register"}, +{"CTR", 9 ,"","Counter Register"}, +{"DSISR", 18 }, +{"DAR", 19 }, +{"DEC", 22 ,"","Decrementer Register","UM297"}, +{"SRR0", 26 }, +{"SRR1", 27 ,"||16EE|PR|FP|ME||SE|BE||26IR|DR||30RI|LE","Machine Status Save/Restore Register1","UM145"}, +{"EIE", 80 }, +{"EID", 81 }, +{"NRI", 82 }, +{"CMPA", 144 ,"","Comparator A Value Register (instr)","UM987"}, +{"CMPB", 145 ,"","Comparator B Value Register (instr)","UM987"}, +{"CMPC", 146 ,"","Comparator C Value Register (instr)","UM987"}, +{"CMPD", 147 ,"","Comparator D Value Register (instr)","UM987"}, +{"ICR", 148 ,"|RST|CHSTP|MCI||6EXTI|ALI|PRI|FPUVI|DECI||13SYSI|TR||17SEI|ITLBMS|DTBLMS|ITLBER|DTLBER||28LBRK|IBRK|EBRK|DPI","Interrupt Cause Register","UM994"}, +{"DER", 149 ,"|RSTE|CHSTPE|MCIE||6EXTIE|ALIE|PRIE|FPUVIE|DECIE||13SYSIE|TRE||17SEIE|ITLBMSE|DTLBMSE|ITLBERE|DTBLERE||28LBRKE|IBRKE|EBRKE|DPIE","Debug Enable Register","UM996"}, +{"COUNTA", 150 ,"CNTCV|16|30CNTC","Breakpoint Counter Value and Control A Register","UM994"}, +{"COUNTB", 151 ,"CNTCV|16|30CNTC","Breakpoint Counter Value and Control B Register","UM994"}, +{"CMPE", 152 ,"","Comparator E Value Register (addr)","UM987"}, +{"CMPF", 153 ,"","Comparator F Value Register (addr)","UM987"}, +{"CMPG", 154 ,"","Comparator G Value Register (data)","UM987"}, +{"CMPH", 155 ,"","Comparator H Value Register (data)","UM987"}, +{"LCTRL1", 156 ,"CTE|3CTF|6CTG|9CTH|12CRWE|14CRWF|16CSG|18CSH|20SUSG|SUSH|CGBMSK|26CHBMSK|30","Load/Store Support Comparators Control Register","UM990"}, +{"LCTRL2", 157 ,"LW0EN|LW0IA|3LW0IADC|LW0LA|6LW0LADC|LW0LD|9LW0LDDC|LW1EN|LW1IA|13LW1IADC|LW1LA|16LW1LADC|LW1LD|19LW1LDDC|BRKNOMSK||28DLW0EN|DLW1EN|SLW0EN|SLW1EN","Load/Store Support AND-OR Control Register","UM991"}, +{"ICTRL", 158 ,"CTA|3CTB|6CTC|9CTD|12IW0|14IW1|16IW2|18IW3|20SIW0EN|SIW1EN|SIW2EN|SIW3EN|DIW0EN|DIW1EN|DIW2EN|DIW3EN|IFM|ISCT_SER","Instruction Support Control Register","UM989"}, +{"BAR", 159 }, +{"TBLR", 268 }, +{"TBUR", 269 }, +{"SPRG0", 272 }, +{"SPRG1", 273 }, +{"SPRG2", 274 }, +{"SPRG3", 275 }, +{"TBLW", 284 }, +{"TBUW", 285 }, +{"PVR", 287 }, +{"IC_CST", 560 ,"IEN||4CMD|7|10CCER1|CCER2|CCER3|","Instruction Cache Control and Status Register","UM200"}, +{"IC_ADR", 561 ,"|18Data|Way1||Set|28Word|30","Instruction Cache Address Register","UM202"}, +{"IC_DAT", 562 ,"Tag|21|Valid|Locked|LRU|","Instruction Cache Data Port Register","UM202"}, +{"DC_CST", 568 ,"DEN|DFWT|LES||CMD|8|10CCER1|CCER2|CCER3|","Data Cache Control an Status Register","UM205"}, +{"DC_ADR", 569 ,"|18Cbb|Way1||Set|28","Data Cache Address Register","UM208"}, +{"DC_DAT", 570 ,"Tag|21|Valid|Locked|LRU|Modified|","Data Cache Data Port Register","UM209"}, +{"DPDR", 630 }, +{"DPIR", 631 }, +{"IMMR", 638 ,"ISB|16PARTNUM|24MASKNUM","Internal Memory Map Register","UM279"}, +{"MI_CTR", 784 ,"GPM|PPM|CIDEF||RSV4I||PPCS||19ITLB_INDX|24","IMMU Control Register","UM242"}, +{"MI_AP", 786 ,"GP0|2GP1|4GP2|6GP3|8GP4|10GP5|12GP6|14GP7|16GP8|18GP9|20GP10|22GP11|24GP12|26GP13|28GP14|30GP15","IMMU Access Protection Register","UM250"}, +{"MI_EPN", 787 ,"EPN|20|22EV||28ASID", "IMMU Effective Page Number Register","UM244"}, +{"MI_TWC", 789 ,"|23APG|G|PS|30|V","IMMU Tablewalk Control Register","UM244"}, +{"MI_RPN", 790 ,"RPN|20|PP|28SPS|SH|CI|V","IMMU Real Page Number Register","UM246"}, +{"MD_CTR", 792 ,"GPM|PPM|CIDEF|WTDEF|RSV4D|TWAM|PPCS||19DTLB_INDX|24","DMMU Control Register","UM243"}, +{"M_CASID", 793 ,"|28CASID","MMU Current Address Space ID Register","UM249"}, +{"MD_AP", 794 ,"GP0|2GP1|4GP2|6GP3|8GP4|10GP5|12GP6|14GP7|16GP8|18GP9|20GP10|22GP11|24GP12|26GP13|28GP14|30GP15","DMMU Access Protection Register","UM250"}, +{"MD_EPN", 795 ,"EPN|20|22EV||28ASID", "IMMU Effective Page Number Register","UM244"}, +{"M_TWB", 796 ,"L1TB|20L1INDX|30","MMU Tablewalk Base Register","UM249"}, +{"MD_TWC", 797 ,"L2TB|20|23APG|27G|PS|30WT|V","DMMU Tablewalk Control Register","UM245"}, +{"MD_RPN", 798 ,"RPN|20PP|28SPS|SH|CI|V","DMMU Real Page Number Register","UM248"}, +{"M_TW", 799 ,0,"MMU Tablewalk Special Register","UM250"}, +{"MI_CAM", 816 ,"EPN|20PS|23ASID|27SH|SPV","IMMU CAM Entry Read Register","UM251"}, +{"MI_RAM0", 817 ,"RPN|20PS_B|23CI|APG|28SFP","IMMU RAM Entry Read Register 0","UM252"}, +{"MI_RAM1", 818 ,"|26UFP|30PV|G","IMMU RAM Entry Read Register 1","UM253"}, +{"MD_CAM", 824 ,"EPN|20SPVF|24PS|27SH|ASID","DMMU CAM Entry Read Register","UM254"}, +{"MD_RAM0", 825 ,"RPN|20PS|23APGI|27G|WT|CI|","DMMU RAM Entry Read Register 0","UM255"}, +{"MD_RAM1", 826 ,"|16RES|C|EVF|SA|23SAT|URP0|UWP0|URP1|UWP1|URP2|UWP2|URP3|UWP3","DMMU RAM Entry Read Register 1","UM256"}, +//{"", (SPRI_MASK|0x0), "","",""}, +{"SIUMCR", (SPRI_MASK|0x000) ,"EARB|EARP|4|8DSHW|DBGC|11DBPC|13|FRC|DLK|OPAR|PNCS|DPC|MPRE|MLRC|22AEME|SEME|BSC|GB5E|B2DD|B3DD|","SIU Module Configuration Register","UM280"}, +{"SYPCR", (SPRI_MASK|0x004), "SWTC|16BMT|24BME||28SWF|SWE|SWRI|SWP","System Protection Control Register","UM283"}, +{"SWSR", (SPRI_MASK|0x00E), "","Software Service Register","UM296"}, /*16bit556CAA39*/ +{"SIPEND", (SPRI_MASK|0x010), "IRQ0|LVL0|IRQ1|LVL1|IRQ2|LVL2|IRQ3|LVL3|IRQ4|LVL4|IRQ5|LVL5|IRQ6|LVL6|IRQ7|LVL7|","SIU Interrupt Pending Register","UM291"}, +{"SIMASK", (SPRI_MASK|0x014), "IRM0|LVM0|IRM1|LVM1|IRM2|LVM2|IRM3|LVM3|IRM4|LVM4|IRM5|LVM5|IRM6|LVM6|IRM7|LVM7|","SIU Interrupt Mask Register","UM291"}, +{"SIEL", (SPRI_MASK|0x018), "ED0|WM0|ED1|WM1|ED2|WM2|ED3|WM3|ED4|WM4|ED5|WM5|ED6|WM6|ED7|WM7|","SIU Interrupt Edge/Level Register","UM292"}, +{"SIVEC", (SPRI_MASK|0x01c), "INTC|8","SIU Interrupt Vector Register","UM293"}, +{"TESR", (SPRI_MASK|0x020), "|18IEXT|ITMT|IPB0|IPB1|IPB2|IPB3||26DEXT|DTMT|DPB0|DPB1|DPB2|DPB3","Transfer Error Status Register","UM284"}, +{"SDCR", (SPRI_MASK|0x032), "|17FRZ|19|25AM||30RAID","SDMA Configuration Register","UM570"}, +{"PBR0", (SPRI_MASK|0x080), "","PCMCIA Base Register 0","UM516"}, +{"POR0", (SPRI_MASK|0x084), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 0","UM517"}, +{"PBR1", (SPRI_MASK|0x088), "","PCMCIA Base Register 1","UM516"}, +{"POR1", (SPRI_MASK|0x08C), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 1","UM517"}, +{"PBR2", (SPRI_MASK|0x090), "","PCMCIA Base Register 2","UM516"}, +{"POR2", (SPRI_MASK|0x094), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 2","UM517"}, +{"PBR3", (SPRI_MASK|0x098), "","PCMCIA Base Register 3","UM516"}, +{"POR3", (SPRI_MASK|0x09C), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 3","UM517"}, +{"PBR4", (SPRI_MASK|0x0A0), "","PCMCIA Base Register 4","UM516"}, +{"POR4", (SPRI_MASK|0x0A4), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 4","UM517"}, +{"PBR5", (SPRI_MASK|0x0A8), "","PCMCIA Base Register 5","UM516"}, +{"POR5", (SPRI_MASK|0x0AC), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 5","UM517"}, +{"PBR6", (SPRI_MASK|0x0B0), "","PCMCIA Base Register 6","UM516"}, +{"POR6", (SPRI_MASK|0x0B4), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 6","UM517"}, +{"PBR7", (SPRI_MASK|0x0B8), "","PCMCIA Base Register 7","UM516"}, +{"POR7", (SPRI_MASK|0x0BC), "BSIZE|5|12PSHT|16PSST|20PSL|25PPS|PRS|29PSLOT|WP|PV","PCMCIA Option Register 7","UM517"}, +{"PGCRA", (SPRI_MASK|0x0E0), "CxIREQLVL|8CxSCHLVL|16CxDREQ|18|24CxOE|CxReset|","PCMCIA Interface General Control Register","UM516"}, +{"PGCRB", (SPRI_MASK|0x0E4), "CxIREQLVL|8CxSCHLVL|16CxDREQ|18|24CxOE|CxReset|","PCMCIA Interface General Control Register","UM516"}, +{"PSCR", (SPRI_MASK|0x0E8), "CAVS1_C|CAVS2_C|CAWP_C|CACD2_C|CACD1_C|CABVD2_C|CABVD1_C||CARDY_L|CARDY_H|CARDY_R|CARDY_F||16CBVS1_C|CBVS2_C|CBWP_C|CBCD2_C|CBCD1_C|CBBVD2_C|CBBVD1_C||CBRDY_L|CBRDY_H|CBRDY_R|CBRDY_F|","PCMCIA Interface Status Changed Register","UM513"}, +{"PIPR", (SPRI_MASK|0x0F0), "CAVS1|CAVS2|CAWP|CACD2|CACD1|CABVD2|CABVD1|CARDY||16CBVS1|CBVS2|CBWP|CBCD2|CBCD1|CBBVD2|CBBVD1|CBRDY|","PCMCIA Interface Input Pins Register","UM512"}, +{"PER", (SPRI_MASK|0x0F8), "CA_EVS1_C|CA_EVS2_C|CA_EWP_C|CA_ECD2_C|CA_ECD1_C|CA_EBVD2_C|CA_EBVD1_C||CA_ERDY_L|CA_ERDY_H|CA_ERDY_R|CA_ERDY_F||16CB_EVS1_C|CB_EVS2_C|CB_EWP_C|CB_ECD2_C|CB_ECD1_C|CB_EBVD2_C|CB_EBVD1_C||CB_ERDY_L|CB_ERDY_H|CB_ERDY_R|CB_ERDY_F|","PCMCIA Interface Enable Register","UM514"}, +{"BR0", (SPRI_MASK|0x100), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 0","UM435"}, +{"OR0", (SPRI_MASK|0x104), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 0","UM437"}, +{"BR1", (SPRI_MASK|0x108), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 1","UM435"}, +{"OR1", (SPRI_MASK|0x10c), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 1","UM437"}, +{"BR2", (SPRI_MASK|0x110), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 2","UM435"}, +{"OR2", (SPRI_MASK|0x114), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 2","UM437"}, +{"BR3", (SPRI_MASK|0x118), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 3","UM435"}, +{"OR3", (SPRI_MASK|0x11c), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 3","UM437"}, +{"BR4", (SPRI_MASK|0x120), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 4","UM435"}, +{"OR4", (SPRI_MASK|0x124), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 4","UM437"}, +{"BR5", (SPRI_MASK|0x128), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 5","UM435"}, +{"OR5", (SPRI_MASK|0x12c), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 5","UM437"}, +{"BR6", (SPRI_MASK|0x130), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 6","UM435"}, +{"OR6", (SPRI_MASK|0x134), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 6","UM437"}, +{"BR7", (SPRI_MASK|0x138), "BA|17AT|20PS|22PARE|WP|MS|26|31V","Base Register 7","UM435"}, +{"OR7", (SPRI_MASK|0x13c), "AM|17ATM|20CSNT/SAM|ACS/G5LA,G5LS|23BIH|SCY|28SETA|TRLX|EHTR|","Option Register 7","UM437"}, +{"MAR", (SPRI_MASK|0x164), "", "Memory Address Register","UM443"}, +{"MCR", (SPRI_MASK|0x168), "OP|2|8UM||16MB|19|MCLF|24|26MAD","Memory Command Register","UM441"}, +{"MAMR", (SPRI_MASK|0x170), "PTA|8PTAE|AMA|12|DSA|15|G0CLA|19GPLA4DIS|RLFA|24WLFA|28TLFA","Machine A Mode Register","UM440"}, +{"MBMR", (SPRI_MASK|0x174), "PTB|8PTBE|AMB|12|DSB|15|G0CLB|19GPLB4DIS|RLFB|24WLFB|28TLFB","Machine B Mode Register","UM440"}, +{"MSTAT", (SPRI_MASK|0x178), "PER0|PER1|PER2|PER3|PER4|PER5|PER6|PER7|WPER||16PTP|24","Memory Status Register & Periodic Timer","UM439"}, /*contains both MSTAT,MPTPR*/ +{"MDR", (SPRI_MASK|0x17C), "CST4|CST1|CST2|CST3|BST4|BST1|BST2|BST3|G0L|10G0H|12G1T4|G1T3|G2T4|G2T3|G3T4|G3T3|G4T4/DLT3|G4T3/WAEN|G5T4|G5T3||24LOOP|EXEN|AMX|28NA|UTA|TODT|LAST", "Memory Data Register", "UM442"}, +{"TBSCR", (SPRI_MASK|0x200), "TBIRQ|8REFA|REFB||12REFAE|REFBE|TBF|TBE|","Timebase Status and Control Register","UM300"}, /*16bit!*/ +{"TBREFA", (SPRI_MASK|0x204), "","Timebase Reference Register A","UM299"}, +{"TBREFB", (SPRI_MASK|0x208), "","Timebase Reference Register B","UM299"}, +{"RTCSC", (SPRI_MASK|0x220), "RTCIRQ|8SEC|ALR||teK|SIE|ALE|RTF|RTE|","Real-Time Clock Status and Control Register","UM301"}, /*16bit!, teK = 38K*/ +{"RTC", (SPRI_MASK|0x224), "","Real-Time Clock Register","UM302"}, +{"RTSEC", (SPRI_MASK|0x228), "COUNTER|14","Real-Time Clock Alarm Seconds Register","UM304"}, +{"RTCAL", (SPRI_MASK|0x22C), "","Real-Time Clock Alarm Register","UM303"}, +{"PISCR", (SPRI_MASK|0x240), "PIRQ|8PS||13PIE|PITF|PTE|","Periodic Interrupt Status and Control Register","UM305"}, /*16bit!*/ +{"PITC", (SPRI_MASK|0x244), "PITC|16","PIT Count Register","UM306"}, +{"PITR", (SPRI_MASK|0x248), "PIT|16","PIT Register","UM307"}, +{"SCCR", (SPRI_MASK|0x280), "|COM|3|6TBS|RTDIV|RTSEL|CRQEN|PRQEN||13EBDF|15|17DFSYNC|19DFBRG|21DFNL|24DFNH|27","System Clock and Reset Control Register","UM421"}, +{"PLPRCR", (SPRI_MASK|0x284), "MF|12|16SPLSS|TEXPS||TMIST||CSRC|LPM|24CSR|LOLRE|FIOPD|","PLL, Low-Power and Reset Control Register","UM423"}, +{"RSR", (SPRI_MASK|0x288), "EHRS|ESRS|LLRS|SWRS|CSRS|DBHRS|DBSRS|JTRS|","Reset Status Register","UM313"}, +{"TBSCRK", (SPRI_MASK|0x300), "","Timebase Status and Control Register Key","UM285"}, +{"CIVR", (SPRI_MASK|0x930), "VN|5|15IACK|","CPM Interrupt Vector Register 16 bit","UM912"}, /*16bit!*/ +{"CICR", (SPRI_MASK|0x940), "|8SCdP|10SCcP|12SCbP|14SCaP|16IRL|19HP|24IEN||31SPS","CPM Interrupt Configuration Register","UM909"}, +{"CIPR", (SPRI_MASK|0x944), "PC15|SCC1|SCC2|SCC3|SCC4|PC14|TIMER1|PC13|PC12|SDMA|IDMA1|IDMA2||TIMER2|RTT|I2C|PC11|PC10||TIMER3|PC9|PC8|PC7||TIMER4|PC6|SPI|SMC1|SMC2|PC5|PC4|","CPM Interrupt Pending Register","UM910"}, +{"CIMR", (SPRI_MASK|0x948), "PC15|SCC1|SCC2|SCC3|SCC4|PC14|TIMER1|PC13|PC12|SDMA|IDMA1|IDMA2||TIMER2|RTT|I2C|PC11|PC10||TIMER3|PC9|PC8|PC7||TIMER4|PC6|SPI|SMC1|SMC2|PC5|PC4|","CPM Interrupt Mask Register","UM910"}, +{"CISR", (SPRI_MASK|0x94C), "PC15|SCC1|SCC2|SCC3|SCC4|PC14|TIMER1|PC13|PC12|SDMA|IDMA1|IDMA2||TIMER2|RTT|I2C|PC11|PC10||TIMER3|PC9|PC8|PC7||TIMER4|PC6|SPI|SMC1|SMC2|PC5|PC4|","CPM Interrupt In-Service Register","UM910"}, +{"PADIR", (SPRI_MASK|0x950), "DIR|16PAR","Port A Data Direction Register 16 bit",""}, /*16bit! PAPAR*/ +{"PAODR", (SPRI_MASK|0x954), "ODR|16DAT","Port A Open-Drain Register 16 bit",""}, /*16bit! PADAT*/ +{"PCDIR", (SPRI_MASK|0x960), "DIR|16PAR","Port C Data Direction Register 16 bit",""}, /*16bit! PCPAR*/ +{"PCSO", (SPRI_MASK|0x964), "SO|16DAT","Port C Special Option Register 16 bit",""}, /*16bit! PCDAT*/ +{"PCINT", (SPRI_MASK|0x968), "INT|16","Port C Interrupt Control Register 16 bit",""}, /*16bit!*/ +{"PDDIR", (SPRI_MASK|0x970), "DIR|16PAR","Port C Data Direction Register 16 bit",""}, /*16bit! PDPAR*/ +{"PDDAT", (SPRI_MASK|0x976), "ODR|16","Port C Data Register 16 bit",""}, /*16bit!*/ +{"PBDIR", (SPRI_MASK|0xAB8), "","Port B Data Direction Register","UM893"}, +{"PBPAR", (SPRI_MASK|0xABC), "","Port B Pin Assignment Register","UM893"}, +{"PBODR", (SPRI_MASK|0xAC0), "","Port B Open-Drain Register","UM891"}, +{"PBDAT", (SPRI_MASK|0xAC4), "","Port B Data Register","UM892"}, +{"SIMODE", (SPRI_MASK|0xAE0), "SMC2|SMC2CS|4SDMb|6RFSDb|8DSCb|CRTb|STZb|CEb|FEb|GMb|TFSDb|16SMC1|SMC1CS|20SDMa|22RFSDa|24DSCa|CRTa|STZa|CEa|FEa|GMa|TFSDa","SI mode register","UM606"}, +{"SIGMR", (SPRI_MASK|0xAE4), "|4ENb|ENa|RDM|8|16CRORa|CROTa|CRORb|CROTb||24CSRRa|CSRTa|CSRRb|CSRTb|","SI global mode register 8 bit","UM605"}, /*8bit! res, SISTR, SICMR*/ +{"SICR", (SPRI_MASK|0xAEC), "GR4|SC4|R4CS|5T4CS|8GR3|SC3|R3CS|13T3CS|16GR2|SC2|R2CS|21T2CS|24GR1|SC1|R1CS|28T1CS","SI clock route register","UM612"}, +{"SIRP", (SPRI_MASK|0xAF0), "|2VTb|TbPTR|8|10VTa|TaPTR|16|18VRb|RbPTR|24|26VRa|RaPTR","SI RAM pointer register","UM614"}, +{"MSR", (SPR_MASK|0x1), "|13POW||ILE|EE|PR|FP|ME||SE|BE||25IP|IR|DR||30RI|LE","Machine State Register","UM145"}, +{"CR", (SPR_MASK|0x2), "CR0|4CR1|8CR2|12CR3|16CR4|20CR5|24CR6|28CR7","Condition Register","UM140"}, +{0 /*last entry for sprnames*/} +}; + +#define SRR1_MASK 0x9002 + +#define BDM_NUM_REGS 24 + +#define BDM_REGMAP \ + GPR_REG_MASK|0, GPR_REG_MASK|1, GPR_REG_MASK|2, GPR_REG_MASK|3, GPR_REG_MASK|4, GPR_REG_MASK|5, GPR_REG_MASK|6, GPR_REG_MASK|7, /* r0-r7 */ \ + GPR_REG_MASK|8, GPR_REG_MASK|9, GPR_REG_MASK|10, GPR_REG_MASK|11, GPR_REG_MASK|12, GPR_REG_MASK|13, GPR_REG_MASK|14, GPR_REG_MASK|15, /* r8-r15 */ \ + GPR_REG_MASK|16, GPR_REG_MASK|17, GPR_REG_MASK|18, GPR_REG_MASK|19, GPR_REG_MASK|20, GPR_REG_MASK|21, GPR_REG_MASK|22, GPR_REG_MASK|23, /* r16-r23 */ \ + GPR_REG_MASK|24, GPR_REG_MASK|25, GPR_REG_MASK|26, GPR_REG_MASK|27, GPR_REG_MASK|28, GPR_REG_MASK|29, GPR_REG_MASK|30, GPR_REG_MASK|31, /* r24-r31 */ \ +\ + 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, /* fp0->fp8 */ \ + 2096, 2098, 2100, 2102, 2104, 2106, 2108, 2110, /* fp0->fp8 */ \ + 2112, 2114, 2116, 2118, 2120, 2122, 2124, 2126, /* fp0->fp8 */ \ + 2128, 2130, 2132, 2134, 2136, 2138, 2140, 2142, /* fp0->fp8 */ \ +\ + SPR_SRR0, /* pc (SRR0 (SPR 26)) */ \ + SPR_MSR, /* ps (MSR) */ \ + SPR_CR, /* cnd (CR) */ \ + SPR_LR, /* lr (SPR 8) */ \ + SPR_CTR, /* cnt (CTR (SPR 9)) */ \ + SPR_XER, /* xer (SPR 1) */ \ + 0, /* mq (SPR 0) */ + +/* + +i86 parallel port registers and pin connections: + +|Funct.| Addr.|Access|Bit 7 |Bit 6 |Bit 5 |Bit 4 |Bit 3 |Bit 2 |Bit 1 |Bit 0 | ++------+------+------+------+------+------+------+------+------+------+------+ +| DATA |0x378 | R/W |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | +| | | |Pin 9 |Pin 8 |Pin 7 |Pin 6 |Pin 5 |Pin 4 |Pin 3 |Pin 2 | +| | | | | | | | | | | | ++------+------+------+------+------+------+------+------+------+------+------+ +| STAT |0x379 | R |~Busy | Ack |PapErr|Select|Error | 1 | 1 |Time- | +| | | |Pin 11|Pin 10|Pin 12| -In |Pin 15| | | out | +| | | | | | |Pin 13| | | | | ++------+------+------+------+------+------+------+------+------+------+------+ +| CTRL |0x37A | W | 1 | 1 |DATDIR|IRQEna|~Se­ | Init |~Auto-|~Stro-| +| | | | | | 1=I | | lect |Pin 16| feed | be | +| | | | | | 0=O | |Pin 17| |Pin 14|Pin 1 | ++------+------+------+------+------+------+------+------+------+------+------+ + +mapping of adapter V1 and V2: + +DATA 7 6 5 4 3 2 1 0 +V1 V5V V5V V5V V5V V5V V5V V5V V5V +V2 V5V V5V V5V V5V V5V TMS DSDI DSCK + +STAT 7 6 5 4 3 2 1 0 +V1 - VDD DSDO - FRZ - - - +V2 VFLS1 VDD1 DSDO VDD2 VFLS0 - - - + +CTRL 7 6 5 4 3 2 1 0 +V1 - - DATDIR IRQEna HRESET# DSDI SRESET# DSCK +V2 - - DATDIR IRQEna HRESET# - sRESET# TRST# + +JTAG/COP (I/O direction as seen from host): + ++------------------+-------------------+ +|1 TDO (I)|2 QACK (I)| ++------------------+-------------------+ +|3 TDI (O)|4 TRST# (O)| ++------------------+-------------------+ +|5 QREQ (I)|6 VDD (I)| ++------------------+-------------------+ +|7 TCLK (O)|8 NC | ++------------------+-------------------+ +|9 TMS (O)|10 NC | ++------------------+-------------------+ +|11 SRESET# (O)|12 GND | ++------------------+-------------------+ +|13 HRESET# (O)|14 NC | ++------------------+-------------------+ +|15 CHKSTOP (I)|16 GND | ++------------------+-------------------+ + +BDM Connector (I/O direction as seen from host): + ++------------------+-------------------+ +|1 VFLS0/FREEZE (I)| 2 SRESET# (O)| ++------------------+-------------------+ +|3 GND | 4 DSCK (O)| ++------------------+-------------------+ +|5 GND | 6 VFLS1/FREEZE (I)| ++------------------+-------------------+ +|7 HRESET# (O)| 8 DSDI (O)| ++------------------+-------------------+ +|9 VDD (I)| 10 DSDO (I)| ++------------------+-------------------+ + +(HRESET#, SRESET#, and TRST# are implemented as open collector signals) + +*/ + +/* abstraction of parallel port layer */ +typedef struct +{ +/* pointer to function to read input lines : DSDO,VFLS0..1,VDD1..2*/ + int (*Read)(void); +/* pointer to function to enable/disable powering adapter from port */ + void (*Power)(unsigned char Data); +/* pointer to function to output DSCK,DSDI*/ + void (*Write)(unsigned char Data); +/* pointer to function to output HRESET,SRESET,TRST*/ + void (*Reset)(unsigned char Data); + void (*Status)(void); + short DATAAddr; + short STATAddr; + short CTRLAddr; + unsigned char DATA; + unsigned char DATAMask; + unsigned char STAT; + unsigned char CTRL; + unsigned char CTRLMask; + unsigned char DSCK; + unsigned char DSDI; + unsigned char TMS; + unsigned char POWER; + unsigned char VFLS0; + unsigned char VDD2; + unsigned char DSDO; + unsigned char VDD1; + unsigned char VFLS1; + unsigned char TRST; + unsigned char SRESET; + unsigned char HRESET; + unsigned char FREEZE; + char sStatus[MAXBUFFERLEN]; + int port; +} Port; + +/* processor idenfication */ + +typedef struct +{ + unsigned int pvr; + unsigned short partmask; + unsigned short revnum; + char * name; + char * regfile; + unsigned int flags; +} Processor; + +Processor CPU[]= +{ + { 0x00500000, 0x0502, 0x0000,"XPC860 Rev. D.4",0,0}, + { 0x00500000, 0x0501, 0x0000,"XPC860 Rev. D.3",0,0}, + { 0x00500000, 0x0031, 0x0065,"XPC860SR Rev. C.1",0,0}, + { 0x00500000, 0x0031, 0x0004,"XPC860 Rev. C.1",0,0}, + { 0x00500000, 0x0030, 0x0065,"XPC860SR Rev. C.0",0,0}, + { 0x00500000, 0x0030, 0x0004,"XPC860 Rev. C.0",0,0}, + { 0x00500000, 0x0020, 0x0064,"XPC860SR Rev. B.1",0,0}, + { 0x00500000, 0x0020, 0x0004,"XPC860 Rev. B",0,0}, + { 0x00500000, 0x0013, 0x0003,"XPC860 Rev. A.3",0,0}, + { 0x00500000, 0x0012, 0x0003,"XPC860 Rev. A.2",0,0}, + { 0x00500000, 0x0010, 0x0003,"XPC860 Rev. A.1",0,0}, + { 0x00500000, 0x0002, 0x0001,"XPC860 Rev. 0",0,0}, + { 0x00500000, 0x2101, 0x0067,"XPC850 Rev. B","XPC850.reg",0}, + { 0x00500000, 0x2100, 0x0065,"XPC850 Rev. A","XPC850.reg",0}, + { 0x00500000, 0x2002, 0x0001,"XPC850 Rev. 0","XPC850.reg",0}, + { 0x00000000, 0x0000, 0x0000,0,0,0} /* last entry for processor*/ +}; + +/* FLASH device sector description */ + +typedef struct +{ + unsigned int ID; + unsigned int Start; + unsigned int End; +} FlashSector; + +/* FlashCycle: an action paired with a adr:data tupel */ +typedef struct +{ + char cType; /* cycle action : one of W R C T P */ + unsigned int Adr; + char cAdrType; + unsigned int Data; + char cDataType; +} FlashCycle; + +typedef struct +{ + char *sName; /* name of FLASH device*/ + FlashSector *Sector; /* array of sectors*/ + int nSectors; /* number of sectors*/ + unsigned int bits; /* number of bits per device */ + unsigned int devices; /* number of devices parallel in bank */ + unsigned int start; /* physical start address of bank */ + unsigned int size; /* size per device */ + unsigned int end; /* physical end address*/ + unsigned int IDshift; /* bit offset for sector id*/ + unsigned int width; /* number of data lines connected to data bus for total bank */ + unsigned int mask; /* (1<