Synchronize with trunk.
[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, IrpSp->Parameters.Power.Type, IrpSp->Parameters.Power.State);
161 break;
162
163 default:
164 DPRINT1("PCMCIA: Invalid MN code in MJ_POWER handler %x\n", IrpSp->MinorFunction);
165 ASSERT(FALSE);
166 Status = STATUS_INVALID_DEVICE_REQUEST;
167 break;
168 }
169
170 Irp->IoStatus.Status = Status;
171 Irp->IoStatus.Information = 0;
172
173 IoCompleteRequest(Irp, IO_NO_INCREMENT);
174
175 return Status;
176 }
177
178 DRIVER_ADD_DEVICE PcmciaAddDevice;
179
180 NTSTATUS
181 NTAPI
182 PcmciaAddDevice(PDRIVER_OBJECT DriverObject,
183 PDEVICE_OBJECT PhysicalDeviceObject)
184 {
185 PPCMCIA_FDO_EXTENSION FdoExt;
186 PDEVICE_OBJECT Fdo;
187 NTSTATUS Status;
188
189 DPRINT("PCMCIA: AddDevice\n");
190
191 Status = IoCreateDevice(DriverObject,
192 sizeof(*FdoExt),
193 NULL,
194 FILE_DEVICE_BUS_EXTENDER,
195 FILE_DEVICE_SECURE_OPEN,
196 FALSE,
197 &Fdo);
198 if (!NT_SUCCESS(Status)) return Status;
199
200 FdoExt = Fdo->DeviceExtension;
201
202 RtlZeroMemory(FdoExt, sizeof(*FdoExt));
203
204 InitializeListHead(&FdoExt->ChildDeviceList);
205 KeInitializeSpinLock(&FdoExt->Lock);
206
207 FdoExt->Common.Self = Fdo;
208 FdoExt->Common.IsFDO = TRUE;
209 FdoExt->Common.State = dsStopped;
210
211 FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
212 PhysicalDeviceObject);
213
214 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
215
216 return STATUS_SUCCESS;
217 }
218
219 NTSTATUS
220 NTAPI
221 DriverEntry(PDRIVER_OBJECT DriverObject,
222 PUNICODE_STRING RegistryPath)
223 {
224 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
225 NTSTATUS Status;
226
227 UNREFERENCED_PARAMETER(RegistryPath);
228
229 DPRINT1("PCMCIA: DriverEntry\n");
230
231 DriverObject->MajorFunction[IRP_MJ_CREATE] = PcmciaCreateClose;
232 DriverObject->MajorFunction[IRP_MJ_CLOSE] = PcmciaCreateClose;
233 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PcmciaDeviceControl;
234 DriverObject->MajorFunction[IRP_MJ_PNP] = PcmciaPlugPlay;
235 DriverObject->MajorFunction[IRP_MJ_POWER] = PcmciaPower;
236
237 DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
238 DriverObject->DriverUnload = PcmciaUnload;
239
240 RtlZeroMemory(QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
241
242 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
243 QueryTable[0].Name = L"IoctlInterface";
244 QueryTable[0].EntryContext = &IoctlEnabled;
245
246 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
247 L"Pcmcia\\Parameters",
248 QueryTable,
249 NULL,
250 NULL);
251 if (!NT_SUCCESS(Status))
252 {
253 /* Key not present so assume disabled */
254 IoctlEnabled = FALSE;
255 }
256
257 DPRINT("PCMCIA: Ioctl interface %s\n",
258 (IoctlEnabled ? "enabled" : "disabled"));
259
260 return STATUS_SUCCESS;
261 }