1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nsc/gfx/msr_rdcl.c,v 1.1 2002/12/10 15:12:27 alanh Exp $ */ 2/* 3 * $Workfile: msr_rdcl.c $ 4 * 5 * This file contains MSR access routines for Redcloud. 6 * 7 * NSC_LIC_ALTERNATIVE_PREAMBLE 8 * 9 * Revision 1.0 10 * 11 * National Semiconductor Alternative GPL-BSD License 12 * 13 * National Semiconductor Corporation licenses this software 14 * ("Software"): 15 * 16 * Durango 17 * 18 * under one of the two following licenses, depending on how the 19 * Software is received by the Licensee. 20 * 21 * If this Software is received as part of the Linux Framebuffer or 22 * other GPL licensed software, then the GPL license designated 23 * NSC_LIC_GPL applies to this Software; in all other circumstances 24 * then the BSD-style license designated NSC_LIC_BSD shall apply. 25 * 26 * END_NSC_LIC_ALTERNATIVE_PREAMBLE */ 27 28/* NSC_LIC_BSD 29 * 30 * National Semiconductor Corporation Open Source License for Durango 31 * 32 * (BSD License with Export Notice) 33 * 34 * Copyright (c) 1999-2001 35 * National Semiconductor Corporation. 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 42 * * Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 45 * * Redistributions in binary form must reproduce the above 46 * copyright notice, this list of conditions and the following 47 * disclaimer in the documentation and/or other materials provided 48 * with the distribution. 49 * 50 * * Neither the name of the National Semiconductor Corporation nor 51 * the names of its contributors may be used to endorse or promote 52 * products derived from this software without specific prior 53 * written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 56 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 57 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 58 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 59 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 60 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 62 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 64 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 65 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 67 * OF SUCH DAMAGE. 68 * 69 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 70 * YOUR JURISDICTION. It is licensee's responsibility to comply with 71 * any export regulations applicable in licensee's jurisdiction. Under 72 * CURRENT (2001) U.S. export regulations this software 73 * is eligible for export from the U.S. and can be downloaded by or 74 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 75 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 76 * Syria, Sudan, Afghanistan and any other country to which the U.S. 77 * has embargoed goods and services. 78 * 79 * END_NSC_LIC_BSD */ 80 81/* NSC_LIC_GPL 82 * 83 * National Semiconductor Corporation Gnu General Public License for Durango 84 * 85 * (GPL License with Export Notice) 86 * 87 * Copyright (c) 1999-2001 88 * National Semiconductor Corporation. 89 * All rights reserved. 90 * 91 * Redistribution and use in source and binary forms, with or without 92 * modification, are permitted under the terms of the GNU General 93 * Public License as published by the Free Software Foundation; either 94 * version 2 of the License, or (at your option) any later version 95 * 96 * In addition to the terms of the GNU General Public License, neither 97 * the name of the National Semiconductor Corporation nor the names of 98 * its contributors may be used to endorse or promote products derived 99 * from this software without specific prior written permission. 100 * 101 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 102 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 103 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 104 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 105 * NATIONAL SEMICONDUCTOR CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY 106 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 108 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 109 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 110 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE, 111 * INTELLECTUAL PROPERTY INFRINGEMENT, OR OTHERWISE) ARISING IN ANY WAY 112 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 113 * OF SUCH DAMAGE. See the GNU General Public License for more details. 114 * 115 * EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF 116 * YOUR JURISDICTION. It is licensee's responsibility to comply with 117 * any export regulations applicable in licensee's jurisdiction. Under 118 * CURRENT (2001) U.S. export regulations this software 119 * is eligible for export from the U.S. and can be downloaded by or 120 * otherwise exported or reexported worldwide EXCEPT to U.S. embargoed 121 * destinations which include Cuba, Iraq, Libya, North Korea, Iran, 122 * Syria, Sudan, Afghanistan and any other country to which the U.S. 123 * has embargoed goods and services. 124 * 125 * You should have received a copy of the GNU General Public License 126 * along with this file; if not, write to the Free Software Foundation, 127 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 128 * 129 * END_NSC_LIC_GPL */ 130 131int redcloud_msr_init(void); 132DEV_STATUS redcloud_id_msr_device(MSR * pDev, unsigned long address); 133DEV_STATUS redcloud_get_msr_dev_address(unsigned int device, 134 unsigned long *address); 135DEV_STATUS redcloud_get_glink_id_at_address(unsigned int *device, 136 unsigned long address); 137DEV_STATUS redcloud_msr_read(unsigned int device, unsigned int msrRegister, 138 Q_WORD * msrValue); 139DEV_STATUS redcloud_msr_write(unsigned int device, unsigned int msrRegister, 140 Q_WORD * msrValue); 141 142void redcloud_build_mbus_tree(void); /* private routine definition */ 143int redcloud_init_msr_devices(MSR aDev[], unsigned int array_size); /* private routine definition */ 144DEV_STATUS redcloud_find_msr_device(MSR * pDev); /* private routine definition */ 145 146/* REDCLOUD MSR BITMASKS */ 147 148#define MBD_MSR_CAP 0x2000 149#define MSR_CAP_ID_MASK 0xFF000 150#define MSR_CAP_ID_SHIFT 12 151#define MSR_CAP_REV_MASK 0x0F 152#define MBIU_CAP 0x86 153#define NUM_PORTS_MASK 0x00380000 154#define NUM_PORTS_SHIFT 19 155#define MBIU_WHOAMI 0x8B 156#define WHOAMI_MASK 0x07 157 158/* REDCLOUD and CS5535 MSR DEVICES */ 159 160MSR msrDev[] = { 161 {FOUND, RC_CC_MBIU, RC_MB0_MBIU0}, 162 {FOUND, RC_CC_MBIU, RC_MB0_MBIU1}, 163 {NOT_KNOWN, RC_CC_MCP, FAKE_ADDRESS}, 164 {NOT_KNOWN, RC_CC_MPCI, FAKE_ADDRESS}, 165 {NOT_KNOWN, RC_CC_MC, FAKE_ADDRESS}, 166 {NOT_KNOWN, RC_CC_GP, FAKE_ADDRESS}, 167 {NOT_KNOWN, RC_CC_VG, FAKE_ADDRESS}, 168 {NOT_KNOWN, RC_CC_DF, FAKE_ADDRESS}, 169 {NOT_KNOWN, RC_CC_FG, FAKE_ADDRESS}, 170 {FOUND, RC_CC_VA, RC_MB0_CPU}, 171 {FOUND, CP_CC_MBIU, CP_MB0_MBIU0}, 172 {NOT_KNOWN, CP_CC_MPCI, FAKE_ADDRESS}, 173 {NOT_KNOWN, CP_CC_USB2, FAKE_ADDRESS}, 174 {NOT_KNOWN, CP_CC_ATAC, FAKE_ADDRESS}, 175 {NOT_KNOWN, CP_CC_MDD, FAKE_ADDRESS}, 176 {NOT_KNOWN, CP_CC_ACC, FAKE_ADDRESS}, 177 {NOT_KNOWN, CP_CC_USB1, FAKE_ADDRESS}, 178 {NOT_KNOWN, CP_CC_MCP, FAKE_ADDRESS}, 179}; 180 181#define NUM_DEVS sizeof(msrDev) / sizeof(struct msr) 182 183/* CAPISTRANO DEVICE INDEX LIMITS */ 184/* These defines represent the start and stop indexes into the device array */ 185/* for all Capistrano devices. These should be updated whenever a device is */ 186/* added or removed to the Capistrano list. */ 187 188#define CP_INDEX_START CP_ID_MBIU 189#define CP_INDEX_STOP CP_ID_MCP 190 191/* GLOBAL MBUS CACHE STRUCTURES */ 192/* These structures contain a "cached" copy of the MBUS topology */ 193/* for easy future lookup. */ 194 195MBUS_NODE MBIU0[8], MBIU1[8], MBIU2[8]; 196 197/* REGISTER MACROS */ 198 199#define GET_DEVICE_ID( CAPABILITIES_HIGH, CAPABILITIES_LOW ) \ 200 ((unsigned int)(( (CAPABILITIES_LOW) & MSR_CAP_ID_MASK ) >> MSR_CAP_ID_SHIFT )) 201 202#define GET_NUM_PORTS( MBIU_CAP_HIGH, MBIU_CAP_LOW ) (((MBIU_CAP_HIGH) & NUM_PORTS_MASK ) >> NUM_PORTS_SHIFT) 203 204/*----------------------------------------------------------------------------- 205 * gfx_msr_init 206 * 207 * This routine initializes the base addresses of all known MBUS devices. 208 *----------------------------------------------------------------------------- 209 */ 210#if GFX_MSR_DYNAMIC 211int 212redcloud_msr_init(void) 213#else 214int 215gfx_msr_init(void) 216#endif 217{ 218 Q_WORD msrValue; 219 int return_value = 1; 220 221 /* CHECK FOR VALID MBUS CONFIGURATION */ 222 /* The CPU and the two MBIUs are assumed to be at known static addresses, so */ 223 /* we will check the device IDs at these addresses as proof of a valid mbus */ 224 /* configuration. */ 225 226 MSR_READ(MBD_MSR_CAP, RC_MB0_CPU, &(msrValue.high), &(msrValue.low)); 227 if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_VA) 228 return_value = 0; 229 230 MSR_READ(MBD_MSR_CAP, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 231 if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_MBIU) 232 return_value = 0; 233 234 MSR_READ(MBD_MSR_CAP, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); 235 if (GET_DEVICE_ID(msrValue.high, msrValue.low) != RC_CC_MBIU) 236 return_value = 0; 237 238 /* ENUMERATE VALID BUS */ 239 /* If all static devices were identified, continue with the enumeration */ 240 241 if (return_value) { 242 /* OPTIMIZATION */ 243 /* Build a local copy of the MBUS topology. This allows us to */ 244 /* quickly search the entire MBUS for a given device ID without */ 245 /* repeated MSR accesses. */ 246 247 redcloud_build_mbus_tree(); 248 249 /* INITIALIZE MSR DEVICES */ 250 251 return_value = redcloud_init_msr_devices(msrDev, NUM_DEVS); 252 253 } 254 255 return return_value; 256 257} 258 259/*-------------------------------------------------------------------------- 260 * void redcloud_build_mbus_tree() (PRIVATE ROUTINE - NOT PART OF DURANGO API) 261 * 262 * This routine walks through the MBUS and records the address value and 263 * device ID found at each node. If a node (aka port) is not populated, 264 * that node returns '0'. The deviceID for that node is set to '0' 265 * (NOT_POPULATED) to reflect this. If the node being queried points back to 266 * Vail or MBIU0, the deviceID for that node is set to 'REFLECTIVE'. Reflective 267 * nodes are nodes that forward the given MBUS address BACK to the initiator. 268 *----------------------------------------------------------------------------- 269 */ 270void 271redcloud_build_mbus_tree(void) 272{ 273 unsigned long mbiu_port_count, reflective; 274 unsigned long port; 275 Q_WORD msrValue; 276 277 /* */ 278 /* ENUMERATE MBIU0 */ 279 /* */ 280 281 /* COUNT MBIU PORTS */ 282 283 MSR_READ(MBIU_CAP, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 284 mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); 285 286 /* FIND REFLECTIVE PORT */ 287 /* Query the MBIU for the port through which we are communicating. */ 288 /* We will avoid accesses to this port to avoid a self-reference. */ 289 290 MSR_READ(MBIU_WHOAMI, RC_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 291 reflective = msrValue.low & WHOAMI_MASK; 292 293 /* ENUMERATE ALL PORTS */ 294 /* For every possible port, set the MBIU.deviceId to something. */ 295 296 for (port = 0; port < 8; port++) { 297 /* FILL IN CLAIMED FIELD */ 298 /* All MBIU ports can only be assigned to one device from the */ 299 /* Durango table */ 300 301 MBIU0[port].claimed = 0; 302 303 /* MBIU0 PORT NUMBERS ARE IN ADDRESS BITS 31:29 */ 304 305 MBIU0[port].address = port << 29; 306 307 /* SPECIAL CASE FOR MBIU0 */ 308 /* MBIU0 port 0 is a special case, as it points back to MBIU0. MBIU0 */ 309 /* responds at address 0x40000xxx, which does not equal 0 << 29. */ 310 311 if (port == 0) 312 MBIU0[port].deviceId = RC_CC_MBIU; 313 else if (port == reflective) 314 MBIU0[port].deviceId = REFLECTIVE; 315 else if (port > mbiu_port_count) 316 MBIU0[port].deviceId = NOT_POPULATED; 317 else { 318 MSR_READ(MBD_MSR_CAP, MBIU0[port].address, &(msrValue.high), 319 &(msrValue.low)); 320 MBIU0[port].deviceId = GET_DEVICE_ID(msrValue.high, msrValue.low); 321 } 322 } 323 324 /* */ 325 /* ENUMERATE MBIU1 */ 326 /* */ 327 328 /* COUNT MBIU PORTS */ 329 330 MSR_READ(MBIU_CAP, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); 331 mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); 332 333 /* FIND REFLECTIVE PORT */ 334 /* Query the MBIU for the port through which we are communicating. */ 335 /* We will avoid accesses to this port to avoid a self-reference. */ 336 337 MSR_READ(MBIU_WHOAMI, RC_MB0_MBIU1, &(msrValue.high), &(msrValue.low)); 338 reflective = msrValue.low & WHOAMI_MASK; 339 340 /* ENUMERATE ALL PORTS */ 341 /* For every possible port, set the MBIU.deviceId to something. */ 342 343 for (port = 0; port < 8; port++) { 344 /* FILL IN CLAIMED FIELD */ 345 /* All MBIU ports can only be assigned to one device from the */ 346 /* Durango table */ 347 348 MBIU1[port].claimed = 0; 349 350 /* MBIU1 PORT NUMBERS ARE IN 28:26 AND 31:29 = 010B */ 351 352 MBIU1[port].address = (0x02l << 29) + (port << 26); 353 354 if (port == reflective) 355 MBIU1[port].deviceId = REFLECTIVE; 356 else if (port > mbiu_port_count) 357 MBIU1[port].deviceId = NOT_POPULATED; 358 else { 359 MSR_READ(MBD_MSR_CAP, MBIU1[port].address, &(msrValue.high), 360 &(msrValue.low)); 361 MBIU1[port].deviceId = GET_DEVICE_ID(msrValue.high, msrValue.low); 362 } 363 } 364 365 /* */ 366 /* ENUMERATE MBIU2 (CS5535) */ 367 /* (if present) */ 368 369 MSR_READ(MBD_MSR_CAP, CP_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 370 if (GET_DEVICE_ID(msrValue.high, msrValue.low) == CP_CC_MBIU) { 371 /* COUNT MBIU PORTS */ 372 373 MSR_READ(MBIU_CAP, CP_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 374 mbiu_port_count = GET_NUM_PORTS(msrValue.high, msrValue.low); 375 376 /* FIND REFLECTIVE PORT */ 377 /* Query the MBIU for the port through which we are communicating. */ 378 /* We will avoid accesses to this port to avoid a self-reference. */ 379 380 MSR_READ(MBIU_WHOAMI, CP_MB0_MBIU0, &(msrValue.high), &(msrValue.low)); 381 reflective = msrValue.low & WHOAMI_MASK; 382 383 /* ENUMERATE ALL PORTS */ 384 /* For every possible port, set the MBIU.deviceId to something. */ 385 386 for (port = 0; port < 8; port++) { 387 /* FILL IN CLAIMED FIELD */ 388 /* All MBIU ports can only be assigned to one device from the */ 389 /* Durango table */ 390 391 MBIU2[port].claimed = 0; 392 393 /* MBIU2 PORT NUMBERS ARE IN 22:20 AND 31:23 = 010100010B */ 394 395 MBIU2[port].address = 396 (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); 397 398 if (port == reflective) 399 MBIU2[port].deviceId = REFLECTIVE; 400 else if (port > mbiu_port_count) 401 MBIU2[port].deviceId = NOT_POPULATED; 402 else { 403 MSR_READ(MBD_MSR_CAP, MBIU2[port].address, &(msrValue.high), 404 &(msrValue.low)); 405 MBIU2[port].deviceId = GET_DEVICE_ID(msrValue.high, msrValue.low); 406 } 407 } 408 } else { 409 /* NO 5535 */ 410 /* If the CS5535 is not installed, fill in the cached table */ 411 /* with the 'NOT_INSTALLED' flag. Also, fill in the device */ 412 /* status from NOT_KNOWN to REQ_NOT_INSTALLED. */ 413 414 for (port = 0; port < 8; port++) { 415 MBIU2[port].claimed = 0; 416 MBIU2[port].deviceId = NOT_INSTALLED; 417 MBIU2[port].address = 418 (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); 419 } 420 for (port = CP_INDEX_START; port <= CP_INDEX_STOP; port++) { 421 msrDev[port].Present = REQ_NOT_INSTALLED; 422 } 423 } 424} 425 426/*------------------------------------------------------------------ 427 * redcloud_init_msr_devices (PRIVATE ROUTINE - NOT PART OF DURANGO API) 428 429 * Handles the details of finding each possible device on the MBUS. 430 * If a given device is not found, its structure is left uninitialized. 431 * If a given device is found, its structure is updated. 432 * 433 * This init routine only checks for devices in aDev[]. 434 * 435 * Passed: 436 * aDev - is a pointer to the array of MBUS devices. 437 * arraySize - number of elements in aDev. 438 * 439 * Returns: 440 * 1 - If, for every device, its address was found. 441 * 0 - If, for any device, an error was encountered. 442 *------------------------------------------------------------------ 443 */ 444int 445redcloud_init_msr_devices(MSR aDev[], unsigned int array_size) 446{ 447 unsigned int i, issues = 0; 448 449 /* TRY TO FIND EACH ITEM IN THE ARRAY */ 450 451 for (i = 0; i < array_size; i++) { 452 /* IGNORE DEVICES THAT ARE ALREADY FOUND */ 453 /* The addresses for "found" devices are already known. */ 454 455 if (aDev[i].Present == FOUND || aDev[i].Present == REQ_NOT_INSTALLED) 456 continue; 457 458 /* TRY TO FIND THE DEVICE ON THE MBUS */ 459 460 aDev[i].Present = redcloud_find_msr_device(&aDev[i]); 461 462 /* INCREMENT ERROR COUNT IF DEVICE NOT FOUND */ 463 464 if (aDev[i].Present != FOUND) 465 issues++; 466 } 467 468 return (issues == 0); 469} 470 471/*------------------------------------------------------------------ 472 * redcloud_find_msr_device (PRIVATE ROUTINE - NOT PART OF DURANGO API) 473 * 474 * Passed: 475 * pDev - is a pointer to one element in the array of MBUS devices 476 * 477 * Returns: 478 * FOUND - Device was found and pDev->Address has been updated. 479 * 480 * REQ_NOT_FOUND - Device was not found and pDev->Address has not 481 * been updated. 482 * 483 *------------------------------------------------------------------ 484*/ 485DEV_STATUS 486redcloud_find_msr_device(MSR * pDev) 487{ 488 unsigned int i; 489 490 /* SEARCH DURANGO'S CACHED MBUS TOPOLOGY */ 491 /* This gets a little tricky. As the only identifier we have for each */ 492 /* device is the device ID and we have multiple devices of the same type */ 493 /* MCP, MPCI, USB, etc. we need to make some assumptions based on table */ 494 /* order. These are as follows: */ 495 /* 1. All Redcloud nodes are searched first, as we assume that they */ 496 /* are first in the table. */ 497 /* 2. If two devices have the same device ID and are found on the same */ 498 /* device (GX2, CS5535, etc.) we assume that they are listed such */ 499 /* that the first device in the table with this device ID has a lower */ 500 /* port address. */ 501 /* 3. After a device ID has been matched, the port is marked as */ 502 /* 'claimed', such that future enumerations continue searching the */ 503 /* GeodeLink topology. */ 504 505 /* SEARCH MBIU0 */ 506 507 for (i = 0; i < 8; i++) { 508 if (MBIU0[i].deviceId == pDev->Id && !(MBIU0[i].claimed)) { 509 MBIU0[i].claimed = 1; 510 pDev->Address = MBIU0[i].address; 511 return FOUND; 512 } 513 } 514 515 /* SEARCH MBIU1 */ 516 517 for (i = 0; i < 8; i++) { 518 if (MBIU1[i].deviceId == pDev->Id && !(MBIU1[i].claimed)) { 519 MBIU1[i].claimed = 1; 520 pDev->Address = MBIU1[i].address; 521 return FOUND; 522 } 523 } 524 525 /* SEARCH MBIU2 */ 526 527 for (i = 0; i < 8; i++) { 528 if (MBIU2[i].deviceId == pDev->Id && !(MBIU2[i].claimed)) { 529 MBIU2[i].claimed = 1; 530 pDev->Address = MBIU2[i].address; 531 return FOUND; 532 } 533 } 534 535 return REQ_NOT_FOUND; 536} 537 538/*-------------------------------------------------------------------- 539 * gfx_id_msr_device 540 * 541 * This routine handles reading the capabilities MSR register (typically 0x2000) 542 * and checking if the 'id' field matchs pDev.Id. This routine is 543 * used by applications/drivers that need to extend the list of known 544 * MBUS devices beyond those known by Durango. 545 * 546 * Passed: 547 * pDev - Pointer to MSR structure containing the device's ID. 548 * address - device address. 549 * 550 * Returns: 551 * FOUND - The IDs do match. 552 * REQ_NOT_FOUND - There was not a match. 553 * 554 *-------------------------------------------------------------------- 555 */ 556#if GFX_MSR_DYNAMIC 557DEV_STATUS 558redcloud_id_msr_device(MSR * pDev, unsigned long address) 559#else 560DEV_STATUS 561gfx_id_msr_device(MSR * pDev, unsigned long address) 562#endif 563{ 564 Q_WORD msrValue; 565 566 MSR_READ(MBD_MSR_CAP, address, &(msrValue.high), &(msrValue.low)); 567 568 if (GET_DEVICE_ID(msrValue.high, msrValue.low) == pDev->Id) 569 return FOUND; 570 else 571 return REQ_NOT_FOUND; 572} 573 574/*-------------------------------------------------------------------- 575 * gfx_get_msr_dev_address 576 * 577 * This function returns the 32-bit address of the requested device. 578 * The device must be a known MBUS device. (It must be in Durango's 579 * device table.) DEV_STATUS should be checked to verify that the address 580 * was updated. 581 * 582 * 583 * Passed: 584 * device - device index of the device in question. 585 * *address - ptr to location where address should be stored. 586 * 587 * Returns: 588 * DEV_STATUS of device in question. (NOT_KNOWN if device is out of range.) 589 * *address - updated if 'device' is within range 590 * 591 * Notes: 592 * This function should only be called after gfx_msr_init 593 * 594 *-------------------------------------------------------------------- 595 */ 596#if GFX_MSR_DYNAMIC 597DEV_STATUS 598redcloud_get_msr_dev_address(unsigned int device, unsigned long *address) 599#else 600DEV_STATUS 601gfx_get_msr_dev_address(unsigned int device, unsigned long *address) 602#endif 603{ 604 if (device < NUM_DEVS) { 605 if (msrDev[device].Present == FOUND) 606 *address = msrDev[device].Address; 607 608 return msrDev[device].Present; 609 } 610 return NOT_KNOWN; 611 612} 613 614/*-------------------------------------------------------------------- 615 * gfx_get_glink_id_at_address 616 * 617 * This function returns the 16-bit deviceId at the requested address. 618 * DEV_STATUS should be checked to make sure that device was updated. 619 * 620 * Passed: 621 * device - ptr to location where device ID should be stored. 622 * address - address of desired device ID. 623 * 624 * Returns: 625 * FOUND if address is a valid address, NOT_KNOWN if address cannot be found 626 * on the mbus. 627 * *device - updated with device Id info. 628 * 629 * Notes: 630 * This function should be called after gfx_msr_init 631 * 632 *-------------------------------------------------------------------- 633 */ 634#if GFX_MSR_DYNAMIC 635DEV_STATUS 636redcloud_get_glink_id_at_address(unsigned int *device, unsigned long address) 637#else 638DEV_STATUS 639gfx_get_glink_id_at_address(unsigned int *device, unsigned long address) 640#endif 641{ 642 int port; 643 644 for (port = 0; port < 8; port++) { 645 if (MBIU0[port].address == address) { 646 *device = MBIU0[port].deviceId; 647 return FOUND; 648 } else if (MBIU1[port].address == address) { 649 *device = MBIU1[port].deviceId; 650 return FOUND; 651 } else if (MBIU2[port].address == address) { 652 *device = MBIU2[port].deviceId; 653 return FOUND; 654 } 655 } 656 657 return NOT_KNOWN; 658 659} 660 661/*-------------------------------------------------------------------- 662 * gfx_msr_read 663 * 664 * Performs a 64-bit read from 'msrRegister' in device 'device'. 'device' is 665 * an index into Durango's table of known MBUS devices. 666 * 667 * Returns: 668 * FOUND - if no errors were detected and msrValue has been updated. 669 * NOT_KNOWN - an error was detected. msrValue is not updated. 670 * REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller 671 * should call msrInit() first. msrValue is not updated. 672 * Notes: 673 * This function should be called after gfx_msr_init 674 *-------------------------------------------------------------------- 675 */ 676#if GFX_MSR_DYNAMIC 677DEV_STATUS 678redcloud_msr_read(unsigned int device, unsigned int msrRegister, 679 Q_WORD * msrValue) 680#else 681DEV_STATUS 682gfx_msr_read(unsigned int device, unsigned int msrRegister, Q_WORD * msrValue) 683#endif 684{ 685 if (device < NUM_DEVS) { 686 if (msrDev[device].Present == FOUND) 687 MSR_READ(msrRegister, msrDev[device].Address, &(msrValue->high), 688 &(msrValue->low)); 689 690 return msrDev[device].Present; 691 } 692 return NOT_KNOWN; 693} 694 695/*-------------------------------------------------------------------- 696 * gfx_msr_write 697 * 698 * Performs a 64-bit write to 'msrRegister' in device 'devID'. 699 * 700 * Returns: 701 * FOUND - if no errors were detected and msrValue has been updated. 702 * NOT_KNOWN - an error was detected. msrValue is not updated. 703 * REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller 704 * should call msrInit() first. msrValue is not updated. 705 * 706 * Notes: 707 * This function is valid to call after initMSR_API() 708 * 709 *-------------------------------------------------------------------- 710 */ 711#if GFX_MSR_DYNAMIC 712DEV_STATUS 713redcloud_msr_write(unsigned int device, unsigned int msrRegister, 714 Q_WORD * msrValue) 715#else 716DEV_STATUS 717gfx_msr_write(unsigned int device, unsigned int msrRegister, 718 Q_WORD * msrValue) 719#endif 720{ 721 if (device < NUM_DEVS) { 722 if (msrDev[device].Present == FOUND) 723 MSR_WRITE(msrRegister, msrDev[device].Address, &(msrValue->high), 724 &(msrValue->low)); 725 726 return msrDev[device].Present; 727 } 728 return NOT_KNOWN; 729} 730