Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1357 lines
42 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  9. //
  10. // I2CSCRPT.C
  11. // I2CScript class implementation.
  12. // Main Include Module.
  13. //
  14. //==========================================================================;
  15. extern "C"
  16. {
  17. #include <wdm.h>
  18. }
  19. #include <unknown.h>
  20. #include "ks.h"
  21. #include "ksmedia.h"
  22. #include <ksdebug.h>
  23. #include "i2script.h"
  24. #include "wdmdebug.h"
  25. //$REVIEW - Let's find a way to get the proper module name into this
  26. //
  27. #define MODULENAME "PhilTune"
  28. #define MODULENAMEUNICODE L"PhilTune"
  29. #define STR_MODULENAME MODULENAME
  30. #define ENSURE do
  31. #define END_ENSURE while( FALSE)
  32. #define FAIL break
  33. /*^^*
  34. * CI2CScript()
  35. * Purpose : CI2CScript class constructor.
  36. * Performs checking of the I2C provider presence. Sets the script in the initial state.
  37. *
  38. * Inputs : PUINT puiError : pointer to return a completion error code
  39. * PHW_STREAM_REQUEST_BLOCK pSrb : pointer to HW_INITIALIZE SRB
  40. *
  41. * Outputs : none
  42. * Author : IKLEBANOV
  43. *^^*/
  44. CI2CScript::
  45. CI2CScript(
  46. PDEVICE_OBJECT pDeviceObject,
  47. NTSTATUS * pStatus
  48. )
  49. {
  50. *pStatus = STATUS_SUCCESS;
  51. m_dwI2CAccessKey = 0;
  52. m_liOperationStartTime.QuadPart = 0;
  53. m_i2cProviderInterface.i2cOpen = NULL;
  54. m_i2cProviderInterface.i2cAccess = NULL;
  55. m_pdoDriver = NULL;
  56. if( !InitializeAttachI2CProvider( &m_i2cProviderInterface, pDeviceObject))
  57. {
  58. *pStatus = STATUS_NOINTERFACE;
  59. }
  60. else
  61. {
  62. // there was no error to get I2CInterface from the MiniVDD
  63. m_pdoDriver = pDeviceObject;
  64. m_ulI2CAccessClockRate = I2C_FIXED_CLOCK_RATE;
  65. }
  66. _DbgPrintF( DEBUGLVL_VERBOSE,
  67. ( "CI2CScript:CI2CScript() exit Error = %x\n", * pStatus)
  68. );
  69. }
  70. /*^^*
  71. * LockI2CProvider()
  72. * Purpose : locks the I2CProvider for exclusive use
  73. *
  74. * Inputs : none
  75. *
  76. * Outputs : BOOL : retunrs TRUE, if the I2CProvider is locked
  77. * Author : IKLEBANOV
  78. *^^*/
  79. BOOL CI2CScript::LockI2CProvider( void)
  80. {
  81. BOOL bResult;
  82. I2CControl i2cAccessBlock;
  83. bResult = FALSE;
  84. ENSURE
  85. {
  86. if(( m_i2cProviderInterface.i2cOpen == NULL) ||
  87. ( m_i2cProviderInterface.i2cAccess == NULL) ||
  88. ( m_pdoDriver == NULL))
  89. FAIL;
  90. i2cAccessBlock.Status = I2C_STATUS_NOERROR;
  91. if( m_i2cProviderInterface.i2cOpen( m_pdoDriver, TRUE, &i2cAccessBlock) != STATUS_SUCCESS)
  92. {
  93. _DbgPrintF( DEBUGLVL_ERROR,
  94. ( "CI2CScript: LockI2CProvider() bResult = %x\n",
  95. bResult)
  96. );
  97. FAIL;
  98. }
  99. if( i2cAccessBlock.Status != I2C_STATUS_NOERROR)
  100. {
  101. _DbgPrintF( DEBUGLVL_ERROR,
  102. ( "CI2CScript: LockI2CProvider() Status = %x\n",
  103. i2cAccessBlock.Status)
  104. );
  105. FAIL;
  106. }
  107. // the I2C Provider has granted access - save dwCookie for further use
  108. m_dwI2CAccessKey = i2cAccessBlock.dwCookie;
  109. bResult = TRUE;
  110. } END_ENSURE;
  111. return( bResult);
  112. }
  113. /*^^*
  114. * LockI2CProvider()
  115. * Purpose : locks the I2CProvider for exclusive use. Provides attempts to lock the
  116. * provider unless either the time-out condition or the attempt succeeded.
  117. *
  118. * Inputs : none
  119. *
  120. * Outputs : BOOL : retunrs TRUE, if the I2CProvider is locked
  121. * Author : IKLEBANOV
  122. *^^*/
  123. BOOL CI2CScript::LockI2CProviderEx( void)
  124. {
  125. LARGE_INTEGER liTime;
  126. m_liOperationStartTime.QuadPart = 0;
  127. while( !LockI2CProvider())
  128. {
  129. KeQuerySystemTime( &liTime);
  130. if( m_liOperationStartTime.QuadPart)
  131. m_liOperationStartTime.QuadPart = liTime.QuadPart;
  132. else
  133. if( liTime.QuadPart - m_liOperationStartTime.QuadPart >
  134. I2CSCRIPT_TIMELIMIT_OPENPROVIDER)
  135. {
  136. // the time is expired - abort the initialization
  137. return( FALSE);
  138. }
  139. liTime.QuadPart = I2CSCRIPT_DELAY_OPENPROVIDER;
  140. KeDelayExecutionThread( KernelMode, FALSE, &liTime);
  141. }
  142. return( TRUE);
  143. }
  144. /*^^*
  145. * GetI2CProviderLockStatus()
  146. * Purpose : retrieves I2CProvider lock status
  147. *
  148. * Inputs : none
  149. *
  150. * Outputs : BOOL : retunrs TRUE, if the I2CProvider has been locked
  151. * Author : IKLEBANOV
  152. *^^*/
  153. BOOL CI2CScript::GetI2CProviderLockStatus( void)
  154. {
  155. return( m_dwI2CAccessKey);
  156. }
  157. /*^^*
  158. * ReleaseI2CProvider()
  159. * Purpose : releases the I2CProvider for other clients' use
  160. *
  161. * Inputs : none
  162. *
  163. * Outputs : BOOL : retunrs TRUE, if the I2CProvider is released
  164. * Author : IKLEBANOV
  165. *^^*/
  166. BOOL CI2CScript::ReleaseI2CProvider( void)
  167. {
  168. BOOL bResult;
  169. I2CControl i2cAccessBlock;
  170. bResult = FALSE;
  171. ENSURE
  172. {
  173. if(( m_i2cProviderInterface.i2cOpen == NULL) ||
  174. ( m_i2cProviderInterface.i2cAccess == NULL) ||
  175. ( m_pdoDriver == NULL))
  176. // the I2CProvider was not found
  177. FAIL;
  178. i2cAccessBlock.Status = I2C_STATUS_NOERROR;
  179. i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
  180. i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;
  181. if( m_i2cProviderInterface.i2cOpen( m_pdoDriver, FALSE, &i2cAccessBlock) != STATUS_SUCCESS)
  182. {
  183. _DbgPrintF( DEBUGLVL_ERROR,
  184. ( "CI2CScript: ReleaseI2CProvider() bResult = %x\n",
  185. bResult)
  186. );
  187. FAIL;
  188. }
  189. if( i2cAccessBlock.Status != I2C_STATUS_NOERROR)
  190. {
  191. _DbgPrintF( DEBUGLVL_ERROR,
  192. ( "CI2CScript: ReleaseI2CProvider() bResult = %x\n",
  193. bResult)
  194. );
  195. FAIL;
  196. }
  197. m_dwI2CAccessKey = 0;
  198. bResult = TRUE;
  199. } END_ENSURE;
  200. return( bResult);
  201. }
  202. /*^^*
  203. * PerformI2CPacketOperation()
  204. * Purpose : synchronosly executes I2C access packet. It assumed to be executed at Low priority.
  205. * The function does not return until the I2C session is done. The execution
  206. * is not dependent on the I2C Provider lock status
  207. *
  208. * Inputs : PI2CPacket pI2CPacket : pointer to I2C access packet
  209. *
  210. * Outputs : BOOL : returns TRUE, if I2C operation was carried out successfuly
  211. * The error status is returned via uchI2CResult field of the PI2CPacket
  212. * Author : IKLEBANOV
  213. *^^*/
  214. BOOL CI2CScript::PerformI2CPacketOperation( IN OUT PI2CPacket pI2CPacket)
  215. {
  216. BOOL bResult;
  217. if( GetI2CProviderLockStatus())
  218. // the Provider was locked before and we're not going to change it
  219. bResult = ExecuteI2CPacket( pI2CPacket);
  220. else
  221. {
  222. // the Provider was not locked and it's our responsibility to lock it first,
  223. // execute I2C operation and release it after the use
  224. if( LockI2CProviderEx())
  225. {
  226. bResult = ExecuteI2CPacket( pI2CPacket);
  227. ReleaseI2CProvider();
  228. }
  229. else
  230. bResult = FALSE;
  231. }
  232. return( bResult);
  233. }
  234. /*^^*
  235. * ExecuteI2CPacket()
  236. * Purpose : synchronosly executes I2C access packet. It assumed to be executed at Low priority.
  237. * The function does not return until the I2C session is done. This kind of access
  238. * is used during initialization ( boot up) time only. This function should be
  239. * called only after the I2CProvider was locked for exclusive service
  240. *
  241. * Inputs : PI2CPacket pI2CPacket : pointer to I2C access packet
  242. *
  243. * Outputs : BOOL : returns TRUE, if I2C operation was carried out successfuly
  244. * The error status is returned via uchI2CResult field of the PI2CPacket
  245. * Author : IKLEBANOV
  246. *^^*/
  247. BOOL CI2CScript::ExecuteI2CPacket( IN OUT PI2CPacket pI2CPacket)
  248. {
  249. UINT nError, cbCount;
  250. UCHAR uchValue;
  251. UCHAR uchI2CResult = I2C_STATUS_ERROR;
  252. ENSURE
  253. {
  254. I2CControl i2cAccessBlock;
  255. if(( nError = CheckI2CScriptPacket( pI2CPacket)) != I2CSCRIPT_NOERROR)
  256. FAIL;
  257. // we'll use I2CProvider interface, assuming there is a syncronous provider
  258. // for asynchronous provider some work has to be added. 16 bits emulation is
  259. // not supported at this time either. This implementation does not support
  260. // Read-Modify-Write request either
  261. ENSURE
  262. {
  263. UINT nIndex;
  264. i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
  265. i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;
  266. // We assume the last byte in the buffer belongs to the Write operation
  267. // after Read-Modify, is specified.
  268. cbCount = ( pI2CPacket->usFlags & I2COPERATION_READWRITE) ?
  269. ( pI2CPacket->cbWriteCount - 1) : ( pI2CPacket->cbWriteCount);
  270. if( cbCount)
  271. {
  272. // implement a write request
  273. // apply START condition with the I2C chip address first
  274. i2cAccessBlock.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  275. i2cAccessBlock.Command = I2C_COMMAND_WRITE;
  276. i2cAccessBlock.Data = pI2CPacket->uchChipAddress & 0xFE;
  277. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  278. FAIL;
  279. i2cAccessBlock.Flags = I2C_FLAGS_ACK;
  280. for( nIndex = 0; nIndex < cbCount; nIndex ++)
  281. {
  282. // write the data from the buffer
  283. i2cAccessBlock.Data = pI2CPacket->puchWriteBuffer[nIndex];
  284. if(( nIndex == cbCount - 1) &&
  285. !( pI2CPacket->usFlags & I2COPERATION_RANDOMACCESS))
  286. // the last byte to write - apply STOP condition, if no
  287. // I2COPERATION_RANDOMACCESS flag is specified
  288. i2cAccessBlock.Flags |= I2C_FLAGS_STOP;
  289. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  290. break;
  291. }
  292. if( nIndex != cbCount)
  293. FAIL;
  294. /* // STOP condition is applied withe the last byte to be written
  295. // apply stop condition as the end of write operation
  296. i2cAccessBlock.Flags = I2C_FLAGS_STOP;
  297. i2cAccessBlock.Command = I2C_COMMAND_NULL;
  298. m_i2cProviderInterface.i2cAccess( m_pdoDriver, &i2cAccessBlock);
  299. */
  300. }
  301. if( pI2CPacket->cbReadCount)
  302. {
  303. // implement a read request
  304. // apply START condition with the I2C chip address first
  305. i2cAccessBlock.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  306. i2cAccessBlock.Command = I2C_COMMAND_WRITE;
  307. i2cAccessBlock.Data = pI2CPacket->uchChipAddress | 0x01;
  308. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  309. FAIL;
  310. i2cAccessBlock.Flags = I2C_FLAGS_ACK;
  311. i2cAccessBlock.Command = I2C_COMMAND_READ;
  312. for( nIndex = 0; nIndex < pI2CPacket->cbReadCount; nIndex ++)
  313. {
  314. // read the data to the buffer
  315. if( nIndex == ( UINT)( pI2CPacket->cbReadCount - 1))
  316. {
  317. // don't apply ACK at the last read - read operation termination
  318. i2cAccessBlock.Flags &= ~I2C_FLAGS_ACK;
  319. // also apply STOP condition for the last byte
  320. i2cAccessBlock.Flags |= I2C_FLAGS_STOP;
  321. }
  322. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  323. break;
  324. pI2CPacket->puchReadBuffer[nIndex] = i2cAccessBlock.Data;
  325. }
  326. if( nIndex != pI2CPacket->cbReadCount)
  327. FAIL;
  328. /* // STOP condition is applied with the last byte to be read
  329. // apply stop condition as the end of read operation
  330. i2cAccessBlock.Flags = I2C_FLAGS_STOP;
  331. i2cAccessBlock.Command = I2C_COMMAND_NULL;
  332. m_i2cProviderInterface.i2cAccess( m_pdoDriver, &i2cAccessBlock);
  333. */
  334. if( pI2CPacket->usFlags & I2COPERATION_READWRITE)
  335. {
  336. // write operation should be taken care again, the last byte in the pbyWriteBuffer
  337. // should be constructed from the value read back and the binary operations OR and AND
  338. // with the values specified in the packet
  339. uchValue = pI2CPacket->puchReadBuffer[pI2CPacket->cbReadCount - 1];
  340. uchValue &= pI2CPacket->uchANDValue;
  341. pI2CPacket->puchWriteBuffer[pI2CPacket->cbWriteCount - 1] = uchValue | pI2CPacket->uchORValue;
  342. if( pI2CPacket->cbWriteCount)
  343. {
  344. // implement a write request
  345. // apply START condition with the I2C chip address first
  346. i2cAccessBlock.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  347. i2cAccessBlock.Command = I2C_COMMAND_WRITE;
  348. i2cAccessBlock.Data = pI2CPacket->uchChipAddress & 0xFE;
  349. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  350. FAIL;
  351. i2cAccessBlock.Flags = I2C_FLAGS_ACK;
  352. for( nIndex = 0; nIndex < pI2CPacket->cbWriteCount; nIndex ++)
  353. {
  354. // write the data from the buffer
  355. i2cAccessBlock.Data = pI2CPacket->puchWriteBuffer[nIndex];
  356. if( nIndex == ( UINT)( pI2CPacket->cbWriteCount - 1))
  357. // the last byte to write - apply STOP condition
  358. i2cAccessBlock.Flags |= I2C_FLAGS_STOP;
  359. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
  360. break;
  361. }
  362. if( nIndex != pI2CPacket->cbWriteCount)
  363. FAIL;
  364. /* // STOP condition is applied withe the last byte to be written
  365. // apply stop condition as the end of write operation
  366. i2cAccessBlock.Flags = I2C_FLAGS_STOP;
  367. i2cAccessBlock.Command = I2C_COMMAND_NULL;
  368. m_i2cProviderInterface.i2cAccess( m_pdoDriver, &i2cAccessBlock);
  369. */
  370. }
  371. }
  372. }
  373. uchI2CResult = I2C_STATUS_NOERROR;
  374. } END_ENSURE;
  375. if( uchI2CResult == I2C_STATUS_ERROR)
  376. {
  377. // there was an error during accessing I2C - issue Reset command
  378. i2cAccessBlock.Command = I2C_COMMAND_RESET;
  379. AccessI2CProvider( m_pdoDriver, &i2cAccessBlock);
  380. }
  381. pI2CPacket->uchI2CResult = uchI2CResult;
  382. return( TRUE);
  383. } END_ENSURE;
  384. _DbgPrintF( DEBUGLVL_VERBOSE,
  385. ( "CI2CScript:ExecuteI2CPacket() nError = %x", nError)
  386. );
  387. return( FALSE);
  388. }
  389. /*^^*
  390. * CheckI2CScriptPacket()
  391. * Purpose : checks integrity of the I2C control package
  392. *
  393. * Inputs : PI2CPacket pI2CPacket : pointer to I2C access packet
  394. *
  395. * Outputs : BOOL : returns TRUE, if I2C control package is a valid one
  396. *
  397. * Author : IKLEBANOV
  398. *^^*/
  399. UINT CI2CScript::CheckI2CScriptPacket( IN PI2CPacket pI2CPacket)
  400. {
  401. UINT nPacketError;
  402. ENSURE
  403. {
  404. if(( m_i2cProviderInterface.i2cOpen == NULL) ||
  405. ( m_i2cProviderInterface.i2cAccess == NULL) ||
  406. ( m_pdoDriver == NULL))
  407. {
  408. // the I2CProvider was not found
  409. nPacketError = I2CSCRIPT_ERROR_NOPROVIDER;
  410. FAIL;
  411. }
  412. if(( !pI2CPacket->cbWriteCount) && ( !pI2CPacket->cbReadCount))
  413. {
  414. // nothing to do
  415. nPacketError = I2CSCRIPT_ERROR_NODATA;
  416. FAIL;
  417. }
  418. if((( pI2CPacket->cbWriteCount) && ( pI2CPacket->puchWriteBuffer == NULL))
  419. || (( pI2CPacket->cbReadCount) && ( pI2CPacket->puchReadBuffer == NULL)))
  420. {
  421. // NULL pointer, when the data is specified
  422. nPacketError = I2CSCRIPT_ERROR_NOBUFFER;
  423. FAIL;
  424. }
  425. if(( pI2CPacket->usFlags & I2COPERATION_READWRITE) && ( !pI2CPacket->cbWriteCount))
  426. {
  427. // if Read-Modify-Write is specified, the Write data should be present
  428. nPacketError = I2CSCRIPT_ERROR_READWRITE;
  429. FAIL;
  430. }
  431. nPacketError = I2CSCRIPT_NOERROR;
  432. } END_ENSURE;
  433. return( nPacketError);
  434. }
  435. /*^^*
  436. * ClearScript()
  437. * Purpose : clears I2CScript to the NULL state - no I2C operations are on hold.
  438. *
  439. * Inputs : none
  440. *
  441. * Outputs : none
  442. * Author : IKLEBANOV
  443. *^^*/
  444. void CI2CScript::ClearScript( void)
  445. {
  446. m_nExecutionIndex = 0;
  447. m_nScriptLength = 0;
  448. m_pfnReturnWhenDone = NULL;
  449. m_bExecutionInProcess = FALSE;
  450. }
  451. /*^^*
  452. * AppendToScript()
  453. * Purpose : appends a I2CPacket to the bottom of the I2CScript.
  454. * The 16 bits emulation is not implemented at this time.
  455. *
  456. * Inputs : PI2CPacket pI2CPacket - pointer to the I2C packet to append
  457. *
  458. * Outputs : BOOL : returns TRUE, if the packet was successfully appended.
  459. * FALSE might happend if the I2CPacket is a bad one, or overflow occurs
  460. * Author : IKLEBANOV
  461. *^^*/
  462. BOOL CI2CScript::AppendToScript( PI2CPacket pI2CPacket)
  463. {
  464. UINT nError, nScriptIndex;
  465. UINT nIndex, cbCount;
  466. ENSURE
  467. {
  468. PI2CScriptPrimitive pI2CPrimitive;
  469. if(( nError = CheckI2CScriptPacket( pI2CPacket)) != I2CSCRIPT_NOERROR)
  470. FAIL;
  471. nError = I2CSCRIPT_ERROR_OVERFLOW;
  472. // m_nExecutionIndex is used as a Script build index. We will work with a local copy of it
  473. // first to ensure we have no overflow
  474. nScriptIndex = m_nExecutionIndex;
  475. pI2CPrimitive = &m_i2cScript[nScriptIndex];
  476. // We assume the last byte in the buffer belongs to the Write operation
  477. // after Read-Modify, is specified.
  478. cbCount = ( pI2CPacket->usFlags & I2COPERATION_READWRITE) ? \
  479. ( pI2CPacket->cbWriteCount - 1) : ( pI2CPacket->cbWriteCount);
  480. if( cbCount)
  481. {
  482. // I2C Chip address should be taken care of first
  483. pI2CPrimitive->ulCommand = I2C_COMMAND_WRITE;
  484. pI2CPrimitive->byData = pI2CPacket->uchChipAddress;
  485. pI2CPrimitive->byANDData = 0xFE;
  486. pI2CPrimitive->byORData = 0x00;
  487. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  488. pI2CPrimitive->byFlags = 0x0;
  489. // check the Script length
  490. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  491. FAIL;
  492. pI2CPrimitive ++;
  493. // I2C write buffer should be taken care of.
  494. for( nIndex = 0; nIndex < cbCount; nIndex ++)
  495. {
  496. pI2CPrimitive->ulCommand = I2C_COMMAND_WRITE;
  497. pI2CPrimitive->byData = pI2CPacket->puchWriteBuffer[nIndex];
  498. pI2CPrimitive->byORData = 0x00;
  499. pI2CPrimitive->byANDData = 0xFF;
  500. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_ACK;
  501. pI2CPrimitive->byFlags = 0x0;
  502. if( nIndex == cbCount - 1)
  503. // this is the last byte to be written - apply STOP
  504. pI2CPrimitive->ulProviderFlags |= I2C_FLAGS_STOP;
  505. // check the Script length
  506. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  507. break;
  508. pI2CPrimitive ++;
  509. }
  510. // check the Script length
  511. if( nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  512. FAIL;
  513. /*
  514. // Stop condition is applied with the last byte to be written
  515. // We finished Write portion here, whether it's a Write only, Read-Modify-Write operation
  516. pI2CPrimitive->ulCommand = I2C_COMMAND_NULL;
  517. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_STOP;
  518. pI2CPrimitive->byFlags = 0x0;
  519. // check the Script length
  520. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  521. FAIL;
  522. pI2CPrimitive ++;
  523. */
  524. }
  525. // We have to see, if there is a Read operation involved
  526. if( pI2CPacket->cbReadCount)
  527. {
  528. // I2C Chip address should be taken care of first
  529. pI2CPrimitive->ulCommand = I2C_COMMAND_WRITE;
  530. pI2CPrimitive->byData = pI2CPacket->uchChipAddress;
  531. pI2CPrimitive->byANDData = 0xFE;
  532. pI2CPrimitive->byORData = 0x01;
  533. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  534. pI2CPrimitive->byFlags = 0x0;
  535. // check the Script length
  536. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  537. FAIL;
  538. pI2CPrimitive ++;
  539. // I2C read buffer should be taken care of. We assume the last byte in the buffer belongs to
  540. // the Write operation after Read-Modify, is specified.
  541. for( nIndex = 0; nIndex < pI2CPacket->cbReadCount; nIndex ++)
  542. {
  543. pI2CPrimitive->ulCommand = I2C_COMMAND_READ;
  544. if( nIndex == ( UINT)( pI2CPacket->cbReadCount - 1))
  545. {
  546. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_STOP;
  547. pI2CPrimitive->byFlags = pI2CPacket->usFlags & I2COPERATION_READWRITE;
  548. }
  549. else
  550. {
  551. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_ACK;
  552. pI2CPrimitive->byFlags = 0x0;
  553. }
  554. // check the Script length
  555. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  556. break;
  557. pI2CPrimitive ++;
  558. }
  559. // check the Script length
  560. if( nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  561. FAIL;
  562. /* // Stop condition is applied with the last byte to be read
  563. // We finished Read portion here, whether it's a Read only, Read-Modify-Write operation
  564. pI2CPrimitive->ulCommand = I2C_COMMAND_NULL;
  565. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_STOP;
  566. pI2CPrimitive->byFlags = 0x0;
  567. // check the Script length
  568. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  569. FAIL;
  570. pI2CPrimitive ++;
  571. */
  572. }
  573. // the last thing left to do, is to implement Write after Read-Modify, if specified
  574. if( pI2CPacket->usFlags & I2COPERATION_READWRITE)
  575. {
  576. // I2C Chip address should be taken care of first
  577. pI2CPrimitive->ulCommand = I2C_COMMAND_WRITE;
  578. pI2CPrimitive->byData = pI2CPacket->uchChipAddress;
  579. pI2CPrimitive->byANDData = 0xFE;
  580. pI2CPrimitive->byORData = 0x00;
  581. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_START | I2C_FLAGS_ACK;
  582. pI2CPrimitive->byFlags = 0x0;
  583. // check the Script length
  584. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  585. FAIL;
  586. pI2CPrimitive ++;
  587. // I2C write buffer should be taken care of.
  588. for( nIndex = 0; nIndex < pI2CPacket->cbWriteCount; nIndex ++)
  589. {
  590. pI2CPrimitive->ulCommand = I2C_COMMAND_WRITE;
  591. pI2CPrimitive->byData = pI2CPacket->puchWriteBuffer[nIndex];
  592. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_ACK;
  593. if( nIndex == ( UINT)( pI2CPacket->cbWriteCount - 1))
  594. {
  595. // it's time to write the byte modified after the Read operation
  596. pI2CPrimitive->byORData = pI2CPacket->uchORValue;
  597. pI2CPrimitive->byANDData = pI2CPacket->uchANDValue;
  598. pI2CPrimitive->byFlags = I2COPERATION_READWRITE;
  599. // apply STOP condition with the last byte to be read
  600. pI2CPrimitive->ulProviderFlags |= I2C_FLAGS_STOP;
  601. }
  602. else
  603. {
  604. pI2CPrimitive->byORData = 0x00;
  605. pI2CPrimitive->byANDData = 0xFF;
  606. pI2CPrimitive->byFlags = 0x0;
  607. }
  608. // check the Script length
  609. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  610. break;
  611. pI2CPrimitive ++;
  612. }
  613. // check the Script length
  614. if( nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  615. FAIL;
  616. /* // Stop condition is applied with the last byte to be written
  617. // We finished Write portion here, whether it's a Write only, Read-Modify-Write operation
  618. pI2CPrimitive->ulCommand = I2C_COMMAND_NULL;
  619. pI2CPrimitive->ulProviderFlags = I2C_FLAGS_STOP;
  620. pI2CPrimitive->byFlags = 0x0;
  621. // check the Script length
  622. if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
  623. FAIL;
  624. pI2CPrimitive ++;
  625. */
  626. }
  627. // the Packet was added succesfully to the Script. Modify the Script propertirs
  628. m_nExecutionIndex = nScriptIndex;
  629. m_nScriptLength = nScriptIndex;
  630. return( TRUE);
  631. } END_ENSURE;
  632. _DbgPrintF( DEBUGLVL_VERBOSE,
  633. ( "CI2CScript:AppendToScript() nError = %x", nError)
  634. );
  635. return( FALSE);
  636. }
  637. /*^^*
  638. * ExecuteScript()
  639. * Purpose : triggers the execution of previously built I2CScript. This function is also
  640. * responsible for allocating I2CProvider for its own exclusive use.
  641. *
  642. * Inputs : PIRP pIrp
  643. * PHWCompletionRoutine pfnScriptCompletion: function pointer will be called,
  644. * when the script execution is completed. Indicates the Script execution
  645. * is to be carried out asynchronously.
  646. *
  647. * Outputs : BOOL : returns TRUE, if the execution was successfully triggered.
  648. * FALSE might happend if the Script has not been built by the time of the call
  649. *
  650. * Note : if pfnScriptExecuted is NULL pointer, the Script will be executed synchronously
  651. *
  652. * Author : IKLEBANOV
  653. *^^*/
  654. BOOL CI2CScript::ExecuteScript( IN PIRP pIrp,
  655. IN PHWCompletionRoutine pfnScriptCompletion)
  656. {
  657. ENSURE
  658. {
  659. if( pfnScriptCompletion != NULL)
  660. // not supported at this point. The idea is to create a new system thread,
  661. // where the Script to be executed. When the Script will be copleted,
  662. // call-back is called and the thred terminates itself.
  663. FAIL;
  664. if( !m_nExecutionIndex)
  665. FAIL;
  666. // there is not a NULL Script - proceed
  667. m_nScriptLength = m_nExecutionIndex;
  668. m_nExecutionIndex = m_nCompletionIndex = 0;
  669. if( !GetI2CProviderLockStatus())
  670. // The provider was not locked prior the Script execution
  671. if( !LockI2CProviderEx())
  672. FAIL;
  673. InterpreterScript();
  674. ReleaseI2CProvider();
  675. return( TRUE);
  676. } END_ENSURE;
  677. return( FALSE);
  678. }
  679. /*^^*
  680. * InterpreterScript()
  681. * Purpose : interpreters the I2CScript line by line. The Script is not cleaned up
  682. * after the completion to allow to client retrive the results of
  683. * the script execution. It's the client responsibility to clean it up
  684. * upon the results retrieving
  685. *
  686. * Inputs : none
  687. * Outputs : none
  688. *
  689. * Author : IKLEBANOV
  690. *^^*/
  691. void CI2CScript::InterpreterScript( void)
  692. {
  693. UINT nScriptIndex, nIndex;
  694. I2CControl i2cAccessBlock;
  695. m_bExecutionInProcess = TRUE;
  696. i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
  697. i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;
  698. // We'll interpreter every line of the Script and call the I2C Provider to
  699. // execute it. It's assumed the I2CProvider is a syncronous one. If it's not the
  700. // case, the special care should be taken of based upon returned value I2C_STATUS_BUSY
  701. // in the Status.
  702. for( nScriptIndex = 0; nScriptIndex < m_nScriptLength; nScriptIndex ++)
  703. {
  704. i2cAccessBlock.Command = m_i2cScript[nScriptIndex].ulCommand;
  705. i2cAccessBlock.Flags = m_i2cScript[nScriptIndex].ulProviderFlags;
  706. if( i2cAccessBlock.Command == I2C_COMMAND_WRITE)
  707. {
  708. i2cAccessBlock.Data = m_i2cScript[nScriptIndex].byData;
  709. i2cAccessBlock.Data &= m_i2cScript[nScriptIndex].byANDData;
  710. i2cAccessBlock.Data |= m_i2cScript[nScriptIndex].byORData;
  711. }
  712. if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) == I2C_STATUS_ERROR)
  713. break;
  714. // check, wether it's a Read operation - save result
  715. if( i2cAccessBlock.Command == I2C_COMMAND_READ)
  716. {
  717. m_i2cScript[nScriptIndex].byData = i2cAccessBlock.Data;
  718. // check, if this data belongs to Read-Modify-Write operation
  719. if( m_i2cScript[nScriptIndex].byFlags & I2COPERATION_READWRITE)
  720. {
  721. // let's look for the next I2COPERATION_READWRITE flag - it is the pair
  722. for( nIndex = nScriptIndex; nIndex < m_nScriptLength; nIndex ++)
  723. if(( m_i2cScript[nIndex].ulCommand == I2C_COMMAND_WRITE) &&
  724. ( m_i2cScript[nIndex].byFlags & I2COPERATION_READWRITE))
  725. break;
  726. if( nIndex >= m_nScriptLength)
  727. // the Script got corrupted
  728. break;
  729. m_i2cScript[nIndex].byData = i2cAccessBlock.Data;
  730. }
  731. }
  732. }
  733. m_nCompletionIndex = nScriptIndex;
  734. m_bExecutionInProcess = FALSE;
  735. }
  736. /*^^*
  737. * AccessI2CProvider()
  738. * Purpose : provide synchronous type of access to I2CProvider
  739. *
  740. * Inputs : PDEVICE_OBJECT pdoDriver : pointer to the client's device object
  741. * PI2CControl pi2cAccessBlock : pointer to a composed I2C access block
  742. *
  743. * Outputs : UINT : status of the I2C operation I2C_STATUS_NOERROR or I2C_STATUS_ERROR
  744. *
  745. * Author : IKLEBANOV
  746. *^^*/
  747. UINT CI2CScript::
  748. AccessI2CProvider( PDEVICE_OBJECT pdoClient, PI2CControl pi2cAccessBlock)
  749. {
  750. UINT uiStatus;
  751. LARGE_INTEGER liTime;
  752. do
  753. {
  754. // this loop is infinitive. It has to be taken care of
  755. ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL);
  756. if( m_i2cProviderInterface.i2cAccess( pdoClient, pi2cAccessBlock) != STATUS_SUCCESS)
  757. {
  758. uiStatus = I2C_STATUS_ERROR;
  759. break;
  760. }
  761. if( pi2cAccessBlock->Status != I2C_STATUS_BUSY)
  762. {
  763. uiStatus = pi2cAccessBlock->Status;
  764. break;
  765. }
  766. liTime.QuadPart = I2CSCRIPT_DELAY_GETPROVIDERSTATUS;
  767. ::KeDelayExecutionThread( KernelMode, FALSE, &liTime);
  768. pi2cAccessBlock->Command = I2C_COMMAND_STATUS;
  769. } while( TRUE);
  770. return( uiStatus);
  771. }
  772. /*^^*
  773. * GetScriptResults()
  774. * Purpose : returns result of the executed Script
  775. * This function idealy is called twice:
  776. * first time with the puchReadBuffer = NULL to retrive the number of bytes read
  777. * second time - to fill in the pointer
  778. * Inputs : PUINT puiReadCount : pointer to the counter of the bytes were read
  779. * PUCH puchReadBuffer : pointer to the buffer to put the data
  780. *
  781. * Outputs : UINT : status of the I2C operation
  782. * If the status is I2C_STATUS_ERROR, puiReadCount will contain the step, where
  783. * I2CScript failed
  784. * Author : IKLEBANOV
  785. *^^*/
  786. UINT CI2CScript::GetScriptResults( PUINT puiReadCount, PUCHAR puchReadBuffer)
  787. {
  788. UINT nScriptIndex, nCount;
  789. ASSERT( puiReadCount != NULL);
  790. if( m_bExecutionInProcess)
  791. return( I2C_STATUS_BUSY);
  792. if( m_nScriptLength != m_nCompletionIndex)
  793. {
  794. // if the case of failure, step where I2CScript failed is return
  795. // instead of Read Counter. The returned status indicates the
  796. // failure
  797. * puiReadCount = m_nCompletionIndex;
  798. return( I2C_STATUS_ERROR);
  799. }
  800. else
  801. {
  802. nCount = 0;
  803. for( nScriptIndex = 0; nScriptIndex < m_nCompletionIndex; nScriptIndex ++)
  804. {
  805. if( m_i2cScript[nScriptIndex].ulCommand == I2C_COMMAND_READ)
  806. {
  807. if( puchReadBuffer != NULL)
  808. // fill in the supplied buffer
  809. puchReadBuffer[nCount] = m_i2cScript[nScriptIndex].byData;
  810. nCount ++;
  811. }
  812. }
  813. * puiReadCount = nCount;
  814. return( I2C_STATUS_NOERROR);
  815. }
  816. }
  817. /*^^*
  818. * InitializeAttachI2CProvider()
  819. * Purpose : gets the pointer to the parent I2C Provider interface using
  820. * several IRP_MJ_??? functions.
  821. * This function will be called at Low priority
  822. *
  823. * Inputs : I2CINTERFACE * pI2CInterface : pointer to the Interface to be filled in
  824. * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of I2C Master
  825. *
  826. * Outputs : BOOL - returns TRUE, if the interface was found
  827. * Author : IKLEBANOV
  828. *^^*/
  829. BOOL CI2CScript::InitializeAttachI2CProvider( I2CINTERFACE * pI2CInterface, PDEVICE_OBJECT pDeviceObject)
  830. {
  831. BOOL bResult;
  832. // try the new path
  833. bResult = LocateAttachI2CProvider( pI2CInterface, pDeviceObject, IRP_MJ_PNP);
  834. if(( pI2CInterface->i2cOpen == NULL) || ( pI2CInterface->i2cAccess == NULL))
  835. {
  836. // TRAP;
  837. _DbgPrintF( DEBUGLVL_ERROR,
  838. ( "CI2CScript(): interface has NULL pointers\n")
  839. );
  840. bResult = FALSE;
  841. }
  842. return( bResult);
  843. }
  844. /*^^*
  845. * LocateAttachI2CProvider()
  846. * Purpose : gets the pointer to the parent I2C Provider interface
  847. * This function will be called at Low priority
  848. *
  849. * Inputs : I2CINTERFACE * pI2CInterface : pointer to the Interface to be filled in
  850. * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of I2C Master
  851. * int nIrpMajorFunction : IRP major function to query the I2C Interface
  852. *
  853. * Outputs : BOOL - returns TRUE, if the interface was found
  854. * Author : IKLEBANOV
  855. *^^*/
  856. BOOL CI2CScript::LocateAttachI2CProvider( I2CINTERFACE * pI2CInterface, PDEVICE_OBJECT pDeviceObject, int nIrpMajorFunction)
  857. {
  858. PIRP pIrp;
  859. BOOL bResult = FALSE;
  860. ENSURE
  861. {
  862. PIO_STACK_LOCATION pNextStack;
  863. NTSTATUS ntStatus;
  864. KEVENT Event;
  865. pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE);
  866. if( pIrp == NULL)
  867. {
  868. // TRAP;
  869. _DbgPrintF( DEBUGLVL_ERROR,
  870. ( "CI2CScript(): can not allocate IRP\n")
  871. );
  872. FAIL;
  873. }
  874. pNextStack = IoGetNextIrpStackLocation( pIrp);
  875. if( pNextStack == NULL)
  876. {
  877. // TRAP;
  878. _DbgPrintF( DEBUGLVL_ERROR,
  879. ( "CI2CScript(): can not allocate NextStack\n")
  880. );
  881. FAIL;
  882. }
  883. //$REVIEW - Should change function decl to make nIrpMajorFunction be UCHAR - TCP
  884. pNextStack->MajorFunction = (UCHAR) nIrpMajorFunction;
  885. pNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  886. KeInitializeEvent( &Event, NotificationEvent, FALSE);
  887. IoSetCompletionRoutine( pIrp,
  888. I2CScriptIoSynchCompletionRoutine,
  889. &Event, TRUE, TRUE, TRUE);
  890. pNextStack->Parameters.QueryInterface.InterfaceType = ( struct _GUID *)&GUID_I2C_INTERFACE;
  891. pNextStack->Parameters.QueryInterface.Size = sizeof( I2CINTERFACE);
  892. pNextStack->Parameters.QueryInterface.Version = 1;
  893. pNextStack->Parameters.QueryInterface.Interface = ( PINTERFACE)pI2CInterface;
  894. pNextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  895. ntStatus = IoCallDriver( pDeviceObject, pIrp);
  896. if( ntStatus == STATUS_PENDING)
  897. KeWaitForSingleObject( &Event,
  898. Suspended, KernelMode, FALSE, NULL);
  899. if(( pI2CInterface->i2cOpen == NULL) || ( pI2CInterface->i2cAccess == NULL))
  900. {
  901. _DbgPrintF( DEBUGLVL_ERROR,
  902. ( "CI2CScript(): interface has NULL pointers\n")
  903. );
  904. FAIL;
  905. }
  906. bResult = TRUE;
  907. } END_ENSURE;
  908. if( pIrp != NULL)
  909. IoFreeIrp( pIrp);
  910. return( bResult);
  911. }
  912. /*^^*
  913. * I2CScriptIoSynchCompletionRoutine()
  914. * Purpose : This routine is for use with synchronous IRP processing.
  915. * All it does is signal an event, so the driver knows it and can continue.
  916. *
  917. * Inputs : PDEVICE_OBJECT DriverObject : Pointer to driver object created by system
  918. * PIRP pIrp : Irp that just completed
  919. * PVOID Event : Event we'll signal to say Irp is done
  920. *
  921. * Outputs : none
  922. * Author : IKLEBANOV
  923. *^^*/
  924. extern "C"
  925. NTSTATUS I2CScriptIoSynchCompletionRoutine( IN PDEVICE_OBJECT pDeviceObject,
  926. IN PIRP pIrp,
  927. IN PVOID Event)
  928. {
  929. KeSetEvent(( PKEVENT)Event, 0, FALSE);
  930. return( STATUS_MORE_PROCESSING_REQUIRED);
  931. }
  932. /*
  933. * WriteSeq()
  934. * Purpose : Write a specified sequence to address specified.
  935. *
  936. *
  937. * Inputs : UCHAR addr : I2CAddress
  938. * UCHAR *p_seq : sequence
  939. * USHORT len : length of the sequence
  940. *
  941. * Outputs : BOOL - TRUE if operation succeeded else FALSE
  942. * Author : MM
  943. *
  944. */
  945. BOOL CI2CScript::WriteSeq(UCHAR addr, UCHAR *p_seq, USHORT len)
  946. {
  947. I2CPacket i2cPacket;
  948. LARGE_INTEGER liTime;
  949. // Init rest of I2CPacket
  950. i2cPacket.usFlags = I2COPERATION_WRITE;
  951. i2cPacket.uchChipAddress = addr;
  952. i2cPacket.cbReadCount = 0;
  953. i2cPacket.cbWriteCount = len;
  954. i2cPacket.puchReadBuffer = NULL;
  955. i2cPacket.puchWriteBuffer = p_seq;
  956. int counter = 0;
  957. // Somewhat arbitrary max of 1 second.
  958. while (!LockI2CProviderEx())
  959. {
  960. if (counter++ >= 100)
  961. {
  962. // ReleaseI2CProvider();
  963. return(FALSE);
  964. }
  965. liTime.QuadPart = 100000;
  966. KeDelayExecutionThread(KernelMode, FALSE, &liTime); // = 10 milliseconds
  967. }
  968. /*
  969. if(!CheckInterface(addr))
  970. {
  971. ReleaseI2CProvider();
  972. return FALSE;
  973. }
  974. */
  975. ExecuteI2CPacket(&i2cPacket);
  976. ReleaseI2CProvider();
  977. //DebugInfo(("CI2CScript::WriteSeq(): Inside\n"));
  978. if (i2cPacket.uchI2CResult != I2C_STATUS_NOERROR)
  979. {
  980. _DbgPrintF( DEBUGLVL_ERROR,("CI2CScript::WriteSeq(): Error\n"));
  981. return(FALSE);
  982. }
  983. return(TRUE);
  984. }
  985. /*
  986. * ReadSeq()
  987. * Purpose : Read a specified number of bytes from address specified.
  988. *
  989. *
  990. * Inputs : UCHAR addr : I2CAddress
  991. * UCHAR *p_seq : sequence
  992. * USHORT len : length of the sequence
  993. *
  994. * Outputs : BOOL - TRUE if operation succeeded else FALSE
  995. * Author : MM
  996. *
  997. *
  998. */
  999. BOOL CI2CScript::ReadSeq(UCHAR addr, UCHAR *p_seq, USHORT len)
  1000. {
  1001. I2CPacket i2cPacket;
  1002. LARGE_INTEGER liTime;
  1003. // Init rest of I2CPacket
  1004. i2cPacket.usFlags = I2COPERATION_READ;
  1005. i2cPacket.uchChipAddress = addr;
  1006. i2cPacket.cbReadCount = len;
  1007. i2cPacket.cbWriteCount = 0;
  1008. i2cPacket.puchReadBuffer = p_seq;
  1009. i2cPacket.puchWriteBuffer = NULL;
  1010. int counter = 0;
  1011. // Somewhat arbitrary max of 1 second.
  1012. while (!LockI2CProviderEx())
  1013. {
  1014. if (counter++ >= 100)
  1015. {
  1016. // ReleaseI2CProvider();
  1017. return(FALSE);
  1018. }
  1019. liTime.QuadPart = 100000;
  1020. KeDelayExecutionThread(KernelMode, FALSE, &liTime); // = 10 milliseconds
  1021. }
  1022. /*
  1023. if(!CheckInterface(addr))
  1024. {
  1025. ReleaseI2CProvider();
  1026. return FALSE;
  1027. }
  1028. */
  1029. ExecuteI2CPacket(&i2cPacket);
  1030. ReleaseI2CProvider();
  1031. // DebugInfo(("CI2CScript::ReadSeq(): Inside\n"));
  1032. if (i2cPacket.uchI2CResult != I2C_STATUS_NOERROR)
  1033. {
  1034. _DbgPrintF( DEBUGLVL_ERROR,("CI2CScript::ReadSeq(): Error\n"));
  1035. return(FALSE);
  1036. }
  1037. return(TRUE);
  1038. }
  1039. /*
  1040. * CombinedSeq()
  1041. * Purpose : Write a specified sequence and then read a specified number of
  1042. * bytes from address specified.
  1043. *
  1044. *
  1045. * Inputs : UCHAR addr : I2CAddress
  1046. * UCHAR seqWr[] : write sequence
  1047. * USHORT lenWr : length of the write sequence
  1048. * UCHAR seqRd[] : read sequence
  1049. * USHORT lenRd : length of the read sequence
  1050. *
  1051. * Outputs : BOOL - TRUE if operation succeeded else FALSE
  1052. * Author : MM
  1053. *
  1054. *
  1055. */
  1056. BOOL
  1057. CI2CScript::CombinedSeq(UCHAR addr, UCHAR seqWr[], USHORT lenWr, UCHAR seqRd[], USHORT lenRd)
  1058. {
  1059. I2CPacket i2cPacket;
  1060. LARGE_INTEGER liTime;
  1061. // Init rest of I2CPacket
  1062. i2cPacket.usFlags = I2COPERATION_READWRITE;
  1063. i2cPacket.uchChipAddress = addr;
  1064. i2cPacket.cbReadCount = lenRd;
  1065. i2cPacket.cbWriteCount = lenWr;
  1066. i2cPacket.puchReadBuffer = seqRd;
  1067. i2cPacket.puchWriteBuffer = seqWr;
  1068. int counter = 0;
  1069. // Somewhat arbitrary max of 1 second.
  1070. while (!LockI2CProviderEx())
  1071. {
  1072. if (counter++ >= 100)
  1073. {
  1074. // ReleaseI2CProvider();
  1075. return(FALSE);
  1076. }
  1077. liTime.QuadPart = 100000;
  1078. KeDelayExecutionThread(KernelMode, FALSE, &liTime); // = 10 milliseconds
  1079. }
  1080. if(!CheckInterface(addr))
  1081. {
  1082. ReleaseI2CProvider();
  1083. return FALSE;
  1084. }
  1085. ExecuteI2CPacket(&i2cPacket);
  1086. ReleaseI2CProvider();
  1087. //DebugInfo(("CI2CScript::CombinedSeq(): Inside\n"));
  1088. if (i2cPacket.uchI2CResult != I2C_STATUS_NOERROR)
  1089. {
  1090. return(FALSE);
  1091. }
  1092. return(TRUE);
  1093. }
  1094. /*
  1095. * CheckInterface()
  1096. * Purpose : Check if I2C Interface is working by reading a byte
  1097. * from the specified address
  1098. *
  1099. * Inputs : UCHAR addr : I2CAddress
  1100. *
  1101. * Outputs : BOOL - TRUE if operation succeeded else FALSE
  1102. * Author : MM
  1103. *
  1104. *
  1105. */
  1106. BOOL CI2CScript::CheckInterface(UCHAR addr)
  1107. {
  1108. I2CPacket i2cPacket;
  1109. LARGE_INTEGER liTime;
  1110. UCHAR ucData;
  1111. // Init rest of I2CPacket
  1112. i2cPacket.usFlags = I2COPERATION_READ;
  1113. i2cPacket.uchChipAddress = addr;
  1114. i2cPacket.cbReadCount = 1;
  1115. i2cPacket.cbWriteCount = 0;
  1116. i2cPacket.puchReadBuffer = &ucData;
  1117. i2cPacket.puchWriteBuffer = NULL;
  1118. ExecuteI2CPacket(&i2cPacket);
  1119. if (i2cPacket.uchI2CResult != I2C_STATUS_NOERROR)
  1120. {
  1121. _DbgPrintF( DEBUGLVL_ERROR,("CI2CScript::CheckInterface(): Error\n"));
  1122. return(FALSE);
  1123. }
  1124. return(TRUE);
  1125. }