📄 initunlo.c
字号:
Context - Actually a pointer to the device extension of the root
device we are adding a port to.
Return Value:
Always TRUE
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = (PSERIAL_DEVICE_EXTENSION)Context;
PSERIAL_MULTIPORT_DISPATCH pOurIsrContext
= (PSERIAL_MULTIPORT_DISPATCH)pDevExt->OurIsrContext;
PSERIAL_DEVICE_EXTENSION pNewExt
= (PSERIAL_DEVICE_EXTENSION)pDevExt->NewExtension;
SerialDump (SERTRACECALLS,("SERIAL: Enter SerialAddToMulti\n"));
if (pDevExt->Indexed == FALSE) {
pOurIsrContext->UsablePortMask |= 1 << (pDevExt->NewPortIndex - 1);
pOurIsrContext->MaskInverted |= pDevExt->NewMaskInverted;
}
//
// Add us to the linked list of common interrupt objects if we are not
// already in it. We may be if there is another device besides our
// multiport card.
//
if (IsListEmpty(&pNewExt->CommonInterruptObject)) {
InsertTailList(&pDevExt->CommonInterruptObject,
&pNewExt->CommonInterruptObject);
}
//
// Give us the list of contexts also
//
pNewExt->OurIsrContext = pOurIsrContext;
//
// Add us to the list of our siblings
//
InsertTailList(&pDevExt->MultiportSiblings, &pNewExt->MultiportSiblings);
SerialDump(SERDIAG1, ("SERIAL: Adding to multi...\n"));
SerialDump(SERDIAG1, ("------: old ext %x\n", pDevExt));
//
// Map us in so the ISR can find us.
//
pOurIsrContext->Extensions[pDevExt->NewPortIndex - 1]
= pDevExt->NewExtension;
pNewExt->TopLevelOurIsr = pDevExt->TopLevelOurIsr;
pNewExt->TopLevelOurIsrContext = pDevExt->TopLevelOurIsrContext;
SerialDump (SERTRACECALLS,("SERIAL: Leave SerialAddToMulti\n"));
return TRUE;
}
NTSTATUS
SerialInitMultiPort(IN PSERIAL_DEVICE_EXTENSION PDevExt,
IN PCONFIG_DATA PConfigData, IN PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
This routine initializes a multiport device by adding a port to an existing
one.
Arguments:
PDevExt - pointer to the device extension of the root of the multiport
device.
PConfigData - pointer to the config data for the new port
PDevObj - pointer to the devobj for the new port
Return Value:
STATUS_SUCCESS on success, appropriate error on failure.
--*/
{
PSERIAL_DEVICE_EXTENSION pOurIsrContext
= (PSERIAL_DEVICE_EXTENSION)PDevExt->OurIsrContext;
PSERIAL_DEVICE_EXTENSION pNewExt
= (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;
NTSTATUS status;
PSERIAL_MULTIPORT_DISPATCH pDispatch;
PAGED_CODE();
SerialDump (SERTRACECALLS,("SERIAL: Enter SerialInitMultiPort\n"));
//
// Allow him to share our CISRsw and interrupt object
//
pNewExt->CIsrSw = PDevExt->CIsrSw;
pNewExt->Interrupt = PDevExt->Interrupt;
//
// First, see if we can initialize the one we have found
//
status = SerialInitOneController(PDevObj, PConfigData);
if (!NT_SUCCESS(status)) {
SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
return status;
}
//
// OK. He's good to go. Find the root controller. He may
// currently be a single, so we have to change him to multi.
//
if (PDevExt->PortOnAMultiportCard != TRUE) {
pDispatch = PDevExt->NewExtension
= ExAllocatePool(NonPagedPool, sizeof(SERIAL_MULTIPORT_DISPATCH));
if (pDispatch == NULL) {
// FAIL and CLEANUP
SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(pDispatch, sizeof(*pDispatch));
KeSynchronizeExecution(PDevExt->Interrupt, SerialSingleToMulti, PDevExt);
}
//
// Update some important fields
//
((PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension)->PortOnAMultiportCard
= TRUE;
((PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension)->OurIsr = NULL;
PDevExt->NewPortIndex = PConfigData->PortIndex;
PDevExt->NewMaskInverted = PConfigData->MaskInverted;
PDevExt->NewExtension = PDevObj->DeviceExtension;
//
// Now, we can add the new guy. He will be hooked in
// immediately, so we need to be able to handle interrupts.
//
KeSynchronizeExecution(PDevExt->Interrupt, SerialAddToMulti, PDevExt);
SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
return STATUS_SUCCESS;
}
NTSTATUS
SerialInitController(IN PDEVICE_OBJECT PDevObj, IN PCONFIG_DATA PConfigData)
/*++
Routine Description:
Really too many things to mention here. In general initializes
kernel synchronization structures, allocates the typeahead buffer,
sets up defaults, etc.
Arguments:
PDevObj - Device object for the device to be started
PConfigData - Pointer to a record for a single port.
Return Value:
STATUS_SUCCCESS if everything went ok. A !NT_SUCCESS status
otherwise.
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
//
// This will hold the string that we need to use to describe
// the name of the device to the IO system.
//
UNICODE_STRING uniNameString;
//
// Holds the NT Status that is returned from each call to the
// kernel and executive.
//
NTSTATUS status = STATUS_SUCCESS;
//
// Indicates that a conflict was detected for resources
// used by this device.
//
BOOLEAN conflictDetected = FALSE;
//
// Indicates if we allocated an ISR switch
//
BOOLEAN allocedISRSw = FALSE;
PAGED_CODE();
SerialDump(
SERDIAG1,
("SERIAL: Initializing for configuration record of %wZ\n",
&pDevExt->DeviceName)
);
//
// This compare is done using **untranslated** values since that is what
// the kernel shoves in regardless of the architecture.
//
if ((*KdComPortInUse) == ((PUCHAR)(PConfigData->Controller.LowPart))) {
SerialDump(SERERRORS, ("SERIAL: Kernel debugger is using port at address "
"%x\n"
"------ Serial driver will not load port\n",
*KdComPortInUse));
SerialLogError(
PDevObj->DriverObject,
NULL,
PConfigData->TrController,
SerialPhysicalZero,
0,
0,
0,
3,
STATUS_SUCCESS,
SERIAL_KERNEL_DEBUGGER_ACTIVE,
pDevExt->DeviceName.Length+sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0,
NULL
);
return STATUS_INSUFFICIENT_RESOURCES;
}
if (pDevExt->CIsrSw == NULL) {
if ((pDevExt->CIsrSw
= ExAllocatePool(NonPagedPool, sizeof(SERIAL_CISR_SW))) == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
InitializeListHead(&pDevExt->CIsrSw->SharerList);
allocedISRSw = TRUE;
}
//
// Propagate that it is a jensen.
//
pDevExt->Jensen = PConfigData->Jensen;
//
// Initialize the spinlock associated with fields read (& set)
// by IO Control functions and the flags spinlock.
//
KeInitializeSpinLock(&pDevExt->ControlLock);
KeInitializeSpinLock(&pDevExt->FlagsLock);
//
// Initialize the timers used to timeout operations.
//
KeInitializeTimer(&pDevExt->ReadRequestTotalTimer);
KeInitializeTimer(&pDevExt->ReadRequestIntervalTimer);
KeInitializeTimer(&pDevExt->WriteRequestTotalTimer);
KeInitializeTimer(&pDevExt->ImmediateTotalTimer);
KeInitializeTimer(&pDevExt->XoffCountTimer);
KeInitializeTimer(&pDevExt->LowerRTSTimer);
//
// Intialialize the dpcs that will be used to complete
// or timeout various IO operations.
//
KeInitializeDpc(&pDevExt->CompleteWriteDpc, SerialCompleteWrite, pDevExt);
KeInitializeDpc(&pDevExt->CompleteReadDpc, SerialCompleteRead, pDevExt);
KeInitializeDpc(&pDevExt->TotalReadTimeoutDpc, SerialReadTimeout, pDevExt);
KeInitializeDpc(&pDevExt->IntervalReadTimeoutDpc, SerialIntervalReadTimeout,
pDevExt);
KeInitializeDpc(&pDevExt->TotalWriteTimeoutDpc, SerialWriteTimeout, pDevExt);
KeInitializeDpc(&pDevExt->CommErrorDpc, SerialCommError, pDevExt);
KeInitializeDpc(&pDevExt->CompleteImmediateDpc, SerialCompleteImmediate,
pDevExt);
KeInitializeDpc(&pDevExt->TotalImmediateTimeoutDpc, SerialTimeoutImmediate,
pDevExt);
KeInitializeDpc(&pDevExt->CommWaitDpc, SerialCompleteWait, pDevExt);
KeInitializeDpc(&pDevExt->XoffCountTimeoutDpc, SerialTimeoutXoff, pDevExt);
KeInitializeDpc(&pDevExt->XoffCountCompleteDpc, SerialCompleteXoff, pDevExt);
KeInitializeDpc(&pDevExt->StartTimerLowerRTSDpc, SerialStartTimerLowerRTS,
pDevExt);
KeInitializeDpc(&pDevExt->PerhapsLowerRTSDpc, SerialInvokePerhapsLowerRTS,
pDevExt);
KeInitializeDpc(&pDevExt->IsrUnlockPagesDpc, SerialUnlockPages, pDevExt);
#if 0 // DBG
//
// Init debug stuff
//
pDevExt->DpcQueued[0].Dpc = &pDevExt->CompleteWriteDpc;
pDevExt->DpcQueued[1].Dpc = &pDevExt->CompleteReadDpc;
pDevExt->DpcQueued[2].Dpc = &pDevExt->TotalReadTimeoutDpc;
pDevExt->DpcQueued[3].Dpc = &pDevExt->IntervalReadTimeoutDpc;
pDevExt->DpcQueued[4].Dpc = &pDevExt->TotalWriteTimeoutDpc;
pDevExt->DpcQueued[5].Dpc = &pDevExt->CommErrorDpc;
pDevExt->DpcQueued[6].Dpc = &pDevExt->CompleteImmediateDpc;
pDevExt->DpcQueued[7].Dpc = &pDevExt->TotalImmediateTimeoutDpc;
pDevExt->DpcQueued[8].Dpc = &pDevExt->CommWaitDpc;
pDevExt->DpcQueued[9].Dpc = &pDevExt->XoffCountTimeoutDpc;
pDevExt->DpcQueued[10].Dpc = &pDevExt->XoffCountCompleteDpc;
pDevExt->DpcQueued[11].Dpc = &pDevExt->StartTimerLowerRTSDpc;
pDevExt->DpcQueued[12].Dpc = &pDevExt->PerhapsLowerRTSDpc;
pDevExt->DpcQueued[13].Dpc = &pDevExt->IsrUnlockPagesDpc;
#endif
if (!((PConfigData->ClockRate == 1843200) ||
(PConfigData->ClockRate == 3072000) ||
(PConfigData->ClockRate == 4233600) ||
(PConfigData->ClockRate == 8000000))) {
SerialLogError(
PDevObj->DriverObject,
PDevObj,
PConfigData->TrController,
SerialPhysicalZero,
0,
0,
0,
6,
STATUS_SUCCESS,
SERIAL_UNSUPPORTED_CLOCK_RATE,
pDevExt->DeviceName.Length+sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0,
NULL
);
SerialDump(
SERERRORS,
("SERIAL: Invalid clock rate specified for %wZ\n",
&pDevExt->DeviceName)
);
status = STATUS_SERIAL_NO_DEVICE_INITED;
goto ExtensionCleanup;
}
//
// Save the value of clock input to the part. We use this to calculate
// the divisor latch value. The value is in Hertz.
//
pDevExt->ClockRate = PConfigData->ClockRate;
//
// Map the memory for the control registers for the serial device
// into virtual memory.
//
pDevExt->Controller =
SerialGetMappedAddress(PConfigData->InterfaceType,
PConfigData->BusNumber,
PConfigData->TrController,
PConfigData->SpanOfController,
(BOOLEAN)PConfigData->AddressSpace,
&pDevExt->UnMapRegisters);
if (!pDevExt->Controller) {
SerialLogError(
PDevObj->DriverObject,
pDevExt->DeviceObject,
PConfigData->TrController,
SerialPhysicalZero,
0,
0,
0,
7,
STATUS_SUCCESS,
SERIAL_REGISTERS_NOT_MAPPED,
pDevExt->DeviceName.Length+sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0,
NULL
);
SerialDump(
SERERRORS,
("SERIAL: Could not map memory for device registers for %wZ\n",
&pDevExt->DeviceName)
);
pDevExt->UnMapRegisters = FALSE;
status = STATUS_NONE_MAPPED;
goto ExtensionCleanup;
}
pDevExt->AddressSpace = PConfigData->AddressSpace;
pDevExt->OriginalController = PConfigData->Controller;
pDevExt->SpanOfController = PConfigData->SpanOfController;
//
// if we have an interrupt status then map it.
//
pDevExt->InterruptStatus =
(PUCHAR)PConfigData->TrInterruptStatus.QuadPart;
if (pDevExt->InterruptStatus) {
pDevExt->InterruptStatus
= SerialGetMappedAddress(PConfigData->InterfaceType,
PConfigData->BusNumber,
PConfigData->TrInterruptStatus,
PConfigData->SpanOfInterruptStatus,
(BOOLEAN)PConfigData->AddressSpace,
&pDevExt->UnMapStatus);
if (!pDevExt->InterruptStatus) {
SerialLogError(
PDevObj->DriverObject,
PDevObj,
PConfigData->TrController,
SerialPhysicalZero,
0,
0,
0,
8,
STATUS_SUCCESS,
SERIAL_REGISTERS_NOT_MAPPED,
pDevExt->DeviceName.Length+sizeof(WCHAR),
pDevExt->DeviceName.Buffer,
0,
NULL
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -