]> Zhao Yanbai Git Server - minix.git/commitdiff
Changed timer library function args.
authorBen Gras <ben@minix3.org>
Fri, 17 Jun 2005 13:37:41 +0000 (13:37 +0000)
committerBen Gras <ben@minix3.org>
Fri, 17 Jun 2005 13:37:41 +0000 (13:37 +0000)
Added select() support for tty fd's (not ptys yet).

drivers/floppy/floppy.c
drivers/fxp/fxp.c
drivers/tty/console.c
drivers/tty/keyboard.c
drivers/tty/pty.c
drivers/tty/rs232.c
drivers/tty/tty.c
drivers/tty/tty.h

index e0ec3784530e3ea49c164c7b1f329f4f784287fd..1de97cdaf2fd2576fa24fb8de56d4782f312d475 100644 (file)
@@ -328,7 +328,7 @@ PRIVATE void f_expire_tmrs(struct driver *dp)
    * for each expired timers. FLOPPY watchdog functions are f_tmr_timeout() 
    * and stop_motor(). Possibly a new alarm call must be scheduled.
    */
-  tmrs_exptimers(&f_timers, now);
+  tmrs_exptimers(&f_timers, now, NULL);
   if (f_timers == NULL) {
        f_next_timeout = TMR_NEVER;
   } else {                                       /* set new sync alarm */
@@ -354,7 +354,7 @@ tmr_func_t watchdog;                        /* watchdog function to be called */
        panic("FLOPPY","Couldn't get uptime from clock.", s);
 
   /* Add the timer to the local timer queue. */
-  tmrs_settimer(&f_timers, tp, now + delta, watchdog);
+  tmrs_settimer(&f_timers, tp, now + delta, watchdog, NULL);
 
   /* Possibly reschedule an alarm call. This happens when the front of the 
    * timers queue was reinserted at another position, i.e., when a timer was 
index ea6e535a65d86bf81ddcc2da690bb026d908602f..8dfca6a1c20df4177c4302252e822f5dd4fbcaec 100644 (file)
@@ -2369,7 +2369,7 @@ tmr_func_t watchdog;                      /* watchdog function to be called */
                panic("FXP","unable to get uptime from clock", r);
 
        /* Add the timer to the local timer queue. */
-       tmrs_settimer(&fxp_timers, tp, now + delta, watchdog);
+       tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
 
        /* Possibly reschedule an alarm call. This happens when a new timer
         * is added in front. 
@@ -2407,7 +2407,7 @@ PRIVATE void fxp_expire_timers()
   /* Scan the timers queue for expired timers. Dispatch the watchdog function
    * for each expired timers. Possibly a new alarm call must be scheduled.
    */
-  tmrs_exptimers(&fxp_timers, now);
+  tmrs_exptimers(&fxp_timers, now, NULL);
   if (fxp_timers == NULL)
        fxp_next_timeout= TMR_NEVER;
   else
index b08dfab4105bc2fa364e291234bef49392966b7b..2dca24fb1757dc93c87e57f4adfe92167a3026e5 100644 (file)
@@ -114,7 +114,7 @@ struct sequence {
        unsigned char value;
 };
 
-FORWARD _PROTOTYPE( void cons_write, (struct tty *tp)                  );
+FORWARD _PROTOTYPE( int cons_write, (struct tty *tp, int try)                  );
 FORWARD _PROTOTYPE( void cons_echo, (tty_t *tp, int c)                 );
 FORWARD _PROTOTYPE( void out_char, (console_t *cons, int c)            );
 FORWARD _PROTOTYPE( void putk, (int c)                                 );
@@ -128,14 +128,15 @@ FORWARD _PROTOTYPE( void get_6845, (int reg, unsigned *val)               );
 FORWARD _PROTOTYPE( void stop_beep, (timer_t *tmrp)                            );
 FORWARD _PROTOTYPE( void cons_org0, (void)                             );
 FORWARD _PROTOTYPE( int ga_program, (struct sequence *seq)             );
-FORWARD _PROTOTYPE( void cons_ioctl, (tty_t *tp)                       );
+FORWARD _PROTOTYPE( int cons_ioctl, (tty_t *tp, int)                   );
 
 
 /*===========================================================================*
  *                             cons_write                                   *
  *===========================================================================*/
-PRIVATE void cons_write(tp)
+PRIVATE int cons_write(tp, try)
 register struct tty *tp;       /* tells which terminal is to be used */
+int try;
 {
 /* Copy as much data as possible to the output queue, then start I/O.  On
  * memory-mapped terminals, such as the IBM console, the I/O will also be
@@ -148,6 +149,8 @@ register struct tty *tp;    /* tells which terminal is to be used */
   char buf[64];
   console_t *cons = tp->tty_priv;
 
+  if(try) return 1;    /* we can always write to console */
+
   /* Check quickly for nothing to do, so this can be called often without
    * unmodular tests elsewhere.
    */
@@ -757,7 +760,7 @@ PRIVATE void beep()
         }
   }
   /* Add a timer to the timers list. Possibly reschedule the alarm. */
