📄 pc8250.cpp
字号:
_disable();
isr_data->line_status &= ~LSR_FRAMING_ERROR;
_enable();
}
return return_value;
}
int PC8250::HardwareOverrunError( int reset )
{
int return_value;
if ( error_status < RS232_SUCCESS )
return error_status;
return_value =
( isr_data->line_status & LSR_OVERRUN_ERROR ) ? 1 : 0;
if ( reset != UNCHANGED && reset != 0 ) {
_disable();
isr_data->line_status &= ~LSR_OVERRUN_ERROR;
_enable();
}
return return_value;
}
// This just reads in the status bit from the isr_data
// structure, and optionally clears it.
int PC8250::SoftwareOverrunError( int clear )
{
int temp = isr_data->overflow;
if ( clear ) {
_disable();
isr_data->overflow = 0;
_enable();
}
return temp;
}
// The three handshaking functions all have approximately the
// same mode of operation. If the setting parameter is set to
// UNCHANGED, they just return a boolean indicating whether or
// not handshaking is in effect. If handshaking is being turned
// on or off, things become a little more complicated. The
// major complication is that after setting the bits needed by
// the ISR to handshake, they also have to take action to make
// sure the control lines and XON/XOFF output are where they need
// to be to accurately get things started.
int PC8250::XonXoffHandshaking( int setting )
{
if ( setting != UNCHANGED ) {
if ( setting )
isr_data->handshaking |= xon_xoff;
else {
isr_data->handshaking &= ~xon_xoff;
isr_data->blocked &= ~xon_xoff;
// If blocking, I need to send an XON
if ( isr_data->blocking & xon_xoff ) {
_disable();
if ( isr_data->send_handshake_char == -1 )
isr_data->send_handshake_char = XON;
else
isr_data->send_handshake_char = -1;
_enable();
}
// Restart TX if I was blocked, or have to send and XON
jump_start( isr_data );
isr_data->blocking &= ~xon_xoff;
}
settings.XonXoff = ( setting != 0 );
}
return( ( isr_data->handshaking & xon_xoff ) != 0 );
}
int PC8250::RtsCtsHandshaking( int setting )
{
int old_setting;
if ( setting != UNCHANGED ) {
old_setting = isr_data->handshaking & rts_cts;
isr_data->handshaking &= ~rts_cts;
isr_data->blocking &= ~rts_cts;
isr_data->blocked &= ~rts_cts;
if ( setting ) {
Rts( 1 );
_disable();
if ( ( isr_data->modem_status & MSR_CTS ) == 0 )
isr_data->blocked |= rts_cts;
isr_data->handshaking |= rts_cts;
_enable();
settings.Rts = REMOTE_CONTROL;
} else {
if ( old_setting )
Rts( 1 ); //If handshaking to go off, set RTS high
if ( isr_data->blocked == 0 )
jump_start( isr_data );
}
settings.RtsCts = ( setting != 0 );
}
return( ( isr_data->handshaking & rts_cts ) != 0 );
}
int PC8250::DtrDsrHandshaking( int setting )
{
int old_setting;
if ( setting != UNCHANGED ) {
old_setting = isr_data->handshaking & dtr_dsr;
isr_data->handshaking &= ~dtr_dsr;
isr_data->blocking &= ~dtr_dsr;
isr_data->blocked &= ~dtr_dsr;
if ( setting ) {
Dtr( 1 );
_disable();
if ( ( isr_data->modem_status & MSR_DSR ) == 0 )
isr_data->blocked |= dtr_dsr;
isr_data->handshaking |= dtr_dsr;
_enable();
settings.Dtr = REMOTE_CONTROL;
} else {
if ( old_setting )
Dtr( 1 ); //If handshaking to go off, set RTS high
if ( isr_data->blocked == 0 )
jump_start( isr_data );
}
settings.DtrDsr = ( setting != 0 );
}
return( ( isr_data->handshaking & dtr_dsr ) != 0 );
}
// Just reading the state of the control line is relatively
// easy. The setting returned is just the stored value in the
// settings element. However, both of the next two routines have
// to handle setting or clearing the line as well. This only
// gets complicated if handshaking is turned on. If it is, these
// routines refuse to play with the control lines.
int PC8250::Dtr( int setting )
{
int mcr;
if ( setting != UNCHANGED ) {
if ( isr_data->handshaking & dtr_dsr )
return PC8250_HANDSHAKE_LINE_IN_USE;
else {
settings.Dtr = setting;
_disable();
mcr = inp( isr_data->uart + MODEM_CONTROL_REGISTER );
if ( setting )
mcr |= MCR_DTR;
else
mcr &= ~MCR_DTR;
outp( isr_data->uart + MODEM_CONTROL_REGISTER, mcr );
_enable();
}
}
return settings.Dtr;
}
int PC8250::Rts( int setting )
{
int mcr;
if ( setting != UNCHANGED ) {
if ( isr_data->handshaking & rts_cts )
return PC8250_HANDSHAKE_LINE_IN_USE;
else {
settings.Rts = setting;
_disable();
mcr = inp( isr_data->uart + MODEM_CONTROL_REGISTER );
if ( setting )
mcr |= MCR_RTS;
else
mcr &= ~MCR_RTS;
outp( isr_data->uart + MODEM_CONTROL_REGISTER, mcr );
_enable();
}
}
return settings.Rts;
}
// PeekBuffer uses the class Queue function to read as many
// bytes as possible from the RXBuffer.
int PC8250::PeekBuffer( void *buffer, unsigned int count )
{
if ( error_status < RS232_SUCCESS )
return error_status;
ByteCount =
isr_data->RXQueue.Peek( (unsigned char *) buffer, count );
( (char *) buffer )[ ByteCount ] = '\0';
return RS232_SUCCESS;
}
// The next two functions just return a count using a Queue
// class primitive function.
int PC8250::RXSpaceFree( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return isr_data->RXQueue.FreeCount();
}
int PC8250::TXSpaceUsed( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
return isr_data->TXQueue.InUseCount();
}
// Flushing the TX buffer is easy when using the Queue class
// primitive.
int PC8250::FlushTXBuffer( void )
{
if ( error_status < RS232_SUCCESS )
return error_status;
_disable();
isr_data->TXQueue.Clear();
_enable();
return RS232_SUCCESS;
}
// The debug output routine has three possible modes. If the
// buffer passed to it is a null, it means it should just return
// the total number of lines used by the the output, which is 6
// plus the number used by the base class. If the line number
// requested is less than where we start, the request is passed
// up the line to the base class. Finally, if it is one of our
// lines, the buffer is formatted and returned to the calling
// routine.
int PC8250::FormatDebugOutput( char *buffer, int line_number )
{
if ( buffer == 0 )
return( first_debug_output_line + 6 );
if ( line_number < first_debug_output_line )
return RS232::FormatDebugOutput( buffer, line_number );
switch( line_number - first_debug_output_line ) {
case 0 :
sprintf( buffer,
"Derived class: PC8250 "
"UART: %04x "
"Overflow: %1d "
"TX Running: %1d "
"Line Status: %02x",
isr_data->uart,
( isr_data->overflow ) ? 1 : 0,
( isr_data->tx_running ) ? 1 : 0,
isr_data->line_status );
break;
case 1 :
sprintf( buffer,
"TX Head, Tail, Count %4d %4d %4d "
"RX Head,Tail,Count %4d %4d %4d",
isr_data->TXQueue.Head(),
isr_data->TXQueue.Tail(),
isr_data->TXQueue.InUseCount(),
isr_data->RXQueue.Head(),
isr_data->RXQueue.Tail(),
isr_data->RXQueue.InUseCount() );
break;
case 2 :
sprintf( buffer,
"Counts: TX: %5u RX: %5u MS: %5u LS: %5u "
"CTS/DSR/RI/CD: %d%d%d%d",
isr_data->tx_int_count,
isr_data->rx_int_count,
isr_data->ms_int_count,
isr_data->ls_int_count,
( isr_data->modem_status & MSR_CTS ) ? 1 : 0,
( isr_data->modem_status & MSR_DSR ) ? 1 : 0,
( isr_data->modem_status & MSR_RI ) ? 1 : 0,
( isr_data->modem_status & MSR_CD ) ? 1 : 0 );
break;
case 3 :
sprintf( buffer,
"Handshake DTR/RTS/XON : %d%d%d "
"Blocking: %d%d%d "
"Blocked: %d%d%d "
"Handshake char: %04x",
( isr_data->handshaking & dtr_dsr ) ? 1 : 0,
( isr_data->handshaking & rts_cts ) ? 1 : 0,
( isr_data->handshaking & xon_xoff ) ? 1 : 0,
( isr_data->blocking & dtr_dsr ) ? 1 : 0,
( isr_data->blocking & rts_cts ) ? 1 : 0,
( isr_data->blocking & xon_xoff ) ? 1 : 0,
( isr_data->blocked & dtr_dsr ) ? 1 : 0,
( isr_data->blocked & rts_cts ) ? 1 : 0,
( isr_data->blocked & xon_xoff ) ? 1 : 0,
isr_data->send_handshake_char );
break;
case 4 :
sprintf( buffer,
"Parity Err: %d "
"Break Det: %d "
"Overrun Err: %d "
"Framing Err: %d "
"FIFO Setting: %2d",
( isr_data->line_status & LSR_PARITY_ERROR )
? 1 : 0,
( isr_data->line_status & LSR_BREAK_DETECT )
? 1 : 0,
( isr_data->line_status & LSR_OVERRUN_ERROR )
? 1 : 0,
( isr_data->line_status & LSR_FRAMING_ERROR )
? 1 : 0,
fifo_setting );
break;
case 5 :
char *uart_name;
switch( isr_data->uart_type ) {
case UART_8250 : uart_name = "8250"; break;
case UART_16550 : uart_name = "16550"; break;
default : uart_name = "Unknown"; break;
}
sprintf( buffer,
"Uart type: %-7s",
uart_name );
break;
default :
return RS232_ILLEGAL_LINE_NUMBER;
}
return RS232_SUCCESS;
}
// Just like the debug format routine, ErrorName has to pass
// most requests up the line to the base class, saving only a few
// for it to respond to.
char * PC8250::ErrorName( int error )
{
if ( error < RS232_NEXT_FREE_ERROR && error >= RS232_ERROR )
return RS232::ErrorName( error );
if (error < RS232_NEXT_FREE_WARNING && error >= RS232_WARNING)
return RS232::ErrorName( error );
if ( error >= RS232_SUCCESS )
return RS232::ErrorName( error );
switch ( error ) {
case PC8250_UART_NOT_FOUND :
return( "UART not found" );
case PC8250_HANDSHAKE_LINE_IN_USE :
return( "Handshake line in use" );
default :
return( "Undefined error" );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -