xref: /reactos/drivers/bus/pcmcia/pcmcia.c (revision 4561998a)
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 }
265