?? pc_com.c
字號:
// 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 + -