www.pudn.com > ·ÂÕæÖÕ¶Ëvt100.zip > COMIO.C


#include  
#include  
 
#define MDMDAT1 0x03F8            /* Address of modem port 1 data */ 
#define MDMSTS1 0x03FD            /* Address of modem port 1 status  */ 
#define MDMCOM1 0x03FB            /* Address of modem port 1 command */ 
#define MDMDAT2 0x02F8            /* Address of modem port 2 data */ 
#define MDMSTS2 0x02FD            /* Address of modem port 2 status */ 
#define MDMCOM2 0x02FB            /* Address of modem port 2 command */ 
#define MDMINTV 0x000C            /* Com 1 interrupt vector */ 
#define MDINTV2 0x000B            /* Com 2 interrupt vector */ 
#define MDMINTO 0x0EF             /* Mask to enable IRQ3 for port 1 */ 
#define MDINTO2 0x0F7             /* Mask to enable IRQ4 for port 2 */ 
#define MDMINTC 0x010             /* Mask to Disable IRQ4 for port 1 */ 
#define MDINTC2 0x008             /* Mask to Disable IRQ3 for port 2 */ 
#define INTCONT 0x0021            /* 8259 interrupt controller ICW2-3 */ 
#define INTCON1 0x0020            /* Address of 8259 ICW1 */ 
 
#define COM_BUFF_SIZE 1024        /* Communications port buffer size */ 
#define XOFFPT  COM_BUFF_SIZE*3/4 /* chars in buff before sending XOFF */ 
#define XONPT   COM_BUFF_SIZE*1/4 /* chars in buff to send XON after XOFF */ 
#define XOFF    0x13              /* XOFF value */ 
#define XON     0x11              /* XON value */ 
 
/*****************************************************************************/ 
/* function prototypes                                                       */ 
 
void TTinit();                    /* Initialize the communications system */ 
int ttopen();                     /* Open a port for communications */ 
int ttclose( void );              /* Close the communications port */ 
int ttchk( void );                /* Return count of received characters */ 
void ttoc( unsigned char );       /* Output a character to the com port */ 
int ttinc( void );                /* Input a character from circular buffer */ 
void ttflui( void );              /* Flush circular buffer of characters */ 
int dobaud( unsigned int );       /* Set the baud rate for the port */ 
void coms( int );                 /* Establish modem data */ 
void serini( void );              /* Initialize the com port for interrupts */ 
void serrst( void );              /* Reset the com port to original settings */ 
void interrupt serint( void );    /* Com port receiver ISR */ 
 
 
/*****************************************************************************/ 
/* Global Data                                                               */ 
 
unsigned int port;                /* COM port */ 
unsigned int speed;               /* BAUD rate */ 
char parity[5];                   /* Parity setting */ 
unsigned int databits;            /* Number of Data bits */ 
unsigned int stopbits;            /* Number of Stop bits */ 
 
/*****************************************************************************/ 
/* External variables                                                        */ 
 
 
 
/*****************************************************************************/ 
/* Local Static Data                                                         */ 
 
static char buffer[COM_BUFF_SIZE];/* Circular buffer */ 
static char *inptr;               /* Pointer to input point of circular buff*/ 
static char *outptr;              /* Pointer to output point of circular buff*/ 
static int  count = 0;            /* Number of characters in buffer */ 
 
struct mdminfo {                  /* struct to hold current com port info */ 
    unsigned int mddat;             /* 8250 data register */ 
    unsigned int mdstat;            /* 8250 line-status register */ 
    unsigned int mdcom;             /* 8250 line-control register */ 
    unsigned char mden;             /* 8259 IRQ enable mask */ 
    unsigned char mddis;            /* 8259 IRQ disable mask */ 
    unsigned char mdintv;           /* Interrupt for selected com port */ 
} modem ; 
 
void interrupt (*oldvec)();       /* Vector of previous com interrupt */ 
int portin = 0;                   /* Flag to indicate com port is open */ 
int xofsnt = 0;                   /* Flag to indicate an XOFF transmitted */ 
int xofrcv = 0;                   /* Flag to indicate an XOFF received */ 
 
/*****************************************************************************/ 
 
/*  T T I N I T  -- Initialize the communications system */ 
 
void TTinit() { 
 
    if (GetTTSetup() == 0) {        /* If no saved values are available */ 
        port = 1;                     /* Then set default values */ 
        speed = 2400; 
        strcpy(parity,"NONE"); 
        databits = 8; 
        stopbits = 1; 
    } 
} 
 
 
/*  T T O P E N  -- Open the communications port */ 
 
ttopen() { 
    if (portin == 0) {            /* Ignore call if already open */ 
        switch (port) { 
            case 1: 
                coms(1);             /* COM 1 */ 
                break; 
            case 2: 
                coms(2);             /* COM 2 */ 
                break; 
            default:                 /* others not supported, return error */ 
                return(-1); 
        } 
        dobaud(speed);               /* Set baud rate */ 
        serini();                    /* enable interrupt handler */ 
    } 
    return(0);                    /* return success */ 
} 
 
 
/*  T T C L O S E --  Close the communications port  */ 
 
ttclose() { 
    if (portin != 0)              /* Ignore if port is already closed */ 
        serrst();                    /* otherwise disable interrupts */ 
    return(0);                    /* return success */ 
} 
 
 
 
 
/* T T C H K  --  Return a count of characters at the serial port */ 
 
ttchk() { 
    return( count );              /* return maintained count */ 
} 
 
 
/* T T O C -- Output a character to the current serial port */ 
 
void ttoc( unsigned char c ) { 
 
    while( (inportb(modem.mdstat) & 0x20) == 0 ) 
       ;                          /* Wait til transmitter is ready */ 
    outportb(modem.mddat,c);      /* then output the character */ 
} 
 
 
/* T T F L U I  --  Clear the input buffer of characters */ 
 
 
void ttflui() { 
 
    if (xofsnt){                  /* Check if XON should be sent after XOFF */ 
       xofsnt = 0;                  /* if so then reset XOFF sent status */ 
       ttoc(XON);                   /* and send the XON */ 
       } 
    disable();                    /* NO interrupts allowed now */ 
    inptr = outptr = buffer;      /* Reset input out output pointers */ 
    count = 0;                    /* Set received characters count to 0 */ 
    enable();                     /* Now interrupts are ok */ 
} 
 
 
/* T T I N C  -- Read a character from serial ports circular buffer */ 
 
ttinc() { 
    int c; 
    register char * ptr; 
 
    if (count < XONPT && xofsnt){ /* Check if XON should be sent after XOFF */ 
       xofsnt = 0;                  /* if so then reset XOFF sent status */ 
       ttoc(XON);                   /* and send the XON */ 
       } 
 
    while (count == 0)            /* If no characters have arrived then */ 
        ;                            /* wait til one arrives */ 
 
    ptr = outptr;                 /* Save address of buffer output point */ 
 
    c = *ptr++;                   /* Get this character and increment ptr */ 
 
                                  /* See if circular buff should be wrapped */ 
    if (ptr == &buffer[COM_BUFF_SIZE]) 
        ptr = buffer;                /* if so then save new output point */ 
 
    disable();                    /* NO interrupts allowed now */ 
    outptr = ptr;                 /* Save the address of output point */ 
    count--;                      /* Decrement count of received characters */ 
    enable();                     /* Interrupts can continue now */ 
 
    return(c);                    /* Return the received character */ 
} 
 
 
/* D O B A U D  --  Set the baud rate for the current port */ 
 
dobaud( unsigned int baudrate ) { 
   unsigned char portval; 
   unsigned char blo, bhi; 
   switch (baudrate) {            /* Get 8250 baud rate divisor values */ 
       case 50:     bhi = 0x9;  blo = 0x00;  break; 
       case 75:     bhi = 0x6;  blo = 0x00;  break; 
       case 110:    bhi = 0x4;  blo = 0x17;  break; 
       case 150:    bhi = 0x3;  blo = 0x00;  break; 
       case 300:    bhi = 0x1;  blo = 0x80;  break; 
       case 600:    bhi = 0x0;  blo = 0xC0;  break; 
       case 1200:   bhi = 0x0;  blo = 0x60;  break; 
       case 1800:   bhi = 0x0;  blo = 0x40;  break; 
       case 2000:   bhi = 0x0;  blo = 0x3A;  break; 
       case 2400:   bhi = 0x0;  blo = 0x30;  break; 
       case 4800:   bhi = 0x0;  blo = 0x18;  break; 
       case 9600:   bhi = 0x0;  blo = 0x0C;  break; 
       case 19200:  bhi = 0x0;  blo = 0x06;  break; 
       case 38400:  bhi = 0x0;  blo = 0x03;  break; 
 
       default:                   /* Return failure if baud unsupported */ 
           return(-1); 
   } 
 
   portval = inportb(modem.mdcom);/* Save current value of command register */ 
 
                                  /* In order to set the baud rate the */ 
                                  /* high bit of command data register is */ 
   outportb(modem.mdcom,portval | 0x80 ); /* set before sending baud data */ 
 
   outportb(modem.mddat,blo);     /* Set LSB Baud-Rate divisor for baud */ 
   outportb(modem.mddat + 1,bhi); /* Set MSB Baud-Rate divisor for baud */ 
 
   outportb(modem.mdcom,portval); /* Reset original command register value */ 
 
   return(0);                     /* Return success */ 
} 
 
 
/*  C O M S  --  Set up the modem structure for the specified com port */ 
 
void coms( int portid ) { 
 
    if (portid == 1) {            /* Port data for COM 1 */ 
        modem.mddat = MDMDAT1;       /* Port 1 Data register */ 
        modem.mdstat = MDMSTS1;      /* Port 1 Status register */ 
        modem.mdcom = MDMCOM1;       /* Port 1 Command register */ 
        modem.mddis = MDMINTC;       /* Port 1 8259 IRQ4 disable mask */ 
        modem.mden = MDMINTO;        /* Port 1 8259 IRQ4 enable mask */ 
        modem.mdintv = MDMINTV;      /* Port 1 interrupt number */ 
    } 
    else if (portid == 2) {       /* Port data for COM 2 */ 
        modem.mddat = MDMDAT2;       /* Port 2 Data register */ 
        modem.mdstat = MDMSTS2;      /* Port 2 Status register */ 
        modem.mdcom = MDMCOM2;       /* Port 2 Command register */ 
        modem.mddis = MDINTC2;       /* Port 2 8259 IRQ4 disable mask */ 
        modem.mden = MDINTO2;        /* Port 2 8259 IRQ4 enable mask */ 
        modem.mdintv = MDINTV2;      /* Port 2 interrupt number */ 
    } 
} 
 
/* S E R I N I  -- initialize the serial port for interrupts */ 
 
void serini() { 
    unsigned char portval; 
 
    if (portin == 0) {            /* Ignore if already open */ 
        portin = 1;                  /* save port open status */ 
        inptr = outptr = buffer;     /* set circular buffer pointers */ 
        count = 0;                   /* indicate no characters received */ 
        oldvec=getvect(modem.mdintv);/* save old com interrupt */ 
        setvect(modem.mdintv,serint);/* set SERINT as communications ISR */ 
 
        portval = 0;              /* Byte value to output to the Line */ 
                                  /* Control Register (LCR) to set the */ 
                                  /* Parity, Stopbits, Databits */ 
                                  /* Start out with all bits zero */ 
 
        if (strcmp(parity,"EVEN") == 0) 
           portval |= 0x8;        /* Set bit 3 on for odd parity */ 
        else if (strcmp(parity,"ODD") == 0) 
           portval |= 0x18;       /* Set bits 3 and 4 on for even parity */ 
                                  /* Leave bits 3 and 4 off for no parity */ 
 
 
        if (stopbits == 2)        /* Set bit 2 on if 2 Stopbits are used */ 
           portval |= 0x4; 
                                  /* Leave bit 2 off for 1 Stopbit */ 
 
        if (databits == 6)        /* Set bit 0 on for 6 data bits */ 
           portval |= 0x1; 
        else if (databits == 7)   /* Set bit 1 on for 7 data bits */ 
           portval |= 0x2; 
        else if (databits == 8)   /* Set bits 0 and 1 on for 8 data bits */ 
           portval |= 0x3; 
                                  /* Leave bits 0 and 1 off for 5 data bits */ 
 
        outportb(modem.mdcom,portval);  /* Output the settings to the LCR */ 
 
 
        outportb(modem.mdcom + 1,0xb); /* Assert OUT2, RTS, DTR */ 
 
        inportb(modem.mddat);        /* Clear any left over characters */ 
        outportb(modem.mddat+1,0x1); /* Enable receiver interrupts */ 
 
        portval = inportb(INTCONT);  /* Read 8259 interrupt enable mask */ 
        outportb(INTCONT,modem.mden & portval); /*Set bit on for com IRQ */ 
    } 
} 
 
 
/* S E R R S T -- Reset serial port interrupts */ 
 
void serrst() { 
    unsigned char portval; 
 
    if (portin != 0) {            /* Ignore if interrupts already disabled */ 
        portin = 0;                    /* save port closed status */ 
        portval = inportb(INTCONT);    /* Read 8259 interrupt enable mask */ 
        outportb(INTCONT,modem.mddis | portval);/*Set bit off for com IRQ */ 
        setvect(modem.mdintv,oldvec);  /* return original interrupt vector */ 
    } 
} 
 
 
/*  S E R I N T  -- Serial interrupt handler, recieves incoming characters */ 
 
void interrupt serint() { 
 
    *inptr++=inportb(modem.mddat);/* Quickly read arriving character */ 
    count++;                      /* Increment received count */ 
 
    if (count > XOFFPT && xofsnt != 1){ /* If buffer almost full then */ 
       ttoc(XOFF);                /* send an XOFF */ 
       xofsnt = 1;                /* and save XOFF sent status */ 
       } 
    disable();                    /* NO interrupts are allowed while */ 
                                  /* new input pointer is stored */ 
    if (inptr == &buffer[COM_BUFF_SIZE]) /* At end of circular buff? */ 
       inptr = buffer;                /* if so then save new output point */ 
 
    enable();                     /* Interrupts ok now */ 
 
    outportb(0x20,0x20);          /* send End Of Interrupt to 8259 */ 
}