Sync with trunk r64509.
[reactos.git] / drivers / bus / pcmcia / pcmcia.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: drivers/bus/pcmcia/pcmcia.c
5 * PURPOSE: PCMCIA Bus Driver
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 */
8
9 #include <pcmcia.h>
10
11 //#define NDEBUG
12 #include <debug.h>
13
14 BOOLEAN IoctlEnabled;
15
16 DRIVER_DISPATCH PcmciaCreateClose;
17
18 NTSTATUS
19 NTAPI
20 PcmciaCreateClose(PDEVICE_OBJECT DeviceObject,
21 PIRP Irp)
22 {
23 UNREFERENCED_PARAMETER(DeviceObject);
24
25 Irp->IoStatus.Status = STATUS_SUCCESS;
26 Irp->IoStatus.Information = 0;
27
28 DPRINT("PCMCIA: Create/Close\n");
29
30 IoCompleteRequest(Irp, IO_NO_INCREMENT);
31
32 return STATUS_SUCCESS;
33 }
34
35 DRIVER_DISPATCH PcmciaDeviceControl;
36
37 NTSTATUS
38 NTAPI
39 PcmciaDeviceControl(PDEVICE_OBJECT DeviceObject,
40 PIRP Irp)
41 {
42 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
43 NTSTATUS Status;
44
45 UNREFERENCED_PARAMETER(DeviceObject);
46
47 DPRINT("PCMCIA: DeviceIoControl\n");
48
49 Irp->IoStatus.Information = 0;
50
51 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
52 {
53 default:
54 DPRINT1("PCMCIA: Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
55 Status = STATUS_NOT_SUPPORTED;
56 }
57
58 Irp->IoStatus.Status = Status;
59
60 IoCompleteRequest(Irp, IO_NO_INCREMENT);
61
62 return Status;
63 }
64
65 DRIVER_UNLOAD PcmciaUnload;
66
67 VOID
68 NTAPI
69 PcmciaUnload(PDRIVER_OBJECT DriverObject)
70 {
71 UNREFERENCED_PARAMETER(DriverObject);
72 DPRINT("PCMCIA: Unload\n");
73 }
74
75 DRIVER_DISPATCH PcmciaPlugPlay;
76
77 NTSTATUS
78 NTAPI
79 PcmciaPlugPlay(PDEVICE_OBJECT DeviceObject,
80 PIRP Irp)
81 {
82 PPCMCIA_COMMON_EXTENSION Common = DeviceObject->DeviceExtension;
83
84 DPRINT("PCMCIA: PnP\n");
85 if (Common->IsFDO)
86 {
87 return PcmciaFdoPlugPlay((PPCMCIA_FDO_EXTENSION)Common,
88 Irp);
89 }
90 else
91 {
92 return PcmciaPdoPlugPlay((PPCMCIA_PDO_EXTENSION)Common,
93 Irp);
94 }
95 }
96
97 DRIVER_DISPATCH PcmciaPower;
98
99 NTSTATUS
100 NTAPI
101 PcmciaPower(PDEVICE_OBJECT DeviceObject,
102 PIRP Irp)
103 {
104 PPCMCIA_COMMON_EXTENSION Common = DeviceObject->DeviceExtension;
105 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
106 NTSTATUS Status;
107
108 switch (IrpSp->MinorFunction)
109 {
110 case IRP_MN_QUERY_POWER:
111 /* I don't see any reason that we should care */
112 DPRINT("PCMCIA: IRP_MN_QUERY_POWER\n");
113 Status = STATUS_SUCCESS;
114 break;
115
116 case IRP_MN_POWER_SEQUENCE:
117 DPRINT("PCMCIA: IRP_MN_POWER_SEQUENCE\n");
118 RtlCopyMemory(IrpSp->Parameters.PowerSequence.PowerSequence,
119 &Common->PowerSequence,
120 sizeof(POWER_SEQUENCE));
121 Status = STATUS_SUCCESS;
122 break;
123
124 case IRP_MN_WAIT_WAKE:
125 /* Not really sure about this */
126 DPRINT("PCMCIA: IRP_MN_WAIT_WAKE\n");
127 Status = STATUS_NOT_SUPPORTED;
128 break;
129
130 case IRP_MN_SET_POWER:
131 DPRINT("PCMCIA: IRP_MN_SET_POWER\n");
132 if (IrpSp->Parameters.Power.Type == SystemPowerState)
133 {
134 Common->SystemPowerState = IrpSp->Parameters.Power.State.SystemState;
135
136 Status = STATUS_SUCCESS;
137 }
138 else
139 {
140 Common->DevicePowerState = IrpSp->Parameters.Power.State.DeviceState;
141
142 /* Update the POWER_SEQUENCE struct */
143 if (Common->DevicePowerState <= PowerDeviceD1)
144 Common->PowerSequence.SequenceD1++;
145
146 if (Common->DevicePowerState <= PowerDeviceD2)
147 Common->PowerSequence.SequenceD2++;
148
149 if (Common->DevicePowerState <= PowerDeviceD3)
150 Common->PowerSequence.SequenceD3++;
151
152 /* Start the underlying device if we are handling this for a PDO */
153 if (!Common->IsFDO)
154 Status = PcmciaPdoSetPowerState((PPCMCIA_PDO_EXTENSION)Common);
155 else
156 Status = STATUS_SUCCESS;
157 }
158
159 /* Report that we changed state to the Power Manager */
160 PoSetPowerState(DeviceObject,
161 IrpSp->Parameters.Power.Type,
162 IrpSp->Parameters.Power.State);
163 break;
164
165 default:
166 DPRINT1("PCMCIA: Invalid MN code in MJ_POWER handler %x\n", IrpSp->MinorFunction);
167 ASSERT(FALSE);
168 Status = STATUS_INVALID_DEVICE_REQUEST;
169 break;
170 }
171
172 Irp->IoStatus.Status = Status;
173 Irp->IoStatus.Information = 0;
174
175 IoCompleteRequest(Irp, IO_NO_INCREMENT);
176
177 return Status;
178 }
179
180 DRIVER_ADD_DEVICE PcmciaAddDevice;
181
182 NTSTATUS
183 NTAPI
184 PcmciaAddDevice(PDRIVER_OBJECT DriverObject,
185 PDEVICE_OBJECT PhysicalDeviceObject)
186 {
187 PPCMCIA_FDO_EXTENSION FdoExt;
188 PDEVICE_OBJECT Fdo;
189 NTSTATUS Status;
190
191 DPRINT("PCMCIA: AddDevice\n");
192
193 Status = IoCreateDevice(DriverObject,
194 sizeof(*FdoExt),
195 NULL,
196 FILE_DEVICE_BUS_EXTENDER,
197 FILE_DEVICE_SECURE_OPEN,
198 FALSE,
199 &Fdo);
200 if (!NT_SUCCESS(Status))
201 return Status;
202
203 FdoExt = Fdo->DeviceExtension;
204
205 RtlZeroMemory(FdoExt, sizeof(*FdoExt));
206
207 InitializeListHead(&FdoExt->ChildDeviceList);
208 KeInitializeSpinLock(&FdoExt->Lock);
209
210 FdoExt->Common.Self = Fdo;
211 FdoExt->Common.IsFDO = TRUE;
212 FdoExt->Common.State = dsStopped;
213
214 FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
215 PhysicalDeviceObject);
216
217 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
218
219 return STATUS_SUCCESS;
220 }
221
222 NTSTATUS
223 NTAPI
224 DriverEntry(PDRIVER_OBJECT DriverObject,
225 PUNICODE_STRING RegistryPath)
226 {
227 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
228 NTSTATUS Status;
229
230 UNREFERENCED_PARAMETER(RegistryPath);
231
232 DPRINT1("PCMCIA: DriverEntry\n");
233
234 DriverObject->MajorFunction[IRP_MJ_CREATE] = PcmciaCreateClose;
235 DriverObject->MajorFunction[IRP_MJ_CLOSE] = PcmciaCreateClose;
236 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PcmciaDeviceControl;
237 DriverObject->MajorFunction[IRP_MJ_PNP] = PcmciaPlugPlay;
238 DriverObject->MajorFunction[IRP_MJ_POWER] = PcmciaPower;
239
240 DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
241 DriverObject->DriverUnload = PcmciaUnload;
242
243 RtlZeroMemory(QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
244
245 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
246 QueryTable[0].Name = L"IoctlInterface";
247 QueryTable[0].EntryContext = &IoctlEnabled;
248
249 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
250 L"Pcmcia\\Parameters",
251 QueryTable,
252 NULL,
253 NULL);
254 if (!NT_SUCCESS(Status))
255 {
256 /* Key not present so assume disabled */
257 IoctlEnabled = FALSE;
258 }
259
260 DPRINT("PCMCIA: Ioctl interface %s\n",
261 (IoctlEnabled ? "enabled" : "disabled"));
262
263 return STATUS_SUCCESS;
264 }