⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cim_msr.c

📁 LX 800 WindowsCE 6.0 BSP
💻 C
字号:
 /*
  * <LIC_AMD_STD>
  * Copyright (C) 2005 Advanced Micro Devices, Inc.  All Rights Reserved.
  * </LIC_AMD_STD>
  *
  * <CTL_AMD_STD>
  * </CTL_AMD_STD>
  *
  * <DOC_AMD_STD>
  * Cimarron MSR access routines.  These routines allow the user to query the
  * state of the GeodeLink Bus and read and write model-specfic registers.
  * </DOC_AMD_STD>
  *
  */

/*--------------------------------------------------------------*/
/* MSR GLOBALS                                                  */
/* These variables hold a local copy of the GeodeLink mapping   */
/* as well as a lookup table for easy device addressing.        */
/*--------------------------------------------------------------*/

GEODELINK_NODE gliu_nodes[24];
GEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY];

#define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF)

/*---------------------------------------------------------------------------
 * msr_init_table
 *
 * This routine intializes the internal MSR table in Cimarron.  This table is
 * used for any MSR device accesses.
 *---------------------------------------------------------------------------*/

int	msr_init_table (void)
{
	Q_WORD msr_value;
	unsigned int i, j;
	int return_value = CIM_STATUS_OK;

	/* CHECK FOR VALID GEODELINK CONFIGURATION                                     */
	/* The CPU and the three GLIUs are assumed to be at known static addresses, so */
	/* we will check the device IDs at these addresses as proof of a valid         */
	/* GeodeLink configuration                                                     */

	MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value);
    if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL)
       	return_value = CIM_STATUS_ERROR;

	MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value);
    if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
    	return_value = CIM_STATUS_ERROR;

	MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value);
    if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
    	return_value = CIM_STATUS_ERROR;

	MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value);
    if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU)
    	return_value = CIM_STATUS_ERROR;

	if (return_value == CIM_STATUS_OK)
	{
		/* BUILD LOCAL COPY OF THE GEODELINK BUS */

		msr_create_geodelink_table (gliu_nodes);

		/* CLEAR TABLE STATUS */

		for (i = 0; i < MSR_DEVICE_EMPTY; i++)
			msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
		
		/* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS    */
		/* Note that MSR_DEVICE_EMPTY is the index after the last */
		/* available device.  Also note that we fill in known     */
		/* devices before filling in the rest of the table.       */

		msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu   = MSR_ADDRESS_GLIU0;
		msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id          = MSR_DEVICE_PRESENT;
		msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu   = MSR_ADDRESS_GLIU1;
		msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id          = MSR_DEVICE_PRESENT;
		msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu      = MSR_ADDRESS_GLIU2;
		msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id             = MSR_DEVICE_PRESENT;
		msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu    = MSR_ADDRESS_VAIL;
		msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id           = MSR_DEVICE_PRESENT;

		for (i = 0; i < MSR_DEVICE_EMPTY; i++)
		{
			if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND)
			{
				for (j = 0; j < 24; j++)
				{
					if (gliu_nodes[j].device_id == i)
						break;					
				}

				if (j == 24)
					msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
				else
				{
					msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT;
					msr_dev_lookup[i].address_from_cpu = gliu_nodes[j].address_from_cpu;
				}
			}
		}	
	}
	else
	{
		/* ERROR OUT THE GEODELINK TABLES */

		for (i = 0; i < 24; i++)
		{
			gliu_nodes[i].address_from_cpu = 0xFFFFFFFF;
			gliu_nodes[i].device_id = MSR_DEVICE_EMPTY;
		}

		for (i = 0; i < MSR_DEVICE_EMPTY; i++)
		{
			msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF;
			msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND;
		}
	}
    return return_value;
}

/*---------------------------------------------------------------------------
 * msr_create_geodelink_table
 *
 * This routine dumps the contents of the GeodeLink bus into an array of
 * 24 GEODELINK_NODE structures.  Indexes 0-7 represent ports 0-7 of GLIU0,
 * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent
 * ports 0-7 of GLIU2 (5535).
 *---------------------------------------------------------------------------*/

