⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 4 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/kernel/tty.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

11700	/* This file contains the terminal driver, both for the IBM console and regular
11701	 * ASCII terminals.  It handles only the device-independent part of a TTY, the
11702	 * device dependent parts are in console.c, rs232.c, etc.  This file contains
11703	 * two main entry points, tty_task() and tty_wakeup(), and several minor entry
11704	 * points for use by the device-dependent code.
11705	 *
11706	 * The device-independent part accepts "keyboard" input from the device-
11707	 * dependent part, performs input processing (special key interpretation),
11708	 * and sends the input to a process reading from the TTY.  Output to a TTY
11709	 * is sent to the device-dependent code for output processing and "screen"
11710	 * display.  Input processing is done by the device by calling 'in_process'
11711	 * on the input characters, output processing may be done by the device itself
11712	 * or by calling 'out_process'.  The TTY takes care of input queuing, the
11713	 * device does the output queuing.  If a device receives an external signal,
11714	 * like an interrupt, then it causes tty_wakeup() to be run by the CLOCK task
11715	 * to, you guessed it, wake up the TTY to check if input or output can
11716	 * continue.
11717	 *
11718	 * The valid messages and their parameters are:
11719	 *
11720	 *   HARD_INT:     output has been completed or input has arrived
11721	 *   DEV_READ:     a process wants to read from a terminal
11722	 *   DEV_WRITE:    a process wants to write on a terminal
11723	 *   DEV_IOCTL:    a process wants to change a terminal's parameters
11724	 *   DEV_OPEN:     a tty line has been opened
11725	 *   DEV_CLOSE:    a tty line has been closed
11726	 *   CANCEL:       terminate a previous incomplete system call immediately
11727	 *
11728	 *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
11729	 * ---------------------------------------------------------------------------
11730	 * | HARD_INT    |         |         |         |         |         |         |
11731	 * |-------------+---------+---------+---------+---------+---------+---------|
11732	 * | DEV_READ    |minor dev| proc nr |  count  |         O_NONBLOCK| buf ptr |
11733	 * |-------------+---------+---------+---------+---------+---------+---------|
11734	 * | DEV_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
11735	 * |-------------+---------+---------+---------+---------+---------+---------|
11736	 * | DEV_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
11737	 * |-------------+---------+---------+---------+---------+---------+---------|
11738	 * | DEV_OPEN    |minor dev| proc nr | O_NOCTTY|         |         |         |
11739	 * |-------------+---------+---------+---------+---------+---------+---------|
11740	 * | DEV_CLOSE   |minor dev| proc nr |         |         |         |         |
11741	 * |-------------+---------+---------+---------+---------+---------+---------|
11742	 * | CANCEL      |minor dev| proc nr |         |         |         |         |
11743	 * ---------------------------------------------------------------------------
11744	 */
11745	
11746	#include "kernel.h"
11747	#include <termios.h>
11748	#include <sys/ioctl.h>
11749	#include <signal.h>
11750	#include <minix/callnr.h>
11751	#include <minix/com.h>
11752	#include <minix/keymap.h>
11753	#include "tty.h"
11754	#include "proc.h"
11755	
11756	/* Address of a tty structure. */
11757	#define tty_addr(line)  (&tty_table[line])
11758	
11759	/* First minor numbers for the various classes of TTY devices. */
11760	#define CONS_MINOR        0
11761	#define LOG_MINOR        15
11762	#define RS232_MINOR      16
11763	#define TTYPX_MINOR     128
11764	#define PTYPX_MINOR     192
11765	
11766	/* Macros for magic tty types. */
11767	#define isconsole(tp)   ((tp) < tty_addr(NR_CONS))
11768	
11769	/* Macros for magic tty structure pointers. */
11770	#define FIRST_TTY       tty_addr(0)
11771	#define END_TTY         tty_addr(sizeof(tty_table) / sizeof(tty_table[0]))
11772	
11773	/* A device exists if at least its 'devread' function is defined. */
11774	#define tty_active(tp)  ((tp)->tty_devread != NULL)
11775	
11776	/* RS232 lines or pseudo terminals can be completely configured out. */
11777	#if NR_RS_LINES == 0
11778	#define rs_init(tp)     ((void) 0)
11779	#endif
11780	#if NR_PTYS == 0
11781	#define pty_init(tp)    ((void) 0)
11782	#define do_pty(tp, mp)  ((void) 0)
11783	#endif
11784	
11785	FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr)         );
11786	FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr)          );
11787	FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr)           );
11788	FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr)          );
11789	FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr)           );
11790	FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr)          );
11791	FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp)                       );
11792	FORWARD _PROTOTYPE( int echo, (tty_t *tp, int ch)                       );
11793	FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch)                   );
11794	FORWARD _PROTOTYPE( int back_over, (tty_t *tp)                          );
11795	FORWARD _PROTOTYPE( void reprint, (tty_t *tp)                           );
11796	FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp)                         );
11797	FORWARD _PROTOTYPE( void setattr, (tty_t *tp)                           );
11798	FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp)                       );
11799	FORWARD _PROTOTYPE( void tty_init, (tty_t *tp)                          );
11800	FORWARD _PROTOTYPE( void settimer, (tty_t *tp, int on)                  );
11801	
11802	/* Default attributes. */
11803	PRIVATE struct termios termios_defaults = {
11804	  TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF,
11805	  {
11806	        TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF,
11807	        TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF,
11808	        TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF,
11809	  },
11810	};
11811	PRIVATE struct winsize winsize_defaults;        /* = all zeroes */
11812	
11813	
11814	/*===========================================================================*
11815	 *                              tty_task                                     *
11816	 *===========================================================================*/
11817	PUBLIC void tty_task()
11818	{
11819	/* Main routine of the terminal task. */
11820	
11821	  message tty_mess;             /* buffer for all incoming messages */
11822	  register tty_t *tp;
11823	  unsigned line;
11824	
11825	  /* Initialize the terminal lines. */
11826	  for (tp = FIRST_TTY; tp < END_TTY; tp++) tty_init(tp);
11827	
11828	  /* Display the Minix startup banner. */
11829	  printf("Minix %s.%s  Copyright 1997 Prentice-Hall, Inc.\n\n",
11830	                                                OS_RELEASE, OS_VERSION);
11831	  printf("Executing in 32-bit protected mode\n\n");
11832	
11833	  while (TRUE) {
11834	        /* Handle any events on any of the ttys. */
11835	        for (tp = FIRST_TTY; tp < END_TTY; tp++) {
11836	                if (tp->tty_events) handle_events(tp);
11837	        }
11838	
11839	        receive(ANY, &tty_mess);
11840	
11841	        /* A hardware interrupt is an invitation to check for events. */
11842	        if (tty_mess.m_type == HARD_INT) continue;
11843	
11844	        /* Check the minor device number. */
11845	        line = tty_mess.TTY_LINE;
11846	        if ((line - CONS_MINOR) < NR_CONS) {
11847	                tp = tty_addr(line - CONS_MINOR);
11848	        } else
11849	        if (line == LOG_MINOR) {
11850	                tp = tty_addr(0);
11851	        } else
11852	        if ((line - RS232_MINOR) < NR_RS_LINES) {
11853	                tp = tty_addr(line - RS232_MINOR + NR_CONS);
11854	        } else
11855	        if ((line - TTYPX_MINOR) < NR_PTYS) {
11856	                tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
11857	        } else
11858	        if ((line - PTYPX_MINOR) < NR_PTYS) {
11859	                tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
11860	                do_pty(tp, &tty_mess);
11861	                continue;                       /* this is a pty, not a tty */
11862	        } else {
11863	                tp = NULL;
11864	        }
11865	
11866	        /* If the device doesn't exist or is not configured return ENXIO. */
11867	        if (tp == NULL || !tty_active(tp)) {
11868	                tty_reply(TASK_REPLY, tty_mess.m_source,
11869	                                                tty_mess.PROC_NR, ENXIO);
11870	                continue;
11871	        }
11872	
11873	        /* Execute the requested function. */
11874	        switch (tty_mess.m_type) {
11875	            case DEV_READ:      do_read(tp, &tty_mess);         break;
11876	            case DEV_WRITE:     do_write(tp, &tty_mess);        break;
11877	            case DEV_IOCTL:     do_ioctl(tp, &tty_mess);        break;
11878	            case DEV_OPEN:      do_open(tp, &tty_mess);         break;
11879	            case DEV_CLOSE:     do_close(tp, &tty_mess);        break;
11880	            case CANCEL:        do_cancel(tp, &tty_mess);       break;
11881	            default:            tty_reply(TASK_REPLY, tty_mess.m_source,
11882	                                                tty_mess.PROC_NR, EINVAL);
11883	        }
11884	  }
11885	}
	
	
11888	/*===========================================================================*
11889	 *                              do_read                                      *
11890	 *===========================================================================*/
11891	PRIVATE void do_read(tp, m_ptr)
11892	register tty_t *tp;             /* pointer to tty struct */
11893	message *m_ptr;                 /* pointer to message sent to the task */
11894	{
11895	/* A process wants to read from a terminal. */
11896	  int r;
11897	
11898	  /* Check if there is already a process hanging in a read, check if the
11899	   * parameters are correct, do I/O.
11900	   */
11901	  if (tp->tty_inleft > 0) {
11902	        r = EIO;
11903	  } else
11904	  if (m_ptr->COUNT <= 0) {
11905	        r = EINVAL;
11906	  } else
11907	  if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
11908	        r = EFAULT;
11909	  } else {
11910	        /* Copy information from the message to the tty struct. */
11911	        tp->tty_inrepcode = TASK_REPLY;
11912	        tp->tty_incaller = m_ptr->m_source;
11913	        tp->tty_inproc = m_ptr->PROC_NR;
11914	        tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
11915	        tp->tty_inleft = m_ptr->COUNT;
11916	
11917	        if (!(tp->tty_termios.c_lflag & ICANON)
11918	                                        && tp->tty_termios.c_cc[VTIME] > 0) {
11919	                if (tp->tty_termios.c_cc[VMIN] == 0) {
11920	                        /* MIN & TIME specify a read timer that finishes the
11921	                         * read in TIME/10 seconds if no bytes are available.
11922	                         */
11923	                        lock();
11924	                        settimer(tp, TRUE);
11925	                        tp->tty_min = 1;
11926	                        unlock();
11927	                } else {
11928	                        /* MIN & TIME specify an inter-byte timer that may
11929	                         * have to be cancelled if there are no bytes yet.
11930	                         */
11931	                        if (tp->tty_eotct == 0) {
11932	                                lock();
11933	                                settimer(tp, FALSE);
11934	                                unlock();
11935	                                tp->tty_min = tp->tty_termios.c_cc[VMIN];
11936	                        }
11937	                }
11938	        }
11939	
11940	        /* Anything waiting in the input buffer? Clear it out... */
11941	        in_transfer(tp);
11942	        /* ...then go back for more */
11943	        handle_events(tp);
11944	        if (tp->tty_inleft == 0) return;                /* already done */
11945	
11946	        /* There were no bytes in the input queue available, so either suspend
11947	         * the caller or break off the read if nonblocking.
11948	         */
11949	        if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
11950	                r = EAGAIN;                             /* cancel the read */
11951	                tp->tty_inleft = tp->tty_incum = 0;
11952	        } else {
11953	                r = SUSPEND;                            /* suspend the caller */
11954	                tp->tty_inrepcode = REVIVE;
11955	        }
11956	  }
11957	  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
11958	}
	
	
11961	/*===========================================================================*
11962	 *                              do_write                                     *
11963	 *===========================================================================*/
11964	PRIVATE void do_write(tp, m_ptr)
11965	register tty_t *tp;
11966	register message *m_ptr;        /* pointer to message sent to the task */
11967	{
11968	/* A process wants to write on a terminal. */
11969	  int r;
11970	
11971	  /* Check if there is already a process hanging in a write, check if the
11972	   * parameters are correct, do I/O.
11973	   */
11974	  if (tp->tty_outleft > 0) {
11975	        r = EIO;
11976	  } else
11977	  if (m_ptr->COUNT <= 0) {
11978	        r = EINVAL;
11979	  } else
11980	  if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
11981	        r = EFAULT;
11982	  } else {
11983	        /* Copy message parameters to the tty structure. */
11984	        tp->tty_outrepcode = TASK_REPLY;
11985	        tp->tty_outcaller = m_ptr->m_source;
11986	        tp->tty_outproc = m_ptr->PROC_NR;
11987	        tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
11988	        tp->tty_outleft = m_ptr->COUNT;
11989	
11990	        /* Try to write. */
11991	        handle_events(tp);
11992	        if (tp->tty_outleft == 0) return;               /* already done */
11993	
11994	        /* None or not all the bytes could be written, so either suspend the
11995	         * caller or break off the write if nonblocking.
11996	         */
11997	        if (m_ptr->TTY_FLAGS & O_NONBLOCK) {            /* cancel the write */
11998	                r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
11999	                tp->tty_outleft = tp->tty_outcum = 0;
12000	        } else {
12001	                r = SUSPEND;                            /* suspend the caller */
12002	                tp->tty_outrepcode = REVIVE;
12003	        }
12004	  }
12005	  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
12006	}
	
	
12009	/*===========================================================================*
12010	 *                              do_ioctl                                     *
12011	 *===========================================================================*/
12012	PRIVATE void do_ioctl(tp, m_ptr)
12013	register tty_t *tp;
12014	message *m_ptr;                 /* pointer to message sent to task */
12015	{
12016	/* Perform an IOCTL on this terminal. Posix termios calls are handled
12017	 * by the IOCTL system call
12018	 */
12019	
12020	  int r;
12021	  union {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -