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.

728 lines
20 KiB

  1. /***************************************************************************\
  2. *
  3. * ************************
  4. * * MINIPORT SAMPLE CODE *
  5. * ************************
  6. *
  7. * Module Name:
  8. *
  9. * power.c
  10. *
  11. * Abstract:
  12. *
  13. * This module contains the code that implements the power management features
  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. #if defined(ALLOC_PRAGMA)
  27. #pragma alloc_text(PAGE,Perm3GetPowerState)
  28. #pragma alloc_text(PAGE,Perm3SetPowerState)
  29. #pragma alloc_text(PAGE,Perm3GetChildDescriptor)
  30. #pragma alloc_text(PAGE,ProgramDFP)
  31. #pragma alloc_text(PAGE,GetDFPEdid)
  32. #pragma alloc_text(PAGE,I2CWriteClock)
  33. #pragma alloc_text(PAGE,I2CWriteData)
  34. #pragma alloc_text(PAGE,I2CReadClock)
  35. #pragma alloc_text(PAGE,I2CReadData)
  36. #pragma alloc_text(PAGE,I2CWriteClockDFP)
  37. #pragma alloc_text(PAGE,I2CWriteDataDFP)
  38. #pragma alloc_text(PAGE,I2CReadClockDFP)
  39. #pragma alloc_text(PAGE,I2CReadDataDFP)
  40. #endif
  41. DDC_CONTROL
  42. DDCControlCRT = {
  43. sizeof(DDC_CONTROL),
  44. I2CWriteClock,
  45. I2CWriteData,
  46. I2CReadClock,
  47. I2CReadData,
  48. 0
  49. };
  50. DDC_CONTROL
  51. DDCControlDFP = {
  52. sizeof(DDC_CONTROL),
  53. I2CWriteClockDFP,
  54. I2CWriteDataDFP,
  55. I2CReadClockDFP,
  56. I2CReadDataDFP,
  57. 0
  58. };
  59. VP_STATUS
  60. Perm3GetPowerState(
  61. PVOID HwDeviceExtension,
  62. ULONG HwId,
  63. PVIDEO_POWER_MANAGEMENT VideoPowerControl
  64. )
  65. /*+++
  66. Routine Description:
  67. Queries whether the device can support the requested power state.
  68. Arguments:
  69. HwDeviceExtension
  70. Pointer to our hardware device extension structure.
  71. HwId
  72. Points to a 32-bit number that uniquely identifies the device that
  73. the miniport should query.
  74. VideoPowerControl
  75. Points to a VIDEO_POWER_MANAGEMENT structure that specifies the
  76. power state for which support is being queried.
  77. Return Value:
  78. NO_ERROR, if the device supports the requested power state, or error code.
  79. ---*/
  80. {
  81. VP_STATUS status;
  82. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  83. VideoDebugPrint((3, "Perm3: Perm3GetPowerState: hwId(0x%x) state = %d\n",
  84. HwId, VideoPowerControl->PowerState ));
  85. switch(HwId) {
  86. case PERM3_DDC_MONITOR:
  87. case PERM3_NONDDC_MONITOR:
  88. switch ( VideoPowerControl->PowerState ) {
  89. case VideoPowerOn:
  90. case VideoPowerStandBy:
  91. case VideoPowerSuspend:
  92. case VideoPowerOff:
  93. case VideoPowerHibernate:
  94. case VideoPowerShutdown:
  95. status = NO_ERROR;
  96. break;
  97. default:
  98. VideoDebugPrint((0, "Perm3: Perm3GetPowerState: Unknown monitor PowerState = %d\n",
  99. VideoPowerControl->PowerState ));
  100. ASSERT(FALSE);
  101. status = ERROR_INVALID_PARAMETER;
  102. }
  103. break;
  104. case DISPLAY_ADAPTER_HW_ID:
  105. switch ( VideoPowerControl->PowerState ) {
  106. case VideoPowerOn:
  107. case VideoPowerStandBy:
  108. case VideoPowerSuspend:
  109. case VideoPowerOff:
  110. case VideoPowerHibernate:
  111. case VideoPowerShutdown:
  112. status = NO_ERROR;
  113. break;
  114. default:
  115. VideoDebugPrint((0, "Perm3: Perm3GetPowerState: Unknown adapter PowerState = %d\n",
  116. VideoPowerControl->PowerState ));
  117. ASSERT(FALSE);
  118. status = ERROR_INVALID_PARAMETER;
  119. }
  120. break;
  121. default:
  122. VideoDebugPrint((0, "Perm3: Perm3GetPowerState: Unknown hwId(0x%x)", HwId));
  123. ASSERT(FALSE);
  124. status = ERROR_INVALID_PARAMETER;
  125. }
  126. return(status);
  127. }
  128. VP_STATUS
  129. Perm3SetPowerState(
  130. PVOID HwDeviceExtension,
  131. ULONG HwId,
  132. PVIDEO_POWER_MANAGEMENT VideoPowerControl
  133. )
  134. /*+++
  135. Routine Description:
  136. Sets the power state of the specified device.
  137. Arguments:
  138. HwDeviceExtension
  139. Pointer to our hardware device extension structure.
  140. HwId
  141. Points to a 32-bit number that uniquely identifies the device
  142. for which the miniport should set the power state.
  143. VideoPowerControl
  144. Points to a VIDEO_POWER_MANAGEMENT structure that specifies the
  145. power state to be set.
  146. Return Value:
  147. NO_ERROR
  148. ---*/
  149. {
  150. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  151. ULONG Polarity;
  152. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  153. VideoDebugPrint((3, "Perm3: Perm3SetPowerState: hwId(0x%x) state = %d\n",
  154. HwId, VideoPowerControl->PowerState));
  155. switch(HwId) {
  156. case PERM3_DDC_MONITOR:
  157. case PERM3_NONDDC_MONITOR:
  158. Polarity = VideoPortReadRegisterUlong(VIDEO_CONTROL);
  159. Polarity &= ~VC_DPMS_MASK;
  160. switch (VideoPowerControl->PowerState) {
  161. case VideoPowerOn:
  162. VideoPortWriteRegisterUlong(VIDEO_CONTROL,
  163. Polarity | hwDeviceExtension->VideoControlMonitorON);
  164. break;
  165. case VideoPowerStandBy:
  166. VideoPortWriteRegisterUlong(VIDEO_CONTROL,
  167. Polarity | VC_DPMS_STANDBY);
  168. break;
  169. case VideoPowerSuspend:
  170. VideoPortWriteRegisterUlong(VIDEO_CONTROL,
  171. Polarity | VC_DPMS_SUSPEND);
  172. break;
  173. case VideoPowerShutdown:
  174. case VideoPowerOff:
  175. VideoPortWriteRegisterUlong(VIDEO_CONTROL,
  176. Polarity | VC_DPMS_OFF);
  177. break;
  178. case VideoPowerHibernate:
  179. //
  180. // The monitor for the vga enabled video device must
  181. // stay on at hibernate.
  182. //
  183. break;
  184. default:
  185. VideoDebugPrint((0, "Perm3: Perm3GetPowerState: Unknown monitor PowerState(0x%x)\n",
  186. VideoPowerControl->PowerState));
  187. ASSERT(FALSE);
  188. }
  189. //
  190. // Track the current monitor power state
  191. //
  192. hwDeviceExtension->bMonitorPoweredOn =
  193. (VideoPowerControl->PowerState == VideoPowerOn) ||
  194. (VideoPowerControl->PowerState == VideoPowerHibernate);
  195. break;
  196. case DISPLAY_ADAPTER_HW_ID:
  197. switch (VideoPowerControl->PowerState) {
  198. case VideoPowerOn:
  199. if ((hwDeviceExtension->PreviousPowerState == VideoPowerOff) ||
  200. (hwDeviceExtension->PreviousPowerState == VideoPowerSuspend) ||
  201. (hwDeviceExtension->PreviousPowerState == VideoPowerHibernate)){
  202. //
  203. // Turn off the monitor while we power back up so
  204. // the user doesn't see any screen corruption
  205. //
  206. Polarity = VideoPortReadRegisterUlong(VIDEO_CONTROL);
  207. Polarity &= ~VC_DPMS_MASK;
  208. VideoPortWriteRegisterUlong(VIDEO_CONTROL, Polarity | VC_DPMS_OFF);
  209. //
  210. // Miniport driver can not rely on video bios to
  211. // initialize the device registers while resuming
  212. // from VideoPowerOff and VideoPowerSuspend.
  213. //
  214. // This is also true for the secondary (vga disabled)
  215. // video device while resuming from VideoPowerHibernate
  216. //
  217. InitializePostRegisters(hwDeviceExtension);
  218. }
  219. break;
  220. case VideoPowerStandBy:
  221. case VideoPowerSuspend:
  222. case VideoPowerOff:
  223. case VideoPowerHibernate:
  224. break;
  225. case VideoPowerShutdown:
  226. //
  227. // We need to make sure no interrupts will be generated
  228. // after the device being powered down
  229. //
  230. VideoPortWriteRegisterUlong(INT_ENABLE, 0);
  231. break;
  232. default:
  233. VideoDebugPrint((0, "Perm3: Perm3GetPowerState: Unknown adapter PowerState(0x%x)\n",
  234. VideoPowerControl->PowerState));
  235. ASSERT(FALSE);
  236. }
  237. hwDeviceExtension->PreviousPowerState = VideoPowerControl->PowerState;
  238. break;
  239. default:
  240. VideoDebugPrint((0, "Perm3: Perm3SetPowerState: Unknown hwId(0x%x)\n",
  241. HwId));
  242. ASSERT(FALSE);
  243. }
  244. return(NO_ERROR);
  245. }
  246. ULONG
  247. Perm3GetChildDescriptor(
  248. PVOID HwDeviceExtension,
  249. PVIDEO_CHILD_ENUM_INFO pChildInfo,
  250. PVIDEO_CHILD_TYPE pChildType,
  251. PUCHAR pChildDescriptor,
  252. PULONG pUId,
  253. PULONG Unused
  254. )
  255. /*+++
  256. Routine Description:
  257. Enumerates all child devices attached to the specified device.
  258. This includes DDC monitors attached to the board, as well as other devices
  259. which may be connected to a proprietary bus.
  260. Arguments:
  261. HwDeviceExtension
  262. Pointer to our hardware device extension structure.
  263. ChildEnumInfo
  264. Pointer to VIDEO_CHILD_ENUM_INFO structure that describes the
  265. device being enumerated.
  266. pChildType
  267. Points to a location in which the miniport returns the type of
  268. child being enumerated.
  269. pChildDescriptor
  270. Points to a buffer in which the miniport can return data that
  271. identifies the device.
  272. pUId
  273. Points to the location in which the miniport returns a unique
  274. 32-bit identifier for this device.
  275. pUnused
  276. Is unused and must be set to zero.
  277. Return Value:
  278. ERROR_MORE_DATA
  279. There are more devices to be enumerated.
  280. ERROR_NO_MORE_DEVICES
  281. There are no more devices to be enumerated.
  282. ERROR_INVALID_NAME
  283. The miniport could not enumerate the child device identified in
  284. ChildEnumInfo but does have more devices to be enumerated.
  285. ---*/
  286. {
  287. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  288. VideoDebugPrint((3, "Perm3: Perm3GetChildDescriptor called\n"));
  289. switch(pChildInfo->ChildIndex) {
  290. case 0:
  291. //
  292. // Case 0 is used to enumerate devices found by the ACPI firmware.
  293. // We don't currently support ACPI devices
  294. //
  295. break;
  296. case 1:
  297. //
  298. // Treat index 1 as monitor
  299. //
  300. *pChildType = Monitor;
  301. //
  302. // First we search for a DFP monitor
  303. //
  304. if (GetDFPEdid(hwDeviceExtension,
  305. pChildDescriptor,
  306. pChildInfo->ChildDescriptorSize)) {
  307. //
  308. // found a DFP monitor
  309. //
  310. *pUId = PERM3_DFP_MONITOR;
  311. return(VIDEO_ENUM_MORE_DEVICES);
  312. }
  313. //
  314. // If we didn't find a DFP, try to detect a DDC CRT monitor
  315. //
  316. if(VideoPortDDCMonitorHelper(HwDeviceExtension,
  317. &DDCControlCRT,
  318. pChildDescriptor,
  319. pChildInfo->ChildDescriptorSize)) {
  320. //
  321. // found a DDC monitor
  322. //
  323. *pUId = PERM3_DDC_MONITOR;
  324. } else {
  325. //
  326. // failed: assume non-DDC monitor
  327. //
  328. *pUId = PERM3_NONDDC_MONITOR;
  329. }
  330. return(VIDEO_ENUM_MORE_DEVICES);
  331. }
  332. return(ERROR_NO_MORE_DEVICES);
  333. }
  334. VOID
  335. ProgramDFP(
  336. PHW_DEVICE_EXTENSION hwDeviceExtension
  337. )
  338. /*+++
  339. Routine Description:
  340. Program the Perm3 chip to use DFP or not use DFP, depending on whether
  341. PERM3_DFP and PERM3_DFP_MON_ATTACHED are enabled in Perm3Capabilities.
  342. ---*/
  343. {
  344. //
  345. // We only try this on boards that are DFP-capable.
  346. //
  347. if (hwDeviceExtension->Perm3Capabilities & PERM3_DFP) {
  348. ULONG rdMisc, vsConf, vsBCtl;
  349. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  350. P3RDRAMDAC *pP3RDRegs = (P3RDRAMDAC *)hwDeviceExtension->pRamdac;
  351. //
  352. // Get values of registers that we are going to trash
  353. //
  354. P3RD_READ_INDEX_REG(P3RD_MISC_CONTROL, rdMisc);
  355. //
  356. // Find out the values of the registers
  357. //
  358. vsConf = VideoPortReadRegisterUlong(VSTREAM_CONFIG);
  359. vsBCtl = VideoPortReadRegisterUlong(VSTREAM_B_CONTROL);
  360. //
  361. // Clear these bits
  362. //
  363. rdMisc &= ~P3RD_MISC_CONTROL_VSB_OUTPUT_ENABLED;
  364. vsConf &= ~VSTREAM_CONFIG_UNITMODE_MASK;
  365. vsBCtl &= ~VSTREAM_B_CONTROL_RAMDAC_ENABLE;
  366. if (hwDeviceExtension->Perm3Capabilities & PERM3_DFP_MON_ATTACHED) {
  367. //
  368. // Enable flat panel output as follows:
  369. //
  370. rdMisc |= P3RD_MISC_CONTROL_VSB_OUTPUT_ENABLED;
  371. vsConf |= VSTREAM_CONFIG_UNITMODE_FP;
  372. vsBCtl |= VSTREAM_B_CONTROL_RAMDAC_ENABLE;
  373. }
  374. else {
  375. //
  376. // set up the registers for non-DFP mode.
  377. //
  378. rdMisc &= (~P3RD_MISC_CONTROL_VSB_OUTPUT_ENABLED);
  379. vsConf |= VSTREAM_CONFIG_UNITMODE_CRT;
  380. vsBCtl |= VSTREAM_B_CONTROL_RAMDAC_DISABLE;
  381. }
  382. VideoDebugPrint((3, "Perm3: P3RD_ProgramDFP: PXRXCaps 0x%x, misc 0x%x, conf 0x%x, ctl 0x%x\n",
  383. hwDeviceExtension->Perm3Capabilities, rdMisc, vsConf, vsBCtl));
  384. //
  385. // Program the registers
  386. //
  387. P3RD_LOAD_INDEX_REG(P3RD_MISC_CONTROL, rdMisc);
  388. VideoPortWriteRegisterUlong(VSTREAM_CONFIG, vsConf);
  389. VideoPortWriteRegisterUlong(VSTREAM_B_CONTROL, vsBCtl);
  390. }
  391. }
  392. VOID
  393. I2CWriteClock(
  394. PVOID HwDeviceExtension,
  395. UCHAR data
  396. )
  397. {
  398. const ULONG nbitClock = 3;
  399. const ULONG ClockMask = 1 << nbitClock;
  400. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  401. ULONG ul;
  402. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  403. ul = VideoPortReadRegisterUlong(DDC_DATA);
  404. ul &= ~ClockMask;
  405. ul |= (data & 1) << nbitClock;
  406. VideoPortWriteRegisterUlong(DDC_DATA, ul);
  407. }
  408. VOID
  409. I2CWriteData(
  410. PVOID HwDeviceExtension,
  411. UCHAR data
  412. )
  413. {
  414. const ULONG nbitData = 2;
  415. const ULONG DataMask = 1 << nbitData;
  416. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  417. ULONG ul;
  418. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  419. ul = VideoPortReadRegisterUlong(DDC_DATA);
  420. ul &= ~DataMask;
  421. ul |= ((data & 1) << nbitData);
  422. VideoPortWriteRegisterUlong(DDC_DATA, ul);
  423. }
  424. BOOLEAN
  425. I2CReadClock(
  426. PVOID HwDeviceExtension
  427. )
  428. {
  429. const ULONG nbitClock = 1;
  430. const ULONG ClockMask = 1 << nbitClock;
  431. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  432. ULONG ul;
  433. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  434. ul = VideoPortReadRegisterUlong(DDC_DATA);
  435. ul &= ClockMask;
  436. ul >>= nbitClock;
  437. return((BOOLEAN)ul);
  438. }
  439. BOOLEAN
  440. I2CReadData(
  441. PVOID HwDeviceExtension
  442. )
  443. {
  444. const ULONG nbitData = 0;
  445. const ULONG DataMask = 1 << nbitData;
  446. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  447. ULONG ul;
  448. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  449. ul = VideoPortReadRegisterUlong(DDC_DATA);
  450. ul &= DataMask;
  451. ul >>= nbitData;
  452. return((BOOLEAN)ul);
  453. }
  454. BOOLEAN
  455. I2CReadDataDFP(
  456. PHW_DEVICE_EXTENSION hwDeviceExtension
  457. )
  458. {
  459. ULONG ul;
  460. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  461. ul = VideoPortReadRegisterUlong(VSTREAM_SERIAL_CONTROL);
  462. ul &= VSTREAM_SERIAL_CONTROL_DATAIN;
  463. return (ul != 0);
  464. }
  465. BOOLEAN
  466. I2CReadClockDFP(
  467. PHW_DEVICE_EXTENSION hwDeviceExtension
  468. )
  469. {
  470. ULONG ul;
  471. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  472. ul = VideoPortReadRegisterUlong(VSTREAM_SERIAL_CONTROL);
  473. ul &= VSTREAM_SERIAL_CONTROL_CLKIN;
  474. return (ul != 0);
  475. }
  476. VOID
  477. I2CWriteDataDFP(
  478. PHW_DEVICE_EXTENSION hwDeviceExtension,
  479. UCHAR data
  480. )
  481. {
  482. ULONG ul = 0x0000E000;
  483. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  484. ul |= VideoPortReadRegisterUlong(VSTREAM_SERIAL_CONTROL);
  485. ul &= ~VSTREAM_SERIAL_CONTROL_DATAOUT;
  486. if(data & 1)
  487. ul |= VSTREAM_SERIAL_CONTROL_DATAOUT;
  488. VideoPortWriteRegisterUlong (VSTREAM_SERIAL_CONTROL, ul);
  489. }
  490. VOID
  491. I2CWriteClockDFP(
  492. PHW_DEVICE_EXTENSION hwDeviceExtension,
  493. UCHAR data
  494. )
  495. {
  496. ULONG ul = 0x0000E000;
  497. pPerm3ControlRegMap pCtrlRegs = hwDeviceExtension->ctrlRegBase[0];
  498. ul |= VideoPortReadRegisterUlong(VSTREAM_SERIAL_CONTROL);
  499. ul &= ~VSTREAM_SERIAL_CONTROL_CLKOUT;
  500. if (data & 1)
  501. ul |= VSTREAM_SERIAL_CONTROL_CLKOUT;
  502. VideoPortWriteRegisterUlong (VSTREAM_SERIAL_CONTROL, ul);
  503. }
  504. BOOLEAN
  505. GetDFPEdid(
  506. PHW_DEVICE_EXTENSION hwDeviceExtension,
  507. PUCHAR EdidBuffer,
  508. LONG EdidSize
  509. )
  510. {
  511. BOOLEAN DFPPresent = FALSE;
  512. //
  513. // If this board is capable of driving a DFP then try using DDC to see
  514. // if there is a monitor there.
  515. //
  516. if (hwDeviceExtension->Perm3Capabilities & PERM3_DFP) {
  517. //
  518. // Let's say that we have a monitor attached
  519. //
  520. hwDeviceExtension->Perm3Capabilities |= PERM3_DFP_MON_ATTACHED;
  521. //
  522. // Set up the DFP accordingly
  523. //
  524. ProgramDFP(hwDeviceExtension);
  525. DFPPresent = VideoPortDDCMonitorHelper(hwDeviceExtension,
  526. &DDCControlDFP,
  527. EdidBuffer,
  528. EdidSize);
  529. }
  530. //
  531. // If the board doesn't support flat panel or one isn't attached then
  532. // configure ourselves for non-DFP working.
  533. //
  534. if (!DFPPresent) {
  535. //
  536. // Well DDC says we don't have a DFP monitor attached, clear this bit
  537. //
  538. hwDeviceExtension->Perm3Capabilities &= ~PERM3_DFP_MON_ATTACHED;
  539. //
  540. // Set up the DFP accordingly
  541. //
  542. ProgramDFP(hwDeviceExtension);
  543. }
  544. return (DFPPresent);
  545. }