int msr_create_geodelink_table (GEODELINK_NODE *gliu_nodes)
{
	unsigned long mbiu_port_count, reflective;
    unsigned long port, index;
	unsigned long gliu_count = 0;
	int glcp_count = 0;
	int usb_count  = 0;
	int mpci_count = 0;
	Q_WORD msr_value;

	/* ALL THREE GLIUS ARE IN ONE ARRAY                               */
	/* Entries 0-7 contain the port information for GLIU0, entries    */
	/* 8-15 contain GLIU1 and 15-23 contain GLIU2.  We perform the    */
	/* enumeration in two passes.  The first simply fills in the      */
	/* addresses and class codes at each node.  The second pass       */
	/* translates the class codes into indexes into Cimarron's device */
	/* lookup table.                                                  */

	/* COUNT GLIU0 PORTS */

	MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value);
	mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;

	/* FIND REFLECTIVE PORT */
	/* Query the GLIU for the port through which we are communicating. */
	/* We will avoid accesses to this port to avoid a self-reference.  */
	
	MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value);
	reflective = msr_value.low & WHOAMI_MASK;

	/* SPECIAL CASE FOR PORT 0 */
	/* GLIU0 port 0 is a special case, as it points back to GLIU0.  GLIU0 */
	/* responds at address 0x10000xxx, which does not equal 0 << 29.      */

	gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0;
	gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU;

	/* ENUMERATE ALL PORTS */

	for (port = 1; port < 8; port++)
	{
		/* FILL IN ADDRESS */

		gliu_nodes[port].address_from_cpu = port << 29;

		if (port == reflective)
			gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE;
		else if (port > mbiu_port_count)
			gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED;
	    else
		{
			MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, &msr_value);
			gliu_nodes[port].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
		}
	}
	
	/* COUNT GLIU1 PORTS */

	MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value);
	mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;

	/* FIND REFLECTIVE PORT */
	
	MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value);
	reflective = msr_value.low & WHOAMI_MASK;

	/* ENUMERATE ALL PORTS */

	for (port = 0; port < 8; port++)
	{
		index = port + 8;

		/* FILL IN ADDRESS */

		gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26);

		if (port == reflective)
			gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
		else if (port > mbiu_port_count)
			gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
	    else
		{
			MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
			gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
		}
	}

	/* COUNT GLIU2 PORTS */

	MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value);
	mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7;

	/* FIND REFLECTIVE PORT */
	
	MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value);
	reflective = msr_value.low & WHOAMI_MASK;

    /* FILL IN PORT 0 AND 1 */
    /* Port 0 on 5535 is MBIU2.  Port 1 is MPCI, but it is referenced at */
    /* a special address.                                                */

    gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2;
    gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU;

    gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI;
    gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI;

	/* ENUMERATE ALL PORTS */

	for (port = 2; port < 8; port++)
	{
		index = port + 16;

		/* FILL IN ADDRESS */

		gliu_nodes[index].address_from_cpu =
			(0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20);

		if (port == reflective)
			gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE;
		else if (port > mbiu_port_count)
			gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED;
	    else
		{
			MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value);
			gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low);
		}
	}

	/* SECOND PASS - TRANSLATION */
	/* Now that the class codes for each device are stored in the  */
	/* array, we walk through the array and translate the class    */
	/* codes to table indexes.  For class codes that have multiple */
	/* instances, the table indexes are sequential.                */

	for (port = 0; port < 24; port++)
	{
		/* SPECIAL CASE FOR GLIU UNITS */
		/* A GLIU can be both on another port and on its own port.  These  */
		/* end up as the same address, but are shown as duplicate nodes in */
		/* the GeodeLink table.                                            */

		if ((port & 7) == 0)
			gliu_count = port >> 3;

		switch (gliu_nodes[port].device_id)
		{
			/* UNPOPULATED OR REFLECTIVE NODES */

			case MSR_CLASS_CODE_UNPOPULATED: index = MSR_DEVICE_EMPTY;       break;	
			case MSR_CLASS_CODE_REFLECTIVE:  index = MSR_DEVICE_REFLECTIVE;  break;
			
			/* KNOWN CLASS CODES */
			
			case MSR_CLASS_CODE_GLIU: index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++;  break;
			case MSR_CLASS_CODE_GLCP: index = MSR_DEVICE_GEODELX_GLCP  + glcp_count++;  break;
			case MSR_CLASS_CODE_MPCI: index = MSR_DEVICE_GEODELX_MPCI  + mpci_count++;  break;
			case MSR_CLASS_CODE_USB:  index = MSR_DEVICE_5535_USB2 + usb_count++; break;
            case MSR_CLASS_CODE_USB2: index = MSR_DEVICE_5536_USB_2_0; break;
			case MSR_CLASS_CODE_ATAC: index = MSR_DEVICE_5535_ATAC;    break;
			case MSR_CLASS_CODE_MDD:  index = MSR_DEVICE_5535_MDD;     break;
			case MSR_CLASS_CODE_ACC:  index = MSR_DEVICE_5535_ACC;     break;
			case MSR_CLASS_CODE_MC:   index = MSR_DEVICE_GEODELX_MC;   break;
			case MSR_CLASS_CODE_GP:   index = MSR_DEVICE_GEODELX_GP;   break;
			case MSR_CLASS_CODE_VG:   index = MSR_DEVICE_GEODELX_VG;   break;
			case MSR_CLASS_CODE_DF:   index = MSR_DEVICE_GEODELX_DF;   break;
			case MSR_CLASS_CODE_FG:   index = MSR_DEVICE_GEODELX_FG;   break;
			case MSR_CLASS_CODE_VIP:  index = MSR_DEVICE_GEODELX_VIP;  break;
			case MSR_CLASS_CODE_AES:  index = MSR_DEVICE_GEODELX_AES;  break;
			case MSR_CLASS_CODE_VAIL: index = MSR_DEVICE_GEODELX_VAIL; break;
			default: index = MSR_DEVICE_EMPTY; break;
		}

		gliu_nodes[port].device_id = index;
	}

	return CIM_STATUS_OK;
}

