/************************************************************* * File: bsps/400x.c * Purpose: provide 400x-specific routines for SerialICE drivers * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970218 Created using code from d4003.c * 970218 Moved do_icache/dcache here from iceif.c * 970224 Disabled dcache dataram printing. * 970225 Fixed the dcache dataram printing. * 970226 Removed lockbit check. * 970226 Various changes to optimize flushes. * 970226 Fixed soft iflush. Set 1 is lockable not set0. * 970226 Added stuff to i/dcache_opts[]. * 970226 Removed set selection from dcache cmd. * 970227 Added code to force alignment in cache display funcs. * 970305 Switched i/dcache to use get_rsa(). * 970310 moved brkInstall and brkRemove here from iceif.c and * rewrote them. * 970310 Created ilockReq, hwibReq, and hwdbReq. * 970311 Removed write_target from method_ram * 970312 Added -l and -v to icache/dcache * 970312 Merged icache and dcache cmds * 970402 Changed the "don't flush locked entries" to iset0 * I don't understand how it worked before! * 980312 Switched to unified scheme for dll and imon. * 980319 Removed code from ilockReq_400x. * 980323 Ignore flush_cache requests if target is running. * 980421 Added cache_size to cache_cmd * 980720 Added nobrkRemove. Needed for force_getsap. * 980803 Added isset=0 to brkRemove. * 980812 Added return if cache_size == 0. Also setFlushneeded(). * 980823 Removed t0 to hold const. No need for value of zero. * 981026 Added lnsize to flush_cache printDiag. * 981215 Added flush_target_400x_ejtag in an attempt to speed up * the time taken to perform a flush. * 981216 400x ejtag needs dflush after dma downloads. */ #ifndef LR4001 #define LR4001 #endif #include #include #include "iceif.h" #include #define ONLY_FLUSH_WHEN_NEEDED /* optimize the cache flushes */ #define LCK_BIT (1<<4) #define USE_SINGLE_LINE_FLUSH /* use single line flushes when possible */ #define k12k0(a) (((Ulong)(a))&~(1<<29)) char *dirty_icache_line; char *dirty_dcache_line; void setupcacheline_400x(Ulong addr); void markIcacheDirty(Ulong addr,int size); void markDcacheDirty(Ulong addr,int size); /************************************************************* * int flush_target_400x(mode) * Flush the designated cache in the target. */ int flush_target_400x(int mode) { Ulong cfg,tmpcfg; /* flush_target_400x: The gpr[10]s in this func were 26 (k0) */ /* flush_target_400x: The gpr[11]s in this func were 27 (k1) */ /* emit code to flush the caches */ /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ if (!target_stopped) return(1); /* 980323 */ if (need_initial_flush) { printDiag(1,"performing initial flush 400x\n"); need_initial_flush = 0; flush_target_400x(DCACHEI); flush_target_400x(ICACHEI); } switch (mode) { case ICACHEI : printDiag(1,"\niflush 400x size=%d lnsize=%d\n", icache_size,icache_line_size); if (icache_size == 0) { iflush_needed = 0; return(1); } send_buffer(); cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); writeGpri(8,K0BASE+icache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-3)); readA0(); /* flush Icache set1 */ tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_IS1EN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); writeGpri(8,K0BASE+icache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-3)); readA0(); iflush_needed = 0; break; case ICACHE : #ifdef ONLY_FLUSH_WHEN_NEEDED if (!iflush_needed) return(1); #endif printDiag(1,"\nsoft iflush 400x size=%d lnsize=%d\n", icache_size,icache_line_size); if (icache_size == 0) { iflush_needed = 0; return(1); } send_buffer(); cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); writeGpri(8,K0BASE+icache_size); /* flush loop */ #if 1 /* only flush non-locked entries */ /* 970226 only set 1 is lockable */ /* 970402 Wrong! only set0 is lockable */ send_instr(LW(10,0,9)); send_instr(0); /* nop */ send_instr(SLLV(10,27)); send_instr(BLTZ(10,2)); send_instr(0); /* nop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-8)); #else send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-3)); #endif readA0(); /* flush Icache set1 */ tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_IS1EN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); writeGpri(8,K0BASE+icache_size); /* flush loop */ #if 0 /* only flush non-locked entries */ /* 970226 only set 1 is lockable. */ /* 970402 Wrong! only set0 is lockable */ send_instr(LW(10,0,9)); send_instr(0); /* nop */ send_instr(SLLV(10,27)); send_instr(BLTZ(10,2)); send_instr(0); /* nop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-8)); #else send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,icache_line_size)); send_instr(BNE(8,9,-3)); #endif readA0(); iflush_needed = 0; break; case DCACHE : #ifdef ONLY_FLUSH_WHEN_NEEDED if (!dflush_needed) return(1); #endif case DCACHEI : printDiag(1,"\ndflush 400x size=%d lnsize=%d\n", dcache_size,dcache_line_size); if (dcache_size == 0) { dflush_needed = 0; return(1); } send_buffer(); /* flush Dcache set0 */ cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_ICEN|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_DCEN|CFG_CMODE_DTEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); writeGpri(8,K0BASE+dcache_size); /* flush loop */ send_instr(SW(0,0,9)); send_instr(ADDIU(9,9,dcache_line_size)); send_instr(BNE(8,9,-3)); readA0(); dflush_needed = 0; break; } /* restore cfg reg */ /* write_target(XT_MEM,M_CFG4001,cfg,4); */ writeGpri(8,cfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); readA0(); return(1); } /************************************************************* */ Ulong readCache_400x(set,what,addr) int set,what; Ulong addr; { Ulong cfg,tmpcfg,val; /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ tmpcfg = cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_ICEN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= CFG_DCEN; tmpcfg &= ~(CFG_WBEN|CFG_PGSZMASK); if (what == ICACHETAG) tmpcfg |= (CFG_ICEN|CFG_CMODE_ITEST); else if (what == ICACHERAM) tmpcfg |= (CFG_ICEN|CFG_CMODE_IDATA); else if (what == DCACHETAG) tmpcfg |= CFG_CMODE_DTEST; else if (what == DCACHERAM) return(0); /* there is no way to read this */ if ((what == ICACHERAM || what == ICACHETAG) && set) tmpcfg |= CFG_IS1EN; else if (what == DCACHERAM || what == DCACHETAG) /* only one set */ ; send_buffer(); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* val = read_target(XT_MEM,addr,4); */ writeGpri(9,addr); send_instr(LW(4,0,9)); send_instr(0); send_instr(0); send_instr(0); /* restore cfg reg write_target(XT_MEM,M_CFG4001,cfg,4); */ writeGpri(8,cfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); val = readA0().lo; return(val); } /************************************************************* */ static void writeCache(int set,int what,Ulong addr,Ulong val,int sz) { Ulong cfg,tmpcfg; /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ tmpcfg = cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_ICEN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= CFG_DCEN; if (what == ICACHETAG) tmpcfg |= (CFG_ICEN|CFG_CMODE_ITEST); else if (what == ICACHERAM) tmpcfg |= (CFG_ICEN|CFG_CMODE_IDATA); else if (what == DCACHETAG) tmpcfg |= CFG_CMODE_DTEST; else if (what == DCACHERAM) ; if ((what == ICACHERAM || what == ICACHETAG) && set) tmpcfg |= CFG_IS1EN; else if (what == DCACHERAM || what == DCACHETAG) /* only one set */ ; send_buffer(); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* write value to cache */ writeGpri(8,val); writeGpri(9,addr); if (sz == 1) send_instr(SB(8,0,9)); else if (sz == 2) send_instr(SH(8,0,9)); else send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* write_target(XT_MEM,M_CFG4001,cfg,4); */ writeGpri(8,cfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); readA0(); } #ifdef PMCC /************************************************************* */ Optdesc cache_opts_400x[] = { {"[-vidl][set [addr [value]]]","display cache"}, {"set","select set (default 0)"}, {"addr","specify address"}, {"-i","display icache"}, {"-d","display dcache (default)"}, {"-v","display only valid entries"}, {"-l","display only locked entries"}, {"-w","write entry"}, {"-t","write tag entry"}, {0}}; int cache_cmd_400x(ac,av) int ac; char *av[]; { int n,i,j,set,vflag,lflag,iflag,wflag,tflag,cachetag; static Ulong next_adr; Ulong adr,tag,msk,dadr,val; int cache_size,cache_line_size; U64 rv; vflag = lflag = iflag = wflag = tflag = 0; for (n=0,i=1;i cache_size/cache_line_size) break; tag = readCache_400x(set,cachetag,adr); if (vflag && (tag&0xf)==0) continue; if (lflag && (tag&0x10)==0) continue; printf("%08x ",adr); if (iflag) { printf("%08x ",readCache_400x(set,ICACHERAM,adr)); printf("%08x ",readCache_400x(set,ICACHERAM,adr+4)); printf("%08x ",readCache_400x(set,ICACHERAM,adr+8)); printf("%08x ",readCache_400x(set,ICACHERAM,adr+12)); } else { dadr = K0BASE|(tag&~msk)|(adr&msk); /* 970225 you can only display the data if the valid * bit is set */ if (tag&1) printf("%08x ",read_target(XT_MEM,dadr+0,4).lo); else printf("xxxxxxxx "); if (tag&2) printf("%08x ",read_target(XT_MEM,dadr+4,4).lo); else printf("xxxxxxxx "); if (tag&4) printf("%08x ",read_target(XT_MEM,dadr+8,4).lo); else printf("xxxxxxxx "); if (tag&8) printf("%08x ",read_target(XT_MEM,dadr+12,4).lo); else printf("xxxxxxxx "); } printf(" %08x\n",tag); j++; } next_adr = adr; return(1); } #endif /************************************************************* * void brkInstall_400x(type) * type=1 install regular+temp bpts * type=2 install trace bpts */ void brkInstall_400x(type) int type; { int i; Ulong dcs,tag,vmask,addr,cfg; OcmRec *p; printDiag(1,"\nbrkInstall_400x(%d)\n",type); for (i=0;ifunc) { if (addr&1) { addr &= ~1; brkList[i].val = run_ocm(p,0,addr,2,0).lo; run_ocm(p,1,addr,2,TINY_BPT_CODE); setFlushneeded(addr,2); } else { brkList[i].val = run_ocm(p,0,addr,4,0).lo; run_ocm(p,1,addr,4,BPT_CODE); setFlushneeded(addr,4); } brkList[i].isset = 1; break; } if (addr&1) { addr &= ~1; brkList[i].val = read_target(XT_MEM,addr,2).lo; writeGpri(8,TINY_BPT_CODE); writeGpri(9,addr); send_instr(SH(8,0,9)); setFlushneeded(addr,2); } else { brkList[i].val = read_target(XT_MEM,addr,4).lo; writeGpri(8,BPT_CODE); writeGpri(9,addr); send_instr(SW(8,0,9)); setFlushneeded(addr,4); } readA0(); brkList[i].isset = 1; break; case BRK_METHOD_ROM : printDiag(1,"installing rom bpt at %08x\n",addr); cfg = read_target(XT_MEM,M_CFG4001,4).lo; if ((cfg&CFG_ISIZEMASK) == CFG_ISIZE_8) { /* handle the irefillsz=8 case */ setupcacheline_400x(addr); /* copy mem to cache */ } tag = readCache_400x(0,ICACHETAG,addr); vmask = 1<<((addr>>2)&3); if (!(tag&LCK_BIT)) { tag &= ~0xf; tag |= LCK_BIT; } tag |= vmask; writeCache(0,ICACHERAM,addr,BPT_CODE,4); writeCache(0,ICACHETAG,addr,tag,4); /* make sure that it is not in set1 */ writeCache(1,ICACHETAG,addr,0,4); brkList[i].isset = 1; break; case BRK_METHOD_HW : if (dbx_needs_pa) addr &= 0x1fffffff; /* convert to PA */ if (brkList[i].type == BPTYPE_DATA) { printDiag(1,"installing hwdb bpt at %08x\n",addr); writeGpri(8,addr); send_instr(MTD(8,DBX_BDA)); writeGpri(8,brkList[i].mask); send_instr(MTD(8,DBX_BDAM)); send_instr(0); send_instr(MFD(4,DBX_DCS)); send_instr(0); dcs = readA0().lo; dcs |= DCS_TR|DCS_UD|DCS_KD|DCS_DE|DCS_DAE; if (brkList[i].aux[0]&2) dcs |= DCS_DR; if (brkList[i].aux[0]&1) dcs |= DCS_DW; } else { printDiag(1,"installing hwib bpt at %08x\n",addr); writeGpri(8,addr); send_instr(MTD(8,DBX_BPC)); writeGpri(8,brkList[i].mask); send_instr(MTD(8,DBX_BPCM)); send_instr(0); send_instr(MFD(4,DBX_DCS)); send_instr(0); dcs = readA0().lo; dcs |= DCS_TR|DCS_UD|DCS_KD|DCS_DE|DCS_PCE; } writeGpri(8,dcs); send_instr(MTD(8,DBX_DCS)); readA0(); brkList[i].isset = 1; break; default : printDiag(0,"%d: error bad method\n",brkList[i].method); return; } } printDiag(1,"\n"); } /************************************************************* * int brkRemove_400x(epc) * returns type: 0=none 1=bpc 2=bda 3=itemp 4=sstep */ int brkRemove_400x(epc) Ulong epc; { int i,type,cnt; Ulong addr; OcmRec *p; if (nobrkRemove) return(0); nobrkRemove = 1; type = cnt = 0; for (i=0;ifunc) { if (addr&1) run_ocm(p,1,addr,2,brkList[i].val); else run_ocm(p,1,addr,4,brkList[i].val); break; } if (addr&1) { writeGpri(8,brkList[i].val); writeGpri(9,addr&~1); send_instr(SH(8,0,9)); setFlushneeded(addr,2); } else { writeGpri(8,brkList[i].val); writeGpri(9,addr); send_instr(SW(8,0,9)); setFlushneeded(addr,4); } readA0(); brkList[i].isset = 0; break; case BRK_METHOD_ROM : addr = brkList[i].addr; if (cnt++ == 1) printDiag(1,"\n"); printDiag(1,"brkRemove: %d rom bpt %08x\n",i,addr); writeCache(0,ICACHETAG,addr,0,4); setFlushneeded(addr,4); #if 0 /* this doesn't work on the 4101 */ /* handle the irefillsz==8 case */ cfg = read_target(XT_MEM,M_CFG4001,4); if ((cfg&CFG_ISIZEMASK) == CFG_ISIZE_8) { if (addr&0x10) writeCache(0,ICACHETAG,addr&~0x10,0,4); else writeCache(0,ICACHETAG,addr|0x10,0,4); } #endif brkList[i].isset = 0; break; case BRK_METHOD_HW : if (cnt++ == 1) printDiag(1,"\n"); printDiag(1,"brkRemove: %d hw bpt\n",i); send_instr(MTD(0,DBX_DCS)); /* 980823 */ readA0(); brkList[i].isset = 0; break; } if (brkList[i].type == BPTYPE_ITMP) brkList[i].type = 0; if (brkList[i].type == BPTYPE_TRACE) brkList[i].type = 0; } nobrkRemove = 0; if (cnt) printDiag(1,"\n"); return(type); } /************************************************************* * void setupcacheline_400x(addr) * This routine sets things up for rom bpts when irefill=8wds * 8 wd refill requires that all 4 valid bits are set * Copy real memory bytes to the correct line. * Write the correct tag and valid bit. */ void setupcacheline_400x(addr) Ulong addr; { Ulong cfg,savedcfg,addrmsk; int n; /* * copy data from memory * operation: * for (r10=4;r10>0;r10--) *r8++ = *r9++; * r2,r4 = tmp * r5 = addr of cfg reg */ savedcfg = cfg = read_target(XT_MEM,M_CFG4001,4).lo; cfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); cfg |= (CFG_ICEN|CFG_DCEN); writeGpri(8,addr&~(icache_line_size-1)); writeGpri(9,K1BASE|addr&~(icache_line_size-1)); writeGpri(10,icache_line_size/4); /* number of words to copy */ writeGpri(5,M_CFG4001); n = 1; /* start of loop */ n += writeGpri(4,savedcfg); n += send_instr(SW(4,0,5)); /*n += send_instr(LW(0,0,5)); /* wbflush */ n += send_instr(0); n += send_instr(0); n += send_instr(0); n += send_instr(LW(2,0,9)); /* read memory */ n += writeGpri(4,cfg|CFG_CMODE_IDATA); /* data */ n += send_instr(SW(4,0,5)); /*n += send_instr(LW(0,0,5)); /* wbflush */ n += send_instr(0); n += send_instr(ADDIU(9,9,4)); n += send_instr(SUBIU(10,1)); n += send_instr(SW(2,0,8)); /* write cache entry */ n += send_instr(BNE(10,0,0-n)); n += send_instr(ADDIU(8,8,4)); /* end of loop */ /* write the tag */ n += writeGpri(4,cfg|CFG_CMODE_ITEST); /* tag */ n += send_instr(SW(4,0,5)); /*n += send_instr(LW(0,0,5)); /* wbflush */ n += send_instr(0); n += writeGpri(9,addr); addrmsk = (0x7<<29)|(icache_size-1); n += writeGpri(8,(addr&~addrmsk)|0x1f); /* 0x1f = lock + 4 valid bits */ n += send_instr(SW(8,0,9)); /* restore cfg */ n += writeGpri(4,savedcfg); n += send_instr(SW(4,0,5)); /*n += send_instr(LW(0,0,5)); /* wbflush */ n += send_instr(0); n += send_instr(0); readA0(); } /************************************************************* * ilockReq_400x(addr) * verify that other ilock bpts don't conflict with this one * (ie. are a cachesize multiple apart). * Also verify that lock bit is not already set. */ int ilockReq_400x(addr) Ulong addr; { Ulong tag; #if 0 Ulong tmsk,omsk; int i; #endif if (!has_ilock) return(0); /* no go if Iset0 is not enabled */ if (!(read_target(XT_MEM,M_CFG4001,4).lo&CFG_ICEN)) return(0); tag = readCache_400x(0,ICACHETAG,addr); if (tag&LCK_BIT) return(0); #if 0 /* 980319 */ tmsk = (icache_size)-1; /* tag mask */ omsk = tmsk&~(icache_line_size-1); for (i=0;i>2)&3); if (!(tag&LCK_BIT)) { tag &= ~0xf; tag |= LCK_BIT; } tag |= vmask; writeCache(0,ICACHERAM,addr,bptcode,sz); writeCache(0,ICACHETAG,addr,tag,4); /* make sure that it is not in set1 */ writeCache(1,ICACHETAG,addr,0,4); } /************************************************************* */ void clrilockbpt_400x(Ulong addr) { writeCache(0,ICACHETAG,addr,0,4); setFlushneeded(addr,4); } /************************************************************* * void flush_target_400x_ejtag(mode) * Flush the designated cache in the target. * This version avoids loops. I flush the cache by sending * blocks of SW instructions terminated by a readA0. */ int flush_target_400x_ejtag(int mode) { Ulong cfg,tmpcfg; int i,blksize,lines,n; int ibs = 64; /* instr buffer size. Should get this value from sah */ /* need to allow space for code appended by ejtag.dll. The value also need to be a multiple of cache_line_size. */ /* flush_target_400x_ejtag: The gpr[10]s in this func were 26 (k0) */ /* flush_target_400x_ejtag: The gpr[11]s in this func were 27 (k1) */ /* emit code to flush the caches */ /* we are already in an isr with ints disabled */ /* the instr buffer is in kseg1 */ if (!target_stopped) return(1); /* 980323 */ if (need_initial_flush) { printDiag(1,"performing initial flush 400x_ejtag\n"); need_initial_flush = 0; flush_target_400x_ejtag(DCACHEI); flush_target_400x_ejtag(ICACHEI); } switch (mode) { case ICACHEI : printDiag(1,"\niflush 400x_ejtag size=%d lnsize=%d\n", icache_size,icache_line_size); if (icache_size == 0) { iflush_needed = 0; return(1); } send_buffer(); cfg = read_target(XT_MEM,M_CFG4001,4).lo; tmpcfg = cfg; tmpcfg &= ~(CFG_CMODEMASK|CFG_IS1EN|CFG_DSIZEMASK|CFG_ISIZEMASK); tmpcfg |= (CFG_ICEN|CFG_DCEN|CFG_CMODE_ITEST); /* write_target(XT_MEM,M_CFG4001,tmpcfg,4); */ writeGpri(8,tmpcfg); writeGpri(9,M_CFG4001); send_instr(SW(8,0,9)); send_instr(0); send_instr(0); send_instr(0); /* actual cache code */ writeGpri(9,K0BASE); blksize = ibs*icache_line_size; for (i=0;i>shamt; dirty_dcache_line[line] = 1; } } /************************************************************* */ void markIcacheDirty(Ulong addr,int size) { int shamt,msk,i,line; if (icache_size == 0) return; if (!dirty_icache_line) dirty_icache_line = (char *)calloc(icache_size/icache_line_size,1); for (shamt=0,msk=1;(icache_line_size&msk)==0;msk<<=1,shamt++) ; for (i=0;i>shamt; dirty_icache_line[line] = 1; } } /************************************************************* * void setFlushneeded_ejtag(Ulong addr,int size) */ void setFlushneeded_ejtag(Ulong addr,int size) { if (IS_K0SEG(addr)) { if (icache_size != 0) { iflush_needed += size; markIcacheDirty(addr,size); printDiag(3,"iflush_needed=%d\n",iflush_needed); } if (ejtag_mode && dcache_size != 0) { dflush_needed += size; /* 981216 */ markDcacheDirty(addr,size); printDiag(3,"dflush_needed=%d\n",dflush_needed); } /* prob was that because ejtag download is performed using dma, the * dcache needed updating. This is not a problem for SI. */ } else if ((addr&0xfff00000)==0xbff00000) ; /* 970225 */ else if (is_ocm(addr)) ; /* 980225 */ else { if (icache_size != 0) { iflush_needed += size; markIcacheDirty(addr,size); printDiag(3,"iflush_needed=%d\n",iflush_needed); } if (dcache_size != 0) { dflush_needed += size; markDcacheDirty(addr,size); printDiag(3,"dflush_needed=%d\n",dflush_needed); } } }