Leaked source code of windows server 2003
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.

494 lines
12 KiB

  1. /***************************************************************************\
  2. *
  3. * ************************
  4. * * MINIPORT SAMPLE CODE *
  5. * ************************
  6. *
  7. * Module Name:
  8. *
  9. * i2c.c
  10. *
  11. * Abstract:
  12. *
  13. * This module contains the code that implements the i2c interface feature
  14. *
  15. *
  16. * Environment:
  17. *
  18. * Kernel mode
  19. *
  20. *
  21. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  22. * Copyright (c) 1995-2003 Microsoft Corporation. All Rights Reserved.
  23. *
  24. \***************************************************************************/
  25. #include "perm3.h"
  26. #include "i2c.h"
  27. #if defined(ALLOC_PRAGMA)
  28. #pragma alloc_text(PAGE,GetCookie)
  29. #pragma alloc_text(PAGE,I2CBusOpenCRT)
  30. #pragma alloc_text(PAGE,I2CBusOpenDFP)
  31. #pragma alloc_text(PAGE,I2CBusOpen)
  32. #pragma alloc_text(PAGE,I2CBusAccessCRT)
  33. #pragma alloc_text(PAGE,I2CBusAccessDFP)
  34. #pragma alloc_text(PAGE,I2CBusAccess)
  35. #pragma alloc_text(PAGE,I2CNull)
  36. #pragma alloc_text(PAGE,I2CRead)
  37. #pragma alloc_text(PAGE,I2CWrite)
  38. #pragma alloc_text(PAGE,I2CStart)
  39. #pragma alloc_text(PAGE,I2CStop)
  40. #pragma alloc_text(PAGE,InterfaceReference)
  41. #pragma alloc_text(PAGE,InterfaceDereference)
  42. #pragma alloc_text(PAGE,Perm3QueryInterface)
  43. #endif
  44. VIDEO_I2C_CONTROL
  45. I2CCallbacksCRT = {
  46. I2CWriteClock,
  47. I2CWriteData,
  48. I2CReadClock,
  49. I2CReadData,
  50. 0
  51. };
  52. VIDEO_I2C_CONTROL
  53. I2CCallbacksDFP = {
  54. I2CWriteClockDFP,
  55. I2CWriteDataDFP,
  56. I2CReadClockDFP,
  57. I2CReadDataDFP,
  58. 0
  59. };
  60. BOOLEAN
  61. GetCookie(
  62. PVOID DeviceObject,
  63. PULONG Cookie
  64. )
  65. {
  66. *Cookie = 0x12345678;
  67. return TRUE;
  68. }
  69. VP_STATUS
  70. I2CBusOpenCRT(
  71. PVOID DeviceObject,
  72. BOOLEAN bOpen,
  73. PI2CControl I2CControl
  74. )
  75. {
  76. return I2CBusOpen(DeviceObject, bOpen, I2CControl, &I2CCallbacksCRT);
  77. }
  78. VP_STATUS
  79. I2CBusOpenDFP(
  80. PVOID DeviceObject,
  81. BOOLEAN bOpen,
  82. PI2CControl I2CControl
  83. )
  84. {
  85. return I2CBusOpen(DeviceObject, bOpen, I2CControl, &I2CCallbacksDFP);
  86. }
  87. VP_STATUS
  88. I2CBusOpen(
  89. PVOID DeviceObject,
  90. BOOLEAN bOpen,
  91. PI2CControl I2CControl,
  92. PVIDEO_I2C_CONTROL I2CCallbacks
  93. )
  94. {
  95. PHW_DEVICE_EXTENSION hwDeviceExtension;
  96. VP_STATUS Status = STATUS_UNSUCCESSFUL;
  97. hwDeviceExtension = VideoPortGetAssociatedDeviceExtension(DeviceObject);
  98. VideoPortAcquireDeviceLock(hwDeviceExtension);
  99. I2CControl->Status = I2C_STATUS_NOERROR;
  100. if (bOpen) {
  101. if (I2CControl->ClockRate > MAX_CLOCK_RATE) {
  102. I2CControl->ClockRate = MAX_CLOCK_RATE;
  103. }
  104. I2CCallbacks->I2CDelay = (MAX_CLOCK_RATE / I2CControl->ClockRate) * 10;
  105. if (GetCookie(DeviceObject, &I2CControl->dwCookie)) {
  106. Status = STATUS_SUCCESS;
  107. }
  108. } else {
  109. I2CControl->dwCookie = 0;
  110. Status = STATUS_SUCCESS;
  111. }
  112. VideoPortReleaseDeviceLock(hwDeviceExtension);
  113. return Status;
  114. }
  115. VP_STATUS
  116. I2CBusAccessCRT(
  117. PVOID DeviceObject,
  118. PI2CControl I2CControl
  119. )
  120. {
  121. return I2CBusAccess(DeviceObject, I2CControl, &I2CCallbacksCRT);
  122. }
  123. VP_STATUS
  124. I2CBusAccessDFP(
  125. PVOID DeviceObject,
  126. PI2CControl I2CControl
  127. )
  128. {
  129. return I2CBusAccess(DeviceObject, I2CControl, &I2CCallbacksDFP);
  130. }
  131. VP_STATUS
  132. I2CBusAccess(
  133. PVOID DeviceObject,
  134. PI2CControl I2CControl,
  135. PVIDEO_I2C_CONTROL I2CCallbacks
  136. )
  137. {
  138. PHW_DEVICE_EXTENSION hwDeviceExtension;
  139. VP_STATUS Status = STATUS_UNSUCCESSFUL;
  140. hwDeviceExtension = VideoPortGetAssociatedDeviceExtension(DeviceObject);
  141. VideoPortAcquireDeviceLock(hwDeviceExtension);
  142. I2CControl->Status = I2C_STATUS_NOERROR;
  143. if (I2CControl->ClockRate > MAX_CLOCK_RATE) {
  144. I2CControl->ClockRate = MAX_CLOCK_RATE;
  145. }
  146. I2CCallbacks->I2CDelay = (MAX_CLOCK_RATE / I2CControl->ClockRate) * 10;
  147. switch(I2CControl->Command) {
  148. case I2C_COMMAND_NULL:
  149. I2CNull(I2CControl, I2CCallbacks, hwDeviceExtension);
  150. break;
  151. case I2C_COMMAND_READ:
  152. I2CRead(I2CControl, I2CCallbacks, hwDeviceExtension);
  153. break;
  154. case I2C_COMMAND_WRITE:
  155. I2CWrite(I2CControl, I2CCallbacks, hwDeviceExtension);
  156. break;
  157. case I2C_COMMAND_RESET:
  158. //
  159. // A reset is just a stop.
  160. //
  161. I2CStop(I2CControl, I2CCallbacks, hwDeviceExtension);
  162. break;
  163. case I2C_COMMAND_STATUS:
  164. break;
  165. default:
  166. I2CControl->Status = I2C_STATUS_ERROR;
  167. }
  168. VideoPortReleaseDeviceLock(hwDeviceExtension);
  169. return I2CControl->Status;
  170. }
  171. ULONG
  172. I2CNull(
  173. PI2CControl I2CControl,
  174. PVIDEO_I2C_CONTROL I2CCallbacks,
  175. PHW_DEVICE_EXTENSION hwDeviceExtension
  176. )
  177. {
  178. I2CControl->Status = I2C_STATUS_NOERROR;
  179. if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
  180. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  181. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  182. }
  183. if (I2CControl->Flags & I2C_FLAGS_START) {
  184. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  185. }
  186. if (I2CControl->Flags & I2C_FLAGS_STOP) {
  187. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  188. }
  189. return I2CControl->Status;
  190. }
  191. ULONG
  192. I2CRead(
  193. PI2CControl I2CControl,
  194. PVIDEO_I2C_CONTROL I2CCallbacks,
  195. PHW_DEVICE_EXTENSION hwDeviceExtension
  196. )
  197. {
  198. BOOLEAN Result;
  199. I2CControl->Status = I2C_STATUS_NOERROR;
  200. if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
  201. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  202. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  203. }
  204. if (I2CControl->Flags & I2C_FLAGS_START) {
  205. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  206. }
  207. Result = hwDeviceExtension->I2CInterface.I2CRead(
  208. hwDeviceExtension,
  209. I2CCallbacks,
  210. &I2CControl->Data,
  211. 1,
  212. (I2CControl->Flags & I2C_FLAGS_ACK) ? FALSE : TRUE);
  213. if (Result == TRUE) {
  214. I2CControl->Status = I2C_STATUS_NOERROR;
  215. } else {
  216. I2CControl->Status = I2C_STATUS_ERROR;
  217. }
  218. if (I2CControl->Flags & I2C_FLAGS_STOP) {
  219. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  220. }
  221. return I2CControl->Status;
  222. }
  223. ULONG
  224. I2CWrite(
  225. PI2CControl I2CControl,
  226. PVIDEO_I2C_CONTROL I2CCallbacks,
  227. PHW_DEVICE_EXTENSION hwDeviceExtension
  228. )
  229. {
  230. BOOLEAN Result;
  231. I2CControl->Status = I2C_STATUS_NOERROR;
  232. if (I2CControl->Flags & I2C_FLAGS_DATACHAINING) {
  233. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  234. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  235. }
  236. if (I2CControl->Flags & I2C_FLAGS_START) {
  237. hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  238. }
  239. Result = hwDeviceExtension->I2CInterface.I2CWrite(
  240. hwDeviceExtension,
  241. I2CCallbacks,
  242. &I2CControl->Data,
  243. 1);
  244. if (Result == TRUE) {
  245. I2CControl->Status = I2C_STATUS_NOERROR;
  246. } else {
  247. I2CControl->Status = I2C_STATUS_ERROR;
  248. }
  249. if (I2CControl->Flags & I2C_FLAGS_STOP) {
  250. hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  251. }
  252. return I2CControl->Status;
  253. }
  254. ULONG
  255. I2CStop(
  256. PI2CControl I2CControl,
  257. PVIDEO_I2C_CONTROL I2CCallbacks,
  258. PHW_DEVICE_EXTENSION hwDeviceExtension
  259. )
  260. {
  261. BOOLEAN Result;
  262. Result = hwDeviceExtension->I2CInterface.I2CStop(hwDeviceExtension, I2CCallbacks);
  263. if (Result == TRUE) {
  264. I2CControl->Status = I2C_STATUS_NOERROR;
  265. } else {
  266. I2CControl->Status = I2C_STATUS_ERROR;
  267. }
  268. return I2CControl->Status;
  269. }
  270. ULONG
  271. I2CStart(
  272. PI2CControl I2CControl,
  273. PVIDEO_I2C_CONTROL I2CCallbacks,
  274. PHW_DEVICE_EXTENSION hwDeviceExtension
  275. )
  276. {
  277. BOOLEAN Result;
  278. Result = hwDeviceExtension->I2CInterface.I2CStart(hwDeviceExtension, I2CCallbacks);
  279. if (Result == TRUE) {
  280. I2CControl->Status = I2C_STATUS_NOERROR;
  281. } else {
  282. I2CControl->Status = I2C_STATUS_ERROR;
  283. }
  284. return I2CControl->Status;
  285. }
  286. VOID
  287. InterfaceReference(
  288. IN PVOID pContext
  289. )
  290. {
  291. return;
  292. }
  293. VOID
  294. InterfaceDereference(
  295. IN PVOID pContext
  296. )
  297. {
  298. return;
  299. }
  300. VP_STATUS
  301. Perm3QueryInterface(
  302. PVOID HwDeviceExtension,
  303. PQUERY_INTERFACE pQueryInterface
  304. )
  305. {
  306. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  307. VP_STATUS Status;
  308. ULONG HwID;
  309. if (IsEqualGUID(pQueryInterface->InterfaceType, &GUID_I2C_INTERFACE)) {
  310. I2CINTERFACE *Interface = (I2CINTERFACE *)pQueryInterface->Interface;
  311. if ((pQueryInterface->Size == sizeof(I2CINTERFACE)) &&
  312. (pQueryInterface->Version == 2))
  313. {
  314. //
  315. // Get interface pointers for i2c interface help functions
  316. //
  317. if (hwDeviceExtension->I2CInterfaceAcquired == FALSE) {
  318. hwDeviceExtension->I2CInterface.Size = sizeof(VIDEO_PORT_I2C_INTERFACE_2);
  319. hwDeviceExtension->I2CInterface.Version = VIDEO_PORT_I2C_INTERFACE_VERSION_2;
  320. Status = VideoPortQueryServices(
  321. hwDeviceExtension,
  322. VideoPortServicesI2C,
  323. (PINTERFACE)&hwDeviceExtension->I2CInterface);
  324. if (Status != NO_ERROR) {
  325. VideoDebugPrint((1, "Perm3QueryInterface: Failed to acquire I2C services\n"));
  326. return Status;
  327. }
  328. hwDeviceExtension->I2CInterfaceAcquired = TRUE;
  329. }
  330. if (((ULONG_PTR)pQueryInterface->InterfaceSpecificData != 0) &&
  331. ((ULONG_PTR)pQueryInterface->InterfaceSpecificData != -1)) {
  332. //
  333. // Get the HwID for the child requesting this interface
  334. //
  335. HwID = VideoPortGetAssociatedDeviceID(
  336. pQueryInterface->InterfaceSpecificData);
  337. } else {
  338. if (hwDeviceExtension->Perm3Capabilities & PERM3_DFP_MON_ATTACHED) {
  339. HwID = PERM3_DFP_MONITOR;
  340. } else {
  341. HwID = PERM3_DDC_MONITOR;
  342. }
  343. }
  344. //
  345. // Initialize the interface
  346. //
  347. Interface->_vddInterface.Size = sizeof(I2CINTERFACE);
  348. Interface->_vddInterface.Version = 2;
  349. Interface->_vddInterface.Context = HwDeviceExtension;
  350. Interface->_vddInterface.InterfaceReference = InterfaceReference;
  351. Interface->_vddInterface.InterfaceDereference = InterfaceDereference;
  352. if (HwID == PERM3_DDC_MONITOR) {
  353. Interface->i2cOpen = I2CBusOpenCRT;
  354. Interface->i2cAccess = I2CBusAccessCRT;
  355. } else if (HwID == PERM3_DFP_MONITOR) {
  356. Interface->i2cOpen = I2CBusOpenDFP;
  357. Interface->i2cAccess = I2CBusAccessDFP;
  358. }
  359. //
  360. // Reference the interface before handing it out
  361. //
  362. Interface->_vddInterface.InterfaceReference(Interface->_vddInterface.Context);
  363. Status = NO_ERROR;
  364. } else {
  365. VideoDebugPrint((1, "Perm3QueryInterface: Size or version incorrect\n"));
  366. Status = ERROR_INVALID_PARAMETER;
  367. }
  368. } else {
  369. VideoDebugPrint((1, "Perm3QueryInteface: Unsupported Interface\n"));
  370. Status = ERROR_INVALID_PARAMETER;
  371. }
  372. VideoDebugPrint((1, "Perm3QueryInterface: Status = 0x%x\n", Status));
  373. return Status;
  374. }