vb_i2c.c revision dfe64dd3
1/* Jong 03/12/2009; added for supporting Xorg 7.0 */ 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "osdef.h" 7#include "vgatypes.h" 8/* #include "vb_util.h" */ /* Jong@08032009 */ 9#include "vb_def.h" 10 11#ifdef WIN2000 12#include <dderror.h> 13#include <devioctl.h> 14#include <miniport.h> 15#include <ntddvdeo.h> 16#include <video.h> 17#include "xgiv.h" 18#include "dd_i2c.h" 19#include "tools.h" 20#endif /* WIN2000 */ 21 22#ifdef LINUX_XF86 23#include "xf86.h" 24#include "xf86PciInfo.h" 25#include "xgi.h" 26#include "xgi_regs.h" 27#include "vb_i2c.h" 28#endif 29 30#ifdef LINUX_KERNEL 31#include <linux/version.h> 32#include <asm/io.h> 33#include <linux/types.h> 34#include "vb_i2c.h" 35 36/* Jong@08052009 */ 37/* #include <linux/delay.h> */ /* udelay */ 38 39#include "XGIfb.h" 40 41#endif 42 43 44 45/*char I2CAccessBuffer(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl I2CCntl, ULONG DevAddr, ULONG Offset, PUCHAR pBuffer, ULONG ulSize); */ 46char vGetEDIDExtensionBlocks(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2C, PUCHAR pjBuffer, ULONG ulBufferSize); 47char vGetEnhancedEDIDBlock(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2C, ULONG ulBlockID, ULONG ulBlockTag, PUCHAR pjBuffer, ULONG ulBufferSize); 48 49char I2COpen (PXGI_HW_DEVICE_INFO pHWDE,ULONG ulI2CEnable, ULONG ulChannelID, PI2CControl pI2CControl); 50char I2CAccess(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 51BOOLEAN I2CNull( PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 52BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 53BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 54BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 55BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE,PI2CControl pI2CControl); 56BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 57BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl); 58BOOLEAN Ack (PXGI_HW_DEVICE_INFO pHWDE, bool fPut); 59BOOLEAN NoAck(PXGI_HW_DEVICE_INFO pHWDE); 60BOOLEAN Start( PXGI_HW_DEVICE_INFO pHWDE); 61BOOLEAN Stop(PXGI_HW_DEVICE_INFO pHWDE); 62BOOLEAN WriteUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, UCHAR cData); 63BOOLEAN ReadUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, PUCHAR pBuffer); 64UCHAR ReverseUCHAR(UCHAR data); 65 66VOID vWriteClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 67VOID vWriteDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 68BOOLEAN bReadClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE); 69BOOLEAN bReadDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE); 70 71BOOLEAN bEDIDCheckSum(PUCHAR pjEDIDBuf,ULONG ulBufSize); 72 73VOID vWriteClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 74VOID vWriteDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 75BOOLEAN bReadClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE); 76BOOLEAN bReadDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE); 77 78/* Jong@08102009 */ 79VOID vWriteClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 80VOID vWriteDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 81BOOLEAN bReadClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE); 82BOOLEAN bReadDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE); 83 84/* #define CRT_I2C */ 85VOID vWriteClockLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 86VOID vWriteDataLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data); 87BOOLEAN bReadClockLine(PXGI_HW_DEVICE_INFO pHWDE); 88BOOLEAN bReadDataLine(PXGI_HW_DEVICE_INFO pHWDE); 89 90/* Jong@08052009 */ 91extern UCHAR XGI_GetRegByte(XGIIOADDRESS port); 92 93/* Jong@08052009 */ 94void I2C_DelayUS(ULONG MicroSeconds) 95{ 96 ErrorF(""); 97 /* udelay(MicroSeconds); */ 98} 99 100 101typedef enum _I2C_ACCESS_CMD 102{ 103 I2C_WRITE = 0, 104 I2C_READ 105/* Jong 08/18/2008; for XFree86 */ 106 /* WRITE = 0, 107 READ */ 108} I2C_ACCESS_CMD; 109 110/* For XG21 */ 111 112#define ENABLE_GPIOA 0x01 113#define ENABLE_GPIOB 0x02 114#define ENABLE_GPIOC 0x04 115VOID 116EnableGPIOA( 117PUCHAR pjIOPort, I2C_ACCESS_CMD CmdType) 118{ 119 PDEBUGI2C(ErrorF("EnableGPIOA()-pjIOPort=0x%x...\n", pjIOPort)); 120 121 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 122 123 if (CmdType == I2C_WRITE) 124 { 125 ujCR4A &= ~ENABLE_GPIOA; 126 } 127 else 128 { 129 ujCR4A |= ENABLE_GPIOA; 130 } 131 132 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 133} 134 135VOID 136EnableGPIOB( 137PUCHAR pjIOPort, I2C_ACCESS_CMD CmdType) 138{ 139 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 140 141 if (CmdType == I2C_WRITE) 142 { 143 ujCR4A &= ~ENABLE_GPIOB; 144 } 145 else 146 { 147 ujCR4A |= ENABLE_GPIOB; 148 } 149 150 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 151} 152 153VOID 154EnableGPIOC( 155PUCHAR pjIOPort, I2C_ACCESS_CMD CmdType) 156{ 157 UCHAR ujCR4A = XGI_GetReg(pjIOPort, IND_CR4A_GPIO_REG_III); 158 159 if (CmdType == I2C_WRITE) 160 { 161 ujCR4A &= ~ENABLE_GPIOC; 162 } 163 else 164 { 165 ujCR4A |= ENABLE_GPIOC; 166 } 167 168 XGI_SetReg(pjIOPort, IND_CR4A_GPIO_REG_III, ujCR4A); 169} 170 171 172 173 174/** 175* Function: getGPIORWTranser() 176* 177* Description: This function is used based on Z9. Because of wrongly wired deployment by HW 178* the CR4A and CR48 for GPIO pins have reverse sequence. For example, 179* D[7:0] for read function is ordered as GPIOA to GPIOH, but D[7:0] for read 180* is as GPIOH~GPIOA 181*/ 182UCHAR 183getGPIORWTransfer( 184UCHAR ujDate) 185{ 186 UCHAR ujRet = 0; 187 UCHAR i = 0; 188 189 for (i=0; i<8; i++) 190 { 191 ujRet = ujRet << 1; 192 ujRet |= GETBITS(ujDate >> i, 0:0); 193 } 194 195 return ujRet; 196} 197 198 199 200char I2CAccessBuffer(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl, ULONG ulDevAddr, 201 ULONG ulOffset, PUCHAR pBuffer,ULONG ulSize) 202{ 203 204 I2CControl I2C; 205 ULONG i; 206 207 if ((ulSize == 0) || (pBuffer == NULL)) { 208 return -1; 209 } 210 if (ulDevAddr & 1) { 211 return -1; 212 } 213 if ((ulDevAddr > 0xFF) || (ulOffset > 0xFF)) { 214 return -1; 215 } 216 217 I2C.Command = pI2CControl->Command; 218 I2C.dwCookie = pI2CControl->dwCookie; 219 I2C.Data = pI2CControl->Data; 220 I2C. Flags = pI2CControl->Flags; 221 I2C.Status = pI2CControl->Status; 222 I2C.ClockRate = pI2CControl->ClockRate; 223 switch (pI2CControl->Command) { 224 case I2C_COMMAND_READ: 225 /* Reset I2C Bus */ 226 I2C.Command = I2C_COMMAND_RESET; 227 I2CAccess(pHWDE, &I2C); 228 if (I2C.Status != I2C_STATUS_NOERROR) { 229 pI2CControl->Status = I2C.Status; 230 break; 231 } 232 233 /* Write Device Address */ 234 I2C.Command = I2C_COMMAND_WRITE; 235 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 236 I2C.Data = (UCHAR)ulDevAddr; 237 I2CAccess(pHWDE, &I2C); 238 if (I2C.Status != I2C_STATUS_NOERROR) { 239 pI2CControl->Status = I2C.Status; 240 break; 241 } 242 243 /* Write Register Offset */ 244 I2C.Command = I2C_COMMAND_WRITE; 245 I2C.Flags = I2C_FLAGS_ACK | I2C_FLAGS_STOP; 246 I2C.Data = (UCHAR)ulOffset; 247 I2CAccess(pHWDE, &I2C); 248 if (I2C.Status != I2C_STATUS_NOERROR) { 249 pI2CControl->Status = I2C.Status; 250 break; 251 } 252 253 /* Write Device Read Address */ 254 I2C.Command = I2C_COMMAND_WRITE; 255 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 256 I2C.Data = (UCHAR)ulDevAddr + 1; 257 I2CAccess(pHWDE, &I2C); 258 if (I2C.Status != I2C_STATUS_NOERROR) { 259 pI2CControl->Status = I2C.Status; 260 break; 261 } 262 263 /* Read Data */ 264 for (i=0; i< ulSize; i++) { 265 I2C.Command = I2C_COMMAND_READ; 266 I2C.Flags = I2C_FLAGS_ACK; 267 if (i == ulSize - 1) { /* Read Last UCHAR */ 268 I2C.Flags |= I2C_FLAGS_STOP; 269 } 270 I2CAccess(pHWDE, &I2C); 271 if (I2C.Status != I2C_STATUS_NOERROR) { 272 pI2CControl->Status = I2C.Status; 273 break; 274 } 275 *pBuffer = I2C.Data; 276 pBuffer++; 277 } 278 pI2CControl->Status = I2C.Status; 279 break; 280 281 case I2C_COMMAND_WRITE: 282 /* Reset I2C Bus */ 283 I2C.Command = I2C_COMMAND_RESET; 284 I2CAccess(pHWDE, &I2C); 285 if (I2C.Status != I2C_STATUS_NOERROR) { 286 pI2CControl->Status = I2C.Status; 287 break; 288 } 289 290 /* Write Device Address */ 291 I2C.Command = I2C_COMMAND_WRITE; 292 I2C.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK; 293 I2C.Data = (UCHAR)ulDevAddr; 294 I2CAccess(pHWDE, &I2C); 295 if (I2C.Status != I2C_STATUS_NOERROR) { 296 pI2CControl->Status = I2C.Status; 297 break; 298 } 299 300 /* Write Register Offset */ 301 I2C.Command = I2C_COMMAND_WRITE; 302 I2C.Flags = I2C_FLAGS_ACK; 303 I2C.Data = (UCHAR)ulOffset; 304 I2CAccess(pHWDE, &I2C); 305 if (I2C.Status != I2C_STATUS_NOERROR) { 306 pI2CControl->Status = I2C.Status; 307 break; 308 } 309 310 /* Write Data */ 311 for (i=0; i< ulSize; i++) { 312 I2C.Command = I2C_COMMAND_WRITE; 313 I2C.Flags = I2C_FLAGS_ACK; 314 if (i == ulSize - 1) { /* Read Last UCHAR */ 315 I2C.Flags |= I2C_FLAGS_STOP; 316 } 317 I2C.Data = *pBuffer; 318 I2CAccess(pHWDE, &I2C); 319 if (I2C.Status != I2C_STATUS_NOERROR) { 320 pI2CControl->Status = I2C.Status; 321 break; 322 } 323 pBuffer++; 324 } 325 pI2CControl->Status = I2C.Status; 326 break; 327 } 328 329 if (pI2CControl->Status == I2C_STATUS_NOERROR) 330 { 331 return 0; 332 } 333 else 334 { 335 return -1; 336 } 337} 338 339 340/************************************************************************* 341// char vGetEDIDExtensionBlocks 342// 343// Routine Description: 344// Reads the extension part behind a 128KB block of EDID which is in 1.3 345// format. The extension part can be distributed into 128KB-blocks. 346// 347// Arguments: 348// pHWDE - Hardware extension object pointer 349// pI2C - I2C pointer 350// pjBuffer - EDID Buffer 351// ulBufferSize - Buffer size 352// 353// 354// Return Value: 355// Status of returning EDID. 356// NO_ERROR - success 357// ERROR_INVALID_PARAMETER - failed 358// 359****************************************************************************/ 360char vGetEDIDExtensionBlocks( 361 PXGI_HW_DEVICE_INFO pHWDE, 362 PI2CControl pI2C, 363 PUCHAR pjBuffer, 364 ULONG ulBufferSize) 365{ 366 char status; 367 ULONG ulBlockTag; 368 ULONG i; 369 PUCHAR pBlockMap; 370 371 372 if ((ulBufferSize < 128) || (pjBuffer == NULL)) 373 { 374 return -1; 375 } 376 377 pI2C->Command = I2C_COMMAND_READ; 378 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, 128, pjBuffer, 128); 379 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 380 { 381 return status; 382 } 383 384 if (bEDIDCheckSum(pjBuffer, 128) != 0) { 385 return -1; 386 } 387 388 if (*pjBuffer == 0xF0) 389 { /* A Block Map, we should read other extension blocks*/ 390 pBlockMap = pjBuffer; 391 for (i=1; i<=126; i++) 392 { 393 ulBlockTag = *(pBlockMap + i); 394 if (ulBlockTag) 395 { 396 pjBuffer += 128; 397 ulBufferSize -= 128; 398 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, i+1, ulBlockTag, pjBuffer, ulBufferSize); 399 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 400 { 401 return -1; 402 } 403 } 404 else 405 { 406 if (i > 1) 407 { 408 return 0; /* All Extension blocks must be sequential, no holes allowed. (VESA E-EDID)*/ 409 } 410 else 411 { 412 return -1; 413 } 414 } 415 } 416 /* We should read block # 128 */ 417 pjBuffer += 128; 418 ulBufferSize -= 128; 419 ulBlockTag = 0xF0; 420 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, 128, ulBlockTag, pjBuffer, ulBufferSize); 421 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 422 { 423 return 0; /* Monitor may has only 128 blocks (0~127) */ 424 } 425 426 pBlockMap = pjBuffer; 427 for (i=1; i<=126; i++) 428 { /* Read Block # 128 ~ 254 */ 429 ulBlockTag = *(pBlockMap + i); 430 if (ulBlockTag) 431 { 432 pjBuffer += 128; 433 ulBufferSize -= 128; 434 status = vGetEnhancedEDIDBlock(pHWDE, pI2C, i+128, ulBlockTag, pjBuffer, ulBufferSize); 435 if ((status != 0) || (pI2C->Status != I2C_STATUS_NOERROR)) 436 { 437 return -1; 438 } 439 } 440 else 441 { 442 if (i > 1) 443 { 444 return 0; /* All Extension blocks must be sequential, no holes allowed. (VESA E-EDID) */ 445 } 446 else 447 { 448 return -1; 449 } 450 } 451 } 452 } 453 454 return 0; 455} 456 457/************************************************************************* 458// char vGetEnhancedEDIDBlock 459// 460// Routine Description: 461// Get the EDID which is in Enhanced-EDID format via I2C. The parse-in block 462// tag(ulBlockTag) and the first UCHAR of the retrieved buffer should be identical. 463// Returns error when they are not, otherwise return NO_ERROR. 464// 465// Arguments: 466// pHWDE - Hardware extension object pointer 467// pI2C - I2C pointer 468// ulBlockID - Block ID 469// ulBlockTag - Block Tag 470// pjBuffer - EDID Buffer 471// ulBufferSize - Buffer size 472// 473// 474// Return Value: 475// Status of returning EDID. 476// NO_ERROR - success 477// ERROR_INVALID_PARAMETER - failed 478// 479****************************************************************************/ 480char vGetEnhancedEDIDBlock( 481 PXGI_HW_DEVICE_INFO pHWDE, 482 PI2CControl pI2C, 483 ULONG ulBlockID, 484 ULONG ulBlockTag, 485 PUCHAR pjBuffer, 486 ULONG ulBufferSize) 487{ 488 ULONG ulOffset, SegmentID; 489 char status; 490 491 if ((ulBufferSize < 128) || (pjBuffer == NULL)) 492 { 493 return -1; 494 } 495 496 SegmentID = ulBlockID / 2; 497 ulOffset = (ulBlockID % 2) * 128; 498 499 pI2C->Command = I2C_COMMAND_WRITE; 500 status = I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, (PUCHAR)&SegmentID, 1); 501 if ((status == NO_ERROR) && (pI2C->Status == I2C_STATUS_NOERROR)) 502 { 503 pI2C->Command = I2C_COMMAND_READ; 504 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, ulOffset, pjBuffer, 128); 505 if ((status == 0) && (pI2C->Status == I2C_STATUS_NOERROR)) 506 { 507 if (*pjBuffer != (UCHAR)ulBlockTag) 508 { 509 return -1; 510 } 511 512 if (bEDIDCheckSum(pjBuffer, 128) != 0) 513 { 514 return -1; 515 } 516 } 517 else 518 { 519 return ERROR_INVALID_PARAMETER; 520 } 521 } 522 else 523 { 524 return ERROR_INVALID_PARAMETER; 525 } 526 527 528 return NO_ERROR; 529} 530char I2COpen (PXGI_HW_DEVICE_INFO pHWDE, ULONG ulI2CEnable, ULONG ulChannelID, PI2CControl pI2CControl) 531{ 532/* 533// printk("\nI2COpen(%d) : Channel ID = %d\n", ulI2CEnable, ulChannelID); 534 // we need to determine the Context area for each command we receive 535 // i.e. which hardware I2C bus is the command for. 536 // this is unimplemented here! 537*/ 538 if (ulChannelID >= MAX_I2C_CHANNEL) 539 { 540 return ERROR_INVALID_PARAMETER; 541 } 542 if (ulI2CEnable) /* Open I2C Port */ 543 { 544/* // verify clock rate. If you cannot implement the given rate, 545 // enable a lower clock rate closest to the request clock rate. 546 // 547 // put a better check here if your device can only do discrete 548 // clock rate values. 549*/ 550 if (pI2CControl->ClockRate > I2C_MAX_CLOCK_RATE) 551 { 552 pI2CControl->ClockRate = I2C_MAX_CLOCK_RATE; 553 } 554 pI2CControl->Status = I2C_STATUS_NOERROR; 555 } 556 else /* Close I2C Port*/ 557 { 558 /* Set Acquired state to FALSE */ 559 560 pI2CControl->dwCookie = 0; 561 /* Set status */ 562 pI2CControl->Status = I2C_STATUS_NOERROR; 563 } 564 565 566 567 return 0; 568} 569/* end of I2COpen */ 570char I2CAccess(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 571{ 572 ULONG ulChannel = pI2CControl->dwCookie % MAX_I2C_CHANNEL; 573 574 575 if (pI2CControl->ClockRate > I2C_MAX_CLOCK_RATE) 576 { 577 pI2CControl->ClockRate = I2C_MAX_CLOCK_RATE; 578 } 579 if (pI2CControl->ClockRate == 0) { 580 pI2CControl->ClockRate = 20000; 581 } 582 583 pHWDE->I2CDelay = (1000000 / pI2CControl->ClockRate) * 10 * 2; /* in 100ns */ 584 /* pHWDE->I2CDelay = (1000000 / pI2CControl->ClockRate) * 10; */ /* in 100ns */ 585 /* pHWDE->I2CDelay = 100; */ 586 /* PDEBUG(ErrorF("I2CAccess()-I2CDelay = %d...\n", pHWDE->I2CDelay)); */ 587 588 /* pHWDE->I2CDelay = 100; */ /* Jong@08032009 */ 589 590 switch (pI2CControl->Command) 591 { 592 /* Issue a STOP or START without a READ or WRITE Command */ 593 case I2C_COMMAND_NULL: 594 if (I2CNull(pHWDE, pI2CControl) == FALSE) break; 595/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 596 pI2CContext->dwI2CPortAcquired = FALSE; 597 } 598*/ break; 599 600 /* READ or WRITE Command */ 601 case I2C_COMMAND_READ: 602 if (I2CRead(pHWDE, pI2CControl) == FALSE) break; 603/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 604 pI2CContext->dwI2CPortAcquired = FALSE; 605 } 606*/ break; 607 608 case I2C_COMMAND_WRITE: 609 if (I2CWrite(pHWDE, pI2CControl) == FALSE) break; 610/* if (pI2CControl->Flags & I2C_FLAGS_STOP) { 611 pI2CContext->dwI2CPortAcquired = FALSE; 612 } 613*/ break; 614 615 case I2C_COMMAND_STATUS: 616 pI2CControl->Status = I2C_STATUS_NOERROR; 617 break; 618 619 case I2C_COMMAND_RESET: 620 /* Reset I2C bus */ 621 if (ResetI2C(pHWDE, pI2CControl) == FALSE) break; 622 break; 623 624 default: 625 /* Invalid Command */ 626 return ERROR_INVALID_PARAMETER; 627 } 628 629 630/* printk("\nI2CAccess(): I2C Cmd = 0x%X I2C Flags = 0x%X I2C Status = 0x%X I2C Data = 0x%X", pI2CControl->Command, pI2CControl->Flags, pI2CControl->Status, pI2CControl->Data); */ 631 632 return NO_ERROR; 633} 634 635 636/*^^* 637 * Function: I2CNull 638 * 639 * Purpose: To complete an I2C instruction. 640 * 641 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 642 * with card being accessed 643 * I2CCntl : PI2CControl, pointer to I2C control structure 644 * 645 * Outputs: void. 646 *^^*/ 647BOOLEAN I2CNull( PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 648{ 649 pI2CControl->Status = I2C_STATUS_ERROR; 650 651/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 652 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 653 { 654 if (Stop(pHWDE) == FALSE) return FALSE; 655 if (Start(pHWDE) == FALSE) return FALSE; 656 } 657 658/*///// Issue START ////////*/ 659 if (pI2CControl->Flags & I2C_FLAGS_START) 660 { 661 if (Start(pHWDE) == FALSE) return FALSE; 662 } 663 664/*////// Issue STOP /////////*/ 665 if (pI2CControl->Flags & I2C_FLAGS_STOP) 666 { 667 if (Stop(pHWDE) == FALSE) return FALSE; 668 } 669 670 pI2CControl->Status = I2C_STATUS_NOERROR; 671 return TRUE; 672}/* end of I2CNull()*/ 673 674/*^^* 675 * Function: I2CRead 676 * 677 * Purpose: To complete an I2C instruction. 678 * 679 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 680 * with card being accessed 681 * I2CCntl : PI2CControl, pointer to I2C control structure 682 * 683 * Outputs: void. 684 *^^*/ 685BOOLEAN I2CRead(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 686{ 687 pI2CControl->Status = I2C_STATUS_ERROR; 688 689/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 690 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 691 { 692 if (Stop(pHWDE) == FALSE) return FALSE; 693 if (Start(pHWDE) == FALSE) return FALSE; 694 } 695 696/*///// Issue START ////////*/ 697 if (pI2CControl->Flags & I2C_FLAGS_START) 698 { 699 if (Start(pHWDE) == FALSE) return FALSE; 700 } 701 702/*///// Read Command ///////*/ 703 if (ReadUCHARI2C(pHWDE, &pI2CControl->Data) == FALSE) 704 return FALSE; 705 706 if (pI2CControl->Flags & I2C_FLAGS_STOP) { 707 if (NoAck(pHWDE) == FALSE) return FALSE; 708 } 709 else { /* Should we issue ACK*/ 710 if (pI2CControl->Flags & I2C_FLAGS_ACK) { 711 if (Ack(pHWDE, SEND_ACK) == FALSE) return FALSE; 712 } 713 } 714 715/*////// Issue STOP /////////*/ 716 if (pI2CControl->Flags & I2C_FLAGS_STOP) 717 { 718 if (Stop(pHWDE) == FALSE) return FALSE; 719 } 720 721 pI2CControl->Status = I2C_STATUS_NOERROR; 722 return TRUE; 723} /* end of I2CRead() */ 724 725/*^^* 726 * Function: I2CWrite 727 * 728 * Purpose: To complete an I2C instruction. 729 * 730 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated 731 * with card being accessed 732 * I2CCntl : PI2CControl, pointer to I2C control structure 733 * 734 * Outputs: void. 735 *^^*/ 736BOOLEAN I2CWrite(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 737{ 738 pI2CControl->Status = I2C_STATUS_ERROR; 739 740/*///// Issue STOP - START, if I2C_FLAGS_DATACHAINING ////////*/ 741 if (pI2CControl->Flags & I2C_FLAGS_DATACHAINING) 742 { 743 if (Stop(pHWDE) == FALSE) 744 { 745 746 return FALSE; 747 } 748 if (Start(pHWDE) == FALSE) 749 { 750 751 752 return FALSE; 753 } 754 } 755 756/*///// Issue START ////////*/ 757 if (pI2CControl->Flags & I2C_FLAGS_START) 758 { 759 if (Start(pHWDE) == FALSE) 760 { 761 return FALSE; 762 } 763 } 764 765/*///// Write Command ///////*/ 766 if (WriteUCHARI2C(pHWDE, pI2CControl->Data) == FALSE) 767 { 768 769 return FALSE; 770 } 771 772 if (pI2CControl->Flags & I2C_FLAGS_ACK) { 773 if (Ack(pHWDE, RECV_ACK) == FALSE) 774 { 775 return FALSE; 776 } 777 } 778 779/*////// Issue STOP /////////*/ 780 if (pI2CControl->Flags & I2C_FLAGS_STOP) 781 { 782 if (Stop(pHWDE) == FALSE) 783 { 784 return FALSE; 785 } 786 } 787 788 pI2CControl->Status = I2C_STATUS_NOERROR; 789 return TRUE; 790} /* end of I2CWrite() */ 791 792/*^^* 793 * Function: ResetI2C 794 * 795 * Purpose: To reset I2CBus 796 * 797 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 798 * lpI2C_ContextData being accessed 799 * 800 * Outputs: UCHAR, the data that was read. 801 *^^*/ 802BOOLEAN ResetI2C(PXGI_HW_DEVICE_INFO pHWDE, PI2CControl pI2CControl) 803{ 804 805 if (Stop(pHWDE) == TRUE) { 806 pI2CControl->Status = I2C_STATUS_NOERROR; 807 return TRUE; 808 } 809 else { 810 pI2CControl->Status = I2C_STATUS_ERROR; 811 return FALSE; 812 } 813} /* ResetI2C() */ 814 815 816 817 818/*^^* 819 * Function: Ack 820 * 821 * Purpose: To ask the I2C bus for an acknowledge. 822 * 823 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 824 * lpI2C_ContextData being accessed 825 * 826 * Outputs: char, ack status. 827 *^^*/ 828BOOLEAN Ack (PXGI_HW_DEVICE_INFO pHWDE, bool fPut) 829{ 830 BOOLEAN status = FALSE; 831 ULONG i, delay, delay2; 832 ULONG ack; 833 834 delay = pHWDE->I2CDelay / 10 / 2; 835 if (fPut == SEND_ACK) /* Send Ack into I2C bus */ 836 { 837 vWriteDataLine(pHWDE, LODAT); 838 I2C_DelayUS(delay); 839 840 vWriteClockLine(pHWDE, HICLK); 841 I2C_DelayUS(delay); 842 if (bReadClockLine(pHWDE) != HICLK) { 843 i = 0; 844 delay2 = delay * 2; 845 I2C_DelayUS(delay2); /* Jong@08052008 */ 846 do { 847 vWriteClockLine(pHWDE, HICLK); 848 I2C_DelayUS(delay2); 849 if (bReadClockLine(pHWDE) == HICLK) break; 850 i++; 851 delay2 *= 2; 852 if (i >= I2C_RETRY_COUNT) return FALSE; 853 } while (1); 854 } 855 856 857 I2C_DelayUS(delay); /* Jong@08052008 */ 858 vWriteClockLine(pHWDE, LOCLK); 859 I2C_DelayUS(delay); 860 861 return TRUE; 862 } 863 else 864 { 865 /* Receive Ack from I2C bus */ 866 vWriteDataLine(pHWDE, HIDAT); 867 I2C_DelayUS(delay); 868 ack = bReadDataLine(pHWDE); 869 870 I2C_DelayUS(delay); /* Jong@08052008 */ 871 vWriteClockLine(pHWDE, HICLK); 872 I2C_DelayUS(delay); 873 if (bReadClockLine(pHWDE) != HICLK) { 874 i = 0; 875 delay2 = delay * 2; 876 do { 877 I2C_DelayUS(delay2); /* Jong@08052008 */ 878 vWriteClockLine(pHWDE, HICLK); 879 I2C_DelayUS(delay2); 880 if (bReadClockLine(pHWDE) == HICLK) break; 881 i++; 882 delay2 *= 2; 883 if (i >= I2C_RETRY_COUNT) return FALSE; 884 } while (1); 885 } 886 887 I2C_DelayUS(delay); /* Jong@08052008 */ 888 status = bReadDataLine(pHWDE); 889 890 I2C_DelayUS(delay); /* Jong@08052008 */ 891 vWriteClockLine(pHWDE, LOCLK); 892 I2C_DelayUS(delay); 893 894 if (status != LODAT) { 895 if (ack == LODAT) { 896 status = LODAT; 897 } 898 899 else { 900 901 } 902 903 } 904 return (BOOLEAN)(status == LODAT); 905 } 906}/* end of Ack() */ 907 908 909BOOLEAN NoAck(PXGI_HW_DEVICE_INFO pHWDE) 910{ 911 ULONG i, delay, delay2; 912 913 delay = pHWDE->I2CDelay / 10 / 2; 914 915 vWriteDataLine(pHWDE, HIDAT); 916 I2C_DelayUS(delay); 917 918 vWriteClockLine(pHWDE, HICLK); 919 I2C_DelayUS(delay); 920 if (bReadClockLine(pHWDE) != HICLK) { 921 delay2 = delay * 2; 922 i = 0; 923 do { 924 I2C_DelayUS(delay2); /* Jong@08052008 */ 925 vWriteClockLine(pHWDE, HICLK); 926 I2C_DelayUS(delay2); 927 if (bReadClockLine(pHWDE) == HICLK) break; 928 i++; 929 delay2 *= 2; 930 if (i >= I2C_RETRY_COUNT) return FALSE; 931 } while (1); 932 } 933 934 I2C_DelayUS(delay); /* Jong@08052008 */ 935 vWriteClockLine(pHWDE, LOCLK); 936 I2C_DelayUS(delay); 937 938 return TRUE; 939} 940 941 942/*^^* 943 * Function: Start 944 * 945 * Purpose: To start a transfer on the I2C bus. 946 * 947 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 948 * lpI2C_ContextData being accessed 949 * 950 * Outputs: void. 951 *^^*/ 952BOOLEAN Start( PXGI_HW_DEVICE_INFO pHWDE) 953{ 954 ULONG i, delay, delay2; 955 956 delay = pHWDE->I2CDelay / 10 / 2; 957 958 vWriteDataLine(pHWDE, HIDAT); 959 I2C_DelayUS(delay); 960 if (bReadDataLine(pHWDE) != HIDAT) { 961 delay2 = delay * 2; 962 i = 0; 963 do { 964 I2C_DelayUS(delay2); /* Jong@08052008 */ 965 vWriteDataLine(pHWDE, HIDAT); 966 I2C_DelayUS(delay2); 967 if (bReadDataLine(pHWDE) == HIDAT) break; 968 i++; 969 delay2 *= 2; 970 if (i >= I2C_RETRY_COUNT) return FALSE; 971 } while (1); 972 } 973 974 I2C_DelayUS(delay); /* Jong@08052008 */ 975 vWriteClockLine(pHWDE, HICLK); 976 I2C_DelayUS(delay); 977 if (bReadClockLine(pHWDE) != HICLK) { 978 delay2 = delay * 2; 979 i = 0; 980 do { 981 I2C_DelayUS(delay2); /* Jong@08052008 */ 982 vWriteClockLine(pHWDE, HICLK); 983 I2C_DelayUS(delay2); 984 if (bReadClockLine(pHWDE) == HICLK) break; 985 i++; 986 delay2 *= 2; 987 if (i >= I2C_RETRY_COUNT) return FALSE; 988 } while (1); 989 } 990 991 I2C_DelayUS(delay); /* Jong@08052008 */ 992 vWriteDataLine(pHWDE, LODAT); 993 I2C_DelayUS(delay); 994 995 vWriteClockLine(pHWDE, LOCLK); 996 I2C_DelayUS(delay); 997 998 return TRUE; 999}/* end of Start */ 1000 1001/*^^* 1002 * Function: Stop 1003 * 1004 * Purpose: To stop a transfer on the I2C bus. 1005 * 1006 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1007 * lpI2C_ContextData being accessed 1008 * 1009 * Outputs: void. 1010 *^^*/ 1011BOOLEAN Stop(PXGI_HW_DEVICE_INFO pHWDE) 1012{ 1013 ULONG i, delay, delay2; 1014 1015 delay = pHWDE->I2CDelay / 10 / 2; 1016 PDEBUGI2C(ErrorF("Stop()-begin-pHWDE->I2CDelay=%d, delay=%d...\n", pHWDE->I2CDelay, delay)); 1017 1018 vWriteDataLine(pHWDE, LODAT); 1019 I2C_DelayUS(delay); 1020 1021 vWriteClockLine(pHWDE, HICLK); 1022 I2C_DelayUS(delay); 1023 if (bReadClockLine(pHWDE) != HICLK) { 1024 i = 0; 1025 delay2 = delay * 2; 1026 do { 1027 I2C_DelayUS(delay2); /* Jong@08052008 */ 1028 vWriteClockLine(pHWDE, HICLK); 1029 I2C_DelayUS(delay2); 1030 if (bReadClockLine(pHWDE) == HICLK) break; 1031 i++; 1032 delay2 *= 2; 1033 if (i >= I2C_RETRY_COUNT) return FALSE; 1034 } while (1); 1035 } 1036 1037 I2C_DelayUS(delay); /* Jong@08052008 */ 1038 vWriteDataLine(pHWDE, HIDAT); 1039 I2C_DelayUS(delay); 1040 1041 return (BOOLEAN)(bReadDataLine(pHWDE) == HIDAT); 1042}/* end of Stop*/ 1043 1044/*^^* 1045 * Function: WriteUCHARI2C 1046 * 1047 * Purpose: To write a UCHAR of data to the I2C bus. 1048 * 1049 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1050 * lpI2C_ContextData being accessed 1051 * cData: UCHAR, the data to write 1052 * 1053 * Outputs: void. 1054 *^^*/ 1055BOOLEAN WriteUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, UCHAR cData) 1056{ 1057 ULONG i, j, delay, delay2; 1058 1059 cData = ReverseUCHAR(cData); 1060 1061 delay = pHWDE->I2CDelay / 10 / 2; 1062 1063 for (j=0; j<8; j++, cData>>=1) 1064 { 1065 I2C_DelayUS(delay); /* Jong@08052008 */ 1066 vWriteDataLine(pHWDE, cData); 1067 I2C_DelayUS(delay); 1068 1069 vWriteClockLine(pHWDE, HICLK); 1070 I2C_DelayUS(delay); 1071 if (bReadClockLine(pHWDE) != HICLK) { 1072 i = 0; 1073 delay2 = delay * 2; 1074 do { 1075 I2C_DelayUS(delay2); /* Jong@08052008 */ 1076 vWriteClockLine(pHWDE, HICLK); 1077 I2C_DelayUS(delay2); 1078 if (bReadClockLine(pHWDE) == HICLK) break; 1079 i++; 1080 delay2 *= 2; 1081 if (i >= I2C_RETRY_COUNT) return FALSE; 1082 } while (1); 1083 } 1084 1085 I2C_DelayUS(delay); /* Jong@08052008 */ 1086 vWriteClockLine(pHWDE, LOCLK); 1087 I2C_DelayUS(delay); 1088 } 1089 return TRUE; 1090}/* end of WriteUCHARI2C */ 1091 1092/*^^* 1093 * Function: ReadUCHARI2C 1094 * 1095 * Purpose: To read a UCHAR of data from the I2C bus. 1096 * 1097 * Inputs: lpI2C_ContextData : PI2C_CONTEXT, pointer to data struct associated with 1098 * lpI2C_ContextData being accessed 1099 * 1100 * Outputs: UCHAR, the data that was read. 1101 *^^*/ 1102BOOLEAN ReadUCHARI2C(PXGI_HW_DEVICE_INFO pHWDE, PUCHAR pBuffer) 1103{ 1104 ULONG ulReadData, data, i, j, delay, delay2; 1105 1106 delay = pHWDE->I2CDelay / 10 / 2; 1107 1108 vWriteDataLine(pHWDE, HIDAT); 1109 I2C_DelayUS(delay); 1110 1111 ulReadData = 0; 1112 for (j = 0; j < 8; j++) 1113 { 1114 vWriteClockLine(pHWDE, HICLK); 1115 I2C_DelayUS(delay); 1116 if (bReadClockLine(pHWDE) != HICLK) { 1117 i = 0; 1118 delay2 = delay * 2; 1119 do { 1120 I2C_DelayUS(delay2); /* Jong@08052008 */ 1121 vWriteClockLine(pHWDE, HICLK); 1122 I2C_DelayUS(delay2); 1123 if (bReadClockLine(pHWDE) == HICLK) break; 1124 i++; 1125 delay2 *= 2; 1126 if (i >= I2C_RETRY_COUNT) return FALSE; 1127 } while (1); 1128 } 1129 1130 I2C_DelayUS(delay); /* Jong@08052008 */ 1131 data = bReadDataLine(pHWDE); 1132 ulReadData = (ulReadData << 1) | (data & 1); 1133 1134 I2C_DelayUS(delay); /* Jong@08052008 */ 1135 vWriteClockLine(pHWDE, LOCLK); 1136 I2C_DelayUS(delay); 1137 1138 vWriteDataLine(pHWDE, HIDAT); 1139 I2C_DelayUS(delay); 1140 } 1141 1142 *pBuffer = (UCHAR) ulReadData; 1143 return TRUE; 1144} 1145 1146 1147UCHAR ReverseUCHAR(UCHAR data) 1148{ 1149 UCHAR rdata = 0; 1150 int i; 1151 1152 for (i=0; i<8; i++) 1153 { 1154 rdata <<= 1; 1155 rdata |= (data & 1); 1156 data >>= 1; 1157 } 1158 1159 return(rdata); 1160} 1161 1162/************************************************************************************ 1163 For DVI I2C Interface 1164***************************************************************************************/ 1165 1166/************************************************************************* 1167// VOID vWriteClockLineDVI() 1168// IOReg xx14, index 0F is defined as follows: 1169// 1170// ... 1 0 1171// --------|------|-------| 1172// ...| Data | Clock | 1173// ------------------------ 1174*************************************************************************/ 1175VOID vWriteClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1176{ 1177 UCHAR temp; 1178 PUCHAR pjI2cIOBase; 1179 1180 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...begin\n")); 1181 1182 if ((pHWDE->jChipType < XG21)&&(pHWDE->jChipType != XG27)) 1183 { 1184 ErrorF("vWriteClockLineDVI()...0\n"); 1185 } 1186 else 1187 { 1188 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...1\n")); 1189 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1190 1191 /* Enable GPIOA Write */ 1192 1193 EnableGPIOA(pjI2cIOBase, I2C_WRITE); 1194 1195 PDEBUGI2C(ErrorF("*1 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1196 pHWDE->ucI2cDVI = (pHWDE->ucI2cDVI & MASK(1:1)) | SETBITS(data, 0:0); 1197 PDEBUGI2C(ErrorF("*2 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1198 1199 temp = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1200 PDEBUGI2C(ErrorF("IND_CR48_GPIO_REG_I = %d\n", temp)); 1201 1202 { 1203 UCHAR temp2 = getGPIORWTransfer(temp); 1204 PDEBUGI2C(ErrorF("temp2 = %d\n", temp2)); 1205 temp = temp2; 1206 } 1207 1208 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cDVI; 1209 PDEBUGI2C(ErrorF("temp= %d\n", temp)); 1210 XGI_SetReg(pjI2cIOBase,IND_CR48_GPIO_REG_I, temp); 1211 } 1212 1213 PDEBUGI2C(ErrorF("vWriteClockLineDVI()...end\n")); 1214} 1215 1216/************************************************************************* 1217// VOID vWriteDataLineDVI() 1218// IOReg xx14, index 0F is defined as follows: 1219// 1220// ... 1 0 1221// --------|------|-------| 1222// ...| Data | Clock | 1223// ------------------------ 1224*************************************************************************/ 1225VOID vWriteDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1226{ 1227 UCHAR temp; 1228 PUCHAR pjI2cIOBase; 1229 1230 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...begin\n")); 1231 1232 if ((pHWDE->jChipType < XG21)&&(pHWDE->jChipType != XG27)) 1233 { 1234 ErrorF("vWriteDataLineDVI()...0\n"); 1235 } 1236 else 1237 { 1238 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...1\n")); 1239 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1240 1241 1242 /* Enable GPIOB Write */ 1243 1244 EnableGPIOB(pjI2cIOBase, I2C_WRITE); 1245 1246 PDEBUGI2C(ErrorF("*1 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1247 pHWDE->ucI2cDVI = (pHWDE->ucI2cDVI & MASK(0:0)) | SETBITS(data, 1:1); 1248 PDEBUGI2C(ErrorF("*2 - pHWDE->ucI2cDVI = %d\n", pHWDE->ucI2cDVI)); 1249 1250 temp = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1251 PDEBUGI2C(ErrorF("IND_CR48_GPIO_REG_I = %d\n", temp)); 1252 1253 { 1254 UCHAR temp2 = getGPIORWTransfer(temp); 1255 PDEBUGI2C(ErrorF("temp2 = %d\n", temp2)); 1256 1257 temp = temp2; 1258 } 1259 1260 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cDVI; 1261 PDEBUGI2C(ErrorF("temp = %d\n", temp)); 1262 1263 XGI_SetReg(pjI2cIOBase,IND_CR48_GPIO_REG_I, temp); 1264 } 1265 1266 PDEBUGI2C(ErrorF("vWriteDataLineDVI()...end\n")); 1267} 1268 1269/************************************************************************* 1270// BOOLEAN bReadClockLineDVI() 1271// IOReg xx14, index 0F is defined as follows: 1272// 1273// ... 1 0 1274// --------|------|-------| 1275// ...| Data | Clock | 1276// ------------------------ 1277*************************************************************************/ 1278BOOLEAN bReadClockLineDVI(PXGI_HW_DEVICE_INFO pHWDE) 1279{ 1280 UCHAR cPortData; 1281 PUCHAR pjI2cIOBase; 1282 1283 PDEBUGI2C(ErrorF("bReadClockLineDVI()...begin\n")); 1284 1285 if ((pHWDE->jChipType != XG21)&&(pHWDE->jChipType != XG27)) 1286 { 1287 ErrorF("bReadClockLineDVI()...0\n"); 1288 } 1289 else 1290 { 1291 PDEBUGI2C(ErrorF("bReadClockLineDVI()...1\n")); 1292 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1293 1294 /* Enable GPIOA READ */ 1295 1296 EnableGPIOA(pjI2cIOBase, I2C_READ); 1297 1298 cPortData = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1299 PDEBUGI2C(ErrorF("*1 - cPortData = %d...\n", cPortData)); 1300 1301 cPortData = GETBITS(cPortData, 7:7); 1302 PDEBUGI2C(ErrorF("*2 - cPortData = %d...\n", cPortData)); 1303 } 1304 1305 PDEBUGI2C(ErrorF("bReadClockLineDVI()...return(cPortData=%d)\n", cPortData)); 1306 return cPortData; 1307} 1308 1309/************************************************************************* 1310// BOOLEAN bReadDataLineDVI() 1311// IOReg xx14, index 0F is defined as follows: 1312// 1313// ... 1 0 1314// --------|------|-------| 1315// ...| Data | Clock | 1316// ------------------------ 1317*************************************************************************/ 1318BOOLEAN bReadDataLineDVI(PXGI_HW_DEVICE_INFO pHWDE) 1319{ 1320 UCHAR cPortData; 1321 PUCHAR pjI2cIOBase; 1322 1323 PDEBUGI2C(ErrorF("bReadDataLineDVI()...begin\n")); 1324 1325 if ((pHWDE->jChipType != XG21)&&(pHWDE->jChipType != XG27)) 1326 { 1327 ErrorF("bReadDataLineDVI()...0\n"); 1328 } 1329 else 1330 { 1331 PDEBUGI2C(ErrorF("bReadDataLineDVI()...1\n")); 1332 pjI2cIOBase = pHWDE->pjIOAddress + CRTC_ADDRESS_PORT_COLOR; 1333 1334 1335 /* Enable GPIOB Write */ 1336 1337 EnableGPIOB(pjI2cIOBase, I2C_READ); 1338 1339 cPortData = XGI_GetReg(pjI2cIOBase, IND_CR48_GPIO_REG_I); 1340 PDEBUGI2C(ErrorF("*1 - cPortData = %d...\n", cPortData)); 1341 cPortData = GETBITS(cPortData, 6:6); 1342 PDEBUGI2C(ErrorF("*2 - cPortData = %d...\n", cPortData)); 1343 } 1344 1345 1346 PDEBUGI2C(ErrorF("bReadDataLineDVI()...return(cPortData=%d)\n", cPortData)); 1347 return cPortData; 1348} 1349 1350//*************************************************************************// 1351// VOID vWaitForCRT1VsyncActive() 1352// IoReg 3DA 1353// ... 3 ... 1354// --------|--------------|-------| 1355// ...| Vertical Sync| | 1356// -------------------------------- 1357//*************************************************************************// 1358VOID vWaitForCRT1HsyncActive(PXGI_HW_DEVICE_INFO pHWDE) 1359{ 1360 PUCHAR pjPort = pHWDE->pjIOAddress + INPUT_STATUS_1_COLOR; 1361 ULONG i; 1362 1363 for (i = 0; i < 0x00FFFF; i++) 1364 { 1365 if ( (XGI_GetRegByte(pjPort) & 0x01) == 0) 1366 { 1367 // Inactive 1368 break; 1369 } //if 1370 } //for-loop 1371 1372 for (i = 0; i < 0x00FFFF; i++) 1373 { 1374 if ( (XGI_GetRegByte(pjPort) & 0x01) != 0) 1375 { 1376 // active 1377 break; 1378 } //if 1379 } //for-loop 1380 1381} //vWaitForCRT1HsyncActive() 1382 1383//////////////////////////////////////////////////////////////////////////////////// 1384// 1385// For CRT I2C Interface 1386// 1387//////////////////////////////////////////////////////////////////////////////////// 1388 1389//*************************************************************************// 1390// VOID vWriteClockLineCRT() 1391// IOReg SR11 is defined as follows: 1392// 1393// ... 1 0 1394// --------|------|-------| 1395// ...| Data | Clock | 1396// ------------------------ 1397//*************************************************************************// 1398VOID vWriteClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1399{ 1400 UCHAR temp, ujSR1F; 1401 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1402 1403 PDEBUGI2C(ErrorF("I2C:Write CRT clock = %x\n", data & 1)); 1404 1405 ujSR1F = XGI_GetReg(pjI2cIOBase, IND_SR1F_POWER_MANAGEMENT); 1406 1407 pHWDE->ucI2cCRT = (pHWDE->ucI2cCRT & MASK(1:1)) | SETBITS(data, 0:0); 1408 1409 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1410 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cCRT; 1411 1412 //wait for CRT1 retrace only when CRT1 is enabled! 1413 /* if (pHWDE->bMonitorPoweredOn) */ /* jong@08042009; ignore here */ 1414 { 1415 if(!(data & 1) && ((ujSR1F & 0xC0)==0) ) 1416 { 1417 vWaitForCRT1HsyncActive(pHWDE); 1418 } 1419 } 1420 1421 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1422} 1423 1424//*************************************************************************// 1425// VOID vWriteDataLineCRT() 1426// IOReg SR11 is defined as follows: 1427// 1428// ... 1 0 1429// --------|------|-------| 1430// ...| Data | Clock | 1431// ------------------------ 1432//*************************************************************************// 1433VOID vWriteDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1434{ 1435 UCHAR temp, ujSR1F; 1436 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1437 1438 PDEBUGI2C(ErrorF("I2C:Write CRT data = %x\n", data & 1)); 1439 1440 ujSR1F = XGI_GetReg(pHWDE->pjIOAddress + SEQ_ADDRESS_PORT, IND_SR1F_POWER_MANAGEMENT); 1441 1442 pHWDE->ucI2cCRT = (pHWDE->ucI2cCRT & MASK(0:0)) | SETBITS(data, 1:1); 1443 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1444 temp = (temp & (~MASK(1:0))) | pHWDE->ucI2cCRT; 1445 1446 //wait for CRT1 retrace only when CRT1 is enabled! 1447 /* if (pHWDE->bMonitorPoweredOn) */ /* Jong@08042009; ignore checking */ 1448 { 1449 if(!(data & 1) && ((ujSR1F & 0xC0)==0) ) 1450 { 1451 vWaitForCRT1HsyncActive(pHWDE); 1452 } 1453 } 1454 1455 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1456} 1457 1458//*************************************************************************// 1459// BOOLEAN bReadClockLineCRT() 1460// IOReg SR11 is defined as follows: 1461// 1462// ... 1 0 1463// --------|------|-------| 1464// ...| Data | Clock | 1465// ------------------------ 1466//*************************************************************************// 1467BOOLEAN bReadClockLineCRT(PXGI_HW_DEVICE_INFO pHWDE) 1468{ 1469 UCHAR cPortData; 1470 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1471 1472 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1473 cPortData = GETBITS(cPortData, 0:0); 1474 1475 PDEBUGI2C(ErrorF("I2C:Read Channel CRT clock = %x\n", cPortData)); 1476 1477 return cPortData; 1478} 1479 1480//*************************************************************************// 1481// BOOLEAN bReadDataLineCRT() 1482// IOReg SR11 is defined as follows: 1483// 1484// ... 1 0 1485// --------|------|-------| 1486// ...| Data | Clock | 1487// ------------------------ 1488//*************************************************************************// 1489BOOLEAN bReadDataLineCRT(PXGI_HW_DEVICE_INFO pHWDE) 1490{ 1491 UCHAR cPortData; 1492 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1493 1494 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1495 cPortData = GETBITS(cPortData, 1:1); 1496 1497 PDEBUGI2C(ErrorF("I2C:Read Channel CRT data = %x\n", cPortData)); 1498 1499 return cPortData; 1500} 1501 1502//////////////////////////////////////////////////////////////////////////////////// 1503// 1504// For Feature Connector I2C Interface 1505// 1506//////////////////////////////////////////////////////////////////////////////////// 1507 1508//*************************************************************************// 1509// VOID vWriteClockLineFCNT() 1510// IOReg SR11 is defined as follows: 1511// 1512// ... 3 2 ... 1513// --------|------|-------|-------| 1514// ...| Data | Clock | | 1515// -------------------------------- 1516//*************************************************************************// 1517VOID vWriteClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1518{ 1519 UCHAR temp; 1520 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1521 1522 PDEBUGI2C(ErrorF("I2C:Write FCNT clock = %x\n", data & 1)); 1523 1524 pHWDE->ucI2cFCNT = (pHWDE->ucI2cFCNT & MASK(3:3)) | SETBITS(data, 2:2); 1525 1526 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1527 temp = (temp & (~MASK(3:2))) | pHWDE->ucI2cFCNT; 1528 1529 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1530} 1531 1532//*************************************************************************// 1533// VOID vWriteDataLineFCNT() 1534// IOReg SR11 is defined as follows: 1535// 1536// ... 3 2 ... 1537// --------|------|-------|-------| 1538// ...| Data | Clock | | 1539// -------------------------------- 1540//*************************************************************************// 1541VOID vWriteDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1542{ 1543 UCHAR temp, temp2, temp3; 1544 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1545 1546 PDEBUGI2C(ErrorF("I2C:Write FCNT data = %x\n", data & 1)); 1547 1548 pHWDE->ucI2cFCNT = (pHWDE->ucI2cFCNT & MASK(2:2)) | SETBITS(data, 3:3); 1549 1550 temp = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1551 temp = (temp & (~MASK(3:2))) | pHWDE->ucI2cFCNT; 1552 1553 XGI_SetReg(pjI2cIOBase, IND_SR11_DDC_REG, temp); 1554} 1555 1556//*************************************************************************// 1557// BOOLEAN bReadClockLineFCNT() 1558// IOReg SR11 is defined as follows: 1559// 1560// ... 3 2 ... 1561// --------|------|-------|-------| 1562// ...| Data | Clock | | 1563// -------------------------------- 1564//*************************************************************************// 1565BOOLEAN bReadClockLineFCNT(PXGI_HW_DEVICE_INFO pHWDE) 1566{ 1567 UCHAR cPortData; 1568 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1569 1570 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1571 cPortData = GETBITS(cPortData, 2:2); 1572 1573 PDEBUGI2C(ErrorF("I2C:Read Channel FCNT clock = %x\n", cPortData)); 1574 1575 return cPortData; 1576} 1577 1578//*************************************************************************// 1579// BOOLEAN bReadDataLineFCNT() 1580// IOReg SR11 is defined as follows: 1581// 1582// ... 3 2 ... 1583// --------|------|-------|-------| 1584// ...| Data | Clock | | 1585// -------------------------------- 1586//*************************************************************************// 1587BOOLEAN bReadDataLineFCNT(PXGI_HW_DEVICE_INFO pHWDE) 1588{ 1589 UCHAR cPortData; 1590 PUCHAR pjI2cIOBase = pHWDE->pjIOAddress + SEQ_ADDRESS_PORT; 1591 1592 cPortData = XGI_GetReg(pjI2cIOBase, IND_SR11_DDC_REG); 1593 cPortData = GETBITS(cPortData, 3:3); 1594 1595 PDEBUGI2C(ErrorF("I2C:Read Channel FCNT data = %x\n", cPortData)); 1596 1597 return cPortData; 1598} 1599 1600/*=======================================================*/ 1601VOID vWriteClockLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1602{ 1603 if(pHWDE->crtno == 0) 1604 vWriteClockLineCRT(pHWDE, data); 1605 else if(pHWDE->crtno == 1) 1606 vWriteClockLineDVI(pHWDE, data); 1607 else if(pHWDE->crtno == 2) 1608 vWriteClockLineFCNT(pHWDE, data); 1609 else 1610 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1611} 1612 1613VOID vWriteDataLine(PXGI_HW_DEVICE_INFO pHWDE, UCHAR data) 1614{ 1615 if(pHWDE->crtno == 0) 1616 vWriteDataLineCRT(pHWDE, data); 1617 else if(pHWDE->crtno == 1) 1618 vWriteDataLineDVI(pHWDE, data); 1619 else if(pHWDE->crtno == 2) 1620 vWriteDataLineFCNT(pHWDE, data); 1621 else 1622 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1623} 1624 1625BOOLEAN bReadClockLine(PXGI_HW_DEVICE_INFO pHWDE) 1626{ 1627 if(pHWDE->crtno == 0) 1628 return(bReadClockLineCRT(pHWDE)); 1629 else if(pHWDE->crtno == 1) 1630 return(bReadClockLineDVI(pHWDE)); 1631 else if(pHWDE->crtno == 2) 1632 return(bReadClockLineFCNT(pHWDE)); 1633 else 1634 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1635} 1636 1637BOOLEAN bReadDataLine(PXGI_HW_DEVICE_INFO pHWDE) 1638{ 1639 if(pHWDE->crtno == 0) 1640 return(bReadDataLineCRT(pHWDE)); 1641 else if(pHWDE->crtno == 1) 1642 return(bReadDataLineDVI(pHWDE)); 1643 else if(pHWDE->crtno == 2) 1644 return(bReadDataLineFCNT(pHWDE)); 1645 else 1646 ErrorF("Error(XGI) : Unkonwn output device! \n"); 1647} 1648 1649BOOLEAN bEDIDCheckSum(PUCHAR pjEDIDBuf,ULONG ulBufSize) 1650{ 1651 ULONG i; 1652 UCHAR ujSum = 0; 1653 PUCHAR pujPtr; 1654 1655 pujPtr = pjEDIDBuf; 1656 1657 for (i = 0; i < ulBufSize; i++) 1658 { 1659 /* printk("pujPtr=%x, ",*pujPtr); */ 1660 ujSum += *(pujPtr++); 1661 } /*for-loop */ 1662 1663 return(ujSum); 1664 1665} 1666 1667/* Jong 08/03/2009; Get EDID functions; ported from MS Windows */ 1668//*************************************************************************\\ 1669// VP_STATUS vGetEDID_1 1670// 1671// Routine Description: 1672// Get the EDID which is in version 1.x format via I2C. 1673// 1674// Arguments: 1675// pHWDE - Hardware extension object pointer 1676// pI2C - I2C pointer 1677// pjBuffer - EDID Buffer 1678// ulBufferSize - Buffer size 1679// 1680// 1681// Return Value: 1682// Status of returning EDID. 1683// NO_ERROR - success 1684// ERROR_INVALID_PARAMETER - failed 1685// 1686//**************************************************************************** 1687VP_STATUS vGetEDID_1( 1688 PXGI_HW_DEVICE_INFO pHWDE, 1689 PI2CControl pI2C, 1690 PUCHAR pjBuffer, 1691 ULONG ulBufferSize) 1692{ 1693 VP_STATUS status; 1694 1695 PDEBUGI2C(ErrorF("vGetEDID_1()\n")); 1696 1697 if ((ulBufferSize < 128) || (pjBuffer == NULL)) { 1698 return ERROR_INVALID_PARAMETER; 1699 } 1700 1701 // Set Segment Block ID as 0 if Monitor support Enhanced-EDID 1702 /* 1703 pI2C->Command = I2C_COMMAND_WRITE_SEGMENT; // to replace I2C_COMMAND_WRITE 1704 pI2C->Data = 0; 1705 I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, &(pI2C->Data), 0); 1706 */ 1707 pI2C->Command = I2C_COMMAND_WRITE; 1708 pI2C->Data = 0; 1709 I2CAccessBuffer(pHWDE, pI2C, 0x60, 0, &(pI2C->Data), 0); 1710 1711 pI2C->Command = I2C_COMMAND_READ; 1712 status = I2CAccessBuffer(pHWDE, pI2C, 0xA0, 0, pjBuffer, 128); 1713 if ((status == NO_ERROR) && (pI2C->Status == I2C_STATUS_NOERROR)) 1714 { 1715 // Check Block 0 EDID Header and its checksum 1716 if ((*((PULONG)(pjBuffer )) != 0xFFFFFF00) || 1717 (*((PULONG)(pjBuffer+4)) != 0x00FFFFFF)) 1718 { 1719 PDEBUGI2C(ErrorF("vGetEDID_1(): EDID Header Incorrect!!\n")); 1720 return ERROR_INVALID_PARAMETER; 1721 } 1722 1723 if (bEDIDCheckSum(pjBuffer, 128) != 0) 1724 { 1725 if ((*((PULONG)(pjBuffer+0x60)) ==0x4d636e79)&& (*((PULONG)(pjBuffer+0x64)) ==0x65747361)) 1726 { 1727 return NO_ERROR; //To Fix SyncMaster Checksum error issue 1728 } 1729 1730 PDEBUGI2C(ErrorF("vGetEDID_1(): EDID Checksum Error!!\n")); 1731 return ERROR_INVALID_PARAMETER; 1732 } 1733 1734 } 1735 else 1736 { 1737 PDEBUGI2C(ErrorF("vGetEDID_1 : call I2CAccessBuffer(0xA0) fail !!!\n")); 1738 return status; 1739 } 1740 1741 return NO_ERROR; 1742} 1743 1744//*************************************************************************\\ 1745// VP_STATUS vGetEDID_2 1746// 1747// Routine Description: 1748// Get the EDID which is in version 2.0 format via I2C. 1749// 1750// Arguments: 1751// pHWDE - Hardware extension object pointer 1752// pI2C - I2C pointer 1753// pjBuffer - EDID Buffer 1754// ulBufferSize - Buffer size 1755// 1756// 1757// Return Value: 1758// Status of returning EDID. 1759// NO_ERROR - success 1760// ERROR_INVALID_PARAMETER - failed 1761// 1762//**************************************************************************** 1763VP_STATUS vGetEDID_2( 1764 PXGI_HW_DEVICE_INFO pHWDE, 1765 PI2CControl pI2C, 1766 PUCHAR pjBuffer, 1767 ULONG ulBufferSize) 1768{ 1769 VP_STATUS status; 1770 1771 PDEBUGI2C(ErrorF("vGetEDID_2()\n")); 1772 1773 if ((ulBufferSize < 256) || (pjBuffer == NULL)) { 1774 return ERROR_INVALID_PARAMETER; 1775 } 1776 1777 pI2C->Command = I2C_COMMAND_READ; 1778 status = I2CAccessBuffer(pHWDE, pI2C, 0xA2, 0, pjBuffer, 256); 1779 if ((status != NO_ERROR) || (pI2C->Status != I2C_STATUS_NOERROR)) { 1780 PDEBUGI2C(ErrorF("vGetEDID_2 : call I2CAccessBuffer(0xA2) fail !!!\n")); 1781 usleep(5); 1782 status = I2CAccessBuffer(pHWDE, pI2C, 0xA6, 0, pjBuffer, 256); 1783 if ((status != NO_ERROR) || (pI2C->Status != I2C_STATUS_NOERROR)) { 1784 PDEBUGI2C(ErrorF("vGetEDID_2 : call I2CAccessBuffer(0xA6) fail !!!\n")); 1785 return ERROR_INVALID_PARAMETER; 1786 } 1787 } 1788 1789 if (*pjBuffer != 0x20) 1790 { 1791 return ERROR_INVALID_PARAMETER; 1792 } 1793 1794 if (bEDIDCheckSum(pjBuffer, 256) != 0) 1795 { 1796 return ERROR_INVALID_PARAMETER; 1797 } 1798 1799 return NO_ERROR; 1800} 1801 1802//*************************************************************************\\ 1803// BOOLEAN bGetEDID 1804// 1805// Routine Description: 1806// For driver to get the monitor EDID through I2C. This function works similar 1807// with VideoPortDDCMonitorHelper() does. 1808// 1809// 1810// Arguments: 1811// pHWDE - Hardware extension object pointer 1812// ulChannelID - Channel ID 1813// pjEDIDBuffer - EDID Buffer 1814// ulBufferSize - Buffer size 1815// 1816// 1817// Return Value: 1818// Status of returning EDID. 1819// TRUE - success 1820// FALSE - failed 1821// 1822//**************************************************************************** 1823BOOLEAN bGetEDID( 1824 PXGI_HW_DEVICE_INFO pHWDE, 1825 ULONG ulChannelID, 1826 PUCHAR pjEDIDBuffer, 1827 ULONG ulBufferSize) 1828{ 1829 I2CControl I2C; 1830 VP_STATUS status; 1831 1832 PDEBUGI2C(ErrorF("bGetEDID() is called.\n")); 1833 1834 if ((ulBufferSize != 0) && (pjEDIDBuffer != NULL)) 1835 { 1836 memset(pjEDIDBuffer, 0, ulBufferSize); 1837 } 1838 else 1839 { 1840 PDEBUGI2C(ErrorF("bGetEDID()-(ulBufferSize == 0) || (pjEDIDBuffer == NULL)\n")); 1841 return FALSE; 1842 } 1843 1844 if (I2COpen(pHWDE, I2C_OPEN, ulChannelID, &I2C) != NO_ERROR) 1845 { 1846 PDEBUGI2C(ErrorF("bGetEDID()-I2COpen()-fail!\n")); 1847 return FALSE; 1848 } 1849 1850 // Force Monitor using DDC2 protocal... 1851 I2C.ClockRate = I2C_MAX_CLOCK_RATE; 1852 I2C.Command = I2C_COMMAND_WRITE; 1853 I2C.Flags = I2C_FLAGS_STOP; 1854 I2C.Data = 0xFF; 1855 I2CAccess(pHWDE, &I2C); 1856 1857 // Reset I2C bus 1858 I2C.Command = I2C_COMMAND_RESET; 1859 I2CAccess(pHWDE, &I2C); 1860 if (I2C.Status != I2C_STATUS_NOERROR) 1861 { 1862 PDEBUGI2C(ErrorF("bGetEDID() fail: Reset I2C bus fail.\n")); 1863 return FALSE; 1864 } 1865 1866 status = vGetEDID_2(pHWDE, &I2C, pjEDIDBuffer, ulBufferSize); 1867 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDID_2-status=%d\n", status == NO_ERROR ? 1:0)); 1868 1869 if (status != NO_ERROR) 1870 { 1871 usleep(5); 1872 status = vGetEDID_1(pHWDE, &I2C, pjEDIDBuffer, ulBufferSize); 1873 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDID_1-status=%d\n", status == NO_ERROR ? 1:0)); 1874 1875 if (status == NO_ERROR) 1876 { 1877 if (*(pjEDIDBuffer+0x7E) != 0) 1878 { 1879 vGetEDIDExtensionBlocks(pHWDE, &I2C, pjEDIDBuffer+128, ulBufferSize-128); 1880 PDEBUGI2C(ErrorF("bGetEDID()-vGetEDIDExtensionBlocks()\n")); 1881 } 1882 } 1883 else 1884 { 1885 ErrorF( "bGetEDID() fail !!\n"); 1886 } 1887 } 1888 1889 I2COpen(pHWDE, I2C_CLOSE, ulChannelID, &I2C); 1890 1891 PDEBUGI2C(ErrorF("bGetEDID()-return(%d)\n", status == NO_ERROR ? 1:0)); 1892 return (status == NO_ERROR); 1893}