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 && nReadpHead++; 
        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->nCountnLength && nWrittenpTail++ = *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->nCountnLength ) 
                { 
                    *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 ( cpPortCP_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<