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

📄 rs232x4.cpp

📁 一个PPP上网协议源码,可通过GPRS网络接入因特网.
💻 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 + -