www.pudn.com > rs232 > RCOMM.C
#include#include #include #include #include #define TRUE 1 #define FALSE 0 typedef unsigned char BYTE; typedef unsigned char BOOL; #include "rcomm.h" #define THR 0 #define RDR 0 #define BRDL 0 #define BRDH 1 #define IER 1 #define IIR 2 #define LCR 3 #define MCR 4 #define LSR 5 #define MSR 6 void COM_ISR( int nPort ); int COM1_ISR( struct INT_DATA *pID ) { COM_ISR(CP_COM1); return( 1 ); } int COM2_ISR( struct INT_DATA *pID ) { COM_ISR(CP_COM2); return( 1 ); } int COM3_ISR( struct INT_DATA *pID ) { COM_ISR(CP_COM3); return( 1 ); } int COM4_ISR( struct INT_DATA *pID ) { COM_ISR(CP_COM4); return( 1 ); } typedef struct tagCYCLIC_BUFFER { BYTE *pBuffer; int nLength; int nCount; BYTE *pHead, *pTail, *pLimit; } CYCLIC_BUFFER; typedef struct tagSERIAL_PORT { BOOL bEnabled; CYCLIC_BUFFER inBuffer; CYCLIC_BUFFER outBuffer; } SERIAL_PORT; static volatile SERIAL_PORT Ports[4]; static volatile unsigned int wIOPortBase[4]={ 0x03f8, 0x02f8, 0x03e8, 0x02e8 }; static volatile unsigned int wPortVector[4]={ 0x0c, 0x0b, 0x0c, 0x0b }; static volatile unsigned int wPortIRQ[4] ={ 0x04, 0x03, 0x04, 0x03 }; static BYTE cbIRQMask[4]; static int (*dwCOMISRs[4])(struct INT_DATA *pID)={ COM1_ISR,COM2_ISR,COM3_ISR,COM4_ISR }; static BOOL CycCreateBuffer( CYCLIC_BUFFER *pCyc,int nSize ) { /* Create and initialise buffer */ if ( (pCyc->pBuffer=(BYTE *)malloc(nSize))==NULL ) return( FALSE ); pCyc->nLength = nSize; pCyc->pLimit = pCyc->pBuffer + nSize - 1; pCyc->pHead = pCyc->pTail = pCyc->pBuffer; pCyc->nCount = 0; return( TRUE ); } static void CycDeleteBuffer( CYCLIC_BUFFER *pCyc ) { free( pCyc->pBuffer ); } static void CycFlushBuffer( CYCLIC_BUFFER *pCyc ) { /* Flush contents of cyclic buffer */ pCyc->pHead = pCyc->pTail = pCyc->pBuffer; pCyc->nCount = 0; } static int CycReadBuffer( CYCLIC_BUFFER *pCyc,void *pBuffer,int nCount ) { /* Read nCount bytes from cyclic buffer */ register BYTE *pDest=(BYTE *)pBuffer; int nRead=0; while ( pCyc->nCount && nRead pHead++; pCyc->nCount--; nRead++; if ( pCyc->pHead>pCyc->pLimit ) pCyc->pHead=pCyc->pBuffer; } return( nRead ); } static int CycWriteBuffer( CYCLIC_BUFFER *pCyc,void *pBuffer,int nCount ) { /* Write nCount bytes to cyclic buffer */ register BYTE *pSource=(BYTE *)pBuffer; int nWritten=0; while ( pCyc->nCount nLength && nWritten pTail++ = *pSource++; pCyc->nCount++; nWritten++; if ( pCyc->pTail>pCyc->pLimit ) pCyc->pTail=pCyc->pBuffer; } return( nWritten ); } static void COM_ISR( int wPort ) { volatile int wBase; volatile BYTE cbChar; volatile CYCLIC_BUFFER *pCyc; outp( 0x20,0x20 ); if ( Ports[wPort].bEnabled ) { wBase = wIOPortBase[wPort]; cbChar = inp(wBase+IIR)&0x06; switch( cbChar ) { case 0x04: /* Character received */ pCyc = &Ports[wPort].inBuffer; if ( pCyc->nCount nLength ) { *pCyc->pTail++ = (BYTE)(unsigned int)inp(wBase+RDR); pCyc->nCount++; if ( pCyc->pTail>pCyc->pLimit ) pCyc->pTail=pCyc->pBuffer; } break; case 0x02: /* Transmit */ pCyc = &Ports[wPort].outBuffer; if ( pCyc->nCount==0 ) { /* Empty - disable THR empty interrupt */ outp( wBase+IER,0x01 ); } else { outp( wBase+THR,(unsigned int)*pCyc->pHead ); pCyc->nCount--; if ( ++pCyc->pHead>pCyc->pLimit ) pCyc->pHead=pCyc->pBuffer; } break; } /* Edge-trigger IER */ cbChar = (BYTE)inp(wBase+IER); outp( wBase+IER,0x00 ); outp( wBase+IER,(unsigned int)cbChar ); } } BOOL COM_Open( COM_PORT cpPort,unsigned long nBaud,COM_DATA_BITS cdbBits,COM_STOP_BITS csbStop,COM_PARITY cbParity,int nBuffSize ) { int wBase; if ( cpPort CP_COM4 ) return( FALSE ); if ( Ports[cpPort].bEnabled ) return( FALSE ); if ( cdbBits!=CDB_8_BITS && cdbBits!=CDB_7_BITS ) return( FALSE ); if ( csbStop!=CSB_1_BIT && csbStop!=CSB_2_BIT ) return( FALSE ); if ( cbParity!=CP_NO_PARITY && cbParity!=CP_ODD_PARITY && cbParity!=CP_EVEN_PARITY ) return( FALSE ); if ( nBuffSize==0 || nBaud<300 ) return( FALSE ); if ( !CycCreateBuffer(&Ports[cpPort].inBuffer,nBuffSize) ) return( FALSE ); if ( !CycCreateBuffer(&Ports[cpPort].outBuffer,nBuffSize) ) { CycDeleteBuffer( &Ports[cpPort].inBuffer ); return( FALSE ); } Ports[cpPort].bEnabled = TRUE; /* Record original interrupt enable mask */ cbIRQMask[cpPort] = inp(0x21)&(0x01< >8)&0xff ); outp( wBase+LCR,(cbParity|cdbBits|csbStop)&0x7f ); _asm sti /* Flush out buffers before return */ COM_Flush( cpPort,TRUE,TRUE ); return( TRUE ); } BOOL COM_Close( COM_PORT cpPort ) { int wBase; if ( CP_COM1<=cpPort && cpPort<=CP_COM4 && Ports[cpPort].bEnabled ) { BYTE cbMask=cbIRQMask[cpPort]&(0x01<