ReactOS 0.4.15-dev-7887-g64a59a1
power.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS DC21x4 Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Power management
5 * COPYRIGHT: Copyright 2023 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "dc21x4.h"
11
12#include <debug.h>
13
14/* FUNCTIONS ******************************************************************/
15
16static
17CODE_SEG("PAGE")
18VOID
20 _In_ PDC21X4_ADAPTER Adapter,
22{
23 ULONG i;
24
25 PAGED_CODE();
26
27 for (i = 0; i < sizeof(*FilterBlock) / sizeof(ULONG); ++i)
28 {
29 DC_WRITE(Adapter, DcCsr1_WakeUpFilter, FilterBlock->AsULONG[i]);
30 }
31}
32
33static
34CODE_SEG("PAGE")
35VOID
37 _In_ PDC21X4_ADAPTER Adapter)
38{
39 DC_PATTERN_FILTER_BLOCK FilterBlock;
40
41 PAGED_CODE();
42
43 /* Save the address filtering */
44 NdisMoveMemory(Adapter->SetupFrameSaved, Adapter->SetupFrame, DC_SETUP_FRAME_SIZE);
45
46 NdisZeroMemory(&FilterBlock, sizeof(FilterBlock));
47
48 // TODO: Convert NDIS patterns to HW filter and prepare a setup frame
49
50 DcDownloadPatternFilter(Adapter, &FilterBlock);
51}
52
53static
54CODE_SEG("PAGE")
55VOID
57 _In_ PDC21X4_ADAPTER Adapter)
58{
59 ULONG WakeUpControl;
60
61 PAGED_CODE();
62
63 /* Clear the wake-up events */
64 WakeUpControl = (DC_WAKE_UP_STATUS_LINK_CHANGE |
67
68 /* Convert NDIS flags to hardware-specific values */
69 if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_LINK_CHANGE)
70 WakeUpControl |= DC_WAKE_UP_CONTROL_LINK_CHANGE;
71 if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
72 WakeUpControl |= DC_WAKE_UP_CONTROL_MAGIC_PACKET;
73#if 0 // TODO: Pattern matching is not yet supported
74 if (Adapter->WakeUpFlags & NDIS_PNP_WAKE_UP_PATTERN_MATCH)
75 WakeUpControl |= DC_WAKE_UP_CONTROL_PATTERN_MATCH;
76#endif
77
78 DC_WRITE(Adapter, DcCsr2_WakeUpControl, WakeUpControl);
79}
80
81static
82CODE_SEG("PAGE")
83VOID
85 _In_ PDC21X4_ADAPTER Adapter)
86{
87 ULONG SiaState, SerialInterface;
88
89 PAGED_CODE();
90
91 /* Stop the receive and transmit processes */
92 DcStopAdapter(Adapter, FALSE);
93
94 Adapter->CurrentInterruptMask = 0;
95
96 /* Enable the link integrity test bit */
97 switch (Adapter->MediaNumber)
98 {
99 case MEDIA_AUI:
100 case MEDIA_BNC:
101 case MEDIA_HMR:
102 {
103 SiaState = DC_READ(Adapter, DcCsr14_SiaTxRx);
104 if (!(SiaState & DC_SIA_TXRX_LINK_TEST))
105 {
106 SiaState |= DC_SIA_TXRX_LINK_TEST;
107 DC_WRITE(Adapter, DcCsr14_SiaTxRx, SiaState);
108 }
109 break;
110 }
111
112 default:
113 break;
114 }
115
116 /* Clear the MDC bit */
117 SerialInterface = DC_READ(Adapter, DcCsr9_SerialInterface);
118 if (SerialInterface & DC_SERIAL_MII_MDC)
119 {
120 SerialInterface &= ~DC_SERIAL_MII_MDC;
121 DC_WRITE(Adapter, DcCsr9_SerialInterface, SerialInterface);
122 }
123
124 /* Unprotect PM access */
125 DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode | DC_BUS_MODE_ON_NOW_UNLOCK);
126
127 /* Program the requested WOL events */
128 DcSetupWakeUpFilter(Adapter);
129 DcProgramWakeUpEvents(Adapter);
130
131 /* Protect PM access */
132 DC_WRITE(Adapter, DcCsr0_BusMode, Adapter->BusMode);
133}
134
135static
136CODE_SEG("PAGE")
137VOID
139 _In_ PDC21X4_ADAPTER Adapter)
140{
141 PAGED_CODE();
142
143 /* Restore the address filtering */
144 NdisMoveMemory(Adapter->SetupFrame, Adapter->SetupFrameSaved, DC_SETUP_FRAME_SIZE);
145
146 /* Re-initialize the chip to leave D3 state */
147 if (Adapter->PrevPowerState == NdisDeviceStateD3)
148 {
150 }
151 else
152 {
153 /* Start the transmit process */
154 Adapter->OpMode |= DC_OPMODE_TX_ENABLE;
155 DC_WRITE(Adapter, DcCsr6_OpMode, Adapter->OpMode);
156
157 /* Load the address recognition RAM */
159 }
160
161 DcStartAdapter(Adapter);
162}
163
164CODE_SEG("PAGE")
165VOID
166NTAPI
170{
171 PDC21X4_ADAPTER Adapter = Context;
172
174
175 PAGED_CODE();
176
177 if (Adapter->PowerState == NdisDeviceStateD0)
178 {
179 DcPowerUp(Adapter);
180 }
181 else
182 {
183 DcPowerDown(Adapter);
184 }
185 Adapter->PrevPowerState = Adapter->PowerState;
186
188}
189
192 _In_ PDC21X4_ADAPTER Adapter,
194{
195 INFO("Power state %u\n", PowerState);
196
197 Adapter->PowerState = PowerState;
198
199 NdisScheduleWorkItem(&Adapter->PowerWorkItem);
200
201 return NDIS_STATUS_PENDING;
202}
203
206 _In_ PDC21X4_ADAPTER Adapter,
208{
209 // TODO: Not implemented
210 ERR("FIXME: Not implemented\n");
212}
213
216 _In_ PDC21X4_ADAPTER Adapter,
218{
219 // TODO: Not implemented
220 ERR("FIXME: Not implemented\n");
222}
223
224VOID
226 _In_ PDC21X4_ADAPTER Adapter,
228{
229 ULONG ConfigValue;
230
231 if (!(Adapter->Features & DC_HAS_POWER_SAVING))
232 return;
233
234 NdisReadPciSlotInformation(Adapter->AdapterHandle,
235 0,
237 &ConfigValue,
238 sizeof(ConfigValue));
239
240 ConfigValue &= ~DC_PCI_DEVICE_CONFIG_SLEEP;
241
242 if (Enable)
243 ConfigValue |= DC_PCI_DEVICE_CONFIG_SNOOZE;
244 else
245 ConfigValue &= ~DC_PCI_DEVICE_CONFIG_SNOOZE;
246
247 NdisWritePciSlotInformation(Adapter->AdapterHandle,
248 0,
250 &ConfigValue,
251 sizeof(ConfigValue));
252}
#define PAGED_CODE()
#define CODE_SEG(...)
unsigned char BOOLEAN
#define ERR(fmt,...)
Definition: debug.h:110
VOID DcStartAdapter(_In_ PDC21X4_ADAPTER Adapter)
Definition: dc21x4.c:168
DECLSPEC_NOINLINE VOID DcStopAdapter(_In_ PDC21X4_ADAPTER Adapter, _In_ BOOLEAN WaitForPackets)
Definition: dc21x4.c:123
NDIS_STATUS DcSetupAdapter(_In_ PDC21X4_ADAPTER Adapter)
Definition: hardware.c:462
FORCEINLINE ULONG DC_READ(_In_ PDC21X4_ADAPTER Adapter, _In_ DC_CSR Register)
Definition: dc21x4.h:262
#define DC_HAS_POWER_SAVING
Definition: dc21x4.h:112
BOOLEAN DcSetupFrameDownload(_In_ PDC21X4_ADAPTER Adapter, _In_ BOOLEAN WaitForCompletion)
Definition: hardware.c:187
#define DC_WRITE(Adapter, Register, Value)
Definition: dc21x4.h:272
#define DC_PCI_DEVICE_CONFIG
Definition: dc21x4hw.h:520
#define DC_WAKE_UP_CONTROL_LINK_CHANGE
Definition: dc21x4hw.h:254
#define DC_OPMODE_TX_ENABLE
Definition: dc21x4hw.h:330
#define DC_WAKE_UP_STATUS_LINK_CHANGE
Definition: dc21x4hw.h:257
@ DcCsr9_SerialInterface
Definition: dc21x4hw.h:183
@ DcCsr14_SiaTxRx
Definition: dc21x4hw.h:190
@ DcCsr6_OpMode
Definition: dc21x4hw.h:180
@ DcCsr0_BusMode
Definition: dc21x4hw.h:172
@ DcCsr1_WakeUpFilter
Definition: dc21x4hw.h:174
@ DcCsr2_WakeUpControl
Definition: dc21x4hw.h:176
#define DC_BUS_MODE_ON_NOW_UNLOCK
Definition: dc21x4hw.h:209
#define DC_WAKE_UP_CONTROL_MAGIC_PACKET
Definition: dc21x4hw.h:255
#define DC_PCI_DEVICE_CONFIG_SNOOZE
Definition: dc21x4hw.h:521
#define DC_SERIAL_MII_MDC
Definition: dc21x4hw.h:382
#define DC_WAKE_UP_CONTROL_PATTERN_MATCH
Definition: dc21x4hw.h:256
#define DC_SETUP_FRAME_SIZE
Definition: dc21x4hw.h:35
#define DC_SIA_TXRX_LINK_TEST
Definition: dc21x4hw.h:466
#define DC_WAKE_UP_STATUS_MAGIC_PACKET
Definition: dc21x4hw.h:258
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define INFO
Definition: debug.h:89
VOID DcPowerSave(_In_ PDC21X4_ADAPTER Adapter, _In_ BOOLEAN Enable)
Definition: power.c:225
NDIS_STATUS DcSetPower(_In_ PDC21X4_ADAPTER Adapter, _In_ NDIS_DEVICE_POWER_STATE PowerState)
Definition: power.c:191
VOID NTAPI DcPowerWorker(_In_ PNDIS_WORK_ITEM WorkItem, _In_opt_ PVOID Context)
Definition: power.c:167
static VOID DcPowerDown(_In_ PDC21X4_ADAPTER Adapter)
Definition: power.c:84
static VOID DcDownloadPatternFilter(_In_ PDC21X4_ADAPTER Adapter, _In_ PDC_PATTERN_FILTER_BLOCK FilterBlock)
Definition: power.c:19
NDIS_STATUS DcRemoveWakeUpPattern(_In_ PDC21X4_ADAPTER Adapter, _In_ PNDIS_PM_PACKET_PATTERN PmPattern)
Definition: power.c:205
NDIS_STATUS DcAddWakeUpPattern(_In_ PDC21X4_ADAPTER Adapter, _In_ PNDIS_PM_PACKET_PATTERN PmPattern)
Definition: power.c:215
static VOID DcSetupWakeUpFilter(_In_ PDC21X4_ADAPTER Adapter)
Definition: power.c:36
static VOID DcProgramWakeUpEvents(_In_ PDC21X4_ADAPTER Adapter)
Definition: power.c:56
static VOID DcPowerUp(_In_ PDC21X4_ADAPTER Adapter)
Definition: power.c:138
ULONG EXPORT NdisReadPciSlotInformation(IN NDIS_HANDLE NdisAdapterHandle, IN ULONG SlotNumber, IN ULONG Offset, IN PVOID Buffer, IN ULONG Length)
Definition: hardware.c:180
ULONG EXPORT NdisWritePciSlotInformation(IN NDIS_HANDLE NdisAdapterHandle, IN ULONG SlotNumber, IN ULONG Offset, IN PVOID Buffer, IN ULONG Length)
Definition: hardware.c:199
NDIS_STATUS EXPORT NdisScheduleWorkItem(IN PNDIS_WORK_ITEM pWorkItem)
Definition: misc.c:467
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define MEDIA_AUI
Definition: media.h:48
#define MEDIA_HMR
Definition: media.h:56
#define MEDIA_BNC
Definition: media.h:47
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define NdisMSetInformationComplete(MiniportAdapterHandle, Status)
Definition: ndis.h:5762
#define NDIS_STATUS_PENDING
Definition: ndis.h:347
#define NdisZeroMemory(Destination, Length)
Definition: ndis.h:3926
#define NDIS_STATUS_NOT_SUPPORTED
Definition: ndis.h:479
#define NDIS_STATUS_SUCCESS
Definition: ndis.h:346
#define NdisMoveMemory(Destination, Source, Length)
Definition: ndis.h:3896
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define NDIS_PNP_WAKE_UP_MAGIC_PACKET
Definition: ntddndis.h:372
enum _NDIS_DEVICE_POWER_STATE NDIS_DEVICE_POWER_STATE
int NDIS_STATUS
Definition: ntddndis.h:475
#define NDIS_PNP_WAKE_UP_LINK_CHANGE
Definition: ntddndis.h:374
@ NdisDeviceStateD0
Definition: ntddndis.h:38
@ NdisDeviceStateD3
Definition: ntddndis.h:41
#define NDIS_PNP_WAKE_UP_PATTERN_MATCH
Definition: ntddndis.h:373
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
NDIS_DEVICE_POWER_STATE PowerState
Definition: dc21x4.h:193
NDIS_HANDLE AdapterHandle
Definition: dc21x4.h:158
NDIS_DEVICE_POWER_STATE PrevPowerState
Definition: dc21x4.h:194
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3034
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3287