⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initunlo.cpp

📁 这个是串口驱动程序开发包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    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(&currentConfig->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(&currentConfig->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(&currentConfig->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 + -