📄 rs232x4.cpp
字号:
#include <dos.h>
#include "rs232x4.h"
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
#define THR 0
#define RDR 0
#define BRDL 0
#define BRDH 1
#define IER 1
#define IIR 2
#define FCR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
#define IRQ2MaskBit 0x04
#define IRQ4MaskBit 0x10
#define IRQ3MaskBit 0x08
#define IRQ8MaskBit 0x01
#define IRQ9MaskBit 0x02
#define BUF_SIZ 1500
#define SEG 0xa800
unsigned char InputBuf[4][BUF_SIZ];
unsigned int IBufGetIdx[4];
unsigned int IBufPutIdx[4];
unsigned char OutputBuf[4][BUF_SIZ];
unsigned int OBufGetIdx[4];
unsigned int OBufPutIdx[4];
unsigned int ErrCNT = 0;
void interrupt ( *oldIRQ4handler)(__CPPARGS);
void interrupt ( *oldIRQ3handler)(__CPPARGS);
void interrupt ( *oldIRQ8handler)(__CPPARGS);
void interrupt ( *oldIRQ9handler)(__CPPARGS);
void interrupt COM1_ISR(__CPPARGS);
void interrupt COM2_ISR(__CPPARGS);
void interrupt COM3_ISR(__CPPARGS);
void interrupt COM4_ISR(__CPPARGS);
int BasePort[4] = { 0x3f8, 0x2f8, 0x2e0, 0x2e8 };
unsigned char* COM3Addr[8];
unsigned char* COM4Addr[8];
#define COM3Reg(a) (*COM3Addr[a])
#define COM4Reg(a) (*COM4Addr[a])
int PutInputData( int PortNum, char abyte ); // call by ISR
int GetOutputData( int PortNum ); // call by ISR
// BaudIdx = 1: 115.2kbps
// BaudIdx = 2: 57.6kbps
// BaudIdx = 3: 38.4kbps
// BaudIdx = 6: 19.2kbps
// BaudIdx = 12: 9600bps
// BaudIdx = ...
int InitUART( int PortNum, int BaudIdx, int Parity )
{
int i1;
int tport;
unsigned char abyte;
switch( Parity )
{
case 1: abyte = 0x0b; break; // 8bit 1stop Odd_parity
case 2: abyte = 0x1b; break; // 8bit 1stop Even_parity
default: abyte = 0x03; break; // 8bit 1stop No_parity
}
// check parameters
switch( PortNum )
{
case COM1:
case COM2:
tport = BasePort[PortNum];
outportb(tport + LCR, 0x80); // DLAB = 1, set baud reg access
outportb(tport + BRDH, BaudIdx>>8);
outport(tport + BRDL, BaudIdx);
outportb(tport + LCR, abyte);
outportb(tport + IER, 0x03); // set IER value
outportb(tport + MCR, 0x0b); // set MCR value
i1 = (int)inportb(tport + LSR); // clear any line status interrupt
if( i1 == -1 ) return -2;
inportb(tport + RDR); // clear any receive interrupt
inportb(tport + IIR); // clear any transmitter interrupt
inportb(tport + MSR); // clear any modem status interrupt
outportb(tport + FCR, 0); // disable FIFO in 16C550
outportb(tport + IER, 0); // some clones require this!?
outportb(tport + IER, 0x05);
break;
case COM3:
for( i1=0; i1<8; i1++ )
{
COM3Addr[i1] = (unsigned char*)MK_FP( SEG, i1 );
}
COM3Reg(LCR) = 0x80; // DLAB = 1, set baud reg access
COM3Reg(BRDH) = BaudIdx>>8;
COM3Reg(BRDL) = BaudIdx;
COM3Reg(LCR) = abyte;
COM3Reg(IER) = 0x03; // set IER value
COM3Reg(MCR) = 0x0b; // set MCR value
i1 = (int)COM3Reg(LSR); // clear any line status interrupt
if( i1 == -1 ) return -2;
i1 = COM3Reg(RDR); // clear any receive interrupt
i1 = COM3Reg(IIR); // clear any transmitter interrupt
i1 = COM3Reg(MSR); // clear any modem status interrupt
//COM3Reg(FCR) = 0; // disable FIFO in 16C550
COM3Reg(FCR) = 0x87; // enable FIFO in 16C550
COM3Reg(IER) = 0; // some clones require this!?
COM3Reg(IER) = 0x05;
break;
case COM4:
for( i1=0; i1<8; i1++ )
{
COM4Addr[i1] = (unsigned char*)MK_FP( SEG, i1+0x10 );
}
COM4Reg(LCR) = 0x80; // DLAB = 1, set baud reg access
COM4Reg(BRDH) = BaudIdx>>8;
COM4Reg(BRDL) = BaudIdx;
COM4Reg(LCR) = abyte;
COM4Reg(IER) = 0x03; // set IER value
COM4Reg(MCR) = 0x0b; // set MCR value
i1 = (int)COM4Reg(LSR); // clear any line status interrupt
if( i1 == -1 ) return -2;
i1 = COM4Reg(RDR); // clear any receive interrupt
i1 = COM4Reg(IIR); // clear any transmitter interrupt
i1 = COM4Reg(MSR); // clear any modem status interrupt
//COM4Reg(FCR) = 0; // disable FIFO in 16C550
COM4Reg(FCR) = 0x87; // enable FIFO in 16C550
COM4Reg(IER) = 0; // some clones require this!?
COM4Reg(IER) = 0x05;
break;
default:
return -1;
}
IBufGetIdx[PortNum] = 0;
IBufPutIdx[PortNum] = 0;
OBufGetIdx[PortNum] = 0;
OBufPutIdx[PortNum] = 0;
return 0;
}
void interrupt COM1_ISR(__CPPARGS)
{
int i1, tport;
unsigned char status;
enable( );
tport = BasePort[COM1];
status = inportb(tport + IIR) & 7;
while( status != 1 )
{
switch (status)
{
case 0: // MODEM status change
inportb(tport + MSR);
break;
case 2: // THR empty
lab1:
i1 = GetOutputData( COM1 );
if( i1 != -1 ) outportb( tport+THR, i1 );
else outportb( tport+IER, inportb(tport+IER) & 0xd);
break;
case 4: // received data available
PutInputData( COM1, inportb( tport+RDR ) );
break;
case 6: // Line status change
i1 = inportb(tport + LSR);
ErrCNT++;
break;
}
status = inportb(tport + IIR) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (inportb(tport + IER)&2) && (inportb(tport + LSR) & 0x20) )
goto lab1;
outportb( 0x20, 0x64 ); // specific EOI command for IRQ3
}
void interrupt COM2_ISR(__CPPARGS)
{
int i1, tport;
unsigned char status;
enable( );
tport = BasePort[COM2];
status = inportb(tport + IIR) & 7;
while( status != 1 )
{
switch (status)
{
case 0: // MODEM status change
inportb(tport + MSR);
break;
case 2: // THR empty
lab2:
i1 = GetOutputData( COM2 );
if( i1 != -1 ) outportb( tport+THR, i1 );
else outportb( tport+IER, inportb(tport+IER) & 0xd);
break;
case 4: // received data available
PutInputData( COM2, inportb( tport+RDR ) );
break;
case 6: // Line status change
i1 = inportb(tport + LSR);
ErrCNT++;
break;
}
status = inportb(tport + IIR) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (inportb(tport + IER)&2) && (inportb(tport + LSR) & 0x20) )
goto lab2;
outportb( 0x20, 0x63 ); // specific EOI command for IRQ3
}
void interrupt COM3_ISR(__CPPARGS)
{
int i, i1;
unsigned char status;
enable( );
status = ( COM3Reg(IIR) ) & 7;
while( status != 1 )
{
i1 = COM3Reg(LSR);
switch (status)
{
case 0: // MODEM status change
i1 = COM3Reg(MSR);
break;
case 2: // THR empty
lab3:
for( i=0; i<16; i++ )
{
i1 = GetOutputData( COM3 );
if( i1 == -1 ) break;
COM3Reg(THR) = i1;
}
if( i==0 )
{
COM3Reg(IER) = COM3Reg(IER) & 0xd;
}
break;
case 4: // received data available
rxaga3:
PutInputData( COM3, COM3Reg( RDR ) );
if ( COM3Reg( LSR) & 0x01)
goto rxaga3;
break;
case 6: // Line status change
i1 = COM3Reg(LSR);
ErrCNT++;
break;
}
status = COM3Reg(IIR) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (COM3Reg(IER)&2) && (COM3Reg(LSR) & 0x20) )
goto lab3;
outportb( 0xa0, 0x60 );
outportb( 0x20, 0x62 ); // specific EOI command for IRQ8
}
void interrupt COM4_ISR(__CPPARGS)
{
int i, i1;
unsigned char status;
enable( );
status = COM4Reg(IIR) & 7;
while( status != 1 )
{
i1 = COM4Reg(LSR);
switch (status)
{
case 0: // MODEM status change
i1 = COM4Reg(MSR);
break;
case 2: // THR empty
lab4:
for( i=0; i<16; i++ )
{
i1 = GetOutputData( COM4 );
if( i1 == -1 ) break;
COM4Reg(THR) = i1;
}
if( i==0 )
{
COM4Reg(IER) = COM4Reg(IER) & 0xd;
}
break;
case 4: // received data available
rxaga4:
PutInputData( COM4, COM4Reg( RDR ) );
if ( COM4Reg( LSR) & 0x01)
goto rxaga4;
case 6: // Line status change
i1 = COM4Reg(LSR);
ErrCNT++;
break;
}
status = COM4Reg(IIR) & 7;
}
// These ugly two lines are here because some PC clones will not give you the
// THR empty interrupt if there is a simultaneous RX available interrupt.
if( (COM4Reg(IER)&2) && (COM4Reg(LSR) & 0x20) )
goto lab4;
outportb( 0xa0, 0x61 );
outportb( 0x20, 0x62 ); // specific EOI command for IRQ9
}
int GetOutputData( int PortNum )
{
int i;
if( OBufGetIdx[PortNum] != OBufPutIdx[PortNum] )
{
i = (int)OutputBuf[PortNum][OBufGetIdx[PortNum]];
OBufGetIdx[PortNum] = ( OBufGetIdx[PortNum] + 1 ) % BUF_SIZ;
return i;
}
return -1;
}
int PutOutputData( int PortNum, char abyte )
{
unsigned int Idx;
if( OBufGetIdx[PortNum] == 0 ) Idx = BUF_SIZ - 1;
else Idx = OBufGetIdx[PortNum] - 1;
if( OBufPutIdx[PortNum] == Idx ) return -1;
OutputBuf[PortNum][OBufPutIdx[PortNum]] = abyte;
OBufPutIdx[PortNum] = ( OBufPutIdx[PortNum] + 1 ) % BUF_SIZ;
return 0;
}
void StartSend( int PortNum )
{
int i1, tport;
unsigned char aa;
switch( PortNum )
{
case COM1:
case COM2:
tport = BasePort[PortNum];
aa = inportb(tport+IER);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( PortNum );
if( i1 == -1 ) return;
outportb( tport+THR, i1 );
outportb( tport+IER, aa|0x02 ); // enable THR interrupt
}
break;
case COM3:
aa = COM3Reg(IER);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( PortNum );
if( i1 == -1 ) return;
COM3Reg(THR) = i1;
COM3Reg(IER) = aa|0x02 ; // enable THR interrupt
}
break;
case COM4:
aa = COM4Reg(IER);
if( (aa&0x02) == 0 )
{
i1 = GetOutputData( PortNum );
if( i1 == -1 ) return;
COM4Reg(THR) = i1;
COM4Reg(IER) = aa|0x02 ; // enable THR interrupt
}
break;
}
}
int PutInputData( int PortNum, char abyte )
{
unsigned int Idx;
if( IBufGetIdx[PortNum] == 0 ) Idx = BUF_SIZ - 1;
else Idx = IBufGetIdx[PortNum] - 1;
if( IBufPutIdx[PortNum] == Idx ) return -1;
InputBuf[PortNum][IBufPutIdx[PortNum]] = abyte;
IBufPutIdx[PortNum] = ( IBufPutIdx[PortNum] + 1 ) % BUF_SIZ;
return 0;
}
int GetInputData( int PortNum )
{
int i;
if( IBufGetIdx[PortNum] != IBufPutIdx[PortNum] )
{
i = (int)InputBuf[PortNum][IBufGetIdx[PortNum]];
IBufGetIdx[PortNum] = ( IBufGetIdx[PortNum] + 1 ) % BUF_SIZ;
return i;
}
return -1;
}
int InstallISR( int PortNum )
{
unsigned char MaskBit;
switch( PortNum )
{
case COM1:
MaskBit = IRQ4MaskBit;
oldIRQ4handler = getvect( 0x0c );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0c, COM1_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM2:
MaskBit = IRQ3MaskBit;
oldIRQ3handler = getvect( 0x0b );
outportb( 0x21, inportb(0x21)|MaskBit );
setvect( 0x0b, COM2_ISR );
MaskBit = ~MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit );
break;
case COM3:
MaskBit = IRQ8MaskBit;
outportb( 0xa1, inportb(0xa1)|MaskBit ); // mask irq8
oldIRQ8handler = getvect( 0x70 );
setvect( 0x70, COM3_ISR );
MaskBit = ~MaskBit;
outportb( 0xa1, inportb(0xa1)&MaskBit ); // unmask irq8
MaskBit = ~IRQ2MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit ); // unmask irq2
break;
case COM4:
MaskBit = IRQ9MaskBit;
outportb( 0xa1, inportb(0xa1)|MaskBit ); // mask irq9
oldIRQ9handler = getvect( 0x71 );
setvect( 0x71, COM4_ISR );
MaskBit = ~MaskBit;
outportb( 0xa1, inportb(0xa1)&MaskBit ); // unmask irq9
MaskBit = ~IRQ2MaskBit;
outportb( 0x21, inportb(0x21)&MaskBit ); // unmask irq2
break;
default:
return -1;
}
return 0;
}
int UninstallISR( int PortNum )
{
unsigned char MaskBit;
switch( PortNum )
{
case COM1:
setvect( 0x0c, oldIRQ4handler );
break;
case COM2:
setvect( 0x0b, oldIRQ3handler );
break;
case COM3:
MaskBit = IRQ8MaskBit;
outportb( 0xa1, inportb(0xa1)|MaskBit ); // mask irq8
setvect( 0x70, oldIRQ8handler );
break;
case COM4:
MaskBit = IRQ9MaskBit;
outportb( 0xa1, inportb(0xa1)|MaskBit ); // mask irq9
setvect( 0x71, oldIRQ9handler );
break;
default:
return -1;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -