📄 iceif.c
字号:
/************************************************************* * File: bsps/iceif.c * Purpose: serialIce interface code * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 961220 Created * 970216 Switched over to addCmdRec for extra commands. * 970218 Added dflush_needed logic. * 970224 Added dbx logic. works for bda. * 970225 Flush not needed if write is to internal register. * 970226 Delay flush until just before RUN. * 970304 Changed type of ch to Uchar in wakeup() (CYGNUS) * 970310 Moved brkInstall and brkRemove from here * 970310 Changed verbose cmd to use a level * 970310 Rewrote setbp_target() * 970311 Created bptReq() to handle bp requests from xvw and gdb * 970313 Rationalized the calls to init and wakeup (hopefully). * 970401 Added unaligned read_target to support MIPS16 disassembly * 970605 Changed is_writeable to use a byte (for 4101) * 970817 Added Hi and LO as PC+1 and PC+2 * 970905 Switched over to new send_buffer * 970905 Added A1 case to write_target and read_target * 970905 Changed to new version of swap32n * 970905 p in send_buffer changed to Uchar * 970917 Added perens to self bra test in setTrcbp. * 970917 Added _ctrl(22) target_stopped. * 971023 Added REV1_WIGGLER switch. * 971112 Added more cmds to "portconfig". * 980127 Added no_gpr30 cmd. Needed for multi in "debug 16" mode. * 980127 Added send_ack_each_word cmd. Removed REV1_WIGGLER switch. * 980127 Removed USE_SIM_TARG switch. * 980127 Changed printDiag to use logfp. Eliminated logfile2. * 980127 Changed logfile to not append. * 980128 Added siemens_mbd cmd * 980128 Added ocm support * 980130 Removed 'verbose'. Now using 'logging'. * 980202 Added 'breakcode'. * 980204 Renamed bptReq, is_bptReq. * 980226 Fixed a bunch of stuff incl SRUN. * 980305 Changed siemens_mbd to force_wakeup * 980309 Added resync * 980309 Changed force_wakeup to force_resync * 980309 Added force_getsap * 980312 Merged iceif.c for dll and imon * 980323 Removed send_buffer from start of send_instr (recursive) * 980704 Changed write_target hword to bypass the buffer. * 980706 Added support for Siemens mbd kernel (force_sap). * 980707 Added support for ocm routines on dll w v1 kernel. * 980720 Added nobrkRemove. Needed for force_getsap. * 980727 Added resyncOk. * 980803 Added mallocOcmRec and freeOcmRec. * 980818 Added getSAP before write_target_byte calls. * 980821 Added undoc1. * 980903 Started adding ejtag support. * 981214 Made setbp_target less dbx-specific. Removed dcs member. * 981216 Added mask support to ibpts in setbp_target. * 981222 Fixed problem with corrupted downloads on 4011. * 990121 Added ejtag_block. * 990203 Fixed reg nums for LO and HI. Was swapped in several places. * 990311 Fixed prob with dup bpts. Added 'type' to which_bpt(). * 990319 Fixed prob w writes to addr zero. * 990331 Added dma op for send_bytes w ejtag. * 990331 Removed ejtag_block. * 990406 Fixed prob w ejtag fill. Byte not replicated across word. */#include "iceif.h"/*#define VERBOSE_DOWNLOAD /* */#define BUFSZ 4096#define MAXRL 65535#define RLTHRESHOLD 84 /* rlcnt of > the value use set_bytes() */#define MAXRETRIES 5 /* max number of attempts to contact target */char *excodes[] = { /* includes r4000 codes */ "Int","MOD","TLBL","TLBS","AdEL","AdES","IBE","DBE", "Sys", "Bp","RI","CpU","Ov","Tr","Resv","FPE", "Resv","Resv", "Resv","Resv","Resv","Resv","Resv", "WATCH", "Resv","Resv","Resv","Resv","Resv","Resv", "Resv","Resv", 0};char *xtcodes[] = { "PC","MEM","GPR","CP0", "CP1","CP1C", "CP2","CP2C", "CP3","CP3C", "DBX",0};Ulong current_r8,current_r9;int instr_buffer_cnt;Ulong instr_buffer[300]; /* must be larger than the largest ibs */int lendian_host;int lendian_target;int ejtag_mode;int dcache_dirty;int has_wb_dcache; /* cpu has a write-back (copy-back) dcache */int need_initial_flush = 1; /* default is yes */int target_stopped;int iflush_needed;int dflush_needed;int ice_baud;char *ice_device;int nonrt;int slow_target;int dbx_needs_pa; /* the dbx module needs physical addresses */int resyncOk; /* kernel accepts 55 at any time */int undoc1; /* undocumented cmd for test use only */int noforcek1; /* don't force addresses to kseg1 *//* For version 2 kernels, ibs and regmap comes from the kernel. * For version 1 kernels, you must specify it in the config file. * However, it is only critical for cases where an ocm routine is provided */int kernel_ibs; /* kernel ibs value */Ulong kernel_map; /* kernel regmap */struct { int rlcnt; int bcnt; Uchar *buf; Ulong start_addr; Ulong expected_addr; Uchar prev_v; } ice;OcmRec *ocmChain,*freeOcmChain;BrkList brkList[MAX_BPT];void gdbstop(int type);void stop(int type);void *malloc(Ulong size);void free(void *ptr);int has_nhwib; /* has N h/w instr break regs */int has_nhwdb; /* has N h/w data break regs */int icache_size;int dcache_size;int cache_line_size;int has_ilock; /* true or false */int _cputype;vFunc *brkInstall_ptr;Func *ilockReq_ptr;vFunc *flush_target_ptr;Func *brkRemove_ptr;vFunc *setFlushneeded_ptr;int no_gpr30;int send_ack_each_word;int force_getsap;Ulong breakcode;int nobrkRemove;SaveArea savearea; /* info about the serialice kernel */#include "defs.h"/************************************************************** int wakeup(void) DEF*/int wakeup(void){printDiag(1,"wakeup() ");resync();printDiag(1,"wakeup: connection established.\n");dcache_dirty = 1;brkRemove(0);return(1);}/************************************************************** int resync(void);* This routine only works for version 2 or greater kernels.*/int resync(void){int i,timeout,ackcnt;Uchar ch;static int resync_active;if (resync_active) return(0); /* avoid unintended recursion */resync_active = 1;printDiag(1,"resync() ");current_r8 = current_r9 = 0;#if defined(EJTAG) && !defined(PMCC)if (ejtag_mode) { extern char *init_fname; if (target_stopped) { resync_active = 0; return(1); } printDiag(3,"EjtagControl(WAKEUP)\n"); if (!EjtagControl(EJTAG_WAKEUP,0,0)) { printDiag(1,"resync failure.\n"); resync_active = 0; return(0); } printDiag(1,"resync achieved.\n"); target_stopped = 2; if (init_fname) { sload(init_fname); init_fname = 0; } resync_active = 0; return(1); }#endifflushInput();/* Try a bunch of times. Use a short timeout for the first 4 attempts. * Then switch to 1 sec for the remaining 15. We also require 2 * successful acks in a row (paranoia). The mbd kernel actually needs * this. */timeout = 500;for (i=ackcnt=0;i<4+15;i++) { ch = ATTN; PUT_BYTES(&ch,1); if (i == 4) timeout = 1000; if (GET_BYTE(&ch,timeout) && ch == ACK) { ackcnt++; printDiag(1,"%02x ",ch); if (ackcnt >= 2) break; } else ackcnt = 0; }if (i >= 4+15) { printDiag(0,"resync failure.\n"); resync_active = 0; return(0); }printDiag(1,"resync achieved.\n");target_stopped = 2;if (force_getsap && !checkSAP()) { deleteOcmRec((Ulong)savearea.sap); savearea.sap = 0; getSAP(); }resync_active = 0;return(1);}/************************************************************** int send_instr(Ulong v) DEF*/int send_instr(Ulong v){char buf[100];printDiag(8,"send_instr(%08x)\n",v);if (diaglevel >= 4 && v != 0x12345678 && v != 0x87654321 && v != 0xdeadbeef) { disasm(buf,instr_buffer_cnt*4,v); printDiag(4,buf); printDiag(4,"\n"); }#if defined(EJTAG) && !defined(PMCC)if (ejtag_mode) { if (v == 0x87654321) { /* RUN_MODE */ if (!EjtagControl(EJTAG_RUN,0,0)) { printDiag(1,"EjtagControl: RUN: failed.\n"); return(0); }#if 0 else target_stopped = 2;#endif } else { if (!EjtagControl(EJTAG_WRITE,v,0)) { printDiag(1,"EjtagControl: WRITE: failed.\n"); return(0); } } return(1); }#endifinstr_buffer[instr_buffer_cnt++] = v;if (lendian_host) swap32n((Uchar *)&v,1);PUT_BYTES((Uchar *)&v,4);if (instr_buffer_cnt == 1) printDiag(2,"buffer_cnt="); printDiag(2,"%d ",instr_buffer_cnt); printDiag(3,"%08x ",v);return(1);}/************************************************************** int readWord(Ulong *vp);*/int readWord(Ulong *vp){int i;Ulong v;Uchar ch;*vp = v = 0;for (i=0;i<4;i++) { if (!GET_BYTE(&ch,1000)) { printDiag(1,"readWord: timeout\n"); return(0); } v <<= 8; v |= ch; }v = (v<<24)|((v<<8)&0x00ff0000)|((v>>8)&0x0000ff00)|(v>>24);if (send_ack_each_word) PUT_BYTES((Uchar *)"0",1);printDiag(1,"v=%08x\n",v);*vp = v;return(1);}/************************************************************** Ulong *save_instr_buffer()*/Ulong *save_instr_buffer(){int i;Ulong *p;printDiag(1,"save_instr_buffer: cnt=%d\n",instr_buffer_cnt);if (instr_buffer_cnt == 0) return(0);p = malloc((instr_buffer_cnt+1)*4);p[0] = instr_buffer_cnt;for (i=0;i<instr_buffer_cnt;i++) p[i+1] = instr_buffer[i];instr_buffer_cnt = 0;return(p);}/************************************************************** void restore_instr_buffer(Ulong *p)*/void restore_instr_buffer(Ulong *p){int i;if (p==0) return;printDiag(1,"restore_instr_buffer cnt=%d\n",p[0]);instr_buffer_cnt = p[0];for (i=0;i<instr_buffer_cnt;i++) instr_buffer[i] = p[i+1];free(p);}/************************************************************** Ulong readA0(void) DEF*/Ulong readA0(void){Ulong v;int i,n,sbc;Ulong *buf;#if defined(EJTAG) && !defined(PMCC)if (ejtag_mode) { send_instr(0); /* nop */ if (!EjtagControl(EJTAG_EXE,0,&v)) { printDiag(0,"EjtagControl: EXE: failed.\n"); return(0); } printDiag(1,"v=%08x\n",v); return(v); }#endifflushInput();send_instr(SENDA0);if (savearea.ibs && instr_buffer_cnt > ((int)savearea.ibs)) { printDiag(0,"ibuf overflow ibc=%d\n",instr_buffer_cnt); instr_buffer_cnt = 0; return(0); }for (n=0;!readWord(&v);n++) { printDiag(1,"readA0: readWord failed\n");#if 0 if (savearea.vers < 2) { v = 0; break;}#else if (!resyncOk) { v = 0; break;}#endif if (n >= MAXRETRIES) {v=0; break;} printDiag(1,"readA0: resending...\n"); buf = save_instr_buffer(); resync(); restore_instr_buffer(buf); sbc = instr_buffer_cnt; instr_buffer_cnt = 0; for (i=0;i<sbc;i++) send_instr(instr_buffer[i]); }instr_buffer_cnt = 0;if (force_getsap) { target_stopped = 1; /* force wakeup at start of each command */ deleteOcmRec((Ulong)savearea.sap); savearea.sap = 0; /* force reread of SAP */ }return(v);}/************************************************************** void swap32n(Uchar *p,int n) DEF*/void swap32n(Uchar *p,int n){Uchar v;for (;n>0;n--) { v = p[0]; p[0] = p[3]; p[3] = v; v = p[1]; p[1] = p[2]; p[2] = v; p += 4; }}/**************************************************************/Ulong read_unaligned_long(Uchar *a){#if defined(EJTAG) && !defined(PMCC)if (ejtag_mode) return (((a)[3]<<24)|((a)[2]<<16)| ((a)[1]<<8)|((a)[0])); #endifreturn (((a)[0]<<24)|((a)[1]<<16)| ((a)[2]<<8)|((a)[3])); }/************************************************************** void flushInput(void) DEF*/void flushInput(void){int i;Uchar ch;printDiag(2,"flushInput ");for (i=0;;i++) if (!GET_BYTE(&ch,1)) break;if (i) printDiag(1,"%d bytes flushed.\n",i);}/************************************************************** int checkSAP(void)*/int checkSAP(void){Ulong v;printDiag(1,"checkSAP ");flushInput();for (;;) { send_instr(SENDSAP); if (readWord(&v)) break; }v &= ~1;if (!noforcek1) v |= K1BASE;instr_buffer_cnt = 0;if (savearea.sap && v == (Ulong)savearea.sap) return(1);printDiag(1,"checkSAP: need new SAP value %08x vs %08x\n",savearea.sap,v);return(0);}/************************************************************** void getSAP(void) DEF*/void getSAP(void){Ulong v,sav,m;int sz,i;static int getsap_active;/* avoid unintended recursion and unnecessary operations */if (getsap_active || savearea.sap) return; getsap_active = 1;printDiag(1,"getSAP ");current_r8 = current_r9 = 0;if (target_stopped != 2) wakeup(); /* 980407 */#if defined(EJTAG) && !defined(PMCC)if (ejtag_mode) { printDiag(4,"EjtagControl(SAP)\n"); if (!EjtagControl(EJTAG_SAP,0,&v)) { printf("EjtagControl: SAP: failed.\n"); getsap_active = 0; return; } printDiag(2,"sap = %08x\n",v); }else {#endif flushInput(); for (;;) { instr_buffer_cnt = 0; send_instr(SENDSAP); if (readWord(&v)) break; }#if defined(EJTAG) && !defined(PMCC) }#endifinstr_buffer_cnt = 0;if (!noforcek1) v |= K1BASE;target_stopped = 2;if (v&1) { printDiag(1,"new style savearea\n"); v &= ~1; savearea.sap = (Ulong *)v; /* need to read header info */ /* check to see if it's the right version */ if ((sav=read_target(XT_MEM,(Ulong)(ICE_SAV+savearea.sap),4)) != 2) { printDiag(1,"bad savearea version %d\n",sav); savearea.sap = 0; getsap_active = 0; return; /* wrong version */ } savearea.vers = sav; resyncOk = 1; savearea.hsize = read_target(XT_MEM,(Ulong)(ICE_SAH+savearea.sap),4); savearea.map = read_target(XT_MEM,(Ulong)(ICE_MAP+savearea.sap),4); savearea.ibs = read_target(XT_MEM,(Ulong)(ICE_IBS+savearea.sap),4); if (savearea.hsize > 7) savearea.le = read_target(XT_MEM,(Ulong)(ICE_LE+savearea.sap),4); printDiag(1,"getSAP vers=%d hsize=%d map=%08x ibs=%d le=%d\n", savearea.vers,savearea.hsize,savearea.map, savearea.ibs,savearea.le); if (savearea.le) lendian_target = 1; /* 980303 turn off flush requirement when writing to savearea */ sz = savearea.hsize; for (i=0,m=1;i<32;i++,m<<=1) if (m&savearea.map) sz++; addOcmRec((Ulong)savearea.sap,sz*4,0,0); }else { printDiag(1,"old style savearea\n"); savearea.sap = (Ulong *)v; savearea.vers = 1; addOcmRec((Ulong)savearea.sap,12*4,0,0); }getsap_active = 0;}/************************************************************** int hwibReq(Ulong addr) DEF* verify that other hw ibpts don't conflict with this one.* i.e. More than one. Return -1 if not possible.* Else return hw resource number.*/int hwibReq(addr)Ulong addr;{int i,n;/* if (is_ocm(addr)) return(-1); 980805 */if (!has_nhwib) return(-1);n = 0;/* count how many are already set */for (i=0;i<MAX_BPT;i++) { if (brkList[i].type==0) continue; if (brkList[i].method != BRK_METHOD_HW) continue; if (brkList[i].type == BPTYPE_DATA) continue; n++; }if (n > (has_nhwib-1)) return(-1);return(n);}/************************************************************** int hwdbReq(Ulong addr) DEF* verify that other hw dbpts don't conflict with this one.* i.e. More than one. Return -1 if not possible.* Else return hw resource number.*/int hwdbReq(addr)Ulong addr;{int i,n;/* if (is_ocm(addr)) return(-1); 980805 */if (!has_nhwdb) return(-1);n = 0;for (i=0;i<MAX_BPT;i++) { if (brkList[i].type==0) continue; if (brkList[i].method != BRK_METHOD_HW) continue; if (brkList[i].type != BPTYPE_DATA) continue; n++; }if (n > (has_nhwdb-1)) return(-1);return(n);}/************************************************************** void printBpts()*/void printBpts(){int i;for (i=0;i<MAX_BPT;i++) { if (brkList[i].type==0) continue; switch (brkList[i].method) { case BRK_METHOD_HW : printDiag(1,"BRK_METHOD_HW %08x\n",brkList[i].addr); break; case BRK_METHOD_RAM : printDiag(1,"BRK_METHOD_RAM %08x\n",brkList[i].addr); break; case BRK_METHOD_ROM : printDiag(1,"BRK_METHOD_ROM %08x\n",brkList[i].addr); break; default: printDiag(0,"%d: BRK_METHOD unknown\n", brkList[i].method); } }}/************************************************************** int is_cacheable(addr)*/int is_cacheable(addr)Ulong addr;{if (IS_K0SEG(addr)) return(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -