📄 initunlo.cpp
字号:
wont be sharing.
Arguments:
ConfigData - Root of a "tree" of configuration records.
--*/
{
PKdSerialDevice rootDevice = NULL;
PCONFIG_DATA originalConfig = ConfigData;
PCONFIG_DATA currentConfig = ConfigData;
LIST_ENTRY listHead;
DebugDump(DBG_DIAG3, ("In SerialInitializeRootInterrupt\n") );
// This makes the listhead imbedded in the root config
// record a local list head. That list no longer has the
// original config record as part of the list.
InitializeListHead(&listHead);
if (!IsListEmpty(&ConfigData->SameInterrupt))
{
PLIST_ENTRY old = ConfigData->SameInterrupt.Flink;
RemoveEntryList(&ConfigData->SameInterrupt);
InsertTailList(old, &listHead);
}
// If we are on a MicroChannel bus then all the configs can simply
// share the interrupt.
if (ConfigData->InterfaceType == MicroChannel)
{
// We know that all of the configs on this "chain"
// are using the MicroChannel.
while (currentConfig)
{
if (!IsListEmpty(¤tConfig->SameInterruptStatus))
{
// This is a multiport card, call its intialization.
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- and status at %x a same interrupt root of multiports\n"
"------- On a MicroChannel.\n",
(PCWSTR)currentConfig->sNtNameForPort,currentConfig->Controller.LowPart,
currentConfig->InterruptStatus.LowPart) );
InitializeRootMultiPort(currentConfig);
rootDevice = (PKdSerialDevice) GetFirstDevice();
}
else
{
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- A same interrupt single controller On a MicroChannel.\n",
(PCWSTR)currentConfig->sNtNameForPort,currentConfig->Controller.LowPart) );
rootDevice = new KdSerialDevice;
if (!NT_SUCCESS(rootDevice->InitializeOneController(currentConfig, FALSE)))
{
delete rootDevice;
rootDevice = NULL;
}
}
DebugDump(DBG_DIAG5, ("It came back with a same interrupt rootDevice of %x\n", rootDevice));
if (!IsListEmpty(&listHead))
{
PLIST_ENTRY head;
head = RemoveHeadList(&listHead);
currentConfig = CONTAINING_RECORD(head, CONFIG_DATA, SameInterrupt);
}
else
{
currentConfig = NULL;
rootDevice = NULL;
}
}
}
else
{
// We have to set up to do "shareing" of interrupt resources.
// We first keep trying to initialize one of the
// configs on the chain until one succeeds.
while ((!rootDevice) && currentConfig)
{
NTSTATUS status;
if (!IsListEmpty(¤tConfig->SameInterruptStatus))
{
// This is a multiport card, call its intialization.
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- and status at %x a same interrupt sharer root controller\n",
(PCWSTR)currentConfig->sNtNameForPort,currentConfig->Controller.LowPart,
currentConfig->InterruptStatus.LowPart) );
status = InitializeRootMultiPort(currentConfig);
rootDevice = (PKdSerialDevice) GetFirstDevice();
}
else
{
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- A single same interrupt sharer root controller.\n",
(PCWSTR) currentConfig->sNtNameForPort,currentConfig->Controller.LowPart) );
rootDevice = new KdSerialDevice;
status = rootDevice->InitializeOneController(currentConfig, FALSE);
if (!NT_SUCCESS(status))
{
delete rootDevice;
rootDevice = NULL;
}
}
DebugDump(DBG_DIAG5, ("It came back with a same interrupt rootDevice of %x\n",
rootDevice) );
if (!NT_SUCCESS(status))
{
// Well that one didn't work. Try the next one.
if (!IsListEmpty(&listHead))
{
PLIST_ENTRY head;
head = RemoveHeadList(&listHead);
currentConfig = CONTAINING_RECORD(head, CONFIG_DATA, SameInterrupt);
}
else
{
currentConfig = NULL;
rootDevice = NULL;
}
}
else
{
// We save off the isr to use and the context to the
// isr into the following fields. Unless the
// device is actually sharing the interrupt with
// another "card" this field will not be
// needed.
rootDevice->m_TopLevelIsr.pFunction = rootDevice->m_Isr.pFunction;
rootDevice->m_TopLevelIsr.Context = rootDevice->m_Isr.Context;
}
}
if (rootDevice)
{
// We have a root device! Now try to
// all intialize all the other configs on this
// interrupt.
ULONG numberOfSharers = 1;
while (!IsListEmpty(&listHead))
{
NTSTATUS status;
PLIST_ENTRY head;
PKdSerialDevice newDevice;
head = RemoveHeadList(&listHead);
currentConfig = CONTAINING_RECORD(head, CONFIG_DATA, SameInterrupt);
if (!IsListEmpty(¤tConfig->SameInterruptStatus))
{
// This is a multiport card, call its intialization.
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- and status at %x a same interrupt sharer multiports\n",
(PCWSTR)currentConfig->sNtNameForPort,currentConfig->Controller.LowPart,
currentConfig->InterruptStatus.LowPart) );
status = InitializeRootMultiPort(currentConfig);
newDevice = (PKdSerialDevice) GetFirstDevice();
}
else
{
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- A single same interrupt sharer controller.\n",
(PCWSTR) currentConfig->sNtNameForPort,currentConfig->Controller.LowPart) );
newDevice = new KdSerialDevice;
status = newDevice->InitializeOneController(
currentConfig,
FALSE
);
if (!NT_SUCCESS(status))
{
delete newDevice;
newDevice = NULL;
}
}
DebugDump(DBG_DIAG5, ("It came back with a same interrupt newDevice of %x\n",
rootDevice) );
if (NT_SUCCESS(status))
{
PLIST_ENTRY rootTail;
PLIST_ENTRY newTail;
// Propagate the isr routine and context
// up to the sharing list.
newDevice->m_TopLevelIsr.pFunction = newDevice->m_Isr.pFunction;
newDevice->m_TopLevelIsr.Context = newDevice->m_Isr.Context;
newDevice->m_Isr.pFunction = NULL;
newDevice->m_Isr.Context = NULL;
// Append this top level device onto the list of
// other top level interrupt sharers.
InsertTailList(
&rootDevice->m_TopLevelSharers,
&newDevice->m_TopLevelSharers
);
// Link together the lists of devices that will
// be using the same interrupt object (not necessarily)
// the same "interrupt service routine" (actually dispatchers).
rootTail = rootDevice->m_CommonInterruptObject.Blink;
newTail = newDevice->m_CommonInterruptObject.Blink;
rootDevice->m_CommonInterruptObject.Blink = newTail;
newDevice->m_CommonInterruptObject.Blink = rootTail;
rootTail->Flink = &newDevice->m_CommonInterruptObject;
newTail->Flink = &rootDevice->m_CommonInterruptObject;
numberOfSharers++;
}
}
// All done initializing the other sharers.
//
// If none of the others actually initialized
// the we simply degenerate into the interrupt
// handling for the root device. (This requires
// no additional work.)
if (numberOfSharers > 1)
{
// Replace the Isr and context for the root
// with the pointer to the "sharer" dispatcher
// and a pointer to the list of share entries
// as context.
DebugDump(DBG_DIAG5, ("We do have more than one sharer for the interrupt.\n"
"------- The controlling Device should be %x\n",
rootDevice) );
rootDevice->m_Isr.pFunction = rootDevice->SharerIsr;
rootDevice->m_Isr.Context = &(rootDevice->m_TopLevelSharers);
}
}
}
}
NTSTATUS KdSerialDriver::InitializeRootMultiPort(PCONFIG_DATA ConfigData)
/*++
Routine Description:
This routine attempts to initialize all the ports on a
multiport board and to build a structure so that an
isr can dispatch to the particular ports device device.
Arguments:
ConfigData - A linked list of configuration information for all
the ports on a multiport card.
--*/
{
PKdSerialDevice rootDevice = NULL;
PCONFIG_DATA originalConfig = ConfigData;
PCONFIG_DATA currentConfig = ConfigData;
ULONG indexed;
ULONG portIndex;
ULONG maskInverted;
LIST_ENTRY listHead;
NTSTATUS status;
DebugDump(DBG_DIAG3, ("In SerialInitializeRootMultiPort\n") );
// This makes the listhead imbedded in the root config
// record a local list head. The old head of the list
// (the current config) will no longer be part of the list.
InitializeListHead(&listHead);
if (!IsListEmpty(&ConfigData->SameInterruptStatus))
{
PLIST_ENTRY old = ConfigData->SameInterruptStatus.Flink;
RemoveEntryList(&ConfigData->SameInterruptStatus);
InsertTailList(
old,
&listHead
);
}
// The indexed field is valid for all ports on the chain.
indexed = ConfigData->Indexed;
DebugDump(DBG_DIAG5, ("This indexed value for this multiport is: %d\n", indexed) );
maskInverted = ConfigData->MaskInverted;
// We first keep trying to initialize one of the
// ports on the chain until one succeeds.
while ((!rootDevice) && currentConfig)
{
portIndex = currentConfig->PortIndex;
DebugDump(DBG_DIAG5, ("Attempting to make %ws with controller at %x\n"
"------- and status at %x a root of multiports\n",
(PCWSTR) currentConfig->sNtNameForPort,currentConfig->Controller.LowPart,
currentConfig->InterruptStatus.LowPart) );
rootDevice = new KdSerialDevice;
status = rootDevice->InitializeOneController(
currentConfig,
TRUE
);
DebugDump(DBG_DIAG5, ("Multiport came back with a same interrupt rootDevice of %x\n",
rootDevice) );
if (!NT_SUCCESS(status))
{
delete rootDevice;
rootDevice = NULL;
// Well that one didn't work. Try the next one.
if (!IsListEmpty(&listHead))
{
PLIST_ENTRY head;
head = RemoveHeadList(&listHead);
currentConfig = CONTAINING_RECORD(head, CONFIG_DATA, SameInterruptStatus);
}
else
{
currentConfig = NULL;
rootDevice = NULL;
}
}
}
if (rootDevice)
{
// Well we have at least one controller. We build a local
// dispatch structure. If we end up being able to
// intialize another port then we will allocate
// the dispatch structure out of pool. If we can't
// intialize anymore ports then this degenerates into a
// single port case.
ULONG numberOfPorts = 1;
SERIAL_MULTIPORT_DISPATCH dispatch;
rootDevice->m_PortOnAMultiportCard = TRUE;
RtlZeroMemory(
&dispatch,
sizeof(SERIAL_MULTIPORT_DISPATCH)
);
if (!indexed)
{
dispatch.UsablePortMask = 1 << (portIndex-1);
dispatch.MaskInverted = maskInverted;
}
dispatch.InterruptStatus = (PUCHAR) rootDevice->m_pInterruptStatus->GetSystemAddress();
dispatch.pdvDevices[portIndex-1] = rootDevice;
while (!IsListEmpty(&listHead))
{
PLIST_ENTRY head;
PKdSerialDevice newDevice;
head = RemoveHeadList(&listHead);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -