This code uses ``debug'' accesses to the cache subsystem to work out the size and shape of the cache to pass in a cache reopen cell to the memory server.
/* Figure out cache configuration */ /* Check set 0 for 32 bit wide R/W memory */ if ((set0 = probedata((volatile unsigned long *) 0xE0000000, (volatile unsigned long *) 0xEFFFFFFF)) != 0) { outstr("Cache set 0 error. Data probe gives "); outhexnum(set0); outstr(".\n"); } /* Check set 1 for 32 bit wide R/W memory */ if ((set1 = probedata((volatile unsigned long *) 0xF0000000, (volatile unsigned long *) 0xFFFFFFFF)) != 0) { outstr("Cache set 1 error. Data probe gives "); outhexnum(set1); outstr(".\n"); } /* If neither set 0 nor 1 has 32 bit wide R/W then we can't go on */ if (set0 && set1) { outstr("The cache has failed\n"); return; } TRC(outstr("Check adr\n")); /* Now see how big the cache memory is by looking at *ACTUAL* RAM*/ /* The idea is that since the lines will form a contiguous block */ /* the result from the probe will have low bits valid == line */ /* next a block don't care == tag */ /* finally a block valid == region */ probeadr((volatile unsigned long *)0xE0000000, 0x1C, 0xffffffff, &aerr, &asame); /* lrbits is the valid bits - low valid is line, top valid is region */ lrbits = aerr | asame | 0xf0000000; TRC(outhexnum(lrbits)); /* zeros -> bit */ TRC(outstr("find bits\n")); /* count line bits == the number of low valid bits */ for(lcou=0, bit=32; ((lrbits & bit)==0);lcou++,bit<<=1); /* skip over tag bits which aren't real in the debug memory */ for(tcou=0; (bit != 0) && ((lrbits & bit)!=0);tcou++,bit<<=1); /* the top valid bits are the region ones */ for(rcou=0; (bit != 0) && ((lrbits & bit)==0);rcou++,bit<<=1); /* Having figured out the size work out associativity */ if (set0 || set1) sa = 0x10; /* One set, direct mapped */ else { /* Both valid, must work out if adr bit selects lru */ /* There are three cases: */ /* a) Direct mapped, lru=0 only use set 0 */ /* b) Direct mapped, lru=tag[4]=a17, set = a17 */ /* c) 2way set assoc, lru=lru */ volatile int *tag0 = (int *) 0xC0000000; volatile int *tag1 = (int *) 0xD0000000; volatile int *tag0a = (int *) 0xC0020000; volatile int *dat = (int *) 0x80000000; int x; /* First find out if it updates lru, which it only will */ /* if it is two way assoc. The plan is to see which set */ /* is marked as lru, set the tags to ensure a hit on it */ /* and see if the lru bit has changed */ *CCTRL_CMD = TAGR; /* NB this only resets the tag memory */ if ((*tag0 & 0x200) == 0) { /* Now showing lru 0 */ *tag0 = 0x80; x = *dat; if ((*tag0 & 0x200) == 0) /* No change -> direct map */ sa = 0; else sa = 1; } else { /* Now showing lru 1 */ *tag1 = 0x80; x = *dat; if ((*tag1 & 0x200) != 0) /* No change -> direct map */ sa = 0; else sa = 1; } /* Now we know if it is direct or set assoc */ if (sa) sa = 0x21; /* 2 sets, assoc */ else { /* In the direct mapped case check for two sets */ /* by looking to see if the lru bit depends on A17 */ if ((*tag0 & 0x200) == (*tag0a & 0x200)) sa = 0x10; /* 1 set, not assoc */ else sa = 0x20; /* 2 sets, not assoc */ } } outstr("Cache has "); outdecnum(lcou); outstr(" bits line, "); outdecnum(tcou); outstr(" bits tag, "); outdecnum(rcou); outstr(" bits region, "); outhexnum(sa >> 4); if (sa & 1) outstr(" set associative"); else outstr(" set direct map"); outch('\n'); /* Need to tell the memory server this */ reopenCell[10] = lcou; reopenCell[11] = tcou; reopenCell[12] = rcou; reopenCell[13] = sa;