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

📄 pc_com.c

📁 DD sample implements serial port support for the Virtual DOS Machine (VDM). Driver for windows. Tool
💻 C
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) Microsoft 1992-1999, All Rights Reserved
// portions copyright 1991 by Insignia Solutions Ltd., used by permission.
//   

/*
 * PC_com.c
 *
 * This module handles the virtual UART I/O and interrupt interface
 *
 * Note:
 *  Refer to National Semiconductor literature for a detailed description
 *  of the NS16450/NS8250A UART.  Refer to the PC-XT Tech Ref Manual 
 *  Section 1-185 for a description of the Asynchronous Adaptor Card.
 *
 *
 * revision history:
 *  24-Dec-1992 John Morgan:  written based (in part) on 
 *                             serial driver support from Windows NT VDM.
 *
 */


//
//    useful utility macros
//
#include "util_def.h"

//
//    standard library include files
//
#include <windows.h>

#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <string.h>

//
//    COM_VDD specific include files
//
#include "com_vdd.h"
#include "PC_def.h"
#include "PC_com.h"
#include "NT_com.h"
#include "vddsvc.h"

/*
 * =====================================================================
 * Subsidiary functions - for interrupt emulation
 * =====================================================================
 */
static void check_interrupt( UART_STATE *asp )
{
    /*
     * Follow somewhat dubious advice on Page 1-188 of XT Tech Ref
     * regarding the adapter card sending interrupts to the system.
     * Apparently confirmed by the logic diagram.
     */
    if (asp->out2_state
        && !asp->loopback_state
        && (asp->data_available_interrupt_state
            || asp->tx_holding_register_empty_interrupt_state
            || asp->receiver_line_status_interrupt_state
            || asp->modem_status_interrupt_state))
    {
        if (!asp->interrupt_line_state)
        {
            asp->interrupt_line_state = TRUE;
            VDDSimulateInterrupt( 0, asp->hw_interrupt_priority, 1);
        }
    }     
    else
    {
        asp->interrupt_line_state = FALSE;
    }
}

extern void raise_rls_interrupt( UART_STATE *asp )
{
    /*
     * Check if receiver line status interrupt is enabled
     */
    if (asp->int_enable_reg.bits.rx_line)
    {
        asp->receiver_line_status_interrupt_state = TRUE;
        check_interrupt(asp);
    }
}

extern void raise_rda_interrupt( UART_STATE *asp )
{
    /*
     * Check if data available interrupt is enabled
     */
    if (asp->int_enable_reg.bits.data_available)
    {
        asp->data_available_interrupt_state = TRUE;
        check_interrupt(asp);
    }
}

extern void raise_ms_interrupt( UART_STATE *asp )
{
    /*
     * Check if modem status interrupt is enabled
     */
    if (asp->int_enable_reg.bits.modem_status)
    {
        asp->modem_status_interrupt_state = TRUE;
        check_interrupt(asp);
    }
    asp->modem_status_changed = TRUE;
}

extern void raise_thre_interrupt( UART_STATE *asp )
{
    /*
     * Check if tx holding register empty interrupt is enabled
     */
    if (asp->int_enable_reg.bits.tx_holding)
    {
        asp->tx_holding_register_empty_interrupt_state = TRUE;
        check_interrupt(asp);
    }
}


/*
 * =====================================================================
 * Subsidiary functions - for data available
 * =====================================================================
 */

/*
 * signal all characters transmitted!
 */
void clear_tbr_flag( UART_STATE *asp )
{
    asp->line_status_reg.bits.tx_shift_empty = 1;
}

/*
 * check for data available and line status changes
 */
static void check_data_available( tAdapter adapter )
{
    UART_STATE *asp = & UART_ADAPTER(adapter);
    DWORD error;
    
    if (!asp->loopback_state)
    {
        if (!asp->line_status_reg.bits.data_ready)
        {
            if (!(asp->line_status_reg.bits.data_ready = (BYTE_BIT_FIELD)host_com_read_rx( adapter, &asp->rx_buff_reg ))
                && asp->int_enable_reg.bits.data_available)
            {
                host_com_rx_wait( adapter );
            }
        }

        if ((error = host_com_get_error( adapter )) != 0)
        {
            /*
             * Set line status register and raise line status interrupt
             */
            if (error & (CE_OVERRUN | CE_RXOVER))
                asp->line_status_reg.bits.overrun_error = 1;

            if (error & CE_FRAME)
                asp->line_status_reg.bits.framing_error = 1;

            if (error & CE_RXPARITY)
                asp->line_status_reg.bits.parity_error = 1;

            if (error & CE_BREAK)
                asp->line_status_reg.bits.break_interrupt = 1;

            raise_rls_interrupt( asp );
        }
    }
}


/*
 * flush all received input
 */
static void com_flush_input(tAdapter adapter)
{
    BYTE dummy;
    
    while (host_com_read_rx( adapter, &dummy ))
        /* do nothing */;

    UART_ADAPTER(adapter).line_status_reg.bits.data_ready = FALSE;
}

/*
 * set the IIR for current interrupts pending
 */
static BYTE generate_iir( tAdapter adapter )
{
    UART_STATE *asp = & UART_ADAPTER(adapter);

    /*
     * Set up interrupt identification register with highest priority
     * pending interrupt.
     */

    check_data_available( adapter );

    return 
        (asp->receiver_line_status_interrupt_state) ?           UART_RLS_INT
        : (asp->line_status_reg.bits.data_ready) ?              UART_RDA_INT
          : (asp->tx_holding_register_empty_interrupt_state) ?  UART_THRE_INT
            : (asp->modem_status_interrupt_state) ?             UART_MS_INT
              :                                                 UART_NO_INT;
}


/*
 * set modem status register to new status
 */
static void set_modem_status( tAdapter adapter, long modem_status )
{
    UART_STATE *asp = & UART_ADAPTER( adapter );
    int cts_state, dsr_state, rlsd_state, ri_state;

    cts_state  = ((modem_status & HOST_MS_CTS)  != 0);
    dsr_state  = ((modem_status & HOST_MS_DSR)  != 0);
    rlsd_state = ((modem_status & HOST_MS_RLSD) != 0);
    ri_state   = ((modem_status & HOST_MS_RI)   != 0);

    /*
     * Establish CTS state
     */
    if (cts_state != asp->modem_status_reg.bits.CTS)
    {
        asp->modem_status_reg.bits.CTS = (BYTE_BIT_FIELD)cts_state;
        asp->modem_status_reg.bits.delta_CTS = TRUE;
        raise_ms_interrupt(asp);
    }

    /*
     * Establish DSR state
     */
    if (dsr_state != asp->modem_status_reg.bits.DSR)
    {
        asp->modem_status_reg.bits.DSR = (BYTE_BIT_FIELD)dsr_state;
        asp->modem_status_reg.bits.delta_DSR = TRUE;
        raise_ms_interrupt(asp);
    }

    /*
     * Establish RLSD state
     */
    if (rlsd_state != asp->modem_status_reg.bits.RLSD)
    {
        asp->modem_status_reg.bits.RLSD = (BYTE_BIT_FIELD)rlsd_state;
        asp->modem_status_reg.bits.delta_RLSD = TRUE;
        raise_ms_interrupt(asp);
    }

    /*
     * Establish RI state
     */
    if (ri_state != asp->modem_status_reg.bits.RI)
    {
        if ((asp->modem_status_reg.bits.RI = (BYTE_BIT_FIELD)ri_state) == FALSE)
        {
            asp->modem_status_reg.bits.TERI = TRUE;
            raise_ms_interrupt(asp);
        }
    }
}

/*
 * One of the modem control input lines has changed state
 */
static void refresh_modem_status( tAdapter adapter )
{
    /*
     * Update the modem status register after a change to one of the
     * modem status input lines
     */
    UART_STATE *asp = & UART_ADAPTER(adapter);

    if (! UART_ADAPTER(adapter).loopback_state)
    {
        /* get current modem input state */
        set_modem_status( adapter, host_com_ioctl( adapter, HOST_COM_MSTATUS, 0 ) );
    }
}


/*
 * =====================================================================
 * Subsidiary functions - for setting comms parameters
 * =====================================================================
 */

static void set_baud_rate( tAdapter adapter )
{
    const long UART_bit_clock = 115200;
    UART_STATE *asp = & UART_ADAPTER(adapter);

    if (UART_ADAPTER(adapter).divisor_latch.all != 0)
    {
        com_flush_input( adapter );
        host_com_ioctl( adapter, 
                        HOST_COM_BAUD, 
                        UART_bit_clock / UART_ADAPTER(adapter).divisor_latch.all
                      );
    }
}

static void set_break( tAdapter adapter )
{
    /*
     * Process the set break control bit. Bit 6 of the Line Control
     * Register.
     */
    UART_STATE *asp = & UART_ADAPTER(adapter);

    if (asp->line_control_reg.bits.set_break != asp->break_state )
    {
        asp->break_state = asp->line_control_reg.bits.set_break;
        host_com_ioctl( adapter, HOST_COM_SBRK, 0 );
    }
}

static void set_line_control( tAdapter adapter )
{
    /*
     * Set Number of data bits
     *     Parity bits
     *     Number of stop bits
     */
    UART_STATE *asp = & UART_ADAPTER(adapter);
    int host_line_ctrl;
    const int host_bits[4][2] =
        { HOST_LC_DATA_5 | HOST_LC_STOP_1,
          HOST_LC_DATA_5 | HOST_LC_STOP_15,
          HOST_LC_DATA_6 | HOST_LC_STOP_1,
          HOST_LC_DATA_6 | HOST_LC_STOP_2,
          HOST_LC_DATA_7 | HOST_LC_STOP_1,
          HOST_LC_DATA_7 | HOST_LC_STOP_2,
          HOST_LC_DATA_8 | HOST_LC_STOP_1,
          HOST_LC_DATA_8 | HOST_LC_STOP_2};

    host_line_ctrl =

    // the number of data bits
        host_bits[asp->line_control_reg.bits.word_length]

    // and stop bits
                    [asp->line_control_reg.bits.no_of_stop_bits]

    // and the parity settings
        | ((asp->line_control_reg.bits.parity_enabled == UART_PARITY_OFF)
            ? HOST_LC_PARITY_NONE

            : (asp->line_control_reg.bits.stick_parity == UART_PARITY_STICK)
                ? (asp->line_control_reg.bits.even_parity == UART_PARITY_ODD)
                    ? HOST_LC_PARITY_MARK

                    : HOST_LC_PARITY_SPACE

                : (asp->line_control_reg.bits.even_parity == UART_PARITY_ODD)
                    ? HOST_LC_PARITY_ODD

                    : HOST_LC_PARITY_EVEN
          );

    host_com_ioctl(adapter, HOST_COM_LINE_CTRL, host_line_ctrl);
}

void set_modem_control( tAdapter adapter )
{
    UART_STATE *asp = & UART_ADAPTER( adapter );

    /*
     * Process the loopback control bit
     */

    if (asp->modem_control_reg.bits.loop != asp->loopback_state)
    {
        if (!(asp->loopback_state = asp->modem_control_reg.bits.loop))
        {
            /*
             * Reset the modem status inputs according to the real
             * modem status
             */
            refresh_modem_status( adapter );
        }
    }

    /*
     * Modem control function depends on the loopback control bit
     */
    
    if (asp->loopback_state)
    {
        set_modem_status( adapter, 

        // loop DTR back to DSR
            (asp->modem_control_reg.bits.DTR && HOST_MS_DSR)

        // loop RTS back to CTS
            | (asp->modem_control_reg.bits.RTS && HOST_MS_CTS)
    
        // loop OUT1 back to RI
            | (asp->modem_control_reg.bits.OUT1 && HOST_MS_RI)

        // loop OUT2 back to RLSD
            | (asp->modem_control_reg.bits.OUT2 && HOST_MS_RLSD) );

    }
    else  // not in loopback state
    {
        BYTE host_modem_control = 
            (asp->modem_control_reg.bits.DTR ? HOST_MC_DTR : 0)
            | (asp->modem_control_reg.bits.RTS ? HOST_MC_RTS : 0);

        /*
         * In the real adapter, the OUT1 control bit is not connected
         * so no real modem control change is required
         */

        /*
         * In the real adapter the OUT2 control bit is used to determine
         * whether the communications card can send interrupts; so no
         * real modem control change is required
         */
        asp->out2_state = asp->modem_control_reg.bits.OUT2;

        if (asp->modem_ctrl_state != host_modem_control)
        {
            asp->modem_ctrl_state = host_modem_control;
            host_com_ioctl( adapter, HOST_COM_MODEM_CTRL, host_modem_control );
        }
    }
}

void com_reset(tAdapter adapter)
{
    /*
     * Set host devices to current state
     */
    set_baud_rate( adapter );
    set_line_control( adapter );
    set_break( adapter );
    set_modem_control( adapter );
}

static int port_start[4] = {PC_COM1_PORT_START,
                            PC_COM2_PORT_START,
                            PC_COM3_PORT_START,
                            PC_COM4_PORT_START};
static int port_end[4] = {PC_COM1_PORT_END,
                          PC_COM2_PORT_END,
                          PC_COM3_PORT_END,

⌨️ 快捷键说明

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