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

📄 tty.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 4 页
字号:
12022	        int i;
12023	        /* these non-Posix params are not used now, but the union is retained
12024	         * to minimize code differences with backward compatible version
12025	         * struct sgttyb sg;
12026	         * struct tchars tc;
12027	         */
12028	  } param;
12029	  phys_bytes user_phys;
12030	  size_t size;
12031	
12032	  /* Size of the ioctl parameter. */
12033	  switch (m_ptr->TTY_REQUEST) {
12034	    case TCGETS:        /* Posix tcgetattr function */
12035	    case TCSETS:        /* Posix tcsetattr function, TCSANOW option */ 
12036	    case TCSETSW:       /* Posix tcsetattr function, TCSADRAIN option */
12037	    case TCSETSF:       /* Posix tcsetattr function, TCSAFLUSH option */
12038	        size = sizeof(struct termios);
12039	        break;
12040	
12041	    case TCSBRK:        /* Posix tcsendbreak function */
12042	    case TCFLOW:        /* Posix tcflow function */
12043	    case TCFLSH:        /* Posix tcflush function */
12044	    case TIOCGPGRP:     /* Posix tcgetpgrp function */
12045	    case TIOCSPGRP:     /* Posix tcsetpgrp function */
12046	        size = sizeof(int);
12047	        break;
12048	
12049	    case TIOCGWINSZ:    /* get window size (not Posix) */
12050	    case TIOCSWINSZ:    /* set window size (not Posix) */
12051	        size = sizeof(struct winsize);
12052	        break;
12053	
12054	    case KIOCSMAP:      /* load keymap (Minix extension) */
12055	        size = sizeof(keymap_t);
12056	        break;
12057	
12058	    case TIOCSFON:      /* load font (Minix extension) */
12059	        size = sizeof(u8_t [8192]);
12060	        break;
12061	
12062	    case TCDRAIN:       /* Posix tcdrain function -- no parameter */
12063	    default:            size = 0;
12064	  }
12065	
12066	  if (size != 0) {
12067	        user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, size);
12068	        if (user_phys == 0) {
12069	                tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EFAULT);
12070	                return;
12071	        }
12072	  }
12073	
12074	  r = OK;
12075	  switch (m_ptr->TTY_REQUEST) {
12076	    case TCGETS:
12077	        /* Get the termios attributes. */
12078	        phys_copy(vir2phys(&tp->tty_termios), user_phys, (phys_bytes) size);
12079	        break;
12080	
12081	    case TCSETSW:
12082	    case TCSETSF:
12083	    case TCDRAIN:
12084	        if (tp->tty_outleft > 0) {
12085	                /* Wait for all ongoing output processing to finish. */
12086	                tp->tty_iocaller = m_ptr->m_source;
12087	                tp->tty_ioproc = m_ptr->PROC_NR;
12088	                tp->tty_ioreq = m_ptr->REQUEST;
12089	                tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
12090	                r = SUSPEND;
12091	                break;
12092	        }
12093	        if (m_ptr->TTY_REQUEST == TCDRAIN) break;
12094	        if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);
12095	        /*FALL THROUGH*/
12096	    case TCSETS:
12097	        /* Set the termios attributes. */
12098	        phys_copy(user_phys, vir2phys(&tp->tty_termios), (phys_bytes) size);
12099	        setattr(tp);
12100	        break;
12101	
12102	    case TCFLSH:
12103	        phys_copy(user_phys, vir2phys(&param.i), (phys_bytes) size);
12104	        switch (param.i) {
12105	            case TCIFLUSH:      tty_icancel(tp);                        break;
12106	            case TCOFLUSH:      (*tp->tty_ocancel)(tp);                 break;
12107	            case TCIOFLUSH:     tty_icancel(tp); (*tp->tty_ocancel)(tp);break;
12108	            default:            r = EINVAL;
12109	        }
12110	        break;
12111	
12112	    case TCFLOW:
12113	        phys_copy(user_phys, vir2phys(&param.i), (phys_bytes) size);
12114	        switch (param.i) {
12115	            case TCOOFF:
12116	            case TCOON:
12117	                tp->tty_inhibited = (param.i == TCOOFF);
12118	                tp->tty_events = 1;
12119	                break;
12120	            case TCIOFF:
12121	                (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);
12122	                break;
12123	            case TCION:
12124	                (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);
12125	                break;
12126	            default:
12127	                r = EINVAL;
12128	        }
12129	        break;
12130	
12131	    case TCSBRK:
12132	        if (tp->tty_break != NULL) (*tp->tty_break)(tp);
12133	        break;
12134	
12135	    case TIOCGWINSZ:
12136	        phys_copy(vir2phys(&tp->tty_winsize), user_phys, (phys_bytes) size);
12137	        break;
12138	
12139	    case TIOCSWINSZ:
12140	        phys_copy(user_phys, vir2phys(&tp->tty_winsize), (phys_bytes) size);
12141	        /* SIGWINCH... */
12142	        break;
12143	
12144	    case KIOCSMAP:
12145	        /* Load a new keymap (only /dev/console). */
12146	        if (isconsole(tp)) r = kbd_loadmap(user_phys);
12147	        break;
12148	
12149	    case TIOCSFON:
12150	        /* Load a font into an EGA or VGA card (hs@hck.hr) */
12151	        if (isconsole(tp)) r = con_loadfont(user_phys);
12152	        break;
12153	
12154	/* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is 
12155	 * not defined.
12156	 */
12157	    case TIOCGPGRP:     
12158	    case TIOCSPGRP:     
12159	    default:
12160	        r = ENOTTY;
12161	  }
12162	
12163	  /* Send the reply. */
12164	  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
12165	}
	
	
12168	/*===========================================================================*
12169	 *                              do_open                                      *
12170	 *===========================================================================*/
12171	PRIVATE void do_open(tp, m_ptr)
12172	register tty_t *tp;
12173	message *m_ptr;                 /* pointer to message sent to task */
12174	{
12175	/* A tty line has been opened.  Make it the callers controlling tty if
12176	 * O_NOCTTY is *not* set and it is not the log device.  1 is returned if
12177	 * the tty is made the controlling tty, otherwise OK or an error code.
12178	 */
12179	  int r = OK;
12180	
12181	  if (m_ptr->TTY_LINE == LOG_MINOR) {
12182	        /* The log device is a write-only diagnostics device. */
12183	        if (m_ptr->COUNT & R_BIT) r = EACCES;
12184	  } else {
12185	        if (!(m_ptr->COUNT & O_NOCTTY)) {
12186	                tp->tty_pgrp = m_ptr->PROC_NR;
12187	                r = 1;
12188	        }
12189	        tp->tty_openct++;
12190	  }
12191	  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
12192	}
	
	
12195	/*===========================================================================*
12196	 *                              do_close                                     *
12197	 *===========================================================================*/
12198	PRIVATE void do_close(tp, m_ptr)
12199	register tty_t *tp;
12200	message *m_ptr;                 /* pointer to message sent to task */
12201	{
12202	/* A tty line has been closed.  Clean up the line if it is the last close. */
12203	
12204	  if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
12205	        tp->tty_pgrp = 0;
12206	        tty_icancel(tp);
12207	        (*tp->tty_ocancel)(tp);
12208	        (*tp->tty_close)(tp);
12209	        tp->tty_termios = termios_defaults;
12210	        tp->tty_winsize = winsize_defaults;
12211	        setattr(tp);
12212	  }
12213	  tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK);
12214	}
	
	
12217	/*===========================================================================*
12218	 *                              do_cancel                                    *
12219	 *===========================================================================*/
12220	PRIVATE void do_cancel(tp, m_ptr)
12221	register tty_t *tp;
12222	message *m_ptr;                 /* pointer to message sent to task */
12223	{
12224	/* A signal has been sent to a process that is hanging trying to read or write.
12225	 * The pending read or write must be finished off immediately.
12226	 */
12227	
12228	  int proc_nr;
12229	  int mode;
12230	
12231	  /* Check the parameters carefully, to avoid cancelling twice. */
12232	  proc_nr = m_ptr->PROC_NR;
12233	  mode = m_ptr->COUNT;
12234	  if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
12235	        /* Process was reading when killed.  Clean up input. */
12236	        tty_icancel(tp);
12237	        tp->tty_inleft = tp->tty_incum = 0;
12238	  }
12239	  if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
12240	        /* Process was writing when killed.  Clean up output. */
12241	        (*tp->tty_ocancel)(tp);
12242	        tp->tty_outleft = tp->tty_outcum = 0;
12243	  }
12244	  if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
12245	        /* Process was waiting for output to drain. */
12246	        tp->tty_ioreq = 0;
12247	  }
12248	  tp->tty_events = 1;
12249	  tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
12250	}
	
	
12253	/*===========================================================================*
12254	 *                              handle_events                                *
12255	 *===========================================================================*/
12256	PUBLIC void handle_events(tp)
12257	tty_t *tp;                      /* TTY to check for events. */
12258	{
12259	/* Handle any events pending on a TTY.  These events are usually device
12260	 * interrupts.
12261	 *
12262	 * Two kinds of events are prominent:
12263	 *      - a character has been received from the console or an RS232 line.
12264	 *      - an RS232 line has completed a write request (on behalf of a user).
12265	 * The interrupt handler may delay the interrupt message at its discretion
12266	 * to avoid swamping the TTY task.  Messages may be overwritten when the
12267	 * lines are fast or when there are races between different lines, input
12268	 * and output, because MINIX only provides single buffering for interrupt
12269	 * messages (in proc.c).  This is handled by explicitly checking each line
12270	 * for fresh input and completed output on each interrupt.
12271	 */
12272	  char *buf;
12273	  unsigned count;
12274	
12275	  do {
12276	        tp->tty_events = 0;
12277	
12278	        /* Read input and perform input processing. */
12279	        (*tp->tty_devread)(tp);
12280	
12281	        /* Perform output processing and write output. */
12282	        (*tp->tty_devwrite)(tp);
12283	
12284	        /* Ioctl waiting for some event? */
12285	        if (tp->tty_ioreq != 0) dev_ioctl(tp);
12286	  } while (tp->tty_events);
12287	
12288	  /* Transfer characters from the input queue to a waiting process. */
12289	  in_transfer(tp);
12290	
12291	  /* Reply if enough bytes are available. */
12292	  if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
12293	        tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
12294	                                                                tp->tty_incum);
12295	        tp->tty_inleft = tp->tty_incum = 0;
12296	  }
12297	}
	
	
12300	/*===========================================================================*
12301	 *                              in_transfer                                  *
12302	 *===========================================================================*/
12303	PRIVATE void in_transfer(tp)
12304	register tty_t *tp;             /* pointer to terminal to read from */
12305	{
12306	/* Transfer bytes from the input queue to a process reading from a terminal. */
12307	
12308	  int ch;
12309	  int count;
12310	  phys_bytes buf_phys, user_base;
12311	  char buf[64], *bp;
12312	
12313	  /* Anything to do? */
12314	  if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;
12315	
12316	  buf_phys = vir2phys(buf);
12317	  user_base = proc_vir2phys(proc_addr(tp->tty_inproc), 0);
12318	  bp = buf;
12319	  while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {
12320	        ch = *tp->tty_intail;
12321	
12322	        if (!(ch & IN_EOF)) {
12323	                /* One character to be delivered to the user. */
12324	                *bp = ch & IN_CHAR;
12325	                tp->tty_inleft--;
12326	                if (++bp == bufend(buf)) {
12327	                        /* Temp buffer full, copy to user space. */
12328	                        phys_copy(buf_phys, user_base + tp->tty_in_vir,
12329	                                                (phys_bytes) buflen(buf));
12330	                        tp->tty_in_vir += buflen(buf);
12331	                        tp->tty_incum += buflen(buf);
12332	                        bp = buf;
12333	                }
12334	        }
12335	
12336	        /* Remove the character from the input queue. */
12337	        if (++tp->tty_intail == bufend(tp->tty_inbuf))
12338	                tp->tty_intail = tp->tty_inbuf;
12339	        tp->tty_incount--;
12340	        if (ch & IN_EOT) {
12341	                tp->tty_eotct--;
12342	                /* Don't read past a line break in canonical mode. */
12343	                if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;
12344	        }
12345	  }
12346	
12347	  if (bp > buf) {

⌨️ 快捷键说明

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