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.

632 lines
17 KiB

  1. //==========================================================================;
  2. //
  3. //
  4. // Gpio.cpp
  5. // Gpio Class implementation
  6. // Based on code from ATI Technologies Inc. Copyright (c) 1996 - 1997
  7. //
  8. // ATIConfg.CPP
  9. // WDM MiniDrivers development.
  10. // ATIHwConfiguration class implementation.
  11. // Copyright (c) 1996 - 1997 ATI Technologies Inc. All Rights Reserved.
  12. //
  13. //==========================================================================;
  14. extern "C"
  15. {
  16. #include <wdm.h>
  17. }
  18. #include <unknown.h>
  19. #include "ks.h"
  20. #include "ksmedia.h"
  21. #include <ksdebug.h>
  22. #include "gpio.h"
  23. #include "wdmdebug.h"
  24. //$REVIEW - Let's find a way to get the proper module name into this
  25. //
  26. #define MODULENAME "PhilTune"
  27. #define MODULENAMEUNICODE L"PhilTune"
  28. #define STR_MODULENAME MODULENAME
  29. #define ENSURE do
  30. #define END_ENSURE while( FALSE)
  31. #define FAIL break
  32. /*^^*
  33. * CGpio()
  34. * Purpose : CGpio Class constructor
  35. * Determines I2CExpander address and all possible hardware IDs and addresses
  36. *
  37. * Inputs : PDEVICE_OBJECT pDeviceObject : pointer to the creator DeviceObject
  38. * CI2CScript * pCScript : pointer to the I2CScript class object
  39. * PUINT puiError : pointer to return Error code
  40. *
  41. * Outputs : none
  42. * Author : IKLEBANOV
  43. *^^*/
  44. CGpio::CGpio( PDEVICE_OBJECT pDeviceObject, NTSTATUS * pStatus)
  45. {
  46. *pStatus = STATUS_SUCCESS;
  47. ENSURE
  48. {
  49. m_gpioProviderInterface.gpioOpen = NULL;
  50. m_gpioProviderInterface.gpioAccess = NULL;
  51. m_pdoDriver = NULL;
  52. if( InitializeAttachGPIOProvider( &m_gpioProviderInterface, pDeviceObject))
  53. {
  54. // There was no error to get GPIOInterface from the MiniVDD
  55. //
  56. m_pdoDriver = pDeviceObject;
  57. }
  58. else
  59. {
  60. * pStatus = STATUS_NOINTERFACE;
  61. FAIL;
  62. }
  63. } END_ENSURE;
  64. _DbgPrintF( DEBUGLVL_VERBOSE, ( "CGPio:CGpio() Status=%x\n", * pStatus));
  65. }
  66. /*^^*
  67. * GPIOIoSynchCompletionRoutine()
  68. * Purpose : This routine is for use with synchronous IRP processing.
  69. * All it does is signal an event, so the driver knows it and can continue.
  70. *
  71. * Inputs : PDEVICE_OBJECT DriverObject : Pointer to driver object created by system
  72. * PIRP pIrp : Irp that just completed
  73. * PVOID Event : Event we'll signal to say Irp is done
  74. *
  75. * Outputs : none
  76. * Author : IKLEBANOV
  77. *^^*/
  78. extern "C"
  79. NTSTATUS GPIOIoSynchCompletionRoutine( IN PDEVICE_OBJECT pDeviceObject,
  80. IN PIRP pIrp,
  81. IN PVOID Event)
  82. {
  83. KeSetEvent(( PKEVENT)Event, 0, FALSE);
  84. return( STATUS_MORE_PROCESSING_REQUIRED);
  85. }
  86. /*^^*
  87. * InitializeAttachGPIOProvider()
  88. * Purpose : determines the pointer to the parent GPIO Provider interface
  89. * This function will be called at Low priority
  90. *
  91. * Inputs : GPIOINTERFACE * pGPIOInterface : pointer to the Interface to be filled in
  92. * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of GPIO Master
  93. *
  94. * Outputs : BOOL - returns TRUE, if the interface was found
  95. * Author : IKLEBANOV
  96. *^^*/
  97. BOOL CGpio::InitializeAttachGPIOProvider( GPIOINTERFACE * pGPIOInterface, PDEVICE_OBJECT pDeviceObject)
  98. {
  99. BOOL bResult;
  100. // Find the GPIO provider
  101. bResult = LocateAttachGPIOProvider( pGPIOInterface, pDeviceObject, IRP_MJ_PNP);
  102. if(( pGPIOInterface->gpioOpen == NULL) || ( pGPIOInterface->gpioAccess == NULL))
  103. {
  104. // TRAP;
  105. _DbgPrintF( DEBUGLVL_ERROR,
  106. ( "CGpio(): GPIO interface has NULL pointers\n")
  107. );
  108. bResult = FALSE;
  109. }
  110. return( bResult);
  111. }
  112. /*^^*
  113. * LocateAttachGPIOProvider()
  114. * Purpose : gets the pointer to the parent GPIO Provider interface
  115. * This function will be called at Low priority
  116. *
  117. * Inputs : GPIOINTERFACE * pGPIOInterface : pointer to the Interface to be filled in
  118. * PDEVICE_OBJECT pDeviceObject : MiniDriver device object, which is a child of I2C Master
  119. * int nIrpMajorFunction : IRP major function to query the GPIO Interface
  120. *
  121. * Outputs : BOOL - returns TRUE, if the interface was found
  122. * Author : IKLEBANOV
  123. *^^*/
  124. BOOL CGpio::LocateAttachGPIOProvider( GPIOINTERFACE * pGPIOInterface, PDEVICE_OBJECT pDeviceObject, int nIrpMajorFunction)
  125. {
  126. PIRP pIrp;
  127. BOOL bResult = FALSE;
  128. ENSURE
  129. {
  130. PIO_STACK_LOCATION pNextStack;
  131. NTSTATUS ntStatus;
  132. KEVENT Event;
  133. pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE);
  134. if( pIrp == NULL)
  135. {
  136. // TRAP;
  137. _DbgPrintF( DEBUGLVL_ERROR, ("CGpio(): can not allocate IRP\n"));
  138. FAIL;
  139. }
  140. pNextStack = IoGetNextIrpStackLocation( pIrp);
  141. if( pNextStack == NULL)
  142. {
  143. // TRAP;
  144. _DbgPrintF( DEBUGLVL_ERROR,
  145. ("CATIHwConfig(): can not allocate NextStack\n")
  146. );
  147. FAIL;
  148. }
  149. //$REVIEW - Should change function decl to make nIrpMajorFunction be UCHAR - TCP
  150. pNextStack->MajorFunction = (UCHAR) nIrpMajorFunction;
  151. pNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
  152. KeInitializeEvent( &Event, NotificationEvent, FALSE);
  153. IoSetCompletionRoutine( pIrp,
  154. GPIOIoSynchCompletionRoutine,
  155. &Event, TRUE, TRUE, TRUE);
  156. pNextStack->Parameters.QueryInterface.InterfaceType = ( struct _GUID *)&GUID_GPIO_INTERFACE;
  157. pNextStack->Parameters.QueryInterface.Size = sizeof( GPIOINTERFACE);
  158. pNextStack->Parameters.QueryInterface.Version = 1;
  159. pNextStack->Parameters.QueryInterface.Interface = ( PINTERFACE)pGPIOInterface;
  160. pNextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  161. ntStatus = IoCallDriver( pDeviceObject, pIrp);
  162. if( ntStatus == STATUS_PENDING)
  163. KeWaitForSingleObject( &Event,
  164. Suspended, KernelMode, FALSE, NULL);
  165. if(( pGPIOInterface->gpioOpen == NULL) || ( pGPIOInterface->gpioAccess == NULL))
  166. {
  167. _DbgPrintF( DEBUGLVL_ERROR,
  168. ( "CATIHwConfig(): GPIO interface has NULL pointers\n")
  169. );
  170. FAIL;
  171. }
  172. bResult = TRUE;
  173. } END_ENSURE;
  174. if( pIrp != NULL)
  175. IoFreeIrp( pIrp);
  176. return( bResult);
  177. }
  178. /*^^*
  179. * QueryGPIOProvider()
  180. * Purpose : queries the GPIOProvider for the pins supported and private interfaces
  181. *
  182. * Inputs : PGPIOControl pgpioAccessBlock : pointer to GPIO control structure
  183. *
  184. * Outputs : BOOL : retunrs TRUE, if the query function was carried on successfully
  185. * Author : IKLEBANOV
  186. *^^*/
  187. BOOL CGpio::QueryGPIOProvider( PGPIOControl pgpioAccessBlock)
  188. {
  189. ENSURE
  190. {
  191. if(( m_gpioProviderInterface.gpioOpen == NULL) ||
  192. ( m_gpioProviderInterface.gpioAccess == NULL) ||
  193. ( m_pdoDriver == NULL))
  194. FAIL;
  195. pgpioAccessBlock->Status = GPIO_STATUS_NOERROR;
  196. pgpioAccessBlock->Command = GPIO_COMMAND_QUERY;
  197. pgpioAccessBlock->AsynchCompleteCallback = NULL;
  198. if(( !NT_SUCCESS( m_gpioProviderInterface.gpioOpen( m_pdoDriver, TRUE, pgpioAccessBlock))) ||
  199. ( pgpioAccessBlock->Status != GPIO_STATUS_NOERROR))
  200. FAIL;
  201. return( TRUE);
  202. } END_ENSURE;
  203. return( FALSE);
  204. }
  205. /*^^*
  206. * LockGPIOProviderEx()
  207. * Purpose : locks the GPIOProvider for exclusive use
  208. *
  209. * Inputs : PGPIOControl pgpioAccessBlock : pointer to GPIO control structure
  210. *
  211. * Outputs : BOOL : retunrs TRUE, if the GPIOProvider is locked
  212. * Author : IKLEBANOV
  213. *^^*/
  214. BOOL CGpio::LockGPIOProviderEx( PGPIOControl pgpioAccessBlock)
  215. {
  216. NTSTATUS ntStatus;
  217. LARGE_INTEGER liStartTime, liCurrentTime;
  218. KeQuerySystemTime( &liStartTime);
  219. ENSURE
  220. {
  221. if(( m_gpioProviderInterface.gpioOpen == NULL) ||
  222. ( m_gpioProviderInterface.gpioAccess == NULL) ||
  223. ( m_pdoDriver == NULL))
  224. FAIL;
  225. pgpioAccessBlock->Status = GPIO_STATUS_NOERROR;
  226. pgpioAccessBlock->Command = GPIO_COMMAND_OPEN_PINS;
  227. while( TRUE)
  228. {
  229. KeQuerySystemTime( &liCurrentTime);
  230. if(( liCurrentTime.QuadPart - liStartTime.QuadPart) >= GPIO_TIMELIMIT_OPENPROVIDER)
  231. {
  232. // time has expired for attempting to lock GPIO provider
  233. return (FALSE);
  234. }
  235. ntStatus = m_gpioProviderInterface.gpioOpen( m_pdoDriver, TRUE, pgpioAccessBlock);
  236. if(( NT_SUCCESS( ntStatus)) && ( pgpioAccessBlock->Status == GPIO_STATUS_NOERROR))
  237. break;
  238. }
  239. // the GPIO Provider has granted access - save dwCookie for further use
  240. m_dwGPIOAccessKey = pgpioAccessBlock->dwCookie;
  241. return( TRUE);
  242. } END_ENSURE;
  243. return( FALSE);
  244. }
  245. /*^^*
  246. * ReleaseGPIOProvider()
  247. * Purpose : releases the GPIOProvider for other clients' use
  248. *
  249. * Inputs : PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block
  250. *
  251. * Outputs : BOOL : retunrs TRUE, if the GPIOProvider is released
  252. * Author : IKLEBANOV
  253. *^^*/
  254. BOOL CGpio::ReleaseGPIOProvider( PGPIOControl pgpioAccessBlock)
  255. {
  256. NTSTATUS ntStatus;
  257. ENSURE
  258. {
  259. if(( m_gpioProviderInterface.gpioOpen == NULL) ||
  260. ( m_gpioProviderInterface.gpioAccess == NULL) ||
  261. ( m_pdoDriver == NULL))
  262. FAIL;
  263. pgpioAccessBlock->Status = GPIO_STATUS_NOERROR;
  264. pgpioAccessBlock->Command = GPIO_COMMAND_CLOSE_PINS;
  265. pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
  266. ntStatus = m_gpioProviderInterface.gpioOpen( m_pdoDriver, FALSE, pgpioAccessBlock);
  267. if( !NT_SUCCESS( ntStatus))
  268. {
  269. _DbgPrintF( DEBUGLVL_ERROR,
  270. ( "CGpio: ReleaseGPIOProvider() NTSTATUS = %x\n",
  271. ntStatus)
  272. );
  273. FAIL;
  274. }
  275. if( pgpioAccessBlock->Status != GPIO_STATUS_NOERROR)
  276. {
  277. _DbgPrintF( DEBUGLVL_ERROR,
  278. ( "CGpio: ReleaseGPIOProvider() Status = %x\n",
  279. pgpioAccessBlock->Status)
  280. );
  281. FAIL;
  282. }
  283. m_dwGPIOAccessKey = 0;
  284. return ( TRUE);
  285. } END_ENSURE;
  286. return( FALSE);
  287. }
  288. /*^^*
  289. * AccessGPIOProvider()
  290. * Purpose : provide synchronous type of access to GPIOProvider
  291. *
  292. * Inputs : PDEVICE_OBJECT pdoDriver : pointer to the client's device object
  293. * PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block
  294. *
  295. * Outputs : BOOL, TRUE if acsepted by the GPIO Provider
  296. *
  297. * Author : IKLEBANOV
  298. *^^*/
  299. //BOOL CGpio::AccessGPIOProvider( PDEVICE_OBJECT pdoClient, PGPIOControl pgpioAccessBlock)
  300. BOOL CGpio::AccessGPIOProvider( PGPIOControl pgpioAccessBlock)
  301. {
  302. NTSTATUS ntStatus;
  303. ENSURE
  304. {
  305. if(( m_gpioProviderInterface.gpioOpen == NULL) ||
  306. ( m_gpioProviderInterface.gpioAccess == NULL) ||
  307. ( m_pdoDriver == NULL))
  308. FAIL;
  309. //ntStatus = m_gpioProviderInterface.gpioAccess( pdoClient, pgpioAccessBlock);
  310. ntStatus = m_gpioProviderInterface.gpioAccess( m_pdoDriver, pgpioAccessBlock);
  311. if( !NT_SUCCESS( ntStatus))
  312. {
  313. _DbgPrintF( DEBUGLVL_ERROR,
  314. ( "CGpio: AccessGPIOProvider() NTSTATUS = %x\n",
  315. ntStatus)
  316. );
  317. FAIL;
  318. }
  319. if( pgpioAccessBlock->Status != GPIO_STATUS_NOERROR)
  320. {
  321. _DbgPrintF( DEBUGLVL_ERROR,
  322. ( "CGpio: AccessGPIOProvider() Status = %x\n",
  323. pgpioAccessBlock->Status)
  324. );
  325. FAIL;
  326. }
  327. return TRUE;
  328. } END_ENSURE;
  329. return( FALSE);
  330. }
  331. /*
  332. * WriteGPIO()
  333. * Purpose : write to GPIO
  334. *
  335. * Inputs : PDEVICE_OBJECT pdoDriver : pointer to the client's device object
  336. * PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block
  337. *
  338. * Outputs : BOOL, TRUE if write succeeds
  339. *
  340. * Author : MM
  341. *
  342. */
  343. BOOL CGpio::WriteGPIO(PGPIOControl pgpioAccessBlock)
  344. {
  345. ENSURE
  346. {
  347. // Put cookie value in the structure
  348. pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
  349. pgpioAccessBlock->Command = GPIO_COMMAND_WRITE_BUFFER;
  350. pgpioAccessBlock->Flags = GPIO_FLAGS_BYTE;
  351. pgpioAccessBlock->nBytes = 1;
  352. pgpioAccessBlock->nBufferSize = 1;
  353. // Put cookie value in the structure
  354. pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
  355. if (AccessGPIOProvider(pgpioAccessBlock) == FALSE)
  356. {
  357. _DbgPrintF( DEBUGLVL_ERROR, ("CGpio: GPIO Write Error\n"));
  358. FAIL;
  359. }
  360. return TRUE;
  361. } END_ENSURE;
  362. return( FALSE);
  363. }
  364. /*
  365. * ReadGPIO()
  366. * Purpose : Read From GPIO
  367. *
  368. * Inputs : PDEVICE_OBJECT pdoDriver : pointer to the client's device object
  369. * PGPIOControl pgpioAccessBlock : pointer to a composed GPIO access block
  370. *
  371. * Outputs : BOOL, TRUE if write succeeds
  372. *
  373. * Author : MM
  374. *
  375. */
  376. BOOL CGpio::ReadGPIO(PGPIOControl pgpioAccessBlock)
  377. {
  378. ENSURE
  379. {
  380. // Put cookie value in the structure
  381. pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
  382. pgpioAccessBlock->Command = GPIO_COMMAND_READ_BUFFER;
  383. pgpioAccessBlock->Flags = GPIO_FLAGS_BYTE;
  384. pgpioAccessBlock->nBytes = 1;
  385. pgpioAccessBlock->nBufferSize = 1;
  386. // Put cookie value in the structure
  387. pgpioAccessBlock->dwCookie = m_dwGPIOAccessKey;
  388. if (AccessGPIOProvider(pgpioAccessBlock) == FALSE)
  389. {
  390. _DbgPrintF( DEBUGLVL_ERROR, ("CGpio: GPIO Read Error\n"));
  391. FAIL;
  392. }
  393. else
  394. _DbgPrintF( DEBUGLVL_BLAB, ("CGpio: GPIO Read OK\n"));
  395. return TRUE;
  396. } END_ENSURE;
  397. return( FALSE);
  398. }
  399. /* WriteGPIO()
  400. * Purpose : write to GPIO
  401. *
  402. * Inputs : UCHAR *p_uchPin : the pin number
  403. * UCHAR *p_uchValue : the pin value
  404. *
  405. * Outputs : BOOL, TRUE if write succeeds
  406. *
  407. * Author : MM
  408. *
  409. */
  410. BOOL CGpio::WriteGPIO(UCHAR *p_uchPin,UCHAR *p_uchValue )
  411. {
  412. GPIOControl gpioAccessBlock;
  413. BOOL bResult = FALSE;
  414. ENSURE
  415. {
  416. // Put cookie value in the structure
  417. gpioAccessBlock.Flags = GPIO_FLAGS_BYTE;
  418. gpioAccessBlock.nBytes = 1;
  419. gpioAccessBlock.nBufferSize = 1;
  420. gpioAccessBlock.AsynchCompleteCallback = NULL;
  421. int counter = 0;
  422. LARGE_INTEGER liTime;
  423. // Somewhat arbitrary max of 1 second.
  424. while (!LockGPIOProviderEx( &gpioAccessBlock))
  425. {
  426. if (counter++ >= 100)
  427. {
  428. _DbgPrintF( DEBUGLVL_ERROR,("PhilTune: unable to lock GPIOProvider\n"));
  429. FAIL;
  430. }
  431. liTime.QuadPart = 100000;
  432. KeDelayExecutionThread(KernelMode, FALSE, &liTime); // = 10 milliseconds
  433. } // try to get GPIO Provider
  434. gpioAccessBlock.Command = GPIO_COMMAND_WRITE_BUFFER;
  435. gpioAccessBlock.Pins = p_uchPin;
  436. // Put cookie value in the structure
  437. gpioAccessBlock.dwCookie = m_dwGPIOAccessKey;
  438. gpioAccessBlock.Buffer = p_uchValue;
  439. if (AccessGPIOProvider(&gpioAccessBlock) == FALSE)
  440. {
  441. _DbgPrintF( DEBUGLVL_ERROR,("CGpio: GPIO Write Error\n"));
  442. FAIL;
  443. }
  444. bResult = TRUE;
  445. } END_ENSURE;
  446. ReleaseGPIOProvider(&gpioAccessBlock);
  447. return bResult;
  448. }
  449. /*
  450. * ReadGPIO()
  451. * Purpose : Read From GPIO
  452. *
  453. * Inputs : UCHAR *p_uchPin : the pin number
  454. * UCHAR *p_uchValue : the pin value
  455. *
  456. * Outputs : BOOL, TRUE if write succeeds
  457. *
  458. * Author : MM
  459. *
  460. */
  461. BOOL CGpio::ReadGPIO(UCHAR *p_uchPin,UCHAR *p_uchValue )
  462. {
  463. GPIOControl gpioAccessBlock;
  464. BOOL bResult = FALSE;
  465. ENSURE
  466. {
  467. // Put cookie value in the structure
  468. gpioAccessBlock.Flags = GPIO_FLAGS_BYTE;
  469. gpioAccessBlock.nBytes = 1;
  470. gpioAccessBlock.nBufferSize = 1;
  471. gpioAccessBlock.AsynchCompleteCallback = NULL;
  472. int counter = 0;
  473. LARGE_INTEGER liTime;
  474. // Somewhat arbitrary max of 1 second.
  475. while (!LockGPIOProviderEx( &gpioAccessBlock))
  476. {
  477. if (counter++ >= 100)
  478. {
  479. _DbgPrintF( DEBUGLVL_ERROR,("PhilTune: unable to lock GPIOProvider"));
  480. FAIL;
  481. }
  482. liTime.QuadPart = 100000;
  483. KeDelayExecutionThread(KernelMode, FALSE, &liTime); // = 10 milliseconds
  484. } // try to get GPIO Provider
  485. gpioAccessBlock.Command = GPIO_COMMAND_READ_BUFFER;
  486. gpioAccessBlock.Pins = p_uchPin;
  487. // Put cookie value in the structure
  488. gpioAccessBlock.dwCookie = m_dwGPIOAccessKey;
  489. gpioAccessBlock.Buffer = p_uchValue;
  490. if (AccessGPIOProvider(&gpioAccessBlock) == FALSE)
  491. {
  492. _DbgPrintF( DEBUGLVL_ERROR,("CGpio: GPIO Read Error\n"));
  493. FAIL;
  494. }
  495. else
  496. {
  497. _DbgPrintF( DEBUGLVL_TERSE,("CGpio: GPIO Read OK\n"));
  498. }
  499. bResult = TRUE;
  500. } END_ENSURE;
  501. ReleaseGPIOProvider(&gpioAccessBlock);
  502. return bResult;
  503. }