📄 pnp.c
字号:
return 1200U;
}
if (Bauds & SERIAL_BAUD_600) {
return 600U;
}
if (Bauds & SERIAL_BAUD_300) {
return 300U;
}
if (Bauds & SERIAL_BAUD_150) {
return 150U;
}
if (Bauds & SERIAL_BAUD_134_5) {
return 135U; // Close enough
}
if (Bauds & SERIAL_BAUD_110) {
return 110U;
}
if (Bauds & SERIAL_BAUD_075) {
return 75U;
}
//
// We're in bad shape
//
return 0;
}
VOID
SerialAddToAllDevs(PLIST_ENTRY PListEntry)
{
KIRQL oldIrql;
KeAcquireSpinLock(&SerialGlobals.GlobalsSpinLock, &oldIrql);
InsertTailList(&SerialGlobals.AllDevObjs, PListEntry);
KeReleaseSpinLock(&SerialGlobals.GlobalsSpinLock, oldIrql);
}
NTSTATUS
SerialFinishStartDevice(IN PDEVICE_OBJECT PDevObj,
IN PCM_RESOURCE_LIST PResList,
IN PCM_RESOURCE_LIST PTrResList,
PSERIAL_USER_DATA PUserData)
/*++
Routine Description:
This routine does serial-specific procedures to start a device. It
does this either for a legacy device detected by its registry entries,
or for a PnP device after the start IRP has been sent down the stack.
Arguments:
PDevObj - Pointer to the devobj that is starting
PResList - Pointer to the untranslated resources needed by this device
PTrResList - Pointer to the translated resources needed by this device
PUserData - Pointer to the user-specified resources/attributes
Return Value:
STATUS_SUCCESS on success, something else appropriate on failure
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
NTSTATUS status;
PCONFIG_DATA pConfig;
HANDLE pnpKey;
ULONG one = 1;
BOOLEAN allocedUserData = FALSE;
KIRQL oldIrql;
PAGED_CODE();
//
// See if this is a restart, and if so don't reallocate the world
//
if ((pDevExt->Flags & SERIAL_FLAGS_STOPPED)
&& (pDevExt->Flags & SERIAL_FLAGS_STARTED)) {
SerialClearFlags(pDevExt, SERIAL_FLAGS_STOPPED);
pDevExt->PNPState = SERIAL_PNP_RESTARTING;
//
// Re-init resource-related things in the extension
//
pDevExt->TopLevelOurIsr = NULL;
pDevExt->TopLevelOurIsrContext = NULL;
pDevExt->OriginalController = SerialPhysicalZero;
pDevExt->OriginalInterruptStatus = SerialPhysicalZero;
pDevExt->OurIsr = NULL;
pDevExt->OurIsrContext = NULL;
pDevExt->Controller = NULL;
pDevExt->InterruptStatus = NULL;
pDevExt->Interrupt = NULL;
pDevExt->SpanOfController = 0;
pDevExt->SpanOfInterruptStatus = 0;
pDevExt->Vector = 0;
pDevExt->Irql = 0;
pDevExt->OriginalVector = 0;
pDevExt->OriginalIrql = 0;
pDevExt->AddressSpace = 0;
pDevExt->BusNumber = 0;
pDevExt->InterfaceType = 0;
pDevExt->CIsrSw = NULL;
ASSERT(PUserData == NULL);
PUserData = ExAllocatePool(PagedPool, sizeof(SERIAL_USER_DATA));
if (PUserData == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
allocedUserData = TRUE;
RtlZeroMemory(PUserData, sizeof(SERIAL_USER_DATA));
PUserData->DisablePort = FALSE;
PUserData->UserClockRate = pDevExt->ClockRate;
PUserData->TxFIFO = pDevExt->TxFifoAmount;
PUserData->PermitShareDefault = pDevExt->PermitShare;
//
// Map betweeen trigger and amount
//
switch (pDevExt->RxFifoTrigger) {
case SERIAL_1_BYTE_HIGH_WATER:
PUserData->RxFIFO = 1;
break;
case SERIAL_4_BYTE_HIGH_WATER:
PUserData->RxFIFO = 4;
break;
case SERIAL_8_BYTE_HIGH_WATER:
PUserData->RxFIFO = 8;
break;
case SERIAL_14_BYTE_HIGH_WATER:
PUserData->RxFIFO = 14;
break;
default:
PUserData->RxFIFO = 1;
}
} else {
//
// Mark as serenumerable -- toss status because we can
// still start without this key.
//
status = IoOpenDeviceRegistryKey(pDevExt->Pdo,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_WRITE, &pnpKey);
if (NT_SUCCESS(status)) {
ULONG powerPolicy = 0;
ULONG powerOnClose = 0;
//
// Find out if we own power policy
//
SerialGetRegistryKeyValue(pnpKey, L"SerialRelinquishPowerPolicy",
sizeof(L"SerialRelinquishPowerPolicy"),
&powerPolicy, sizeof(ULONG));
pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;
SerialGetRegistryKeyValue(pnpKey, L"EnablePowerManagement",
sizeof(L"EnablePowerManagement"),
&powerOnClose, sizeof(ULONG));
pDevExt->RetainPowerOnClose = powerOnClose ? TRUE : FALSE;
ZwClose(pnpKey);
}
}
//
// Allocate the config record.
//
pConfig = ExAllocatePool (PagedPool, sizeof(CONFIG_DATA));
if (pConfig == NULL) {
SerialLogError(pDevExt->DriverObject, NULL, SerialPhysicalZero,
SerialPhysicalZero, 0, 0, 0, 37, STATUS_SUCCESS,
SERIAL_INSUFFICIENT_RESOURCES, 0, NULL, 0, NULL);
SerialDbgPrintEx(SERERRORS, "Couldn't allocate memory for the\n"
"------ user configuration record\n");
status = STATUS_INSUFFICIENT_RESOURCES;
goto SerialFinishStartDeviceError;
}
RtlZeroMemory(pConfig, sizeof(CONFIG_DATA));
//
// Get the configuration info for the device.
//
status = SerialGetPortInfo(PDevObj, PResList, PTrResList, pConfig,
PUserData);
if (!NT_SUCCESS(status)) {
goto SerialFinishStartDeviceError;
}
//
// See if we are in the proper power state.
//
if (pDevExt->PowerState != PowerDeviceD0) {
status = SerialGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);
if (!NT_SUCCESS(status)) {
goto SerialFinishStartDeviceError;
}
}
//
// Find and initialize the controller
//
status = SerialFindInitController(PDevObj, pConfig);
if (!NT_SUCCESS(status)) {
goto SerialFinishStartDeviceError;
}
//
// The hardware that is set up to NOT interrupt, connect an interrupt.
//
//
// If a device doesn't already have an interrupt and it has an isr then
// we attempt to connect to the interrupt if it is not shareing with other
// serial devices. If we fail to connect to an interrupt we will delete
// this device.
//
if (pDevExt != NULL) {
SerialDbgPrintEx(SERDIAG5, "pDevExt: Interrupt %x\n"
"------- OurIsr %x\n", pDevExt->Interrupt,
pDevExt->OurIsr);
} else {
SerialDbgPrintEx(SERERRORS, "SerialFinishStartDevice got NULL "
"pDevExt\n");
}
if ((!pDevExt->Interrupt) && (pDevExt->OurIsr)) {
SerialDbgPrintEx(SERDIAG5,
"About to connect to interrupt for port %wZ\n"
"------- address of extension is %x\n",
&pDevExt->DeviceName, pDevExt);
SerialDbgPrintEx(SERDIAG5, "IoConnectInterrupt Args:\n"
"Interrupt %x\n"
"OurIsr %x\n"
"OurIsrContext %x\n"
"NULL\n"
"Vector %x\n"
"Irql %x\n"
"InterruptMode %x\n"
"InterruptShareable %x\n"
"ProcessorAffinity %x\n"
"FALSE\n",
&pDevExt->Interrupt,
SerialCIsrSw,
pDevExt->CIsrSw,
pDevExt->Vector,
pDevExt->Irql,
pConfig->InterruptMode,
pDevExt->InterruptShareable,
pConfig->Affinity
);
//
// Do a just in time construction of the ISR switch.
//
pDevExt->CIsrSw->IsrFunc = pDevExt->OurIsr;
pDevExt->CIsrSw->Context = pDevExt->OurIsrContext;
status = IoConnectInterrupt(&pDevExt->Interrupt, SerialCIsrSw,
pDevExt->CIsrSw, NULL,
pDevExt->Vector, pDevExt->Irql,
pDevExt->Irql,
pConfig->InterruptMode,
pDevExt->InterruptShareable,
pConfig->Affinity, FALSE);
if (!NT_SUCCESS(status)) {
//
// Hmmm, how'd that happen? Somebody either
// didn't report their resources, or they
// sneaked in since the last time I looked.
//
// Oh well, delete this device.
//
SerialDbgPrintEx(SERERRORS, "Couldn't connect to interrupt for %wZ\n",
&pDevExt->DeviceName);
SerialDbgPrintEx(SERERRORS, "IoConnectInterrupt Args:\n"
"Interrupt %x\n"
"OurIsr %x\n"
"OurIsrContext %x\n"
"NULL\n"
"Vector %x\n"
"Irql %x\n"
"InterruptMode %x\n"
"InterruptShareable %x\n"
"ProcessorAffinity %x\n"
"FALSE\n",
&pDevExt->Interrupt,
SerialCIsrSw,
pDevExt->CIsrSw,
pDevExt->Vector,
pDevExt->Irql,
pConfig->InterruptMode,
pDevExt->InterruptShareable,
pConfig->Affinity);
SerialLogError(PDevObj->DriverObject, PDevObj,
pDevExt->OriginalController,
SerialPhysicalZero, 0, 0, 0, 1, status,
SERIAL_UNREPORTED_IRQL_CONFLICT,
pDevExt->DeviceName.Length + sizeof(WCHAR),
pDevExt->DeviceName.Buffer, 0, NULL);
status = SERIAL_UNREPORTED_IRQL_CONFLICT;
goto SerialFinishStartDeviceError;
}
}
SerialDbgPrintEx(SERDIAG5, "Connected interrupt %08X\n", pDevExt->Interrupt);
//
// Add the PDevObj to the master list
//
SerialAddToAllDevs(&pDevExt->AllDevObjs);
//
// Reset the device.
//
//
// While the device isn't open, disable all interrupts.
//
DISABLE_ALL_INTERRUPTS (pDevExt->Controller);
WRITE_MODEM_CONTROL(pDevExt->Controller, (UCHAR)0);
//
// This should set up everything as it should be when
// a device is to be opened. We do need to lower the
// modem lines, and disable the recalcitrant fifo
// so that it will show up if the user boots to dos.
//
KeSynchronizeExecution(
pDevExt->Interrupt,
SerialReset,
pDevExt
);
KeSynchronizeExecution( //Disables the fifo.
pDevExt->Interrupt,
SerialMarkClose,
pDevExt
);
KeSynchronizeExecution(
pDevExt->Interrupt,
SerialClrRTS,
pDevExt
);
KeSynchronizeExecution(
pDevExt->Interrupt,
SerialClrDTR,
pDevExt
);
if (pDevExt->PNPState == SERIAL_PNP_ADDED ) {
//
// Do the external naming now that the device is accessible.
//
status = SerialDoExternalNaming(pDevExt, pDevExt->DeviceObject->
DriverObject);
if (!NT_SUCCESS(status)) {
SerialDbgPrintEx(SERERRORS, "External Naming Failed - Status %x\n",
status);
//
// Allow the device to start anyhow
//
status = STATUS_SUCCESS;
}
} else {
SerialDbgPrintEx(SERPNPPOWER, "Not doing external naming -- state is %x"
"\n", pDevExt->PNPState);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -