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

📄 initunlo.cpp

📁 这个是串口驱动程序开发包
💻 CPP
📖 第 1 页 / 共 5 页
字号:

            currentConfig = CONTAINING_RECORD(head, CONFIG_DATA, SameInterruptStatus);

            portIndex = currentConfig->PortIndex;
            maskInverted = currentConfig->MaskInverted;
            
            newDevice = new KdSerialDevice;
            if (!NT_SUCCESS(newDevice->InitializeOneController(currentConfig, FALSE))) 
            {
                delete newDevice;
                newDevice = NULL;
            }
            else
            {
                numberOfPorts++;
                newDevice->m_PortOnAMultiportCard = TRUE;

                if (!indexed) 
                {
                    dispatch.UsablePortMask |= 1 << (portIndex-1);
                    dispatch.MaskInverted |= maskInverted;
                }

                dispatch.pdvDevices[portIndex-1] = newDevice;

                InsertTailList(
                    &rootDevice->m_CommonInterruptObject,
                    &newDevice->m_CommonInterruptObject
                    );
            }
        }

        // If the number of ports is still one that means we
        // couldn't initialize any more devices.  This then
        // degenerates into a single port card.  Note that there
        // is no work to do in that case, it was set up in
        // SerialInitializeSingleController.

        if (numberOfPorts > 1) 
        {
            // Now allocate the dispatch structure out of pool
            // since it certain that we will actually use it.

            rootDevice->m_Isr.Context = ExAllocatePool(
                                               NonPagedPool,
                                               sizeof(SERIAL_MULTIPORT_DISPATCH)
                                               );

            if (!rootDevice->m_Isr.Context) 
            {
                // Darn!  Couldn't allocate the dispatch structure.
                //
                // Seems as though the safest thing to do in
                // this case is to act as though none of the ports
                // initialized.  Go through and delete all of the
                // devices that were initialized.
                //
                // This should be fairly safe since the initialize controller
                // code completely disables the port from interrupting.

                ULONG i;

                DebugDump(DBG_ERRORS, ("Couldn't allocate memory for %ws\n"
                     "------- multiport dispatch structure"
                     "------- deleting all associated devices",
                     rootDevice->DeviceName()));

                // We couldn't allocate memory for it, hopefully
                // the logger can make some headway.

                LogError(
                    2,
                    STATUS_SUCCESS,
                    SERIAL_INSUFFICIENT_RESOURCES,
                    rootDevice,
                    rootDevice->m_OriginalController
                    );

                for (i=0; numberOfPorts; i++) 
                {
                    if (dispatch.pdvDevices[i]) 
                    {
                        delete dispatch.pdvDevices[i];
                        numberOfPorts--;
                    }
                }
                return STATUS_INSUFFICIENT_RESOURCES;

            } 
            else 
            {
                ULONG i;
                PSERIAL_MULTIPORT_DISPATCH allocatedDispatch = 
                    (PSERIAL_MULTIPORT_DISPATCH)(rootDevice->m_Isr.Context);

                // Go throught the list of devices and NULL
                // their pointers to the isr.  The only device
                // that will truely have an isr is the root.

                allocatedDispatch->UsablePortMask = dispatch.UsablePortMask;
                allocatedDispatch->MaskInverted = dispatch.MaskInverted;
                allocatedDispatch->InterruptStatus = dispatch.InterruptStatus;

                for (i=0; i<SERIAL_MAX_PORTS_NONINDEXED; i++)
                {
                    allocatedDispatch->pdvDevices[i] = dispatch.pdvDevices[i];
                    if (dispatch.pdvDevices[i])
                        dispatch.pdvDevices[i]->m_Isr.pFunction = NULL;
                }

                if (indexed)
                    rootDevice->m_Isr.pFunction = rootDevice->IndexedMultiportIsr;
                else
                    rootDevice->m_Isr.pFunction = rootDevice->BitMappedMultiportIsr;
            }
        }

        PKdSerialDevice *firstDevice = (PKdSerialDevice *) GetFirstDevice();
        *firstDevice = rootDevice;
        return STATUS_SUCCESS;
    } 
    else 
    {
        PKdSerialDevice *firstDevice = (PKdSerialDevice *) GetFirstDevice();
        *firstDevice = NULL;
        return STATUS_UNSUCCESSFUL;
    }
}

NTSTATUS KdSerialDevice::InitializeOneController(PCONFIG_DATA ConfigData, BOOLEAN MapInterruptStatus)
/*++
Routine Description:
    This routine will call the real port initializatio code.
    If all was successful, it will save off in the device
    the isr that should be used as well as a pointer to
    the device itself.

    This is the only routine responsible for deleting the
    configuration information subsequent to getting it all
    from the registry.

Arguments:
    ConfigData - Pointer to a record for a single port.
    MapInterruptStatus - Simply passed on to the controller initialization
                         routine.

Return Value:
    Status returned from the controller initialization routine.
--*/
{
    NTSTATUS status;

    status = InitializeController(
                 ConfigData,
                 MapInterruptStatus
                 );

    if (NT_SUCCESS(status)) 
    {
        // We successfully initialized the single controller.
        // Stick the isr routine and the parameter for it
        // back into the device.
       m_Isr.pFunction = ISR;
       m_Isr.Context = NULL;
    }
    return status;
}

NTSTATUS KdSerialDevice::InitializeController( PCONFIG_DATA ConfigData, BOOLEAN MapInterruptStatus)
/*++
Routine Description:
    Really too many things to mention here.  In general, it forms
    and sets up names, creates the device, initializes kernel
    synchronization structures, allocates the typeahead buffer,
    sets up defaults, etc.

Arguments:
    ConfigData - Pointer to a record for a single port.
        NOTE: This routine will deallocate the config data.
    MapInterruptStatus - If true, we will attempt to map the
                         interrupt status register associated
                         with this port..

Return Value:
    STATUS_SUCCCESS if everything went ok.  A !NT_SUCCESS status
    otherwise.
--*/
{
    // Holds the NT Status that is returned from each call to the
    // kernel and executive.
    NTSTATUS status = STATUS_SUCCESS;

    DebugDump(DBG_DIAG1, ("Initializing for configuration record of %ws\n",
         (PCWSTR)ConfigData->sNtNameForPort) );
    
    if ((*KdComPortInUse)==((PUCHAR)(ConfigData->Controller.LowPart))) 
    {
        DebugDump(DBG_ERRORS, ("Kernel debugger is using port at address %x\n"
             "------  Serial driver will not load port %ws\n",
             *KdComPortInUse, (PCWSTR)ConfigData->sSymbolicLinkName) );

        KdSerialDriver::LogError(
            3,
            STATUS_SUCCESS,
            SERIAL_KERNEL_DEBUGGER_ACTIVE,
            NULL,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );

        delete ConfigData;
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // This will hold the string that we need to use to describe
    // the name of the device to the IO system (like \Device\Serial0).
    KdString sNameString;
    sNameString.Format(L"\\Device\\%s", (PCWSTR)ConfigData->sNtNameForPort);

    KdString sWin32Name;
    sWin32Name.Format(L"\\%s\\%s", DEFAULT_DIRECTORY, (PCWSTR)ConfigData->sSymbolicLinkName);

    status = Init(FILE_DEVICE_SERIAL_PORT,
                 (PCWSTR) sNameString,
                 (PCWSTR) sWin32Name,
                 0,
                 TRUE
                 );

    if (!NT_SUCCESS(status)) 
    {
        DebugDump(DBG_ERRORS, ("Could not create a device for %ws\n",
             (PCWSTR)ConfigData->sNtNameForPort) );

        KdSerialDriver::LogError(
            5,
            status,
            SERIAL_INSUFFICIENT_RESOURCES,
            NULL,
            ConfigData->Controller
            );
        delete ConfigData;
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    status = RtlWriteRegistryValue(
             RTL_REGISTRY_DEVICEMAP,
             L"SERIALCOMM",
             (PWSTR)((PCWSTR)ConfigData->sNtNameForPort),
             REG_SZ,
             (PWSTR)((PCWSTR)ConfigData->sSymbolicLinkName),
             ConfigData->sSymbolicLinkName.Length()*2+sizeof(WCHAR)
             );

    if (!NT_SUCCESS(status)) 
    {
        KdSerialDriver::LogError(
            53,
            status,
            SERIAL_NO_DEVICE_MAP_CREATED,
            this,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );
        DebugDump(DBG_ERRORS, ("Couldn't create the device map entry\n"
             "------- for port %ws\n",
            (PCWSTR) ConfigData->sNtNameForPort) );
    }
    else
        m_fRegisteredDeviceMap = TRUE;

    // Propagate that it is a jensen.
    m_Jensen = ConfigData->Jensen;

    // Intialialize the dpcs that will be used to complete
    // or timeout various IO operations.

    if (!((ConfigData->ClockRate == 1843200) ||
          (ConfigData->ClockRate == 3072000) ||
          (ConfigData->ClockRate == 4233600) ||
          (ConfigData->ClockRate == 8000000))) 
    {
        KdSerialDriver::LogError(
            6,
            STATUS_SUCCESS,
            SERIAL_UNSUPPORTED_CLOCK_RATE,
            this,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );
        DebugDump(DBG_ERRORS, ("Invalid clock rate specified for %ws\n",
             (PCWSTR)ConfigData->sNtNameForPort) );
        status = STATUS_SERIAL_NO_DEVICE_INITED;
        goto deviceCleanup;
    }

    // Save the value of clock input to the part.  We use this to calculate
    // the divisor latch value.  The value is in Hertz.
    m_ClockRate = ConfigData->ClockRate;

    // Get a "back pointer" to the device object and specify
    // that this driver only supports buffered IO.  This basically
    // means that the IO system copies the users data to and from
    // system supplied buffers.
    m_pDeviceObject->Flags |= DO_BUFFERED_IO;

    // Map the memory for the control registers for the serial device
    // into virtual memory.
    m_pController = new KdMapKernel(ConfigData->InterfaceType,
                                    ConfigData->BusNumber,
                                    ConfigData->Controller.QuadPart,
                                    ConfigData->SpanOfController,
                                    (ADDR_RANGE_TYPE)ConfigData->AddressSpace
                                    );

    if (!m_pController) 
    {
        KdSerialDriver::LogError(
            7,
            STATUS_SUCCESS,
            SERIAL_REGISTERS_NOT_MAPPED,
            this,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );
        DebugDump(DBG_ERRORS, ("Could not map memory for device registers for %ws\n",
              (PCWSTR)ConfigData->sNtNameForPort) );
        
        m_UnMapRegisters = FALSE;
        status = STATUS_NONE_MAPPED;
        goto deviceCleanup;
    }

    m_OriginalController = ConfigData->Controller;

    // if we were requested to map the interrupt status do so.

    if (MapInterruptStatus) 
    {
        m_pInterruptStatus = new KdMapKernel(ConfigData->InterfaceType,
                                              ConfigData->BusNumber,
                                              ConfigData->InterruptStatus.QuadPart,
                                              ConfigData->SpanOfInterruptStatus,
                                              (ADDR_RANGE_TYPE)ConfigData->AddressSpace);
        if (!m_pInterruptStatus) 
        {
            KdSerialDriver::LogError(
                8,
                STATUS_SUCCESS,
                SERIAL_REGISTERS_NOT_MAPPED,
                this,
                ConfigData->Controller,
                ConfigData->sSymbolicLinkName
                );
            DebugDump(DBG_ERRORS, ("Could not map memory for interrupt status for %ws\n",
                  (PCWSTR)ConfigData->sNtNameForPort) );
            m_UnMapRegisters = FALSE;
            status = STATUS_NONE_MAPPED;
            goto deviceCleanup;
        }
        m_OriginalInterruptStatus = ConfigData->InterruptStatus;
    }

    m_InterruptShareable = ConfigData->PermitSystemWideShare ? TRUE : FALSE;

    m_KdInterrupt.Init(
        (KDIRQ_CALLBACK) IsrCallBack,
        this,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -