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