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

📄 tty.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 4 页
字号:
12674	/*==========================================================================*
12675	 *                              out_process                                 *
12676	 *==========================================================================*/
12677	PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
12678	tty_t *tp;
12679	char *bstart, *bpos, *bend;     /* start/pos/end of circular buffer */
12680	int *icount;                    /* # input chars / input chars used */
12681	int *ocount;                    /* max output chars / output chars used */
12682	{
12683	/* Perform output processing on a circular buffer.  *icount is the number of
12684	 * bytes to process, and the number of bytes actually processed on return.
12685	 * *ocount is the space available on input and the space used on output.
12686	 * (Naturally *icount < *ocount.)  The column position is updated modulo
12687	 * the TAB size, because we really only need it for tabs.
12688	 */
12689	
12690	  int tablen;
12691	  int ict = *icount;
12692	  int oct = *ocount;
12693	  int pos = tp->tty_position;
12694	
12695	  while (ict > 0) {
12696	        switch (*bpos) {
12697	        case '\7':
12698	                break;
12699	        case '\b':
12700	                pos--;
12701	                break;
12702	        case '\r':
12703	                pos = 0;
12704	                break;
12705	        case '\n':
12706	                if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
12707	                                                        == (OPOST|ONLCR)) {
12708	                        /* Map LF to CR+LF if there is space.  Note that the
12709	                         * next character in the buffer is overwritten, so
12710	                         * we stop at this point.
12711	                         */
12712	                        if (oct >= 2) {
12713	                                *bpos = '\r';
12714	                                if (++bpos == bend) bpos = bstart;
12715	                                *bpos = '\n';
12716	                                pos = 0;
12717	                                ict--;
12718	                                oct -= 2;
12719	                        }
12720	                        goto out_done;  /* no space or buffer got changed */
12721	                }
12722	                break;
12723	        case '\t':
12724	                /* Best guess for the tab length. */
12725	                tablen = TAB_SIZE - (pos & TAB_MASK);
12726	
12727	                if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
12728	                                                        == (OPOST|XTABS)) {
12729	                        /* Tabs must be expanded. */
12730	                        if (oct >= tablen) {
12731	                                pos += tablen;
12732	                                ict--;
12733	                                oct -= tablen;
12734	                                do {
12735	                                        *bpos = ' ';
12736	                                        if (++bpos == bend) bpos = bstart;
12737	                                } while (--tablen != 0);
12738	                        }
12739	                        goto out_done;
12740	                }
12741	                /* Tabs are output directly. */
12742	                pos += tablen;
12743	                break;
12744	        default:
12745	                /* Assume any other character prints as one character. */
12746	                pos++;
12747	        }
12748	        if (++bpos == bend) bpos = bstart;
12749	        ict--;
12750	        oct--;
12751	  }
12752	out_done:
12753	  tp->tty_position = pos & TAB_MASK;
12754	
12755	  *icount -= ict;       /* [io]ct are the number of chars not used */
12756	  *ocount -= oct;       /* *[io]count are the number of chars that are used */
12757	}
	
	
12760	/*===========================================================================*
12761	 *                              dev_ioctl                                    *
12762	 *===========================================================================*/
12763	PRIVATE void dev_ioctl(tp)
12764	tty_t *tp;
12765	{
12766	/* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make
12767	 * sure that an attribute change doesn't affect the processing of current
12768	 * output.  Once output finishes the ioctl is executed as in do_ioctl().
12769	 */
12770	  phys_bytes user_phys;
12771	
12772	  if (tp->tty_outleft > 0) return;              /* output not finished */
12773	
12774	  if (tp->tty_ioreq != TCDRAIN) {
12775	        if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
12776	        user_phys = proc_vir2phys(proc_addr(tp->tty_ioproc), tp->tty_iovir);
12777	        phys_copy(user_phys, vir2phys(&tp->tty_termios),
12778	                                        (phys_bytes) sizeof(tp->tty_termios));
12779	        setattr(tp);
12780	  }
12781	  tp->tty_ioreq = 0;
12782	  tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, OK);
12783	}
	
	
12786	/*===========================================================================*
12787	 *                              setattr                                      *
12788	 *===========================================================================*/
12789	PRIVATE void setattr(tp)
12790	tty_t *tp;
12791	{
12792	/* Apply the new line attributes (raw/canonical, line speed, etc.) */
12793	  u16_t *inp;
12794	  int count;
12795	
12796	  if (!(tp->tty_termios.c_lflag & ICANON)) {
12797	        /* Raw mode; put a "line break" on all characters in the input queue.
12798	         * It is undefined what happens to the input queue when ICANON is
12799	         * switched off, a process should use TCSAFLUSH to flush the queue.
12800	         * Keeping the queue to preserve typeahead is the Right Thing, however
12801	         * when a process does use TCSANOW to switch to raw mode.
12802	         */
12803	        count = tp->tty_eotct = tp->tty_incount;
12804	        inp = tp->tty_intail;
12805	        while (count > 0) {
12806	                *inp |= IN_EOT;
12807	                if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
12808	                --count;
12809	        }
12810	  }
12811	
12812	  /* Inspect MIN and TIME. */
12813	  lock();
12814	  settimer(tp, FALSE);
12815	  unlock();
12816	  if (tp->tty_termios.c_lflag & ICANON) {
12817	        /* No MIN & TIME in canonical mode. */
12818	        tp->tty_min = 1;
12819	  } else {
12820	        /* In raw mode MIN is the number of chars wanted, and TIME how long
12821	         * to wait for them.  With interesting exceptions if either is zero.
12822	         */
12823	        tp->tty_min = tp->tty_termios.c_cc[VMIN];
12824	        if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
12825	                tp->tty_min = 1;
12826	  }
12827	
12828	  if (!(tp->tty_termios.c_iflag & IXON)) {
12829	        /* No start/stop output control, so don't leave output inhibited. */
12830	        tp->tty_inhibited = RUNNING;
12831	        tp->tty_events = 1;
12832	  }
12833	
12834	  /* Setting the output speed to zero hangs up the phone. */
12835	  if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
12836	
12837	  /* Set new line speed, character size, etc at the device level. */
12838	  (*tp->tty_ioctl)(tp);
12839	}
	
	
12842	/*===========================================================================*
12843	 *                              tty_reply                                    *
12844	 *===========================================================================*/
12845	PUBLIC void tty_reply(code, replyee, proc_nr, status)
12846	int code;                       /* TASK_REPLY or REVIVE */
12847	int replyee;                    /* destination address for the reply */
12848	int proc_nr;                    /* to whom should the reply go? */
12849	int status;                     /* reply code */
12850	{
12851	/* Send a reply to a process that wanted to read or write data. */
12852	
12853	  message tty_mess;
12854	
12855	  tty_mess.m_type = code;
12856	  tty_mess.REP_PROC_NR = proc_nr;
12857	  tty_mess.REP_STATUS = status;
12858	  if ((status = send(replyee, &tty_mess)) != OK)
12859	        panic("tty_reply failed, status\n", status);
12860	}
	
	
12863	/*===========================================================================*
12864	 *                              sigchar                                      *
12865	 *===========================================================================*/
12866	PUBLIC void sigchar(tp, sig)
12867	register tty_t *tp;
12868	int sig;                        /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
12869	{
12870	/* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from
12871	 * a tty close, "stty 0", or a real RS-232 hangup.  MM will send the signal to
12872	 * the process group (INT, QUIT), all processes (KILL), or the session leader
12873	 * (HUP).
12874	 */
12875	
12876	  if (tp->tty_pgrp != 0) cause_sig(tp->tty_pgrp, sig);
12877	
12878	  if (!(tp->tty_termios.c_lflag & NOFLSH)) {
12879	        tp->tty_incount = tp->tty_eotct = 0;    /* kill earlier input */
12880	        tp->tty_intail = tp->tty_inhead;
12881	        (*tp->tty_ocancel)(tp);                 /* kill all output */
12882	        tp->tty_inhibited = RUNNING;
12883	        tp->tty_events = 1;
12884	  }
12885	}
	
	
12888	/*==========================================================================*
12889	 *                              tty_icancel                                 *
12890	 *==========================================================================*/
12891	PRIVATE void tty_icancel(tp)
12892	register tty_t *tp;
12893	{
12894	/* Discard all pending input, tty buffer or device. */
12895	
12896	  tp->tty_incount = tp->tty_eotct = 0;
12897	  tp->tty_intail = tp->tty_inhead;
12898	  (*tp->tty_icancel)(tp);
12899	}
	
	
12902	/*==========================================================================*
12903	 *                              tty_init                                    *
12904	 *==========================================================================*/
12905	PRIVATE void tty_init(tp)
12906	tty_t *tp;                      /* TTY line to initialize. */
12907	{
12908	/* Initialize tty structure and call device initialization routines. */
12909	
12910	  tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
12911	  tp->tty_min = 1;
12912	  tp->tty_termios = termios_defaults;
12913	  tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
12914	                                                                tty_devnop;
12915	  if (tp < tty_addr(NR_CONS)) {
12916	        scr_init(tp);
12917	  } else
12918	  if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
12919	        rs_init(tp);
12920	  } else {
12921	        pty_init(tp);
12922	  }
12923	}
	
	
12926	/*==========================================================================*
12927	 *                              tty_wakeup                                  *
12928	 *==========================================================================*/
12929	PUBLIC void tty_wakeup(now)
12930	clock_t now;                            /* current time */
12931	{
12932	/* Wake up TTY when something interesting is happening on one of the terminal
12933	 * lines, like a character arriving on an RS232 line, a key being typed, or
12934	 * a timer on a line expiring by TIME.
12935	 */
12936	  tty_t *tp;
12937	
12938	  /* Scan the timerlist for expired timers and compute the next timeout time. */
12939	  tty_timeout = TIME_NEVER;
12940	  while ((tp = tty_timelist) != NULL) {
12941	        if (tp->tty_time > now) {
12942	                tty_timeout = tp->tty_time;     /* this timer is next */
12943	                break;
12944	        }
12945	        tp->tty_min = 0;                        /* force read to succeed */
12946	        tp->tty_events = 1;
12947	        tty_timelist = tp->tty_timenext;
12948	  }
12949	
12950	  /* Let TTY know there is something afoot. */
12951	  interrupt(TTY);
12952	}
	
	
12955	/*===========================================================================*
12956	 *                              settimer                                     *
12957	 *===========================================================================*/
12958	PRIVATE void settimer(tp, on)
12959	tty_t *tp;                      /* line to set or unset a timer on */
12960	int on;                         /* set timer if true, otherwise unset */
12961	{
12962	/* Set or unset a TIME inspired timer.  This function is interrupt sensitive
12963	 * due to tty_wakeup(), so it must be called from within lock()/unlock().
12964	 */
12965	  tty_t **ptp;
12966	
12967	  /* Take tp out of the timerlist if present. */
12968	  for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
12969	        if (tp == *ptp) {
12970	                *ptp = tp->tty_timenext;        /* take tp out of the list */
12971	                break;
12972	        }
12973	  }
12974	  if (!on) return;                              /* unsetting it is enough */
12975	
12976	  /* Timeout occurs TIME deciseconds from now. */
12977	  tp->tty_time = get_uptime() + tp->tty_termios.c_cc[VTIME] * (HZ/10);
12978	
12979	  /* Find a new place in the list. */
12980	  for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
12981	        if (tp->tty_time <= (*ptp)->tty_time) break;
12982	  }
12983	  tp->tty_timenext = *ptp;
12984	  *ptp = tp;
12985	  if (tp->tty_time < tty_timeout) tty_timeout = tp->tty_time;
12986	}
	
	
12989	/*==========================================================================*
12990	 *                              tty_devnop                                  *
12991	 *==========================================================================*/
12992	PUBLIC void tty_devnop(tp)
12993	tty_t *tp;
12994	{
12995	  /* Some functions need not be implemented at the device level. */
12996	}

⌨️ 快捷键说明

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