📄 mpcbdm.c
字号:
/******************************************************************* ** 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 <bfd.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <signal.h>#include <string.h>#include <stdio.h>#include <fcntl.h>#include <ctype.h>#include <sys/types.h>#include <sys/ioctl.h>#include "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" /*?*//******************************************************************* 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 <ctrl>-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 <asm/io.h>#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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -