Main Page   Packages   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Search  

C:/temp/src/j2k/QNX4/driver/ser/async.c

Go to the documentation of this file.
00001 #include <conio.h>
00002 #include <sys/_devdrvr.h>
00003 #include <sys/trace.h>
00004 #include <sys/tracecod.h>
00005 #include "struct.h"
00006 
00007 /*
00008  * Stack checking MUST be disabled in the following routines
00009  */
00010 
00011 #pragma off (check_stack);
00012 
00013 extern pid_t (far *tti)(int, int, unsigned);
00014 extern unsigned tti_ds;
00015 
00016 extern struct dev_entry *dev_list[];
00017 extern struct driver_ctrl drv_ctrl;
00018 extern int num_asyncs;
00019 
00020 /*
00021  * Compensate for a "bug" in the 8250/450/550 which misses a Tx interrupt if
00022  * a Rx or Line status int occurs at the "same time". Re-setting the IER
00023  * will cause the Tx interrupt to be re-generated if THRE is now set.
00024  * We only do this work if QNX is "waiting" for a Tx interrupt when a
00025  * Rx or line status interrupt is received.
00026  *
00027  * Note: That a high level timeout on Tx interrupts is also used to recover
00028  * from "other" hardware bugs which cause some UARTs (especially CMOS parts)
00029  * to lose Tx interrupts.
00030  */
00031 
00032 static void test_tx(struct dev_entry *dev, unsigned char lsr) {
00033    if(dev->tx_pending == 0)
00034       return;
00035    if((lsr & 0x20) == 0)
00036       return;
00037    outp(dev->iobase+1, 0x0f);
00038    return;
00039    }
00040 
00041 /*
00042  * Process data in a line status register
00043  */
00044 
00045 static pid_t process_lsr(struct dev_entry *dev, unsigned char lsr) {
00046    unsigned key = 0;
00047 
00048    if((lsr & 0x1e) == 0)
00049       return(0);
00050 
00051    /*
00052     * Read whatever input data happens to be in the
00053     * buffer (to "eat" the spurious data associated
00054     * with break, parity error, etc.)
00055     */
00056    key = inp(dev->iobase);
00057 
00058    if(lsr & 0x10) {
00059       Trace1( (long)_TRACE_DEV_SER_HUP+1, _TRACE_TRANSIENT, dev->iobase );
00060       key |= RCV_BREAK;
00061       }
00062    else {
00063       if(lsr & 0x04) {
00064          key |= RCV_PARITY;
00065          Trace1( (long)_TRACE_DEV_SER_PARITY, _TRACE_TRANSIENT, dev->iobase );
00066          }
00067       if(lsr & 0x08) {
00068          key |= RCV_FRAME;
00069          Trace1( (long)_TRACE_DEV_SER_FRAME, _TRACE_TRANSIENT, dev->iobase );
00070          }
00071       }
00072 
00073    if(lsr & 0x02) {
00074       key |= RCV_OVERRUN;
00075       Trace1( (long)_TRACE_DEV_SER_OVERRUN, _TRACE_TRANSIENT, dev->iobase );
00076       }
00077    return( (*tti) (key, dev->tty, tti_ds) );
00078    }
00079 
00080 /************************************************************************
00081  * ASYNC interrupt handler                                              *
00082  ************************************************************************/
00083 
00084 pid_t far async_irq0()  { return(async_int(0));  }
00085 pid_t far async_irq1()  { return(async_int(1));  }
00086 pid_t far async_irq2()  { return(async_int(2));  }
00087 pid_t far async_irq3()  { return(async_int(3));  }
00088 pid_t far async_irq4()  { return(async_int(4));  }
00089 pid_t far async_irq5()  { return(async_int(5));  }
00090 pid_t far async_irq6()  { return(async_int(6));  }
00091 pid_t far async_irq7()  { return(async_int(7));  }
00092 pid_t far async_irq8()  { return(async_int(8));  }
00093 pid_t far async_irq9()  { return(async_int(9));  }
00094 pid_t far async_irq10() { return(async_int(10)); }
00095 pid_t far async_irq11() { return(async_int(11)); }
00096 pid_t far async_irq12() { return(async_int(12)); }
00097 pid_t far async_irq13() { return(async_int(13)); }
00098 pid_t far async_irq14() { return(async_int(14)); }
00099 pid_t far async_irq15() { return(async_int(15)); }
00100 
00101 
00102 pid_t async_int(int irq) {
00103    pid_t status = 0;
00104    int nothing;
00105    struct dev_entry *dev;
00106    unsigned char iir;
00107    unsigned char lsr;
00108    unsigned char msr;
00109 
00110    while(1) {
00111       nothing = 1;
00112       for(dev = dev_list[irq]; dev != 0; dev = dev->link) {
00113          if(dev->iobase == 0)
00114             continue;
00115          iir = inp(dev->iobase+2);
00116          if((iir & 0x01) != 0)
00117             continue;
00118          /*
00119           * Interrupt pending
00120           */
00121          nothing = 0;
00122          iir &= 7;
00123          if(iir == 4) {
00124             /*
00125              * Input Interrupt
00126              */
00127             while(1) {
00128                status |= (*tti) (inp(dev->iobase), dev->tty, tti_ds);
00129                ++dev->rx_count;
00130                lsr = inp(dev->iobase+5);
00131                status |= process_lsr(dev, lsr);
00132                if((lsr & 0x01) == 0) {
00133                   test_tx(dev, lsr);
00134                   break;
00135                   }
00136                }
00137             }
00138          else if(iir == 2) {
00139             /*
00140              * Output Interrupt
00141              */
00142             dev->tx_pending = 0;
00143             status |= tto(dev, dev->obuf);
00144             ++dev->tx_count;
00145             }
00146          else if(iir == 0) {
00147             /*
00148              * Modem change
00149              */
00150             msr = inp(dev->iobase+6);
00151             dev->modem_status = (dev->modem_status & 0x0F) | (msr & 0xF0);
00152 
00153             if(dev->mode & MODE_PKT) /* Special mode for custom hardware */
00154                status |= (*tti) (RCV_PKT_SPECIAL, dev->tty, tti_ds);
00155 
00156             if((msr & 0x08) != 0  &&  (dev->mode & MODE_NOHUP) == 0) {
00157                if(msr & 0x80) {
00158                   status |= (*tti) (RCV_CARRIER, dev->tty, tti_ds);
00159                   Trace1( _TRACE_DEV_SER_CARRIER, _TRACE_EXPECTED, dev->iobase );
00160                   }
00161                else {
00162                   status |= (*tti) (RCV_HNGUP, dev->tty, tti_ds);
00163                   Trace1( _TRACE_DEV_SER_HUP, _TRACE_EXPECTED, dev->iobase );
00164                   }
00165                }
00166                
00167 
00168             if(dev->mode & MODE_SPLIT) {
00169                if(msr & 0x01) {
00170                   /*
00171                    * Require "ONLY" CTS for hardware flow control
00172                    */
00173                   if(msr & 0x10)
00174                      status |= (*tti) (RCV_HW_ON, dev->tty, tti_ds);
00175                   else
00176                      status |= (*tti) (RCV_HW_OFF, dev->tty, tti_ds);
00177                   }
00178                }
00179             else {
00180                if(msr & 0x03) {
00181                   /*
00182                    * Require "BOTH" DSR and CTS to be on
00183                    * before we will transmit in HFLOW mode
00184                    */
00185                   if((msr & 0x30) == 0x30)
00186                      status |= (*tti) (RCV_HW_ON, dev->tty, tti_ds);
00187                   else
00188                      status |= (*tti) (RCV_HW_OFF, dev->tty, tti_ds);
00189                   }
00190                }
00191             }
00192          else {
00193             /*
00194              * Line status change
00195              */
00196             lsr = inp(dev->iobase+5);
00197             status |= process_lsr(dev, lsr);
00198             test_tx(dev, lsr);
00199             }
00200          }
00201       if(nothing)
00202          break;
00203       }
00204    return(status);
00205    }
00206 
00207 #pragma on (check_stack);

Generated on Sun Oct 14 18:46:41 2001 for Standard J2K Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001