-  tmrs_settimer(&tty_timers, &tmr_stop_beep, now+B_TIME, stop_beep);
+  tmrs_settimer(&tty_timers, &tmr_stop_beep, now+B_TIME, stop_beep, NULL);
   if (tty_timers->tmr_exp_time != tty_next_timeout) {
        tty_next_timeout = tty_timers->tmr_exp_time;
        if ((s=sys_syncalrm(SELF, tty_next_timeout, 1)) != OK)
@@ -873,7 +876,7 @@ tty_t *tp;
        cons->c_column = 0;
   }
   select_console(0);
-  cons_ioctl(tp);
+  cons_ioctl(tp, 0);
 }
 
 /*==========================================================================*
@@ -1110,8 +1113,9 @@ struct sequence *seq;
 /*===========================================================================*
  *                             cons_ioctl                                   *
  *===========================================================================*/
-PRIVATE void cons_ioctl(tp)
+PRIVATE int cons_ioctl(tp, try)
 tty_t *tp;
+int try;
 {
 /* Set the screen dimensions. */
 
index 932e5915ba4d695a83c5946a77ba963abbfed56d..a878344f9d64b69b10c89e21f6fad18a82646931 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include "../drivers.h"
+#include <sys/time.h>
+#include <sys/select.h>
 #include <termios.h>
 #include <signal.h>
 #include <unistd.h>
@@ -84,7 +86,7 @@ FORWARD _PROTOTYPE( int scan_keyboard, (void) );
 FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
 FORWARD _PROTOTYPE( void set_leds, (void) );
 FORWARD _PROTOTYPE( void show_key_mappings, (void) );
-FORWARD _PROTOTYPE( void kb_read, (struct tty *tp) );
+FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
 FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
 
 
@@ -147,6 +149,9 @@ message *m_ptr;
        if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
        icount++;
        tty_table[ccurrent].tty_events = 1;
+       if(tty_table[ccurrent].tty_select_ops & SEL_RD) {
+               select_retry(&tty_table[ccurrent]);
+       }
   }
 }
 
@@ -154,8 +159,9 @@ message *m_ptr;
 /*==========================================================================*
  *                             kb_read                                     *
  *==========================================================================*/
-PRIVATE void kb_read(tp)
+PRIVATE int kb_read(tp, try)
 tty_t *tp;
+int try;
 {
 /* Process characters from the circular keyboard buffer. */
 
@@ -165,6 +171,12 @@ tty_t *tp;
 
   tp = &tty_table[ccurrent];           /* always use the current console */
 
+  if(try) {
+       printf("tty: kb: try: %d icount: %d\n", try, icount);
+       if(icount > 0) return 1;
+       return 0;
+  }
+
   while (icount > 0) {
        scode = *itail++;                       /* take one key scan code */
        if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
@@ -213,6 +225,8 @@ tty_t *tp;
            }
        }
   }
+
+  return 1;
 }
 
 
index 1a8ed81415445ce6358a74c61be0375a52fe588a..bbc4f58499013f4d6e1b7352ea1a7aa4af4cf89b 100644 (file)
@@ -59,14 +59,14 @@ typedef struct pty {
 PRIVATE pty_t pty_table[NR_PTYS];      /* PTY bookkeeping */
 
 
-FORWARD _PROTOTYPE( void pty_write, (tty_t *tp)                                );
+FORWARD _PROTOTYPE( int pty_write, (tty_t *tp, int try)                                );
 FORWARD _PROTOTYPE( void pty_echo, (tty_t *tp, int c)                  );
 FORWARD _PROTOTYPE( void pty_start, (pty_t *pp)                                );
 FORWARD _PROTOTYPE( void pty_finish, (pty_t *pp)                       );
-FORWARD _PROTOTYPE( void pty_read, (tty_t *tp)                         );
-FORWARD _PROTOTYPE( void pty_close, (tty_t *tp)                                );
-FORWARD _PROTOTYPE( void pty_icancel, (tty_t *tp)                      );
-FORWARD _PROTOTYPE( void pty_ocancel, (tty_t *tp)                      );
+FORWARD _PROTOTYPE( int pty_read, (tty_t *tp, int try)                         );
+FORWARD _PROTOTYPE( int pty_close, (tty_t *tp, int try)                                );
+FORWARD _PROTOTYPE( int pty_icancel, (tty_t *tp, int try)                      );
+FORWARD _PROTOTYPE( int pty_ocancel, (tty_t *tp, int try)                      );
 
 
 /*==========================================================================*
@@ -201,8 +201,9 @@ message *m_ptr;
 /*==========================================================================*
  *                             pty_write                                   *
  *==========================================================================*/
-PRIVATE void pty_write(tp)
+PRIVATE int pty_write(tp, try)
 tty_t *tp;
+int try;
 {
 /* (*dev_write)() routine for PTYs.  Transfer bytes from the writer on
  * /dev/ttypX to the output buffer.
@@ -213,6 +214,7 @@ tty_t *tp;
 
   /* PTY closed down? */
   if (pp->state & PTY_CLOSED) {
+       if(try) return 1;
        if (tp->tty_outleft > 0) {
                tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
                                                        tp->tty_outproc, EIO);
@@ -227,7 +229,11 @@ tty_t *tp;
        count = bufend(pp->obuf) - pp->ohead;
        if (count > ocount) count = ocount;
        if (count > tp->tty_outleft) count = tp->tty_outleft;
-       if (count == 0 || tp->tty_inhibited) break;
+       if (count == 0 || tp->tty_inhibited) {
+               if(try) return 0;
+               break;
+       }
+       if(try) return 1;
 
        /* Copy from user space to the PTY output buffer. */
        if((s = sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
@@ -258,9 +264,9 @@ tty_t *tp;
        }
   }
   pty_finish(pp);
+  return 1;
 }
 
-
 /*==========================================================================*
  *                             pty_echo                                    *
  *==========================================================================*/
@@ -341,8 +347,9 @@ pty_t *pp;
 /*==========================================================================*
  *                             pty_read                                    *
  *==========================================================================*/
-PRIVATE void pty_read(tp)
+PRIVATE int pty_read(tp, try)
 tty_t *tp;
+int try;
 {
 /* Offer bytes from the PTY writer for input on the TTY.  (Do it one byte at
  * a time, 99% of the writes will be for one byte, so no sense in being smart.)
@@ -351,12 +358,19 @@ tty_t *tp;
   char c;
 
   if (pp->state & PTY_CLOSED) {
+       if(try) return 1;
        if (tp->tty_inleft > 0) {
                tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
                                                                tp->tty_incum);
                tp->tty_inleft = tp->tty_incum = 0;
        }
-       return;
+       return 1;
+  }
+
+  if(try) {
+       if(pp->wrleft > 0)
+               return 1;
+       return 0;
   }
 
   while (pp->wrleft > 0) {
@@ -386,8 +400,9 @@ tty_t *tp;
 /*==========================================================================*
  *                             pty_close                                   *
  *==========================================================================*/
-PRIVATE void pty_close(tp)
+PRIVATE int pty_close(tp, try)
 tty_t *tp;
+int try;
 {
 /* The tty side has closed, so shut down the pty side. */
   pty_t *pp = tp->tty_priv;
@@ -411,8 +426,9 @@ tty_t *tp;
 /*==========================================================================*
  *                             pty_icancel                                 *
  *==========================================================================*/
-PRIVATE void pty_icancel(tp)
+PRIVATE int pty_icancel(tp, try)
 tty_t *tp;
+int try;
 {
 /* Discard waiting input. */
   pty_t *pp = tp->tty_priv;
@@ -428,8 +444,9 @@ tty_t *tp;
 /*==========================================================================*
  *                             pty_ocancel                                 *
  *==========================================================================*/
-PRIVATE void pty_ocancel(tp)
+PRIVATE int pty_ocancel(tp, try)
 tty_t *tp;
+int try;
 {
 /* Drain the output buffer. */
   pty_t *pp = tp->tty_priv;
index 8fa1b2d16ae9f671bfdba5b18680a51d90cc07a2..1023fdab3f79c5e9e60915c301e592650cbd8030 100644 (file)
@@ -253,11 +253,11 @@ FORWARD _PROTOTYPE( int rs232_handler, (message *m)                       );
 FORWARD _PROTOTYPE( void in_int, (rs232_t *rs)                         );
 FORWARD _PROTOTYPE( void line_int, (rs232_t *rs)                       );
 FORWARD _PROTOTYPE( void modem_int, (rs232_t *rs)                      );
-FORWARD _PROTOTYPE( void rs_write, (tty_t *tp)                         );
+FORWARD _PROTOTYPE( int rs_write, (tty_t *tp, int try)                         );
 FORWARD _PROTOTYPE( void rs_echo, (tty_t *tp, int c)                   );
 FORWARD _PROTOTYPE( void rs_ioctl, (tty_t *tp)                         );
 FORWARD _PROTOTYPE( void rs_config, (rs232_t *rs)                      );
-FORWARD _PROTOTYPE( void rs_read, (tty_t *tp)                          );
+FORWARD _PROTOTYPE( int rs_read, (tty_t *tp, int try)                          );
 FORWARD _PROTOTYPE( void rs_icancel, (tty_t *tp)                       );
 FORWARD _PROTOTYPE( void rs_ocancel, (tty_t *tp)                       );
 FORWARD _PROTOTYPE( void rs_ostart, (rs232_t *rs)                      );
@@ -282,8 +282,9 @@ PRIVATE int my_inb(port_t port)
 /*==========================================================================*
  *                             rs_write                                    *
  *==========================================================================*/
-PRIVATE void rs_write(tp)
+PRIVATE void rs_write(tp, try)
 register tty_t *tp;
+int try;
 {
 /* (*devwrite)() routine for RS232. */
 
@@ -301,7 +302,7 @@ register tty_t *tp;
 
   if (rs->drain) {
        /* Wait for the line to drain then reconfigure and continue output. */
-       if (rs->ocount > 0) return;
+       if (rs->ocount > 0) return 0;
        rs->drain = FALSE;
        rs_config(rs);
   }
@@ -312,7 +313,11 @@ register tty_t *tp;
        count = bufend(rs->obuf) - rs->ohead;
        if (count > ocount) count = ocount;
        if (count > tp->tty_outleft) count = tp->tty_outleft;
-       if (count == 0 || tp->tty_inhibited) break;
+       if (count == 0 || tp->tty_inhibited) {
+               if(try) return 0;
+               break;
+       }
+       if(try) return 1;
 
        /* Copy from user space to the RS232 output buffer. */
        sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir, 
@@ -346,6 +351,8 @@ register tty_t *tp;
        tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc, EIO);
        tp->tty_outleft = tp->tty_outcum = 0;
   }
+
+  return 1;
 }
 
 
@@ -650,8 +657,9 @@ tty_t *tp;                  /* which TTY */
 /*==========================================================================*
  *                             rs_read                                     *
  *==========================================================================*/
-PRIVATE void rs_read(tp)
+PRIVATE void rs_read(tp, try)
 tty_t *tp;                     /* which tty */
+int try;
 {
 /* Process characters from the circular input buffer. */
 
@@ -659,6 +667,7 @@ tty_t *tp;                  /* which tty */
   int icount, count, ostate;
 
   if (!(tp->tty_termios.c_cflag & CLOCAL)) {
+       if(try) return 1;
        /* Send a SIGHUP if hangup detected. */
        lock();
        ostate = rs->ostate;
@@ -671,6 +680,12 @@ tty_t *tp;                 /* which tty */
        }
   }
 
+  if(try) {
+       if(rs->icount > 0)
+               return 1;
+       return 0;
+  }
+
   while ((count = rs->icount) > 0) {
        icount = bufend(rs->ibuf) - rs->itail;
        if (count > icount) count = icount;
index 846371950327e3e0e8ea08750dcf49b17112396c..f20c8ded98d9f30fa343c32199b2b2745e640e9a 100644 (file)
  *
  * The valid messages and their parameters are:
  *
- *   HARD_INT:     output has been completed or input has arrived
- *   HARD_STOP:    MINIX wants to shutdown; run code to cleanly stop
- *   DEV_READ:     a process wants to read from a terminal
- *   DEV_WRITE:    a process wants to write on a terminal
- *   DEV_IOCTL:    a process wants to change a terminal's parameters
- *   DEV_OPEN:     a tty line has been opened
- *   DEV_CLOSE:    a tty line has been closed
- *   CANCEL:       terminate a previous incomplete system call immediately
+ *   HARD_INT:       output has been completed or input has arrived
+ *   HARD_STOP:      MINIX wants to shutdown; run code to cleanly stop
+ *   DEV_READ:       a process wants to read from a terminal
+ *   DEV_WRITE:      a process wants to write on a terminal
+ *   DEV_IOCTL:      a process wants to change a terminal's parameters
+ *   DEV_OPEN:       a tty line has been opened
+ *   DEV_CLOSE:      a tty line has been closed
+ *   DEV_SELECT:     start select notification request
+ *   DEV_SELECT_CAN: cancel select notification
+ *   CANCEL:         terminate a previous incomplete system call immediately
  *
  *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
  * ---------------------------------------------------------------------------
@@ -52,6 +54,7 @@
  *   Jul 13, 2004   support for function key observers  (Jorrit N. Herder)  
  */
 
+#include "../drivers.h"
 #include "../drivers.h"
 #include <termios.h>
 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
@@ -65,6 +68,9 @@
 #endif
 #include "tty.h"
 
+#include <sys/time.h>
+#include <sys/select.h>
+
 extern int irq_hook_id;
 
 /* Address of a tty structure. */
@@ -105,6 +111,7 @@ FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr)               );
 FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr)         );
 FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr)          );
 FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr)         );
+FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr)                );
 FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp)                      );
 FORWARD _PROTOTYPE( int tty_echo, (tty_t *tp, int ch)                  );
 FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch)                  );
@@ -265,12 +272,13 @@ PUBLIC void main(void)
 
        /* Execute the requested device driver function. */
        switch (tty_mess.m_type) {
-           case DEV_READ:      do_read(tp, &tty_mess);         break;
-           case DEV_WRITE:     do_write(tp, &tty_mess);        break;
-           case DEV_IOCTL:     do_ioctl(tp, &tty_mess);        break;
-           case DEV_OPEN:      do_open(tp, &tty_mess);         break;
-           case DEV_CLOSE:     do_close(tp, &tty_mess);        break;
-           case CANCEL:        do_cancel(tp, &tty_mess);       break;
+           case DEV_READ:       do_read(tp, &tty_mess);          break;
+           case DEV_WRITE:      do_write(tp, &tty_mess);         break;
+           case DEV_IOCTL:      do_ioctl(tp, &tty_mess);         break;
+           case DEV_OPEN:       do_open(tp, &tty_mess);          break;
+           case DEV_CLOSE:      do_close(tp, &tty_mess);         break;
+           case DEV_SELECT:     do_select(tp, &tty_mess);        break;
+           case CANCEL:         do_cancel(tp, &tty_mess);        break;
            default:            
                printf("Warning, TTY got unexpected request %d from %d\n",
                        tty_mess.m_type, tty_mess.m_source);
@@ -335,8 +343,11 @@ register message *m_ptr;   /* pointer to message sent to the task */
        in_transfer(tp);
        /* ...then go back for more. */
        handle_events(tp);
-       if (tp->tty_inleft == 0) 
+       if (tp->tty_inleft == 0)  {
+               if(tp->tty_select_ops)
+                       select_retry(tp);
                return;                 /* already done */
+       }
 
        /* There were no bytes in the input queue available, so either suspend
         * the caller or break off the read if nonblocking.
@@ -350,6 +361,8 @@ register message *m_ptr;    /* pointer to message sent to the task */
        }
   }
   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
+  if(tp->tty_select_ops)
+       select_retry(tp);
 }
 
 
@@ -386,7 +399,11 @@ register message *m_ptr;   /* pointer to message sent to the task */
 
        /* Try to write. */
        handle_events(tp);
-       if (tp->tty_outleft == 0) return;               /* already done */
+       if (tp->tty_outleft == 0) {
+               if(tp->tty_select_ops)
+                       select_retry(tp);
+               return;         /* already done */
+       }
 
        /* None or not all the bytes could be written, so either suspend the
         * caller or break off the write if nonblocking.
@@ -400,6 +417,8 @@ register message *m_ptr;    /* pointer to message sent to the task */
        }
   }
   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
+  if(tp->tty_select_ops)
+       select_retry(tp);
 }
 
 
@@ -509,8 +528,8 @@ message *m_ptr;                     /* pointer to message sent to task */
        if (r != OK) break;
        switch (param.i) {
            case TCIFLUSH:      tty_icancel(tp);                        break;
-           case TCOFLUSH:      (*tp->tty_ocancel)(tp);                 break;
-           case TCIOFLUSH:     tty_icancel(tp); (*tp->tty_ocancel)(tp);break;
+           case TCOFLUSH:      (*tp->tty_ocancel)(tp, 0);                      break;
+           case TCIOFLUSH:     tty_icancel(tp); (*tp->tty_ocancel)(tp, 0);break;
            default:            r = EINVAL;
        }
        break;
@@ -537,7 +556,7 @@ message *m_ptr;                     /* pointer to message sent to task */
        break;
 
     case TCSBRK:
-       if (tp->tty_break != NULL) (*tp->tty_break)(tp);
+       if (tp->tty_break != NULL) (*tp->tty_break)(tp,0);
        break;
 
     case TIOCGWINSZ:
@@ -658,8 +677,8 @@ message *m_ptr;                     /* pointer to message sent to task */
   if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
        tp->tty_pgrp = 0;
        tty_icancel(tp);
-       (*tp->tty_ocancel)(tp);
-       (*tp->tty_close)(tp);
+       (*tp->tty_ocancel)(tp, 0);
+       (*tp->tty_close)(tp, 0);
        tp->tty_termios = termios_defaults;
        tp->tty_winsize = winsize_defaults;
        setattr(tp);
@@ -692,7 +711,7 @@ message *m_ptr;                     /* pointer to message sent to task */
   }
   if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
        /* Process was writing when killed.  Clean up output. */
-       (*tp->tty_ocancel)(tp);
+       (*tp->tty_ocancel)(tp, 0);
        tp->tty_outleft = tp->tty_outcum = 0;
   }
   if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
@@ -703,6 +722,60 @@ message *m_ptr;                    /* pointer to message sent to task */
   tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
 }
 
+PUBLIC int select_try(struct tty *tp, int ops)
+{
+       int ready_ops = 0;
+
+       /* special case. if line is hung up, no operations will block.
+        * (and it can be seen as an exceptional condition.)
+        */
+       if (tp->tty_termios.c_ospeed == B0) {
+               printf("tty: hangup always ok\n");
+               ready_ops |= ops;
+       }
+
+       if(ops & SEL_RD) {
+               /* will i/o not block on read? */
+               if (tp->tty_inleft > 0) {
+                       ready_ops |= SEL_RD;    /* EIO - no blocking */
+               } else if(tp->tty_incount > 0) {
+                       /* is a regular read possible? tty_incount
+                        * says there is data. but a read will only succeed
+                        * in canonical mode if a newline has been seen.
+                        */
+                       if(!(tp->tty_termios.c_lflag & ICANON) ||
+                               tp->tty_eotct > 0) {
+                               ready_ops |= SEL_RD;
+                       }
+               }
+       }
+
+       if(ops & SEL_WR) {
+               if (tp->tty_outleft > 0) {
+                       ready_ops |= SEL_WR;    /* EIO - no blocking */
+               }
+               if((*tp->tty_devwrite)(tp, 1)) {
+                       ready_ops |= SEL_WR;    /* real write possible */
+               }
+       }
+
+       return ready_ops;
+}
+
+PUBLIC int select_retry(struct tty *tp)
+{
+       int ops;
+       if((ops = select_try(tp, tp->tty_select_ops))) {
+               message m;
+               m.NOTIFY_TYPE = DEV_SELECTED;
+               m.NOTIFY_ARG = tp->tty_index;
+               m.NOTIFY_FLAGS = ops;
+               notify(tp->tty_select_proc, &m);
+               tp->tty_select_ops &= ~ops;
+       }
+
+       return OK;
+}
 
 /*===========================================================================*
  *                             handle_events                                *
@@ -731,10 +804,10 @@ tty_t *tp;                        /* TTY to check for events. */
        tp->tty_events = 0;
 
        /* Read input and perform input processing. */
-       (*tp->tty_devread)(tp);
+       (*tp->tty_devread)(tp, 0);
 
        /* Perform output processing and write output. */
-       (*tp->tty_devwrite)(tp);
+       (*tp->tty_devwrite)(tp, 0);
 
        /* Ioctl waiting for some event? */
        if (tp->tty_ioreq != 0) dev_ioctl(tp);
@@ -1288,7 +1361,7 @@ tty_t *tp;
   if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
 
   /* Set new line speed, character size, etc at the device level. */
-  (*tp->tty_ioctl)(tp);
+  (*tp->tty_ioctl)(tp, 0);
 }
 
 
@@ -1335,7 +1408,7 @@ int sig;                  /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
   if (!(tp->tty_termios.c_lflag & NOFLSH)) {
        tp->tty_incount = tp->tty_eotct = 0;    /* kill earlier input */
        tp->tty_intail = tp->tty_inhead;
-       (*tp->tty_ocancel)(tp);                 /* kill all output */
+       (*tp->tty_ocancel)(tp, 0);                      /* kill all output */
        tp->tty_inhibited = RUNNING;
        tp->tty_events = 1;
   }
@@ -1352,7 +1425,7 @@ register tty_t *tp;
 
   tp->tty_incount = tp->tty_eotct = 0;
   tp->tty_intail = tp->tty_inhead;
-  (*tp->tty_icancel)(tp);
+  (*tp->tty_icancel)(tp, 0);
 }
 
 
@@ -1411,7 +1484,7 @@ PRIVATE void expire_timers(void)
   /* Scan the queue of timers for expired timers. This dispatch the watchdog
    * functions of expired timers. Possibly a new alarm call must be scheduled.
    */
-  tmrs_exptimers(&tty_timers, now);
+  tmrs_exptimers(&tty_timers, now, NULL);
   if (tty_timers == NULL) tty_next_timeout = TMR_NEVER;
   else {                                         /* set new sync alarm */
        tty_next_timeout = tty_timers->tmr_exp_time;
@@ -1438,10 +1511,10 @@ int enable;                     /* set timer if true, otherwise unset */
        exp_time = now + tty_ptr->tty_termios.c_cc[VTIME] * (HZ/10);
        /* Set a new timer for enabling the TTY events flags. */
        tmrs_settimer(&tty_timers, &tty_ptr->tty_tmr, 
-               exp_time, tty_timed_out);  
+               exp_time, tty_timed_out, NULL);  
   } else {
        /* Remove the timer from the active and expired lists. */
-       tmrs_clrtimer(&tty_timers, &tty_ptr->tty_tmr);
+       tmrs_clrtimer(&tty_timers, &tty_ptr->tty_tmr, NULL);
   }
   
   /* Now check if a new alarm must be scheduled. This happens when the front
@@ -1460,12 +1533,39 @@ int enable;                     /* set timer if true, otherwise unset */
 /*==========================================================================*
  *                             tty_devnop                                  *
  *==========================================================================*/
-PUBLIC void tty_devnop(tp)
+PUBLIC int tty_devnop(tp, try)
 tty_t *tp;
+int try;
 {
   /* Some functions need not be implemented at the device level. */
 }
 
+/*===========================================================================*
+ *                             do_select                            *
+ *===========================================================================*/
+PRIVATE void do_select(tp, m_ptr)
+register tty_t *tp;            /* pointer to tty struct */
+register message *m_ptr;       /* pointer to message sent to the task */
+{
+       int ops, ready_ops = 0, watch;
+       printf("doing select..\n");
+
+       ops = m_ptr->PROC_NR & (SEL_RD|SEL_WR|SEL_ERR);
+       watch = (m_ptr->PROC_NR & SEL_NOTIFY) ? 1 : 0;
+
+       ready_ops = select_try(tp, ops);
+
+       if(!ready_ops && ops && watch) {
+               printf("doing select.. ops %d\n", ops);
+               tp->tty_select_ops |= ops;
+               tp->tty_select_proc = m_ptr->m_source;
+       } else printf("not doing select.. ready_ops %d ops %d watch %d\n",
+               ready_ops, ops, watch);
+
+        tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, ready_ops);
+
+        return;
+}
 
 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
 /*===========================================================================*
index d931cb4fa32a4969ad9ca9726f9d8a6ab5f5c1ed..436ccdf21c073e805f01cbd814ed396ac6856dbd 100644 (file)
@@ -13,7 +13,7 @@
 #define O_NONBLOCK     04000
 
 struct tty;
-typedef _PROTOTYPE( void (*devfun_t), (struct tty *tp) );
+typedef _PROTOTYPE( int (*devfun_t), (struct tty *tp, int try_only) );
 typedef _PROTOTYPE( void (*devfunarg_t), (struct tty *tp, int c) );
 
 typedef struct tty {
@@ -62,6 +62,10 @@ typedef struct tty {
   int tty_ioreq;               /* ioctl request code */
   vir_bytes tty_iovir;         /* virtual address of ioctl buffer */
 
+  /* select() data */
+  int tty_select_ops;          /* which operations are interesting */
+  int tty_select_proc;         /* which process wants notification */
+
   /* Miscellaneous. */
   devfun_t tty_ioctl;          /* set line speed, etc. at the device level */
   devfun_t tty_close;          /* tell the device that the tty is closed */
@@ -70,6 +74,7 @@ typedef struct tty {
   struct winsize tty_winsize;  /* window size (#lines and #columns) */
 
   u16_t tty_inbuf[TTY_IN_BYTES];/* tty input buffer */
+
 } tty_t;
 
 /* Memory allocated in tty.c, so extern here. */
@@ -116,7 +121,8 @@ _PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos,
 _PROTOTYPE( void tty_wakeup, (clock_t now)                             );
 _PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
                                                        int status)     );
-_PROTOTYPE( void tty_devnop, (struct tty *tp)                          );
+_PROTOTYPE( int tty_devnop, (struct tty *tp, int try)                          );
+_PROTOTYPE( int select_retry, (struct tty *tp)                         );
 
 /* rs232.c */
 _PROTOTYPE( void rs_init, (struct tty *tp)                             );