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