Coherent4.2.10/i386/cyrix.c
/*************************************************************************
* Function: unsigned short cyrix_detect(void)
* Returns: 0xFFFF -- non-Cyrix CPU detected
* 0xFFFE -- Cyrix OEM CPU detected (no cache startup)
* id# -- Cyrix Upgrade CPU detected (cache startup possible)
*
* This code is based on code provided by Cyrix. For current code,
* contact Cyrix.
*/
#define CR2_MASK 0x04 /* LockNW */
#define CR3_MASK 0x02 /* NMIEN */
#define _KERNEL 1
#include <sys/cyrix.h>
#include <sys/coherent.h>
#if __USE_PROTO__
unsigned short cyrix_detect(void)
#else
unsigned short
cyrix_detect()
#endif
{
unsigned char orgc2, newc2, orgc3, newc3;
int cr2_rw = 0, cr3_rw = 0;
unsigned short type = 0;
unsigned short ret;
/*
* See if it is a Cyrix CPU, and if so what kind.
*/
if(iscyrix()) {
/*
* Test Cyrix C2 register read/writeable.
*/
orgc2 = cx_r(0xC2); /* Get current c2 value */
newc2 = orgc2 | CR2_MASK; /* Set test bits */
cx_w(0xC2, newc2); /* Write test value to c2 */
cx_r(0xC0); /* Dummy read to change bus */
/* See if only mask bits were set */
if((cx_r(0xC2) & CR2_MASK) == CR2_MASK) {
newc2 = orgc2 & ~CR2_MASK; /* Clear test bits */
cx_w(0xC2, newc2); /* Write cleared mask */
cx_r(0xC0); /* Dummy read to change bus */
/* See if the mask bits were cleared */
if((cx_r(0xC2) & CR2_MASK) == 0)
cr2_rw = 1;
}
/* Return c2 to original value */
cx_w(0xC2, orgc2);
/*
* Test Cyrix c3 register read/writeable.
*/
orgc3 = cx_r(0xC3); /* Get current c3 value */
newc3 = orgc3 | CR3_MASK; /* Set NMI_ENABLE */
cx_w(0xC3, newc3); /* Write test value to c3 */
/* See if only the mask bits were set. */
if((cx_r(0xC3) & CR3_MASK) == CR3_MASK) {
newc3 = orgc3 & ~CR3_MASK; /* Clear NMI_ENABLE */
cx_w(0xC3, newc3); /* Write cleared mask to c3 */
/* See if mask bits were cleared. */
if((cx_r(0xC3) & CR3_MASK) == 0)
cr3_rw = 1;
}
cx_w(0xC3, orgc3);
/*
* Only the DRx2 and SRx2 have a cache we can enable,
* so, those are the only ones we care about.
*/
if((cr2_rw && cr3_rw) || (!cr2_rw && cr3_rw)) {
type = cx_r(0xFE); /* IDIR0 */
type += cx_r(0xFF) << 8; /* IDIR1 */
}
/*
* If we know it's not one of the above, get out.
* It must be either a Cx486S_a or a Cx486_pr.
*/
if(type == 0)
ret = CYRIX_OEM;
switch(type & 0xFF) {
case (CYRIX_SRX): /* We only care about these */
case (CYRIX_DRX):
case (CYRIX_SRX2):
case (CYRIX_DRX2):
ret = type;
break;
default:
ret = CYRIX_OEM;
break;
}
} else /* Non-Cyrix */
ret = CYRIX_NOT;
return ret;
}
#define CX_NC0 1
#define CX_NC1 2
#define CX_FLUSH 16
#define CX_RPL 1
/* Turn the cache on a Cyrix user-upgrade chip */
#if __USE_PROTO__
void
cyrix_cache_on(void)
#else
void
cyrix_cache_on()
#endif
{
unsigned char tmp_reg;
int s;
/* Lock out interrupts */
s = sphi();
/* Invalidate cache and turn off caching */
cx_invalidate_cache();
/* Turn on caching control regs */
tmp_reg = cx_r(0xC0);
tmp_reg |= (CX_NC0 | CX_NC1 | CX_FLUSH);
cx_w(0xC0, tmp_reg);
tmp_reg = cx_r(0xC1);
tmp_reg &= ~CX_RPL;
cx_w(0xC1, tmp_reg);
/* Zero out the non-cacheable regions. */
cx_w(0xC6, 0x00);
cx_w(0xC5, 0x00);
cx_w(0xC6, 0x00);
/*
* Cyrix doesn't clear these in their example.
* They depend on the fact
* that hardware will have them zero'ed out as part
* of the initialization during reset.
*/
#if 0
cx_w(0xC8, 0x00);
cx_w(0xC9, 0x00);
cx_w(0xCB, 0x00);
cx_w(0xCC, 0x00);
cx_w(0xCE, 0x00);
cx_w(0xCF, 0x00);
#endif
/* Re-enable caching */
cx_start_cache();
/* Interrupts restored */
spl(s);
}