📄 pnp.c
字号:
pResDesc->ShareDisposition = CmResourceShareDriverExclusive;
SerialDbgPrintEx(SERPNPPOWER, "Sharing I/O port for "
"device %x\n", pLowerDevObj);
}
break;
case CmResourceTypeInterrupt:
if (!gotInt) {
gotInt = 1;
if (pResDesc->ShareDisposition != CmResourceShareShared) {
pResDesc->ShareDisposition = CmResourceShareDriverExclusive;
SerialDbgPrintEx(SERPNPPOWER, "Sharing interrupt "
"for device %x\n", pLowerDevObj);
} else {
pDevExt->InterruptShareable = TRUE;
SerialDbgPrintEx(SERPNPPOWER, "Globally sharing"
" interrupt for device %x\n",
pLowerDevObj);
}
}
break;
default:
break;
}
//
// If we found what we need, we can break out of the loop
//
if ((isMulti && gotInt && gotISR) || (!isMulti && gotInt)) {
break;
}
}
pResList = (PIO_RESOURCE_LIST)((PUCHAR)pResList
+ sizeof(IO_RESOURCE_LIST)
+ sizeof(IO_RESOURCE_DESCRIPTOR)
* (pResList->Count - 1));
}
PIrp->IoStatus.Status = STATUS_SUCCESS;
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE:
{
if (pDevExt->Flags & SERIAL_FLAGS_BROKENHW) {
(PNP_DEVICE_STATE)PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
PIrp->IoStatus.Status = STATUS_SUCCESS;
}
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
case IRP_MN_STOP_DEVICE:
{
ULONG pendingIRPs;
KIRQL oldIrql;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_STOP_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
ASSERT(!pDevExt->PortOnAMultiportCard);
SerialSetFlags(pDevExt, SERIAL_FLAGS_STOPPED);
SerialSetAccept(pDevExt,SERIAL_PNPACCEPT_STOPPED);
SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
pDevExt->PNPState = SERIAL_PNP_STOPPING;
//
// From this point on all non-PNP IRP's will be queued
//
//
// Decrement for entry here
//
InterlockedDecrement(&pDevExt->PendingIRPCnt);
//
// Decrement for stopping
//
pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
if (pendingIRPs) {
KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
KernelMode, FALSE, NULL);
}
//
// Re-increment the count for later
//
InterlockedIncrement(&pDevExt->PendingIRPCnt);
//
// We need to free resources...basically this is a remove
// without the detach from the stack.
//
if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
SerialReleaseResources(pDevExt);
}
//
// Pass the irp down
//
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(PIrp);
return IoCallDriver(pLowerDevObj, PIrp);
}
case IRP_MN_QUERY_STOP_DEVICE:
{
KIRQL oldIrql;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_STOP_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
//
// See if we should succeed a stop query
//
if (pDevExt->PortOnAMultiportCard) {
PIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
SerialDbgPrintEx(SERPNPPOWER, "------- failing; multiport node\n");
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
//
// If the device hasn't started yet, we ignore this request
// and just pass it down.
//
if (pDevExt->PNPState != SERIAL_PNP_STARTED) {
IoSkipCurrentIrpStackLocation(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
//
// Lock around the open status
//
ExAcquireFastMutex(&pDevExt->OpenMutex);
if (pDevExt->DeviceIsOpened) {
ExReleaseFastMutex(&pDevExt->OpenMutex);
PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
SerialDbgPrintEx(SERPNPPOWER, "failing; device open\n");
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_DEVICE_BUSY;
}
pDevExt->PNPState = SERIAL_PNP_QSTOP;
SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
//
// Unlock around the open status
//
ExReleaseFastMutex(&pDevExt->OpenMutex);
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
case IRP_MN_CANCEL_STOP_DEVICE:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_CANCEL_STOP_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
if (pDevExt->PNPState == SERIAL_PNP_QSTOP) {
//
// Restore the device state
//
pDevExt->PNPState = SERIAL_PNP_STARTED;
SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_STOPPING);
}
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
case IRP_MN_CANCEL_REMOVE_DEVICE:
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_CANCEL_REMOVE_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
//
// Restore the device state
//
pDevExt->PNPState = SERIAL_PNP_STARTED;
SerialClearAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
case IRP_MN_QUERY_REMOVE_DEVICE:
{
KIRQL oldIrql;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_QUERY_REMOVE_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
ExAcquireFastMutex(&pDevExt->OpenMutex);
//
// See if we should succeed a remove query
//
if (pDevExt->DeviceIsOpened) {
ExReleaseFastMutex(&pDevExt->OpenMutex);
PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
SerialDbgPrintEx(SERPNPPOWER, "failing; device open\n");
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return STATUS_DEVICE_BUSY;
}
pDevExt->PNPState = SERIAL_PNP_QREMOVE;
SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
ExReleaseFastMutex(&pDevExt->OpenMutex);
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
case IRP_MN_SURPRISE_REMOVAL:
{
ULONG pendingIRPs;
KIRQL oldIrql;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_SURPRISE_REMOVAL Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
//
// Prevent any new I/O to the device
//
SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_SURPRISE_REMOVING);
//
// Dismiss all pending requests
//
SerialKillPendingIrps(PDevObj);
//
// Wait for any pending requests we raced on.
//
//
// Decrement once for ourselves
//
InterlockedDecrement(&pDevExt->PendingIRPCnt);
//
// Decrement for the remove
//
pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
if (pendingIRPs) {
KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
KernelMode, FALSE, NULL);
}
//
// Reset for subsequent remove
//
InterlockedIncrement(&pDevExt->PendingIRPCnt);
//
// Remove any external interfaces and release resources
//
SerialDisableInterfacesResources(PDevObj, FALSE);
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(PIrp);
return SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
}
case IRP_MN_REMOVE_DEVICE:
{
ULONG pendingIRPs;
KIRQL oldIrql;
SerialDbgPrintEx(SERPNPPOWER, "Got IRP_MN_REMOVE_DEVICE Irp\n");
SerialDbgPrintEx(SERPNPPOWER, "for device %x\n", pLowerDevObj);
//
// If we get this, we have to remove
//
//
// Mark as not accepting requests
//
SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
//
// Complete all pending requests
//
SerialKillPendingIrps(PDevObj);
//
// Decrement for this Irp itself
//
InterlockedDecrement(&pDevExt->PendingIRPCnt);
//
// Wait for any pending requests we raced on -- this decrement
// is for our "placeholder".
//
pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
if (pendingIRPs) {
KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
KernelMode, FALSE, NULL);
}
//
// Remove us
//
SerialRemoveDevObj(PDevObj);
//
// Pass the irp down
//
PIrp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(PIrp);
//
// We do decrement here because we incremented on entry here.
//
return IoCallDriver(pLowerDevObj, PIrp);
}
default:
break;
} // switch (pIrpStack->MinorFunction)
//
// Pass to driver beneath us
//
IoSkipCurrentIrpStackLocation(PIrp);
status = SerialIoCallDriver(pDevExt, pLowerDevObj, PIrp);
return status;
}
UINT32
SerialReportMaxBaudRate(ULONG Bauds)
/*++
Routine Description:
This routine returns the max baud rate given a selection of rates
Arguments:
Bauds - Bit-encoded list of supported bauds
Return Value:
The max baud rate listed in Bauds
--*/
{
PAGED_CODE();
if (Bauds & SERIAL_BAUD_128K) {
return (128U * 1024U);
}
if (Bauds & SERIAL_BAUD_115200) {
return 115200U;
}
if (Bauds & SERIAL_BAUD_56K) {
return (56U * 1024U);
}
if (Bauds & SERIAL_BAUD_57600) {
return 57600U;
}
if (Bauds & SERIAL_BAUD_38400) {
return 38400U;
}
if (Bauds & SERIAL_BAUD_19200) {
return 19200U;
}
if (Bauds & SERIAL_BAUD_14400) {
return 14400U;
}
if (Bauds & SERIAL_BAUD_9600) {
return 9600U;
}
if (Bauds & SERIAL_BAUD_7200) {
return 7200U;
}
if (Bauds & SERIAL_BAUD_4800) {
return 4800U;
}
if (Bauds & SERIAL_BAUD_2400) {
return 2400U;
}
if (Bauds & SERIAL_BAUD_1800) {
return 1800U;
}
if (Bauds & SERIAL_BAUD_1200) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -