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;