?? pc_com.c
字號:
PC_COM4_PORT_END};
static BYTE int_pri[4] = {PC_COM1_INT,
PC_COM2_INT,
PC_COM3_INT,
PC_COM4_INT};
static int timeout[4] = {PC_COM1_TIMEOUT,
PC_COM2_TIMEOUT,
PC_COM3_TIMEOUT,
PC_COM4_TIMEOUT};
void com_init( tAdapter adapter )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
asp->had_first_read = FALSE;
asp->hw_interrupt_priority = int_pri[adapter];
/*
* Set default state of all adapter registers
*/
asp->int_enable_reg.all = 0;
asp->line_control_reg.all = 0;
asp->line_control_reg.bits.word_length = 3;
asp->line_status_reg.all = 0;
asp->line_status_reg.bits.tx_holding_empty = 1;
asp->line_status_reg.bits.tx_shift_empty = 1;
asp->break_state = FALSE;
/*
* set up modem control reg so set_modem_control
* will set host adapter to the reset state
*/
asp->modem_control_reg.all = 0;
asp->modem_control_reg.bits.DTR = TRUE;
asp->modem_control_reg.bits.RTS = TRUE;
asp->modem_control_reg.bits.OUT1 = TRUE;
asp->modem_control_reg.bits.OUT2 = TRUE;
asp->modem_ctrl_state = 0; // different from DTR & RTS
asp->loopback_state = FALSE;
asp->modem_status_reg.all = 0;
asp->modem_status_changed = TRUE;
/*
* Set up default state of our state variables
*/
asp->receiver_line_status_interrupt_state = FALSE;
asp->data_available_interrupt_state = FALSE;
asp->tx_holding_register_empty_interrupt_state = FALSE;
asp->modem_status_interrupt_state = FALSE;
check_interrupt( asp ); /* sets interrupt line state */
return;
}
void com_close(tAdapter adapter)
{
}
/*
* =====================================================================
* The Adaptor functions
* =====================================================================
*/
static void inb_RBR( tAdapter adapter, BYTE *value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
if (asp->divisor_latch_state)
*value = (BYTE)asp->divisor_latch.byte.LSB;
else
{
host_com_lock(adapter);
//
// Read of rx buffer
//
check_data_available( adapter ); // get char if available
*value = asp->rx_buff_reg;
asp->line_status_reg.bits.data_ready = FALSE; // signal character read
check_data_available( adapter ); // check next char
asp->data_available_interrupt_state =
(asp->int_enable_reg.bits.data_available
&& asp->line_status_reg.bits.data_ready);
check_interrupt(asp); // set interrupt line
host_com_unlock(adapter);
}
}
static void inb_IER( tAdapter adapter, BYTE *value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
if (asp->divisor_latch_state)
*value = (BYTE)asp->divisor_latch.byte.MSB;
else
*value = asp->int_enable_reg.all;
}
static void inb_IIR( tAdapter adapter, BYTE *value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock( adapter );
if ((*value = generate_iir( adapter )) == UART_THRE_INT)
{
asp->tx_holding_register_empty_interrupt_state = FALSE;
check_interrupt( asp );
}
host_com_unlock(adapter);
}
static void inb_LCR( tAdapter adapter, BYTE *value )
{
*value = UART_ADAPTER(adapter).line_control_reg.all;
}
static void inb_MCR( tAdapter adapter, BYTE *value )
{
*value = UART_ADAPTER(adapter).modem_control_reg.all;
}
static void inb_LSR( tAdapter adapter, BYTE *value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
*value = asp->line_status_reg.all;
asp->line_status_reg.bits.overrun_error = 0;
asp->line_status_reg.bits.parity_error = 0;
asp->line_status_reg.bits.framing_error = 0;
asp->line_status_reg.bits.break_interrupt = 0;
asp->receiver_line_status_interrupt_state = FALSE;
check_interrupt(asp);
host_com_unlock(adapter);
}
static void inb_MSR( tAdapter adapter, BYTE *value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
if (!asp->modem_status_changed && !asp->loopback_state)
{
*value = asp->last_modem_status_value.all;
}
else
{
host_com_lock(adapter);
if (asp->loopback_state)
{
*value = asp->modem_status_reg.all;
asp->modem_status_changed = TRUE;
}
else
{
refresh_modem_status( adapter );
*value = asp->modem_status_reg.all;
asp->modem_status_changed = FALSE;
}
asp->modem_status_reg.bits.delta_CTS = 0;
asp->modem_status_reg.bits.delta_DSR = 0;
asp->modem_status_reg.bits.delta_RLSD = 0;
asp->modem_status_reg.bits.TERI = 0;
asp->modem_status_interrupt_state = FALSE;
check_interrupt(asp);
asp->last_modem_status_value.all = asp->modem_status_reg.all;
host_com_unlock(adapter);
}
}
static void inb_SCR( tAdapter adapter, BYTE *value )
{
*value = UART_ADAPTER(adapter).scratch; // Just read the value stored.
}
void com_inb( WORD port, BYTE *value )
{
void (*(inb_func[]))( tAdapter, BYTE * ) =
{
inb_RBR,
inb_IER,
inb_IIR,
inb_LCR,
inb_MCR,
inb_LSR,
inb_MSR,
inb_SCR
};
tAdapter adapter = adapter_for_port(port);
if (adapter < NUM_SERIAL_PORTS)
inb_func[port & 0x7] (adapter, value);
else
*value = 0xFF;
}
static void outb_THR( tAdapter adapter, BYTE value )
{
const BYTE selectBits[4] = { 0x1f, 0x3f, 0x7f, 0xff } ;
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
if (asp->divisor_latch_state)
{
if (asp->divisor_latch.byte.LSB != value)
{
asp->divisor_latch.byte.LSB = value;
asp->baud_rate_changed = TRUE;
}
}
else
{
/*
* Write char to tx buffer
*/
if (!asp->loopback_state)
{
asp->line_status_reg.bits.tx_shift_empty = 0;
host_com_write_tx( adapter, value );
}
else
{
/* Loopback case requires masking off */
/* of bits based upon word length. */
asp->rx_buff_reg = value
& selectBits[ asp->line_control_reg.bits.word_length ];
/*
* Check for data overrun and set up correct interrupt
*/
if ( asp->line_status_reg.bits.data_ready)
{
asp->line_status_reg.bits.overrun_error = TRUE;
raise_rls_interrupt(asp);
}
else
{
asp->line_status_reg.bits.data_ready = TRUE;
raise_rda_interrupt(asp);
}
asp->line_status_reg.bits.tx_shift_empty = 1;
}
// holding register permanently empty!!!
asp->line_status_reg.bits.tx_holding_empty = 1;
raise_thre_interrupt( asp );
}
host_com_unlock(adapter);
}
static void outb_IER( tAdapter adapter, BYTE value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
if (asp->divisor_latch_state)
{
if (asp->divisor_latch.byte.MSB != value)
{
asp->divisor_latch.byte.MSB = value;
asp->baud_rate_changed = TRUE;
}
}
else
{
int org_da = asp->int_enable_reg.bits.data_available;
asp->int_enable_reg.all = value & 0xf;
//
// Kill off any pending interrupts for those items
// which are set now as disabled
//
if (!asp->int_enable_reg.bits.data_available)
asp->data_available_interrupt_state = FALSE;
if (!asp->int_enable_reg.bits.tx_holding)
asp->tx_holding_register_empty_interrupt_state = FALSE;
if (!asp->int_enable_reg.bits.rx_line)
asp->receiver_line_status_interrupt_state = FALSE;
if (!asp->int_enable_reg.bits.modem_status)
asp->modem_status_interrupt_state = FALSE;
//
// Check for immediately actionable interrupts
//
check_data_available( adapter );
if ( asp->line_status_reg.bits.data_ready == 1 )
raise_rda_interrupt( asp );
if ( asp->line_status_reg.bits.tx_holding_empty == 1 )
raise_thre_interrupt( asp );
check_interrupt(asp); // lower int line if no outstanding interrupts
}
host_com_unlock(adapter);
}
static void outb_IIR( tAdapter adapter, BYTE value )
{
//
// Essentially a READ ONLY register
//
}
static void outb_LCR( tAdapter adapter, BYTE value )
{
const LINE_CONTROL_REG LCRFlushMask =
{
(unsigned) ~0, // word_length:2;
(unsigned) 0, // no_of_stop_bits:1;
(unsigned) ~0, // parity_enabled:1;
(unsigned) ~0, // even_parity:1;
(unsigned) ~0, // stick_parity:1;
(unsigned) 0, // set_break:1;
(unsigned) 0 // DLAB:1;
};
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
if (((value ^ asp->line_control_reg.all) & LCRFlushMask.all) != 0)
com_flush_input(adapter);
if (asp->line_control_reg.all != value)
{
asp->line_control_reg.all = value;
set_line_control( adapter );
}
if (asp->divisor_latch_state != asp->line_control_reg.bits.DLAB)
{
asp->divisor_latch_state = asp->line_control_reg.bits.DLAB;
if (asp->divisor_latch_state)
asp->baud_rate_changed = FALSE;
else
{
if (asp -> baud_rate_changed)
{
set_baud_rate(adapter);
}
}
}
set_break(adapter);
host_com_unlock(adapter);
}
static void outb_MCR( tAdapter adapter, BYTE value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
// Optimisation - DOS keeps re-writing this register
if ( asp->modem_control_reg.all != value )
{
asp->modem_control_reg.all = value;
asp->modem_control_reg.bits.pad = 0;
set_modem_control(adapter);
}
host_com_unlock(adapter);
}
static void outb_LSR( tAdapter adapter, BYTE value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
int temp;
host_com_lock(adapter);
temp = asp->line_status_reg.bits.tx_shift_empty; /* READ ONLY */
asp->line_status_reg.all = value;
asp->line_status_reg.bits.tx_shift_empty = (BYTE_BIT_FIELD)temp;
host_com_unlock(adapter);
}
static void outb_MSR( tAdapter adapter, BYTE value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
host_com_lock(adapter);
//
// Essentially a READ ONLY register, except that DR-DOS
// writes to this reg after setting int on MSR change and
// expects to get an interrupt back!!! So we will oblige.
// Writing to this reg only seems to affect the delta bits
// (bits 0-3) of the reg.
//
if (((value ^ asp->modem_status_reg.all) & 0xf) != 0)
{
asp->modem_status_reg.all &= 0xf0;
asp->modem_status_reg.all |= value & 0xf;
if (!asp->loopback_state)
raise_ms_interrupt(asp);
}
host_com_unlock(adapter);
}
static void outb_SCR( tAdapter adapter, BYTE value )
{
UART_STATE *asp = & UART_ADAPTER(adapter);
asp->scratch = value; // Scratch register - just store the value.
}
void com_outb(WORD port, BYTE value)
{
void (*(outb_func[]))(tAdapter, BYTE) =
{
outb_THR,
outb_IER,
outb_IIR,
outb_LCR,
outb_MCR,
outb_LSR,
outb_MSR,
outb_SCR
};
tAdapter adapter = adapter_for_port(port);
if (adapter < NUM_SERIAL_PORTS)
{
outb_func[port & 0x7] (adapter, value);
}
}
/********************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -