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