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 * 4679d5fcd7Smrg * This routine initializes the internal MSR table in Cimarron. This table is 47f29dbc25Smrg * used for any MSR device accesses. 48f29dbc25Smrg *--------------------------------------------------------------------------*/ 49f29dbc25Smrg 50f29dbc25Smrgint 51f29dbc25Smrgmsr_init_table(void) 52f29dbc25Smrg{ 5304007ebaSmrg 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; 9604007ebaSmrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = MSR_DEVICE_PRESENT; 97f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = 98f29dbc25Smrg MSR_ADDRESS_GLIU1; 9904007ebaSmrg msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = MSR_DEVICE_PRESENT; 100f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = 101f29dbc25Smrg MSR_ADDRESS_GLIU2; 102f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT; 103f29dbc25Smrg msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = 104f29dbc25Smrg MSR_ADDRESS_VAIL; 10504007ebaSmrg msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = MSR_DEVICE_PRESENT; 106f29dbc25Smrg 107f29dbc25Smrg for (i = 0; i < MSR_DEVICE_EMPTY; i++) { 108f29dbc25Smrg if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND) { 109f29dbc25Smrg for (j = 0; j < 24; j++) { 110f29dbc25Smrg if (gliu_nodes[j].device_id == i) 111f29dbc25Smrg break; 112f29dbc25Smrg } 113f29dbc25Smrg 114f29dbc25Smrg if (j == 24) 115f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; 116f29dbc25Smrg else { 117f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT; 118f29dbc25Smrg msr_dev_lookup[i].address_from_cpu = 119f29dbc25Smrg gliu_nodes[j].address_from_cpu; 120f29dbc25Smrg } 121f29dbc25Smrg } 122f29dbc25Smrg } 12304007ebaSmrg } 12404007ebaSmrg else { 125f29dbc25Smrg /* ERROR OUT THE GEODELINK TABLES */ 126f29dbc25Smrg 127f29dbc25Smrg for (i = 0; i < 24; i++) { 128f29dbc25Smrg gliu_nodes[i].address_from_cpu = 0xFFFFFFFF; 129f29dbc25Smrg gliu_nodes[i].device_id = MSR_DEVICE_EMPTY; 130f29dbc25Smrg } 131f29dbc25Smrg 132f29dbc25Smrg for (i = 0; i < MSR_DEVICE_EMPTY; i++) { 133f29dbc25Smrg msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF; 134f29dbc25Smrg msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; 135f29dbc25Smrg } 136f29dbc25Smrg } 137f29dbc25Smrg return return_value; 138f29dbc25Smrg} 139f29dbc25Smrg 140f29dbc25Smrg/*--------------------------------------------------------------------------- 141f29dbc25Smrg * msr_create_geodelink_table 142f29dbc25Smrg * 143f29dbc25Smrg * This routine dumps the contents of the GeodeLink bus into an array of 144f29dbc25Smrg * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0, 145f29dbc25Smrg * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent 146f29dbc25Smrg * ports 0-7 of GLIU2 (5535). 147f29dbc25Smrg *--------------------------------------------------------------------------*/ 148f29dbc25Smrg 149f29dbc25Smrgint 150f29dbc25Smrgmsr_create_geodelink_table(GEODELINK_NODE * gliu_nodes) 151f29dbc25Smrg{ 152f29dbc25Smrg unsigned long mbiu_port_count, reflective; 153f29dbc25Smrg unsigned long port, index; 154f29dbc25Smrg unsigned long gliu_count = 0; 155f29dbc25Smrg int glcp_count = 0; 156f29dbc25Smrg int usb_count = 0; 157f29dbc25Smrg int mpci_count = 0; 15804007ebaSmrg Q_WORD msr_value = { 0, 0 }; 159f29dbc25Smrg 160f29dbc25Smrg /* ALL THREE GLIUS ARE IN ONE ARRAY */ 161f29dbc25Smrg /* Entries 0-7 contain the port information for GLIU0, entries */ 162f29dbc25Smrg /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */ 163f29dbc25Smrg /* enumeration in two passes. The first simply fills in the */ 164f29dbc25Smrg /* addresses and class codes at each node. The second pass */ 165f29dbc25Smrg /* translates the class codes into indexes into Cimarron's device */ 166f29dbc25Smrg /* lookup table. */ 167f29dbc25Smrg 168f29dbc25Smrg /* COUNT GLIU0 PORTS */ 169f29dbc25Smrg 170f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value); 171f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 172f29dbc25Smrg 173f29dbc25Smrg /* FIND REFLECTIVE PORT */ 174f29dbc25Smrg /* Query the GLIU for the port through which we are communicating. */ 175f29dbc25Smrg /* We will avoid accesses to this port to avoid a self-reference. */ 176f29dbc25Smrg 177f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value); 178f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 179f29dbc25Smrg 180f29dbc25Smrg /* SPECIAL CASE FOR PORT 0 */ 181f29dbc25Smrg /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */ 182f29dbc25Smrg /* responds at address 0x10000xxx, which does not equal 0 << 29. */ 183f29dbc25Smrg 184f29dbc25Smrg gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0; 185f29dbc25Smrg gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU; 186f29dbc25Smrg 187f29dbc25Smrg /* ENUMERATE ALL PORTS */ 188f29dbc25Smrg 189f29dbc25Smrg for (port = 1; port < 8; port++) { 190f29dbc25Smrg /* FILL IN ADDRESS */ 191f29dbc25Smrg 192f29dbc25Smrg gliu_nodes[port].address_from_cpu = port << 29; 193f29dbc25Smrg 194f29dbc25Smrg if (port == reflective) 195f29dbc25Smrg gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE; 196f29dbc25Smrg else if (port > mbiu_port_count) 197f29dbc25Smrg gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED; 198f29dbc25Smrg else { 199f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, 20004007ebaSmrg &msr_value); 201f29dbc25Smrg gliu_nodes[port].device_id = 202f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 203f29dbc25Smrg } 204f29dbc25Smrg } 205f29dbc25Smrg 206f29dbc25Smrg /* COUNT GLIU1 PORTS */ 207f29dbc25Smrg 208f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value); 209f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 210f29dbc25Smrg 211f29dbc25Smrg /* FIND REFLECTIVE PORT */ 212f29dbc25Smrg 213f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value); 214f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 215f29dbc25Smrg 216f29dbc25Smrg /* ENUMERATE ALL PORTS */ 217f29dbc25Smrg 218f29dbc25Smrg for (port = 0; port < 8; port++) { 219f29dbc25Smrg index = port + 8; 220f29dbc25Smrg 221f29dbc25Smrg /* FILL IN ADDRESS */ 222f29dbc25Smrg 223f29dbc25Smrg gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26); 224f29dbc25Smrg 225f29dbc25Smrg if (port == reflective) 226f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; 227f29dbc25Smrg else if (port > mbiu_port_count) 228f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; 229f29dbc25Smrg else { 230f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, 23104007ebaSmrg &msr_value); 232f29dbc25Smrg gliu_nodes[index].device_id = 233f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 234f29dbc25Smrg } 235f29dbc25Smrg } 236f29dbc25Smrg 237f29dbc25Smrg /* COUNT GLIU2 PORTS */ 238f29dbc25Smrg 239f29dbc25Smrg MSR_READ(MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value); 240f29dbc25Smrg mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; 241f29dbc25Smrg 242f29dbc25Smrg /* FIND REFLECTIVE PORT */ 243f29dbc25Smrg 244f29dbc25Smrg MSR_READ(MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value); 245f29dbc25Smrg reflective = msr_value.low & WHOAMI_MASK; 246f29dbc25Smrg 247f29dbc25Smrg /* FILL IN PORT 0 AND 1 */ 248f29dbc25Smrg /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */ 249f29dbc25Smrg /* a special address. */ 250f29dbc25Smrg 251f29dbc25Smrg gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2; 252f29dbc25Smrg gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU; 253f29dbc25Smrg 254f29dbc25Smrg gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI; 255f29dbc25Smrg gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI; 256f29dbc25Smrg 257f29dbc25Smrg /* ENUMERATE ALL PORTS */ 258f29dbc25Smrg 259f29dbc25Smrg for (port = 2; port < 8; port++) { 260f29dbc25Smrg index = port + 16; 261f29dbc25Smrg 262f29dbc25Smrg /* FILL IN ADDRESS */ 263f29dbc25Smrg 264f29dbc25Smrg gliu_nodes[index].address_from_cpu = 265f29dbc25Smrg (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); 266f29dbc25Smrg 267f29dbc25Smrg if (port == reflective) 268f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; 269f29dbc25Smrg else if (port > mbiu_port_count) 270f29dbc25Smrg gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; 271f29dbc25Smrg else { 272f29dbc25Smrg MSR_READ(MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, 27304007ebaSmrg &msr_value); 274f29dbc25Smrg gliu_nodes[index].device_id = 275f29dbc25Smrg GET_DEVICE_ID(msr_value.high, msr_value.low); 276f29dbc25Smrg } 277f29dbc25Smrg } 278f29dbc25Smrg 279f29dbc25Smrg /* SECOND PASS - TRANSLATION */ 280f29dbc25Smrg /* Now that the class codes for each device are stored in the */ 281f29dbc25Smrg /* array, we walk through the array and translate the class */ 282f29dbc25Smrg /* codes to table indexes. For class codes that have multiple */ 283f29dbc25Smrg /* instances, the table indexes are sequential. */ 284f29dbc25Smrg 285f29dbc25Smrg for (port = 0; port < 24; port++) { 286f29dbc25Smrg /* SPECIAL CASE FOR GLIU UNITS */ 287f29dbc25Smrg /* A GLIU can be both on another port and on its own port. These */ 288f29dbc25Smrg /* end up as the same address, but are shown as duplicate nodes in */ 289f29dbc25Smrg /* the GeodeLink table. */ 290f29dbc25Smrg 291f29dbc25Smrg if ((port & 7) == 0) 292f29dbc25Smrg gliu_count = port >> 3; 293f29dbc25Smrg 294f29dbc25Smrg switch (gliu_nodes[port].device_id) { 295f29dbc25Smrg /* UNPOPULATED OR REFLECTIVE NODES */ 296f29dbc25Smrg 297f29dbc25Smrg case MSR_CLASS_CODE_UNPOPULATED: 298f29dbc25Smrg index = MSR_DEVICE_EMPTY; 299f29dbc25Smrg break; 300f29dbc25Smrg case MSR_CLASS_CODE_REFLECTIVE: 301f29dbc25Smrg index = MSR_DEVICE_REFLECTIVE; 302f29dbc25Smrg break; 303f29dbc25Smrg 304f29dbc25Smrg /* KNOWN CLASS CODES */ 305f29dbc25Smrg 306f29dbc25Smrg case MSR_CLASS_CODE_GLIU: 307f29dbc25Smrg index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; 308f29dbc25Smrg break; 309f29dbc25Smrg case MSR_CLASS_CODE_GLCP: 310f29dbc25Smrg index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; 311f29dbc25Smrg break; 312f29dbc25Smrg case MSR_CLASS_CODE_MPCI: 313f29dbc25Smrg index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; 314f29dbc25Smrg break; 315f29dbc25Smrg case MSR_CLASS_CODE_USB: 316f29dbc25Smrg index = MSR_DEVICE_5535_USB2 + usb_count++; 317f29dbc25Smrg break; 318f29dbc25Smrg case MSR_CLASS_CODE_USB2: 319f29dbc25Smrg index = MSR_DEVICE_5536_USB_2_0; 320f29dbc25Smrg break; 321f29dbc25Smrg case MSR_CLASS_CODE_ATAC: 322f29dbc25Smrg index = MSR_DEVICE_5535_ATAC; 323f29dbc25Smrg break; 324f29dbc25Smrg case MSR_CLASS_CODE_MDD: 325f29dbc25Smrg index = MSR_DEVICE_5535_MDD; 326f29dbc25Smrg break; 327f29dbc25Smrg case MSR_CLASS_CODE_ACC: 328f29dbc25Smrg index = MSR_DEVICE_5535_ACC; 329f29dbc25Smrg break; 330f29dbc25Smrg case MSR_CLASS_CODE_MC: 331f29dbc25Smrg index = MSR_DEVICE_GEODELX_MC; 332f29dbc25Smrg break; 333f29dbc25Smrg case MSR_CLASS_CODE_GP: 334f29dbc25Smrg index = MSR_DEVICE_GEODELX_GP; 335f29dbc25Smrg break; 336f29dbc25Smrg case MSR_CLASS_CODE_VG: 337f29dbc25Smrg index = MSR_DEVICE_GEODELX_VG; 338f29dbc25Smrg break; 339f29dbc25Smrg case MSR_CLASS_CODE_DF: 340f29dbc25Smrg index = MSR_DEVICE_GEODELX_DF; 341f29dbc25Smrg break; 342f29dbc25Smrg case MSR_CLASS_CODE_FG: 343f29dbc25Smrg index = MSR_DEVICE_GEODELX_FG; 344f29dbc25Smrg break; 345f29dbc25Smrg case MSR_CLASS_CODE_VIP: 346f29dbc25Smrg index = MSR_DEVICE_GEODELX_VIP; 347f29dbc25Smrg break; 348f29dbc25Smrg case MSR_CLASS_CODE_AES: 349f29dbc25Smrg index = MSR_DEVICE_GEODELX_AES; 350f29dbc25Smrg break; 351f29dbc25Smrg case MSR_CLASS_CODE_VAIL: 352f29dbc25Smrg index = MSR_DEVICE_GEODELX_VAIL; 353f29dbc25Smrg break; 354f29dbc25Smrg default: 355f29dbc25Smrg index = MSR_DEVICE_EMPTY; 356f29dbc25Smrg break; 357f29dbc25Smrg } 358f29dbc25Smrg 359f29dbc25Smrg gliu_nodes[port].device_id = index; 360f29dbc25Smrg } 361f29dbc25Smrg 362f29dbc25Smrg return CIM_STATUS_OK; 363f29dbc25Smrg} 364f29dbc25Smrg 365f29dbc25Smrg/*--------------------------------------------------------------------------- 366f29dbc25Smrg * msr_create_device_list 367f29dbc25Smrg * 368f29dbc25Smrg * This routine dumps a list of all known GeodeLX/5535 devices as well as their 369f29dbc25Smrg * respective status and address. 370f29dbc25Smrg *--------------------------------------------------------------------------*/ 371f29dbc25Smrg 372f29dbc25Smrgint 373f29dbc25Smrgmsr_create_device_list(GEODELINK_NODE * gliu_nodes, int max_devices) 374f29dbc25Smrg{ 375f29dbc25Smrg int i, count; 376f29dbc25Smrg 377f29dbc25Smrg if (max_devices < MSR_DEVICE_EMPTY) 378f29dbc25Smrg count = max_devices; 379f29dbc25Smrg else 380f29dbc25Smrg count = MSR_DEVICE_EMPTY; 381f29dbc25Smrg 382f29dbc25Smrg for (i = 0; i < count; i++) { 383f29dbc25Smrg gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu; 384f29dbc25Smrg gliu_nodes[i].device_id = msr_dev_lookup[i].device_id; 385f29dbc25Smrg } 386f29dbc25Smrg 387f29dbc25Smrg return CIM_STATUS_OK; 388f29dbc25Smrg} 389f29dbc25Smrg 390f29dbc25Smrg/*-------------------------------------------------------------------- 391f29dbc25Smrg * msr_read64 392f29dbc25Smrg * 393f29dbc25Smrg * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is 394f29dbc25Smrg * an index into Cimarron's table of known GeodeLink devices. 395f29dbc25Smrg *-------------------------------------------------------------------*/ 396f29dbc25Smrg 397f29dbc25Smrgint 39804007ebaSmrgmsr_read64(unsigned long device, unsigned long msr_register, Q_WORD * msr_value) 399f29dbc25Smrg{ 400f29dbc25Smrg if (device < MSR_DEVICE_EMPTY) { 401f29dbc25Smrg if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { 402f29dbc25Smrg MSR_READ(msr_register, msr_dev_lookup[device].address_from_cpu, 40304007ebaSmrg msr_value); 404f29dbc25Smrg return CIM_STATUS_OK; 405f29dbc25Smrg } 406f29dbc25Smrg } 407f29dbc25Smrg 408f29dbc25Smrg msr_value->low = msr_value->high = 0; 409f29dbc25Smrg return CIM_STATUS_DEVNOTFOUND; 410f29dbc25Smrg} 411f29dbc25Smrg 412f29dbc25Smrg/*-------------------------------------------------------------------- 413f29dbc25Smrg * msr_write64 414f29dbc25Smrg * 415f29dbc25Smrg * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is 416f29dbc25Smrg * an index into Cimarron's table of known GeodeLink devices. 417f29dbc25Smrg *-------------------------------------------------------------------*/ 418f29dbc25Smrg 419f29dbc25Smrgint 420f29dbc25Smrgmsr_write64(unsigned long device, unsigned long msr_register, 42104007ebaSmrg Q_WORD * msr_value) 422f29dbc25Smrg{ 423f29dbc25Smrg if (device < MSR_DEVICE_EMPTY) { 424f29dbc25Smrg if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) { 425f29dbc25Smrg MSR_WRITE(msr_register, msr_dev_lookup[device].address_from_cpu, 42604007ebaSmrg msr_value); 427f29dbc25Smrg return CIM_STATUS_OK; 428f29dbc25Smrg } 429f29dbc25Smrg } 430f29dbc25Smrg return CIM_STATUS_DEVNOTFOUND; 431f29dbc25Smrg} 432