reactos/drivers/bus/pcmcia/pcmcia.c

265 lines
7.1 KiB
C

/*
* 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>
BOOLEAN IoctlEnabled;
DRIVER_DISPATCH PcmciaCreateClose;
NTSTATUS
NTAPI
PcmciaCreateClose(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
DPRINT("PCMCIA: Create/Close\n");
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
DRIVER_DISPATCH PcmciaDeviceControl;
NTSTATUS
NTAPI
PcmciaDeviceControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
UNREFERENCED_PARAMETER(DeviceObject);
DPRINT("PCMCIA: DeviceIoControl\n");
Irp->IoStatus.Information = 0;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
default:
DPRINT1("PCMCIA: Unknown ioctl code: %x\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_NOT_SUPPORTED;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
DRIVER_UNLOAD PcmciaUnload;
VOID
NTAPI
PcmciaUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DPRINT("PCMCIA: Unload\n");
}
DRIVER_DISPATCH PcmciaPlugPlay;
NTSTATUS
NTAPI
PcmciaPlugPlay(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
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);
}
}
DRIVER_DISPATCH PcmciaPower;
NTSTATUS
NTAPI
PcmciaPower(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
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;
}
DRIVER_ADD_DEVICE PcmciaAddDevice;
NTSTATUS
NTAPI
PcmciaAddDevice(PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT PhysicalDeviceObject)
{
PPCMCIA_FDO_EXTENSION FdoExt;
PDEVICE_OBJECT Fdo;
NTSTATUS Status;
DPRINT("PCMCIA: AddDevice\n");
Status = IoCreateDevice(DriverObject,
sizeof(*FdoExt),
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
return Status;
FdoExt = Fdo->DeviceExtension;
RtlZeroMemory(FdoExt, sizeof(*FdoExt));
InitializeListHead(&FdoExt->ChildDeviceList);
KeInitializeSpinLock(&FdoExt->Lock);
FdoExt->Common.Self = Fdo;
FdoExt->Common.IsFDO = TRUE;
FdoExt->Common.State = dsStopped;
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
PhysicalDeviceObject);
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
UNREFERENCED_PARAMETER(RegistryPath);
DPRINT1("PCMCIA: DriverEntry\n");
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;
DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
DriverObject->DriverUnload = PcmciaUnload;
RtlZeroMemory(QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 2);
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = L"IoctlInterface";
QueryTable[0].EntryContext = &IoctlEnabled;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
L"Pcmcia\\Parameters",
QueryTable,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
/* Key not present so assume disabled */
IoctlEnabled = FALSE;
}
DPRINT("PCMCIA: Ioctl interface %s\n",
(IoctlEnabled ? "enabled" : "disabled"));
return STATUS_SUCCESS;
}