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);
}