📄 mpcbdm.c
字号:
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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -