2010-04-15 01:59:15 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* FILE: drivers/bus/pcmcia/pcmcia.c
|
|
|
|
* PURPOSE: PCMCIA Bus Driver
|
|
|
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <pcmcia.h>
|
|
|
|
|
|
|
|
//#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2010-04-17 23:32:29 +00:00
|
|
|
BOOLEAN IoctlEnabled;
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_DISPATCH PcmciaCreateClose;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PcmciaCreateClose(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
2013-05-10 10:30:21 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DPRINT("PCMCIA: Create/Close\n");
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_DISPATCH PcmciaDeviceControl;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PcmciaDeviceControl(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
NTSTATUS Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
2013-05-10 10:30:21 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DPRINT("PCMCIA: DeviceIoControl\n");
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Irp->IoStatus.Information = 0;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
DPRINT1("PCMCIA: Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
|
|
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
|
|
}
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Irp->IoStatus.Status = Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
return Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_UNLOAD PcmciaUnload;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
PcmciaUnload(PDRIVER_OBJECT DriverObject)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
UNREFERENCED_PARAMETER(DriverObject);
|
|
|
|
DPRINT("PCMCIA: Unload\n");
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_DISPATCH PcmciaPlugPlay;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PcmciaPlugPlay(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
PPCMCIA_COMMON_EXTENSION Common = DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
DPRINT("PCMCIA: PnP\n");
|
|
|
|
if (Common->IsFDO)
|
|
|
|
{
|
|
|
|
return PcmciaFdoPlugPlay((PPCMCIA_FDO_EXTENSION)Common,
|
|
|
|
Irp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return PcmciaPdoPlugPlay((PPCMCIA_PDO_EXTENSION)Common,
|
|
|
|
Irp);
|
|
|
|
}
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_DISPATCH PcmciaPower;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PcmciaPower(PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
PPCMCIA_COMMON_EXTENSION Common = DeviceObject->DeviceExtension;
|
|
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
switch (IrpSp->MinorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MN_QUERY_POWER:
|
|
|
|
/* I don't see any reason that we should care */
|
|
|
|
DPRINT("PCMCIA: IRP_MN_QUERY_POWER\n");
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
|
|
DPRINT("PCMCIA: IRP_MN_POWER_SEQUENCE\n");
|
|
|
|
RtlCopyMemory(IrpSp->Parameters.PowerSequence.PowerSequence,
|
|
|
|
&Common->PowerSequence,
|
|
|
|
sizeof(POWER_SEQUENCE));
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_WAIT_WAKE:
|
|
|
|
/* Not really sure about this */
|
|
|
|
DPRINT("PCMCIA: IRP_MN_WAIT_WAKE\n");
|
|
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_SET_POWER:
|
|
|
|
DPRINT("PCMCIA: IRP_MN_SET_POWER\n");
|
|
|
|
if (IrpSp->Parameters.Power.Type == SystemPowerState)
|
|
|
|
{
|
|
|
|
Common->SystemPowerState = IrpSp->Parameters.Power.State.SystemState;
|
|
|
|
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Common->DevicePowerState = IrpSp->Parameters.Power.State.DeviceState;
|
|
|
|
|
|
|
|
/* Update the POWER_SEQUENCE struct */
|
|
|
|
if (Common->DevicePowerState <= PowerDeviceD1)
|
|
|
|
Common->PowerSequence.SequenceD1++;
|
|
|
|
|
|
|
|
if (Common->DevicePowerState <= PowerDeviceD2)
|
|
|
|
Common->PowerSequence.SequenceD2++;
|
|
|
|
|
|
|
|
if (Common->DevicePowerState <= PowerDeviceD3)
|
|
|
|
Common->PowerSequence.SequenceD3++;
|
|
|
|
|
|
|
|
/* Start the underlying device if we are handling this for a PDO */
|
|
|
|
if (!Common->IsFDO)
|
|
|
|
Status = PcmciaPdoSetPowerState((PPCMCIA_PDO_EXTENSION)Common);
|
|
|
|
else
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Report that we changed state to the Power Manager */
|
|
|
|
PoSetPowerState(DeviceObject,
|
|
|
|
IrpSp->Parameters.Power.Type,
|
|
|
|
IrpSp->Parameters.Power.State);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DPRINT1("PCMCIA: Invalid MN code in MJ_POWER handler %x\n", IrpSp->MinorFunction);
|
|
|
|
ASSERT(FALSE);
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
return Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-10 10:30:21 +00:00
|
|
|
DRIVER_ADD_DEVICE PcmciaAddDevice;
|
|
|
|
|
2010-04-15 01:59:15 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PcmciaAddDevice(PDRIVER_OBJECT DriverObject,
|
|
|
|
PDEVICE_OBJECT PhysicalDeviceObject)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
PPCMCIA_FDO_EXTENSION FdoExt;
|
|
|
|
PDEVICE_OBJECT Fdo;
|
|
|
|
NTSTATUS Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DPRINT("PCMCIA: AddDevice\n");
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Status = IoCreateDevice(DriverObject,
|
|
|
|
sizeof(*FdoExt),
|
|
|
|
NULL,
|
|
|
|
FILE_DEVICE_BUS_EXTENDER,
|
|
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
|
|
FALSE,
|
|
|
|
&Fdo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
FdoExt = Fdo->DeviceExtension;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
RtlZeroMemory(FdoExt, sizeof(*FdoExt));
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
InitializeListHead(&FdoExt->ChildDeviceList);
|
|
|
|
KeInitializeSpinLock(&FdoExt->Lock);
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
FdoExt->Common.Self = Fdo;
|
|
|
|
FdoExt->Common.IsFDO = TRUE;
|
|
|
|
FdoExt->Common.State = dsStopped;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
|
|
|
|
PhysicalDeviceObject);
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
DriverEntry(PDRIVER_OBJECT DriverObject,
|
|
|
|
PUNICODE_STRING RegistryPath)
|
|
|
|
{
|
2013-11-23 18:36:05 +00:00
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
|
|
|
NTSTATUS Status;
|
2010-04-17 23:32:29 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
2013-05-10 10:30:21 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DPRINT1("PCMCIA: DriverEntry\n");
|
2010-04-17 23:32:29 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = PcmciaCreateClose;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PcmciaCreateClose;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PcmciaDeviceControl;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = PcmciaPlugPlay;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = PcmciaPower;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
|
|
|
|
DriverObject->DriverUnload = PcmciaUnload;
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
RtlZeroMemory(QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
|
2010-04-17 23:32:29 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
|
|
QueryTable[0].Name = L"IoctlInterface";
|
|
|
|
QueryTable[0].EntryContext = &IoctlEnabled;
|
2010-04-17 23:32:29 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
|
|
|
|
L"Pcmcia\\Parameters",
|
|
|
|
QueryTable,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Key not present so assume disabled */
|
|
|
|
IoctlEnabled = FALSE;
|
|
|
|
}
|
2010-04-17 23:32:29 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
DPRINT("PCMCIA: Ioctl interface %s\n",
|
|
|
|
(IoctlEnabled ? "enabled" : "disabled"));
|
2010-04-15 01:59:15 +00:00
|
|
|
|
2013-11-23 18:36:05 +00:00
|
|
|
return STATUS_SUCCESS;
|
2010-04-15 01:59:15 +00:00
|
|
|
}
|