windows-nt/Source/XPSP1/NT/net/irda/comm/ircomm/openclos.c
2020-09-26 16:20:57 +08:00

230 lines
4.5 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
openclos.c
Abstract:
This module contains the code that is very specific to initialization
and unload operations in the irenum driver
Author:
Brian Lieuallen, 7-13-2000
Environment:
Kernel mode
Revision History :
--*/
#include "internal.h"
#include "ircomm.h"
NTSTATUS
IrCommCreate(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
{
NTSTATUS Status=STATUS_SUCCESS;
IRDA_HANDLE Handle;
PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
UCHAR ControlBuffer[4];
IRCOMM_BUS_INFO BusInfo;
if (InterlockedIncrement(&DeviceExtension->OpenCount) > 1) {
D_ERROR(DbgPrint("IRCOMM: Create already open\n");)
InterlockedDecrement(&DeviceExtension->OpenCount);
Irp->IoStatus.Status=STATUS_ACCESS_DENIED;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
Status=QueryPdoInformation(
DeviceExtension->Pdo,
IRENUM_CONFIG_SPACE_INFO,
&BusInfo,
sizeof(BusInfo)
);
if (NT_SUCCESS(Status)) {
DeviceExtension->DeviceAddress=BusInfo.DeviceAddress;
}
Status=IrdaConnect(
DeviceExtension->DeviceAddress,
"IrDA:IrCOMM",
BusInfo.OutGoingConnection,
&DeviceExtension->ConnectionHandle,
DataAvailibleHandler,
EventNotification,
DeviceExtension
);
D_TRACE(DbgPrint("IRCOMM: Create %08lx\n",Status);)
if (NT_SUCCESS(Status)) {
DeviceExtension->HandFlow.ControlHandShake=SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE;
DeviceExtension->HandFlow.FlowReplace=SERIAL_RTS_HANDSHAKE;
} else {
//
// could not creat the connection
//
goto CleanUp;
}
Irp->IoStatus.Status=Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
CleanUp:
//
// something failed, undo what we did in this function
//
if (DeviceExtension->ConnectionHandle != NULL) {
FreeConnection(DeviceExtension->ConnectionHandle);
DeviceExtension->ConnectionHandle=NULL;
}
InterlockedDecrement(&DeviceExtension->OpenCount);
Irp->IoStatus.Status=Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
NTSTATUS
IrCommClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
{
PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
NTSTATUS Status=STATUS_SUCCESS;
FreeConnection(DeviceExtension->ConnectionHandle);
DeviceExtension->ConnectionHandle=NULL;
InterlockedDecrement(&DeviceExtension->OpenCount);
Irp->IoStatus.Status=Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
VOID
CleanupIoRequests(
PFDO_DEVICE_EXTENSION DeviceExtension
)
{
KIRQL OldIrql;
PIRP WaitIrp=NULL;
FlushQueuedPackets(&DeviceExtension->Write.Queue,FLUSH_ALL_IRPS);
FlushQueuedPackets(&DeviceExtension->Read.Queue,FLUSH_ALL_IRPS);
ReadPurge(DeviceExtension,0);
FlushQueuedPackets(&DeviceExtension->Mask.Queue,FLUSH_ALL_IRPS);
FlushQueuedPackets(&DeviceExtension->Uart.Queue,FLUSH_ALL_IRPS);
KeAcquireSpinLock(&DeviceExtension->Mask.Lock,&OldIrql);
WaitIrp=DeviceExtension->Mask.CurrentWaitMaskIrp;
DeviceExtension->Mask.CurrentWaitMaskIrp=NULL;
KeReleaseSpinLock(&DeviceExtension->Mask.Lock,OldIrql);
if (WaitIrp != NULL) {
WaitIrp->IoStatus.Status=STATUS_CANCELLED;
WaitIrp->IoStatus.Information=0;
IoCompleteRequest(WaitIrp,IO_NO_INCREMENT);
}
return;
}
NTSTATUS
IrCommCleanup(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
{
PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
NTSTATUS Status=STATUS_SUCCESS;
D_TRACE(DbgPrint("IRCOMM: Cleanup\n");)
CleanupIoRequests(DeviceExtension);
Irp->IoStatus.Status=Status;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}
NTSTATUS
IrCommQueryInformation(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
{
PFDO_DEVICE_EXTENSION DeviceExtension=(PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
NTSTATUS Status=STATUS_SUCCESS;
Irp->IoStatus.Status=Status;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return Status;
}