/*---------------------------------------------------------------------------
 * msr_create_device_list
 *
 * This routine dumps a list of all known GeodeLX/5535 devices as well as their
 * respective status and address.
 *---------------------------------------------------------------------------*/

int msr_create_device_list (GEODELINK_NODE *gliu_nodes, int max_devices)
{
	int i, count;

	if (max_devices < MSR_DEVICE_EMPTY) count = max_devices;
	else                                count = MSR_DEVICE_EMPTY;

	for (i = 0; i < count; i++)
	{
		gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu;
		gliu_nodes[i].device_id        = msr_dev_lookup[i].device_id;
	}

	return CIM_STATUS_OK;
}

/*--------------------------------------------------------------------
 * msr_read64
 *
 * Performs a 64-bit read from 'msr_register' in device 'device'.  'device' is
 * an index into Cimarron's table of known GeodeLink devices.
 *-------------------------------------------------------------------*/

int msr_read64 (unsigned long device, unsigned long msr_register,
	Q_WORD *msr_value)
{
	if (device < MSR_DEVICE_EMPTY)
	{
		if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
		{
			MSR_READ (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
			return CIM_STATUS_OK;
		}
	}

    msr_value->low = msr_value->high = 0;
	return CIM_STATUS_DEVNOTFOUND;
}

/*--------------------------------------------------------------------
 * msr_write64
 *
 * Performs a 64-bit write to 'msr_register' in device 'device'.  'device' is
 * an index into Cimarron's table of known GeodeLink devices.
 *-------------------------------------------------------------------*/

int msr_write64 (unsigned long device, unsigned long msr_register,
	Q_WORD *msr_value)
{
	if (device < MSR_DEVICE_EMPTY)
	{
		if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT)
		{
			MSR_WRITE (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value);
			return CIM_STATUS_OK;
		}
	}
	return CIM_STATUS_DEVNOTFOUND;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -