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/tto.c

Go to the documentation of this file.
00001 
00002 #include "struct.h"
00003 #include <sys/stat.h>
00004 #include <conio.h>
00005 #include <i86.h>
00006 
00007 /*
00008    declare the calls 'Dev' will make into driver.
00009 */
00010 int __far   Kick(struct output_buffer __far *obuf);
00011 int __far   Stty(struct termios __far *tios); 
00012 int __far   Ctrl(union ioctl_entry __far *ioc); 
00013 
00014 #pragma aux (_dev_call) Kick;
00015 #pragma aux (_dev_call) Stty;
00016 #pragma aux (_dev_call) Ctrl;
00017 
00018 #pragma off (check_stack);
00019 
00020 extern struct dev_entry dev_table[];
00021 extern struct driver_ctrl drv_ctrl;
00022 extern int num_asyncs;
00023 
00024 int idle[MAX_ASYNCS] = {1};
00025 
00026 /*
00027  * TTO is called by the int handler everytime a TX interrupt is
00028  * received.
00029  *
00030  * Since this routine is "called" by either DEV, or the Int handler,
00031  * it will ALWAYS run at higher
00032  * priority than the driver task, so cannot be interrupted.
00033  */
00034 
00035 pid_t tto(struct dev_entry *dev, struct output_buffer far *obuf)  {
00036    char far *p;
00037    unsigned c, i, n;
00038    int sig = 0;
00039 
00040    if(obuf->mode & OUTPUT_XOFF) {
00041       obuf->mode &= ~OUTPUT_XOFF;
00042       outp(dev->iobase, 0x13);
00043       return(0);
00044       }
00045 
00046    if(obuf->mode & OUTPUT_XON) {
00047       obuf->mode &= ~OUTPUT_XON;
00048       outp(dev->iobase, 0x11);
00049       return(0);
00050       }
00051 
00052    if(obuf->mode & OUTPUT_STOPPED) {
00053       dev->busy = 0;
00054       return(0);
00055       }
00056 
00057    if(obuf->mode & OUTPUT_STOPPED_HW) {
00058       dev->busy = 0;
00059       return(0);
00060       }
00061 
00062    if(obuf->discard) {
00063       /*
00064        * Discard some (or all) data instead of sending it
00065        */
00066       n = obuf->discard;
00067       obuf->discard -= n;
00068       obuf->size -= n;
00069       i = &obuf->buffer[obuf->length] - obuf->tail;
00070       if(i > n)
00071          obuf->tail += n;
00072       else
00073          obuf->tail = &obuf->buffer[n-i];
00074       }
00075 
00076    if(dev->state  ||  obuf->size > 0) {
00077       if(dev->state) {
00078          c = dev->state;
00079          dev->state = 0;
00080          }
00081       else {
00082          /*
00083           * Get the next character to print
00084           * from the output buffer
00085           */
00086          p = obuf->tail;
00087          if(p >= &obuf->buffer[obuf->length-1])
00088             obuf->tail = &obuf->buffer[0];
00089          else
00090             ++obuf->tail;
00091          --obuf->size;
00092          c = *p;
00093          }
00094 
00095       if(obuf->mode & OUTPUT_XNL) {
00096          if(c == '\l')
00097             dev->state = '\r';
00098          }
00099    
00100       /*
00101        * print the character
00102        */
00103       _disable();
00104       dev->tx_pending = 10;  /* Timeout */
00105       outp(dev->iobase, c);
00106       _enable();
00107       }
00108    else
00109       dev->busy = 0;
00110    
00111    /*
00112     * If size of buffer drops below notification threshold,
00113     * inform DEV of the new information
00114     */
00115    if(obuf->size < obuf->bcount) {
00116       obuf->bcount = 0;
00117       obuf->action |= ACT_OUTPUT_READY;
00118       sig = drv_ctrl.hw_pid;
00119       }
00120 
00121    return(sig);
00122    }
00123 
00124 /*
00125  * Kick is called by DEV everytime something "new" happens
00126  * to the output buffer
00127  *
00128  * It will set es:di to be the output buffer (1st register pointer)
00129  * It will also set ds to be the data segment of the driver being called
00130  *
00131  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00132  * priority than the driver task, so cannot be interrupted.
00133  * If the interrupt handler has called it, then DEV cannot interrupt this
00134  * process either.
00135  */
00136 
00137 int far Kick(struct output_buffer far *obuf)
00138    {
00139    register struct dev_entry *dev;
00140 
00141    dev = &dev_table[obuf->handle];
00142 
00143    if(obuf->mode & OUTPUT_HFLOW_OFF) {
00144       obuf->mode &= ~OUTPUT_HFLOW_OFF;
00145       /*
00146        * turn off RTS
00147         */
00148       dev->modem_control &= ~0x02;
00149       outp(dev->iobase+4, dev->modem_control);
00150       }
00151 
00152    if(obuf->mode & OUTPUT_HFLOW_ON) {
00153       obuf->mode &= ~OUTPUT_HFLOW_ON;
00154       /*
00155        * turn on RTS
00156        */
00157       dev->modem_control |= 0x02;
00158       outp(dev->iobase+4, dev->modem_control);
00159       }
00160 
00161    if(dev->busy)
00162       return(0);
00163 
00164    if((obuf->mode & (OUTPUT_XON|OUTPUT_XOFF)) != 0
00165          ||  obuf->size > 0  &&  (obuf->mode & OUTPUT_STOPPED) == 0) {
00166       dev->busy = 1;
00167       tto(dev, obuf);
00168       }
00169    return(1);
00170    }
00171 
00172 /*
00173  * STTY is called by DEV everytime something "new" happens
00174  * to the termios control parameters
00175  *
00176  * It will set es:di to be the termios buffer (1st register pointer)
00177  * It will also set ds to be the data segment of the driver being called
00178  *
00179  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00180  * priority than the driver task, so cannot be interrupted.
00181  */
00182 
00183 int far Stty(struct termios far *tios) {
00184    register struct dev_entry *dev;
00185    int index;
00186    unsigned short cflag;
00187    int status;
00188 
00189    cflag = tios->c_cflag;
00190    index = tios->handle;
00191    dev = &dev_table[index];
00192    dev->baud = tios->c_ospeed;
00193    /*
00194     * Parities are: (stick:even:enable)
00195     *   xx0 none
00196     *   001 odd
00197     *   011 even
00198     *   101 mark
00199     *   111 space
00200     */
00201    dev->parity = (((~cflag) & PARODD) >> 8)
00202             | ((cflag & PARENB) >> 8)
00203             | ((cflag & PARSTK) >> 0);
00204    dev->stop_bits = ((cflag & CSTOPB) >> 6) + 1;
00205    dev->data_bits = ((cflag & CSIZE) >> 4) + 5;
00206    status = reset_async(index, 0);
00207    return(status);
00208    }
00209 
00210 /*
00211  * Ctrl is called by DEV to indicate a high level
00212  * control function
00213  *
00214  * It will set es:di to be an ioctl control block (1st register pointer)
00215  * It will also set ds to be the data segment of the driver being called
00216  *
00217  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00218  * priority than the driver task, so cannot be interrupted.
00219  */
00220 
00221 int far Ctrl(union ioctl_entry far *ioc) {
00222    int type;
00223    unsigned unit;
00224    struct dev_entry *dev;
00225 
00226    type = ioc->type;
00227    ioc->status = IOCTL_ERROR;
00228 
00229    if(type == IOCTL_OPEN) { /* First Open */
00230       ioc->status = IOCTL_OK;
00231       return(0);
00232       }
00233    else if(type == IOCTL_CLOSE) { /* Last Close */
00234       /*
00235        * Reset (rows,cols) to (0,0) on last close (ie: undefined)
00236        */
00237       ioc->close.obuf->rows = 0;
00238       ioc->close.obuf->cols = 0;
00239       ioc->close_return.status = IOCTL_OK;
00240       return(0);
00241       }
00242    else if(type == IOCTL_CTL) { /* Ctl */
00243       unsigned char bits, mask, oldbits;
00244 
00245       unit = ioc->close.unit;
00246       if(unit > num_asyncs  ||  unit <= 0) {
00247          ioc->status = IOCTL_BAD_UNIT;
00248          return(0);
00249          }
00250       dev = &dev_table[unit-1];
00251 
00252       mask = ioc->user.data[4] & 0x03;
00253       bits = ioc->user.data[0];
00254       _disable();
00255       oldbits = inp( dev->iobase + 4 );
00256       dev->modem_control = (oldbits & ~mask & 0xE7) | (bits & mask) | 0x08;
00257       outp( dev->iobase + 4, dev->modem_control);
00258       _enable();
00259       ioc->user_return.data[0] = oldbits;
00260 
00261       mask = ioc->user.data[5] & 0x40;
00262       bits = ioc->user.data[1];
00263       _disable();
00264       oldbits = inp( dev->iobase + 3 );
00265       outp( dev->iobase + 3, (oldbits & ~mask) | (bits & mask));
00266       _enable();
00267       ioc->user_return.data[1] = oldbits;
00268 
00269       ioc->user_return.data[2] = dev->modem_status & 0xF0;
00270 
00271       ioc->user_return.data[3] = 0;
00272       ioc->user_return.nbytes = 4;
00273       ioc->user_return.status = IOCTL_OK;
00274       return(0);
00275       }
00276    else if(type == IOCTL_STARTBREAK) {
00277       unit = ioc->startbreak.unit;
00278       if(unit > num_asyncs  ||  unit <= 0) {
00279          ioc->status = IOCTL_BAD_UNIT;
00280          return(0);
00281          }
00282       dev = &dev_table[unit-1];
00283       outp( dev->iobase + 3, inp( dev->iobase + 3 ) | 0x40);
00284       ioc->status = IOCTL_OK;
00285       return(0);
00286       }
00287    else if(type == IOCTL_STOPBREAK) {
00288       unit = ioc->stopbreak.unit;
00289       if(unit > num_asyncs  ||  unit <= 0) {
00290          ioc->status = IOCTL_BAD_UNIT;
00291          return(0);
00292          }
00293       dev = &dev_table[unit-1];
00294       outp( dev->iobase + 3, inp( dev->iobase + 3 ) & ~0x40);
00295       ioc->status = IOCTL_OK;
00296       return(0);
00297       }
00298    else if(type == IOCTL_STARTDROP) {
00299       unit = ioc->startdrop.unit;
00300       if(unit > num_asyncs  ||  unit <= 0) {
00301          ioc->status = IOCTL_BAD_UNIT;
00302          return(0);
00303          }
00304       dev = &dev_table[unit-1];
00305       dev->modem_control &= ~0x01;
00306       outp(dev->iobase+4, dev->modem_control);
00307       ioc->status = IOCTL_OK;
00308       return(0);
00309       }
00310    else if(type == IOCTL_STOPDROP) {
00311       unit = ioc->stopdrop.unit;
00312       if(unit > num_asyncs  ||  unit <= 0) {
00313          ioc->status = IOCTL_BAD_UNIT;
00314          return(0);
00315          }
00316       dev = &dev_table[unit-1];
00317       dev->modem_control |= 0x01;
00318       outp(dev->iobase+4, dev->modem_control);
00319       ioc->status = IOCTL_OK;
00320       return(0);
00321       }
00322    return(-1);
00323    }
00324 
00325 #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