cim_msr.c revision f29dbc25
1f29dbc25Smrg/* 2f29dbc25Smrg * Copyright (c) 2006 Advanced Micro Devices, Inc. 3f29dbc25Smrg * 4f29dbc25Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5f29dbc25Smrg * copy of this software and associated documentation files (the "Software"), 6f29dbc25Smrg * to deal in the Software without restriction, including without limitation 7f29dbc25Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f29dbc25Smrg * and/or sell copies of the Software, and to permit persons to whom the 9f29dbc25Smrg * Software is furnished to do so, subject to the following conditions: 10f29dbc25Smrg * 11f29dbc25Smrg * The above copyright notice and this permission notice shall be included in 12f29dbc25Smrg * all copies or substantial portions of the Software. 13f29dbc25Smrg * 14f29dbc25Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f29dbc25Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f29dbc25Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17f29dbc25Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18f29dbc25Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19f29dbc25Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20f29dbc25Smrg * DEALINGS IN THE SOFTWARE. 21f29dbc25Smrg * 22f29dbc25Smrg * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 23f29dbc25Smrg * contributors may be used to endorse or promote products derived from this 24f29dbc25Smrg * software without specific prior written permission. 25f29dbc25Smrg */ 26f29dbc25Smrg 27f29dbc25Smrg /* 28f29dbc25Smrg * Cimarron MSR access routines. These routines allow the user to query the 29f29dbc25Smrg * state of the GeodeLink Bus and read and write model-specfic registers. 30f29dbc25Smrg */ 31f29dbc25Smrg 32f29dbc25Smrg/*--------------------------------------------------------------*/ 33f29dbc25Smrg/* MSR GLOBALS */ 34f29dbc25Smrg/* These variables hold a local copy of the GeodeLink mapping */ 35f29dbc25Smrg/* as well as a lookup table for easy device addressing. */ 36f29dbc25Smrg/*--------------------------------------------------------------*/ 37f29dbc25Smrg 38f29dbc25SmrgGEODELINK_NODE gliu_nodes[24]; 39f29dbc25SmrgGEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY]; 40f29dbc25Smrg 41f29dbc25Smrg#define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF) 42f29dbc25Smrg 43f29dbc25Smrg/*--------------------------------------------------------------------------- 44f29dbc25Smrg * msr_init_table 45f29dbc25Smrg * 46f29dbc25Smrg * This routine intializes the internal MSR table in Cimarron. This table is 47f29dbc25Smrg * used for any MSR device accesses. 48f29dbc25Smrg *--------------------------------------------------------------------------*/ 49f29dbc25Smrg 50f29dbc25Smrgint 51f29dbc25Smrgmsr_init_table(void) 52f29dbc25Smrg{ 53f29dbc25Smrg Q_WORD msr_value = {0, 0}; 54f29dbc25Smrg unsigned int i, j; 55f29dbc25Smrg int return_value = CIM_STATUS_OK; 56f29dbc25Smrg 57f29dbc25Smrg /* CHECK FOR VALID GEODELINK CONFIGURATION 58f29dbc25Smrg * The CPU and the three GLIUs are assumed to be at known static 59f29dbc25Smrg * addresses, so we will check the device IDs at these addresses as proof 60f29dbc25Smrg * of a valid GeodeLink configuration 61f29dbc25Smrg */ 62f29dbc25Smrg 63f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value); 64f29dbc25Smrg if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL) 65f29dbc25Smrg return_value = CIM_STATUS_ERROR; 66f29dbc25Smrg 67f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value); 68f29dbc25Smrg if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) 69f29dbc25Smrg return_value = CIM_STATUS_ERROR; 70f29dbc25Smrg 71f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value); 72f29dbc25Smrg if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) 73f29dbc25Smrg return_value = CIM_STATUS_ERROR; 74f29dbc25Smrg 75f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value); 76f29dbc25Smrg if (GET_DEVICE_ID(msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) 77f29dbc25Smrg return_value = CIM_STATUS_ERROR; 78f29dbc25Smrg 79f29dbc25Smrg if (return_value == CIM_STATUS_OK) { 80f29dbc25Smrg /* BUILD LOCAL COPY OF THE GEODELINK BUS */ 81f29dbc25Smrg 82f29dbc25Smrg msr_create_geodelink_table(gliu_nodes); 83f29dbc25Smrg 84f29dbc25Smrg /* CLEAR TABLE STATUS */ 85f29dbc25Smrg 86f29dbc25Smrg for (i = 0; i < MSR_DEVICE_EMPTY; i++) 87f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; 88f29dbc25Smrg 89f29dbc25Smrg /* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS */ 90f29dbc25Smrg /* Note that MSR_DEVICE_EMPTY is the index after the last */ 91f29dbc25Smrg /* available device. Also note that we fill in known */ 92f29dbc25Smrg /* devices before filling in the rest of the table. */ 93f29dbc25Smrg 94f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu = 95f29dbc25Smrg MSR_ADDRESS_GLIU0; 96f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = 97f29dbc25Smrg MSR_DEVICE_PRESENT; 98f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = 99f29dbc25Smrg MSR_ADDRESS_GLIU1; 100f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = 101f29dbc25Smrg MSR_DEVICE_PRESENT; 102f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = 103f29dbc25Smrg MSR_ADDRESS_GLIU2; 104f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT; 105f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = 106f29dbc25Smrg MSR_ADDRESS_VAIL; 107f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = 108f29dbc25Smrg MSR_DEVICE_PRESENT; 109f29dbc25Smrg 110f29dbc25Smrg for (i = 0; i < MSR_DEVICE_EMPTY; i++) { 111f29dbc25Smrg if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND) { 112f29dbc25Smrg for (j = 0; j < 24; j++) { 113f29dbc25Smrg if (gliu_nodes[j].device_id == i) 114f29dbc25Smrg break; 115f29dbc25Smrg } 116f29dbc25Smrg 117f29dbc25Smrg if (j == 24) 118f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; 119f29dbc25Smrg else { 120f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT; 121f29dbc25Smrg msr_dev_lookup[i].address_from_cpu = 122f29dbc25Smrg gliu_nodes[j].address_from_cpu; 123f29dbc25Smrg } 124f29dbc25Smrg } 125f29dbc25Smrg } 126f29dbc25Smrg } else { 127f29dbc25Smrg /* ERROR OUT THE GEODELINK TABLES */ 128f29dbc25Smrg 129f29dbc25Smrg for (i = 0; i < 24; i++) { 130f29dbc25Smrg gliu_nodes[i].address_from_cpu = 0xFFFFFFFF; 131f29dbc25Smrg gliu_nodes[i].device_id = MSR_DEVICE_EMPTY; 132f29dbc25Smrg } 133f29dbc25Smrg 134f29dbc25Smrg for (i = 0; i < MSR_DEVICE_EMPTY; i++) { 135f29dbc25Smrg msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF; 136f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; 137f29dbc25Smrg } 138f29dbc25Smrg } 139f29dbc25Smrg return return_value; 140f29dbc25Smrg} 141f29dbc25Smrg 142f29dbc25Smrg/*--------------------------------------------------------------------------- 143f29dbc25Smrg * msr_create_geodelink_table 144f29dbc25Smrg * 145f29dbc25Smrg * This routine dumps the contents of the GeodeLink bus into an array of 146f29dbc25Smrg * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0, 147f29dbc25Smrg * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent 148f29dbc25Smrg * ports 0-7 of GLIU2 (5535). 149f29dbc25Smrg *--------------------------------------------------------------------------*/ 150f29dbc25Smrg 151f29dbc25Smrgint 152f29dbc25Smrgmsr_create_geodelink_table(GEODELINK_NODE * gliu_nodes) 153f29dbc25Smrg{ 154f29dbc25Smrg unsigned long mbiu_port_count, reflective; 155f29dbc25Smrg unsigned long port, index; 156f29dbc25Smrg unsigned long gliu_count = 0; 157f29dbc25Smrg int glcp_count = 0; 158f29dbc25Smrg int usb_count = 0; 159f29dbc25Smrg int mpci_count = 0; 160f29dbc25Smrg Q_WORD msr_value = {0, 0}; 161f29dbc25Smrg 162f29dbc25Smrg /* ALL THREE GLIUS ARE IN ONE ARRAY */ 163f29dbc25Smrg /* Entries 0-7 contain the port information for GLIU0, entries */ 164f29dbc25Smrg /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */ 165f29dbc25Smrg /* enumeration in two passes. The first simply fills in the */ 166f29dbc25Smrg /* addresses and class codes at each node. The second pass */ 167f29dbc25Smrg /* translates the class codes into indexes into Cimarron's device */ 168f29dbc25Smrg /* lookup table. */ 169f29dbc25Smrg 170f29dbc25Smrg /* COUNT GLIU0 PORTS */ 171f29dbc25Smrg 172f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value); 173f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 174f29dbc25Smrg 175f29dbc25Smrg /* FIND REFLECTIVE PORT */ 176f29dbc25Smrg /* Query the GLIU for the port through which we are communicating. */ 177f29dbc25Smrg /* We will avoid accesses to this port to avoid a self-reference. */ 178f29dbc25Smrg 179f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value); 180f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 181f29dbc25Smrg 182f29dbc25Smrg /* SPECIAL CASE FOR PORT 0 */ 183f29dbc25Smrg /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */ 184f29dbc25Smrg /* responds at address 0x10000xxx, which does not equal 0 << 29. */ 185f29dbc25Smrg 186f29dbc25Smrg gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0; 187f29dbc25Smrg gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU; 188f29dbc25Smrg 189f29dbc25Smrg /* ENUMERATE ALL PORTS */ 190f29dbc25Smrg 191f29dbc25Smrg for (port = 1; port < 8; port++) { 192f29dbc25Smrg /* FILL IN ADDRESS */ 193f29dbc25Smrg 194f29dbc25Smrg gliu_nodes[port].address_from_cpu = port << 29; 195f29dbc25Smrg 196f29dbc25Smrg if (port == reflective) 197f29dbc25Smrg gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE; 198f29dbc25Smrg else if (port > mbiu_port_count) 199f29dbc25Smrg gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED; 200f29dbc25Smrg else { 201f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, 202f29dbc25Smrg &msr_value); 203f29dbc25Smrg gliu_nodes[port].device_id = 204f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 205f29dbc25Smrg } 206f29dbc25Smrg } 207f29dbc25Smrg 208f29dbc25Smrg /* COUNT GLIU1 PORTS */ 209f29dbc25Smrg 210f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value); 211f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 212f29dbc25Smrg 213f29dbc25Smrg /* FIND REFLECTIVE PORT */ 214f29dbc25Smrg 215f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value); 216f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 217f29dbc25Smrg 218f29dbc25Smrg /* ENUMERATE ALL PORTS */ 219f29dbc25Smrg 220f29dbc25Smrg for (port = 0; port < 8; port++) { 221f29dbc25Smrg index = port + 8; 222f29dbc25Smrg 223f29dbc25Smrg /* FILL IN ADDRESS */ 224f29dbc25Smrg 225f29dbc25Smrg gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26); 226f29dbc25Smrg 227f29dbc25Smrg if (port == reflective) 228f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; 229f29dbc25Smrg else if (port > mbiu_port_count) 230f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; 231f29dbc25Smrg else { 232f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, 233f29dbc25Smrg &msr_value); 234f29dbc25Smrg gliu_nodes[index].device_id = 235f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 236f29dbc25Smrg } 237f29dbc25Smrg } 238f29dbc25Smrg 239f29dbc25Smrg /* COUNT GLIU2 PORTS */ 240f29dbc25Smrg 241f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value); 242f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 243f29dbc25Smrg 244f29dbc25Smrg /* FIND REFLECTIVE PORT */ 245f29dbc25Smrg 246f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value); 247f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 248f29dbc25Smrg 249f29dbc25Smrg /* FILL IN PORT 0 AND 1 */ 250f29dbc25Smrg /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */ 251f29dbc25Smrg /* a special address. */ 252f29dbc25Smrg 253f29dbc25Smrg gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2; 254f29dbc25Smrg gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU; 255f29dbc25Smrg 256f29dbc25Smrg gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI; 257f29dbc25Smrg gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI; 258f29dbc25Smrg 259f29dbc25Smrg /* ENUMERATE ALL PORTS */ 260f29dbc25Smrg 261f29dbc25Smrg for (port = 2; port < 8; port++) { 262f29dbc25Smrg index = port + 16; 263f29dbc25Smrg 264f29dbc25Smrg /* FILL IN ADDRESS */ 265f29dbc25Smrg 266f29dbc25Smrg gliu_nodes[index].address_from_cpu = 267f29dbc25Smrg (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); 268f29dbc25Smrg 269f29dbc25Smrg if (port == reflective) 270f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; 271f29dbc25Smrg else if (port > mbiu_port_count) 272f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; 273f29dbc25Smrg else { 274f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, 275f29dbc25Smrg &msr_value); 276f29dbc25Smrg gliu_nodes[index].device_id = 277f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 278f29dbc25Smrg } 279f29dbc25Smrg } 280f29dbc25Smrg 281f29dbc25Smrg /* SECOND PASS - TRANSLATION */ 282f29dbc25Smrg /* Now that the class codes for each device are stored in the */ 283f29dbc25Smrg /* array, we walk through the array and translate the class */ 284f29dbc25Smrg /* codes to table indexes. For class codes that have multiple */ 285f29dbc25Smrg /* instances, the table indexes are sequential. */ 286f29dbc25Smrg 287f29dbc25Smrg for (port = 0; port < 24; port++) { 288f29dbc25Smrg /* SPECIAL CASE FOR GLIU UNITS */ 289f29dbc25Smrg /* A GLIU can be both on another port and on its own port. These */ 290f29dbc25Smrg /* end up as the same address, but are shown as duplicate nodes in */ 291f29dbc25Smrg /* the GeodeLink table. */ 292f29dbc25Smrg 293f29dbc25Smrg if ((port & 7) == 0) 294f29dbc25Smrg gliu_count = port >> 3; 295f29dbc25Smrg 296f29dbc25Smrg switch (gliu_nodes[port].device_id) { 297f29dbc25Smrg /* UNPOPULATED OR REFLECTIVE NODES */ 298f29dbc25Smrg 299f29dbc25Smrg case MSR_CLASS_CODE_UNPOPULATED: 300f29dbc25Smrg index = MSR_DEVICE_EMPTY; 301f29dbc25Smrg break; 302f29dbc25Smrg case MSR_CLASS_CODE_REFLECTIVE: 303f29dbc25Smrg index = MSR_DEVICE_REFLECTIVE; 304f29dbc25Smrg break; 305f29dbc25Smrg 306f29dbc25Smrg /* KNOWN CLASS CODES */ 307f29dbc25Smrg 308f29dbc25Smrg case MSR_CLASS_CODE_GLIU: 309f29dbc25Smrg index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; 310f29dbc25Smrg break; 311f29dbc25Smrg case MSR_CLASS_CODE_GLCP: 312f29dbc25Smrg index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; 313f29dbc25Smrg break; 314f29dbc25Smrg case MSR_CLASS_CODE_MPCI: 315f29dbc25Smrg index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; 316f29dbc25Smrg break; 317f29dbc25Smrg case MSR_CLASS_CODE_USB: 318f29dbc25Smrg index = MSR_DEVICE_5535_USB2 + usb_count++; 319f29dbc25Smrg break; 320f29dbc25Smrg case MSR_CLASS_CODE_USB2: 321f29dbc25Smrg index = MSR_DEVICE_5536_USB_2_0; 322f29dbc25Smrg break; 323f29dbc25Smrg case MSR_CLASS_CODE_ATAC: 324f29dbc25Smrg index = MSR_DEVICE_5535_ATAC; 325f29dbc25Smrg break; 326f29dbc25Smrg case MSR_CLASS_CODE_MDD: 327f29dbc25Smrg index = MSR_DEVICE_5535_MDD; 328f29dbc25Smrg break; 329f29dbc25Smrg case MSR_CLASS_CODE_ACC: 330f29dbc25Smrg index = MSR_DEVICE_5535_ACC; 331f29dbc25Smrg break; 332f29dbc25Smrg case MSR_CLASS_CODE_MC: 333f29dbc25Smrg index = MSR_DEVICE_GEODELX_MC; 334f29dbc25Smrg break; 335f29dbc25Smrg case MSR_CLASS_CODE_GP: 336f29dbc25Smrg index = MSR_DEVICE_GEODELX_GP; 337f29dbc25Smrg break; 338f29dbc25Smrg case MSR_CLASS_CODE_VG: 339f29dbc25Smrg index = MSR_DEVICE_GEODELX_VG; 340f29dbc25Smrg break; 341f29dbc25Smrg case MSR_CLASS_CODE_DF: 342f29dbc25Smrg index = MSR_DEVICE_GEODELX_DF; 343f29dbc25Smrg break; 344f29dbc25Smrg case MSR_CLASS_CODE_FG: 345f29dbc25Smrg index = MSR_DEVICE_GEODELX_FG; 346f29dbc25Smrg break; 347f29dbc25Smrg case MSR_CLASS_CODE_VIP: 348f29dbc25Smrg index = MSR_DEVICE_GEODELX_VIP; 349f29dbc25Smrg break; 350f29dbc25Smrg case MSR_CLASS_CODE_AES: 351f29dbc25Smrg index = MSR_DEVICE_GEODELX_AES; 352f29dbc25Smrg break; 353f29dbc25Smrg case MSR_CLASS_CODE_VAIL: 354f29dbc25Smrg index = MSR_DEVICE_GEODELX_VAIL; 355f29dbc25Smrg break; 356f29dbc25Smrg default: 357f29dbc25Smrg index = MSR_DEVICE_EMPTY; 358f29dbc25Smrg break; 359f29dbc25Smrg } 360f29dbc25Smrg 361f29dbc25Smrg gliu_nodes[port].device_id = index; 362f29dbc25Smrg } 363f29dbc25Smrg 364f29dbc25Smrg return CIM_STATUS_OK; 365f29dbc25Smrg} 366f29dbc25Smrg 367f29dbc25Smrg/*--------------------------------------------------------------------------- 368f29dbc25Smrg * msr_create_device_list 369f29dbc25Smrg * 370f29dbc25Smrg * This routine dumps a list of all known GeodeLX/5535 devices as well as their 371f29dbc25Smrg * respective status and address. 372f29dbc25Smrg *--------------------------------------------------------------------------*/ 373f29dbc25Smrg 374f29dbc25Smrgint 375f29dbc25Smrgmsr_create_device_list(GEODELINK_NODE * gliu_nodes, int max_devices) 376f29dbc25Smrg{ 377f29dbc25Smrg int i, count; 378f29dbc25Smrg 379f29dbc25Smrg if (max_devices < MSR_DEVICE_EMPTY) 380f29dbc25Smrg count = max_devices; 381f29dbc25Smrg else 382f29dbc25Smrg count = MSR_DEVICE_EMPTY; 383f29dbc25Smrg 384f29dbc25Smrg for (i = 0; i < count; i++) { 385f29dbc25Smrg gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu; 386f29dbc25Smrg gliu_nodes[i].device_id = msr_dev_lookup[i].device_id; 387f29dbc25Smrg } 388f29dbc25Smrg 389f29dbc25Smrg return CIM_STATUS_OK; 390f29dbc25Smrg} 391f29dbc25Smrg 392f29dbc25Smrg/*-------------------------------------------------------------------- 393f29dbc25Smrg * msr_read64 394f29dbc25Smrg * 395f29dbc25Smrg * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is 396f29dbc25Smrg * an index into Cimarron's table of known GeodeLink devices. 397f29dbc25Smrg *-------------------------------------------------------------------*/ 398f29dbc25Smrg 399f29dbc25Smrgint 400f29dbc25Smrgmsr_read64(unsigned long device, unsigned long msr_register, 401f29dbc25Smrg Q_WORD * msr_value) 402f29dbc25Smrg{ 403f29dbc25Smrg if (device < MSR_DEVICE_EMPTY) { 404f29dbc25Smrg if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { 405f29dbc25Smrg MSR_READ(msr_register, msr_dev_lookup[device].address_from_cpu, 406f29dbc25Smrg msr_value); 407f29dbc25Smrg return CIM_STATUS_OK; 408f29dbc25Smrg } 409f29dbc25Smrg } 410f29dbc25Smrg 411f29dbc25Smrg msr_value->low = msr_value->high = 0; 412f29dbc25Smrg return CIM_STATUS_DEVNOTFOUND; 413f29dbc25Smrg} 414f29dbc25Smrg 415f29dbc25Smrg/*-------------------------------------------------------------------- 416f29dbc25Smrg * msr_write64 417f29dbc25Smrg * 418f29dbc25Smrg * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is 419f29dbc25Smrg * an index into Cimarron's table of known GeodeLink devices. 420f29dbc25Smrg *-------------------------------------------------------------------*/ 421f29dbc25Smrg 422f29dbc25Smrgint 423f29dbc25Smrgmsr_write64(unsigned long device, unsigned long msr_register, 424f29dbc25Smrg Q_WORD * msr_value) 425f29dbc25Smrg{ 426f29dbc25Smrg if (device < MSR_DEVICE_EMPTY) { 427f29dbc25Smrg if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { 428f29dbc25Smrg MSR_WRITE(msr_register, msr_dev_lookup[device].address_from_cpu, 429f29dbc25Smrg msr_value); 430f29dbc25Smrg return CIM_STATUS_OK; 431f29dbc25Smrg } 432f29dbc25Smrg } 433f29dbc25Smrg return CIM_STATUS_DEVNOTFOUND; 434f29dbc25Smrg} 435