windows-nt/Source/XPSP1/NT/base/busdrv/pccard/pcmcibus/pcmcia.c
2020-09-26 16:20:57 +08:00

410 lines
7.7 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
pcmcia.c
Abstract:
This module contains the code that controls the PCMCIA slots.
Author:
Bob Rinne (BobRi) 3-Aug-1994
Jeff McLeman 12-Apr-1994
Ravisankar Pudipeddi (ravisp) 1-Nov-96
Neil Sandlin (neilsa) 1-Jun-1999
Environment:
Kernel mode
Revision History :
6-Apr-95
Modified for databook support - John Keys Databook
1-Nov-96
Total overhaul to make this a bus enumerator - Ravisankar Pudipeddi (ravisp)
--*/
#include "pch.h"
//
// Internal References
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
VOID
PcmciaUnload(
IN PDRIVER_OBJECT DriverObject
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(PAGE, PcmciaUnload)
#pragma alloc_text(PAGE, PcmciaOpenCloseDispatch)
#pragma alloc_text(PAGE, PcmciaCleanupDispatch)
#pragma alloc_text(PAGE, PcmciaFdoSystemControl)
#pragma alloc_text(PAGE, PcmciaPdoSystemControl)
#endif
PUNICODE_STRING DriverRegistryPath;
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
The entry point that the system point calls to initialize
any driver.
Since this is a plug'n'play driver, we should return after setting
the entry points & initializing our dispatch table.
Currently we also detect our own PCMCIA controllers and report
them - which should not be needed in the future when a root bus
driver such as PCI or ISAPNP will locate the controllers for us.
Arguments:
DriverObject - Pointer to object representing this driver
RegistryPath - Pointer the the registry key for this driver
under \CurrentControlSet\Services
Return Value:
--*/
{
NTSTATUS status = STATUS_SUCCESS;
ULONG i;
PAGED_CODE();
DebugPrint((PCMCIA_DEBUG_INFO,"Initializing Driver\n"));
//
// Load in common parameters from the registry
//
status = PcmciaLoadGlobalRegistryValues();
if (!NT_SUCCESS(status)) {
return status;
}
//
//
// Set up the device driver entry points.
//
DriverObject->DriverExtension->AddDevice = PcmciaAddDevice;
DriverObject->DriverUnload = PcmciaUnload;
//
//
// Save our registry path
DriverRegistryPath = RegistryPath;
//
// Initialize the event used by the delay execution
// routine.
//
KeInitializeEvent (&PcmciaDelayTimerEvent,
NotificationEvent,
FALSE);
//
// Initialize tone generation objects
//
KeInitializeTimer(&PcmciaToneTimer);
KeInitializeDpc(&PcmciaToneDpc, PcmciaPlayToneCompletion, NULL);
KeInitializeSpinLock(&PcmciaToneLock);
//
// Initialize global lock
//
KeInitializeSpinLock(&PcmciaGlobalLock);
//
// Init device dispatch table
//
PcmciaInitDeviceDispatchTable(DriverObject);
//
// Locate PCMCIA controllers and report them - this
// is temporary - till the detection for these
// controllers is moved into
// appropriate root bus driver such as the PCI bus driver..
// if (PcmciaLegacyDetectionOk()) {
status = PcmciaDetectPcmciaControllers(DriverObject,RegistryPath);
// }
//
// Ignore the status. Regardless of whether we found controllers or not
// we need to stick around since we might get an AddDevice non-legacy
// controllers
//
return STATUS_SUCCESS;
}
NTSTATUS
PcmciaOpenCloseDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Open or Close device routine
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the IRP
Return Value:
Status
--*/
{
NTSTATUS status;
PAGED_CODE();
DebugPrint((PCMCIA_DEBUG_INFO, "PCMCIA: Open / close of Pcmcia controller for IO \n"));
status = STATUS_SUCCESS;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, 0);
return status;
}
NTSTATUS
PcmciaCleanupDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handles IRP_MJ_CLEANUP
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the IRP
Return Value:
Status
--*/
{
NTSTATUS status;
PAGED_CODE();
DebugPrint((PCMCIA_DEBUG_INFO, "PCMCIA: Cleanup of Pcmcia controller for IO \n"));
status = STATUS_SUCCESS;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, 0);
return status;
}
NTSTATUS
PcmciaFdoSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handles IRP_MJ_SYSTEM_CONTROL
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the IRP
Return Value:
Status
--*/
{
PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(fdoExtension->LowerDevice, Irp);
}
NTSTATUS
PcmciaPdoSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handles IRP_MJ_SYSTEM_CONTROL
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the IRP
Return Value:
Status
--*/
{
NTSTATUS status;
PPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension;
PAGED_CODE();
if (IsCardBusCard(pdoExtension)) {
//
// Pass irp down the stack for cardbus cards
//
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdoExtension->LowerDevice, Irp);
} else {
//
// Complete the irp for R2 cards
//
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
VOID
PcmciaUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Description:
Unloads the driver after cleaning up
Arguments:
DriverObject -- THe device drivers object
Return Value:
None
--*/
{
PDEVICE_OBJECT fdo, pdo, nextFdo, nextPdo;
PFDO_EXTENSION fdoExtension;
PSOCKET socket, nextSocket;
PPCMCIA_NTDETECT_DATA pData, pNextData;
PAGED_CODE();
DebugPrint((PCMCIA_DEBUG_INFO, "PcmciaUnload Entered\n"));
pData = pNtDetectDataList;
while(pData != NULL) {
pNextData = pData->Next;
ExFreePool(pData);
pData = pNextData;
}
for (fdo = FdoList; fdo !=NULL ; fdo = nextFdo) {
fdoExtension = fdo->DeviceExtension;
MarkDeviceDeleted(fdoExtension);
if (fdoExtension->PcmciaInterruptObject) {
IoDisconnectInterrupt(fdoExtension->PcmciaInterruptObject);
}
//
// Cleanup socket structures
//
for (socket=fdoExtension->SocketList; socket !=NULL; socket=nextSocket) {
nextSocket = socket->NextSocket;
ExFreePool(socket);
}
//
// Remove symbolic links
//
if (fdoExtension->LinkName.Buffer != NULL) {
IoDeleteSymbolicLink(&fdoExtension->LinkName);
RtlFreeUnicodeString(&fdoExtension->LinkName);
}
//
// Clean up all the PDOs
//
for (pdo=fdoExtension->PdoList; pdo != NULL; pdo=nextPdo) {
nextPdo = ((PPDO_EXTENSION) pdo->DeviceExtension)->NextPdoInFdoChain;
MarkDeviceDeleted((PPDO_EXTENSION)pdo->DeviceExtension);
PcmciaCleanupPdo(pdo);
IoDeleteDevice(pdo);
}
if (fdoExtension->Flags & PCMCIA_USE_POLLED_CSC) {
//
// Cancel the poll timer
//
KeCancelTimer(&fdoExtension->PollTimer);
}
IoDetachDevice(fdoExtension->LowerDevice);
nextFdo = fdoExtension->NextFdo;
IoDeleteDevice(fdo);
}
}