Ignore machine-check MSRs
[freebsd-src/fkvm-freebsd.git] / sys / kern / tty.c
blobbb0fb02c99f0737d37a6e694d68492841281df2f
1 /*-
2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
5 * Portions of this software were developed under sponsorship from Snow
6 * B.V., the Netherlands.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include "opt_compat.h"
35 #include <sys/param.h>
36 #include <sys/conf.h>
37 #include <sys/cons.h>
38 #include <sys/fcntl.h>
39 #include <sys/filio.h>
40 #ifdef COMPAT_43TTY
41 #include <sys/ioctl_compat.h>
42 #endif /* COMPAT_43TTY */
43 #include <sys/kernel.h>
44 #include <sys/limits.h>
45 #include <sys/malloc.h>
46 #include <sys/mount.h>
47 #include <sys/poll.h>
48 #include <sys/priv.h>
49 #include <sys/proc.h>
50 #include <sys/serial.h>
51 #include <sys/signal.h>
52 #include <sys/stat.h>
53 #include <sys/sx.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 #include <sys/tty.h>
57 #include <sys/ttycom.h>
58 #define TTYDEFCHARS
59 #include <sys/ttydefaults.h>
60 #undef TTYDEFCHARS
61 #include <sys/ucred.h>
63 #include <machine/stdarg.h>
65 static MALLOC_DEFINE(M_TTY, "tty", "tty device");
67 static void tty_rel_free(struct tty *tp);
69 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
70 static struct sx tty_list_sx;
71 SX_SYSINIT(tty_list, &tty_list_sx, "tty list");
72 static unsigned int tty_list_count = 0;
75 * Flags that are supported and stored by this implementation.
77 #define TTYSUP_IFLAG (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|\
78 INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL)
79 #define TTYSUP_OFLAG (OPOST|ONLCR|TAB3|ONOEOT|OCRNL|ONOCR|ONLRET)
80 #define TTYSUP_LFLAG (ECHOKE|ECHOE|ECHOK|ECHO|ECHONL|ECHOPRT|\
81 ECHOCTL|ISIG|ICANON|ALTWERASE|IEXTEN|TOSTOP|\
82 FLUSHO|NOKERNINFO|NOFLSH)
83 #define TTYSUP_CFLAG (CIGNORE|CSIZE|CSTOPB|CREAD|PARENB|PARODD|\
84 HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\
85 CDSR_OFLOW|CCAR_OFLOW)
87 #define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d))
90 * Set TTY buffer sizes.
93 static void
94 tty_watermarks(struct tty *tp)
96 speed_t sp;
98 /* Provide an input buffer for 0.2 seconds of data. */
99 sp = MAX(tp->t_termios.c_ispeed, 0);
100 ttyinq_setsize(&tp->t_inq, tp, sp / 5);
102 /* Set low watermark at 10% (when 90% is available). */
103 tp->t_inlow = (ttyinq_getsize(&tp->t_inq) * 9) / 10;
105 /* Provide an ouput buffer for 0.2 seconds of data. */
106 sp = MAX(tp->t_termios.c_ospeed, 0);
107 ttyoutq_setsize(&tp->t_outq, tp, sp / 5);
109 /* Set low watermark at 10% (when 90% is available). */
110 tp->t_outlow = (ttyoutq_getsize(&tp->t_outq) * 9) / 10;
113 static int
114 tty_drain(struct tty *tp)
116 int error;
118 while (ttyoutq_bytesused(&tp->t_outq) > 0) {
119 ttydevsw_outwakeup(tp);
120 /* Could be handled synchronously. */
121 if (ttyoutq_bytesused(&tp->t_outq) == 0)
122 return (0);
124 /* Wait for data to be drained. */
125 error = tty_wait(tp, &tp->t_outwait);
126 if (error)
127 return (error);
130 return (0);
134 * Because the revoke() call already calls d_close() without making sure
135 * all threads are purged from the TTY, we can only destroy the buffers
136 * and such when the last thread leaves the TTY. ttydev_enter() and
137 * ttydev_leave() are called from within the cdev functions, to make
138 * sure we can garbage collect the TTY.
141 static __inline int
142 ttydev_enter(struct tty *tp)
144 tty_lock(tp);
146 if (tty_gone(tp) || !tty_opened(tp)) {
147 /* Device is already gone. */
148 tty_unlock(tp);
149 return (ENXIO);
152 return (0);
155 static void
156 ttydev_leave(struct tty *tp)
158 tty_lock_assert(tp, MA_OWNED);
160 if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
161 /* Device is still opened somewhere. */
162 tty_unlock(tp);
163 return;
166 tp->t_flags |= TF_OPENCLOSE;
168 /* Stop asynchronous I/O. */
169 funsetown(&tp->t_sigio);
171 /* Remove console TTY. */
172 if (constty == tp)
173 constty_clear();
175 /* Drain any output. */
176 MPASS((tp->t_flags & TF_STOPPED) == 0);
177 if (!tty_gone(tp))
178 tty_drain(tp);
180 ttydisc_close(tp);
182 /* Destroy associated buffers already. */
183 ttyinq_free(&tp->t_inq);
184 tp->t_inlow = 0;
185 ttyoutq_free(&tp->t_outq);
186 tp->t_outlow = 0;
188 knlist_clear(&tp->t_inpoll.si_note, 1);
189 knlist_clear(&tp->t_outpoll.si_note, 1);
191 if (!tty_gone(tp))
192 ttydevsw_close(tp);
194 tp->t_flags &= ~TF_OPENCLOSE;
195 tty_rel_free(tp);
199 * Operations that are exposed through the character device in /dev.
201 static int
202 ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
204 struct tty *tp = dev->si_drv1;
205 int error;
207 /* Disallow access when the TTY belongs to a different prison. */
208 if (dev->si_cred != NULL &&
209 dev->si_cred->cr_prison != td->td_ucred->cr_prison &&
210 priv_check(td, PRIV_TTY_PRISON)) {
211 return (EPERM);
214 tty_lock(tp);
215 if (tty_gone(tp)) {
216 /* Device is already gone. */
217 tty_unlock(tp);
218 return (ENXIO);
221 * Prevent the TTY from being opened when being torn down or
222 * built up by unrelated processes.
224 if (tp->t_flags & TF_OPENCLOSE) {
225 tty_unlock(tp);
226 return (EBUSY);
228 tp->t_flags |= TF_OPENCLOSE;
231 * Make sure the "tty" and "cua" device cannot be opened at the
232 * same time.
234 if (TTY_CALLOUT(tp, dev)) {
235 if (tp->t_flags & TF_OPENED_IN) {
236 error = EBUSY;
237 goto done;
239 } else {
240 if (tp->t_flags & TF_OPENED_OUT) {
241 error = EBUSY;
242 goto done;
246 if (tp->t_flags & TF_EXCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) {
247 error = EBUSY;
248 goto done;
251 if (!tty_opened(tp)) {
252 /* Set proper termios flags. */
253 if (TTY_CALLOUT(tp, dev)) {
254 tp->t_termios = tp->t_termios_init_out;
255 } else {
256 tp->t_termios = tp->t_termios_init_in;
258 ttydevsw_param(tp, &tp->t_termios);
260 ttydevsw_modem(tp, SER_DTR|SER_RTS, 0);
262 error = ttydevsw_open(tp);
263 if (error != 0)
264 goto done;
266 ttydisc_open(tp);
267 tty_watermarks(tp);
270 /* Wait for Carrier Detect. */
271 if (!TTY_CALLOUT(tp, dev) && (oflags & O_NONBLOCK) == 0 &&
272 (tp->t_termios.c_cflag & CLOCAL) == 0) {
273 while ((ttydevsw_modem(tp, 0, 0) & SER_DCD) == 0) {
274 error = tty_wait(tp, &tp->t_dcdwait);
275 if (error != 0)
276 goto done;
280 if (TTY_CALLOUT(tp, dev)) {
281 tp->t_flags |= TF_OPENED_OUT;
282 } else {
283 tp->t_flags |= TF_OPENED_IN;
286 done: tp->t_flags &= ~TF_OPENCLOSE;
287 ttydev_leave(tp);
288 return (error);
291 static int
292 ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
294 struct tty *tp = dev->si_drv1;
296 tty_lock(tp);
299 * This can only be called once. The callin and the callout
300 * devices cannot be opened at the same time.
302 MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
303 tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED);
305 /* Properly wake up threads that are stuck - revoke(). */
306 tp->t_revokecnt++;
307 tty_wakeup(tp, FREAD|FWRITE);
308 cv_broadcast(&tp->t_bgwait);
310 ttydev_leave(tp);
312 return (0);
315 static __inline int
316 tty_is_ctty(struct tty *tp, struct proc *p)
318 tty_lock_assert(tp, MA_OWNED);
320 return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
323 static int
324 tty_wait_background(struct tty *tp, struct thread *td, int sig)
326 struct proc *p = td->td_proc;
327 struct pgrp *pg;
328 int error;
330 MPASS(sig == SIGTTIN || sig == SIGTTOU);
331 tty_lock_assert(tp, MA_OWNED);
333 for (;;) {
334 PROC_LOCK(p);
336 * The process should only sleep, when:
337 * - This terminal is the controling terminal
338 * - Its process group is not the foreground process
339 * group
340 * - The parent process isn't waiting for the child to
341 * exit
342 * - the signal to send to the process isn't masked
344 if (!tty_is_ctty(tp, p) ||
345 p->p_pgrp == tp->t_pgrp || p->p_flag & P_PPWAIT ||
346 SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) ||
347 SIGISMEMBER(td->td_sigmask, sig)) {
348 /* Allow the action to happen. */
349 PROC_UNLOCK(p);
350 return (0);
354 * Send the signal and sleep until we're the new
355 * foreground process group.
357 pg = p->p_pgrp;
358 PROC_UNLOCK(p);
359 if (pg->pg_jobc == 0)
360 return (EIO);
361 PGRP_LOCK(pg);
362 pgsignal(pg, sig, 1);
363 PGRP_UNLOCK(pg);
365 error = tty_wait(tp, &tp->t_bgwait);
366 if (error)
367 return (error);
371 static int
372 ttydev_read(struct cdev *dev, struct uio *uio, int ioflag)
374 struct tty *tp = dev->si_drv1;
375 int error;
377 error = ttydev_enter(tp);
378 if (error)
379 return (0);
381 error = tty_wait_background(tp, curthread, SIGTTIN);
382 if (error)
383 goto done;
385 error = ttydisc_read(tp, uio, ioflag);
386 done: ttydev_leave(tp);
389 * The read() and write() calls should not throw an error when
390 * the device is ripped offline.
392 if (error == ENXIO)
393 return (0);
395 return (error);
398 static int
399 ttydev_write(struct cdev *dev, struct uio *uio, int ioflag)
401 struct tty *tp = dev->si_drv1;
402 int error;
404 error = ttydev_enter(tp);
405 if (error)
406 return (0);
408 if (tp->t_termios.c_lflag & TOSTOP) {
409 error = tty_wait_background(tp, curthread, SIGTTOU);
410 if (error)
411 goto done;
414 error = ttydisc_write(tp, uio, ioflag);
415 done: ttydev_leave(tp);
418 * The read() and write() calls should not throw an error when
419 * the device is ripped offline.
421 if (error == ENXIO)
422 return (0);
424 return (error);
427 static int
428 ttydev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
429 struct thread *td)
431 struct tty *tp = dev->si_drv1;
432 int error;
434 error = ttydev_enter(tp);
435 if (error)
436 return (error);
438 switch (cmd) {
439 case TIOCCBRK:
440 case TIOCCONS:
441 case TIOCDRAIN:
442 case TIOCEXCL:
443 case TIOCFLUSH:
444 case TIOCNXCL:
445 case TIOCSBRK:
446 case TIOCSCTTY:
447 case TIOCSETA:
448 case TIOCSETAF:
449 case TIOCSETAW:
450 case TIOCSPGRP:
451 case TIOCSTART:
452 case TIOCSTAT:
453 case TIOCSTOP:
454 case TIOCSWINSZ:
455 #if 0
456 case TIOCSDRAINWAIT:
457 case TIOCSETD:
458 case TIOCSTI:
459 #endif
460 #ifdef COMPAT_43TTY
461 case TIOCLBIC:
462 case TIOCLBIS:
463 case TIOCLSET:
464 case TIOCSETC:
465 case OTIOCSETD:
466 case TIOCSETN:
467 case TIOCSETP:
468 case TIOCSLTC:
469 #endif /* COMPAT_43TTY */
471 * If the ioctl() causes the TTY to be modified, let it
472 * wait in the background.
474 error = tty_wait_background(tp, curthread, SIGTTOU);
475 if (error)
476 goto done;
479 error = tty_ioctl(tp, cmd, data, td);
480 done: ttydev_leave(tp);
482 return (error);
485 static int
486 ttydev_poll(struct cdev *dev, int events, struct thread *td)
488 struct tty *tp = dev->si_drv1;
489 int error, revents = 0;
491 error = ttydev_enter(tp);
492 if (error) {
493 /* Don't return the error here, but the event mask. */
494 return (events &
495 (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
498 if (events & (POLLIN|POLLRDNORM)) {
499 /* See if we can read something. */
500 if (ttydisc_read_poll(tp) > 0)
501 revents |= events & (POLLIN|POLLRDNORM);
503 if (events & (POLLOUT|POLLWRNORM)) {
504 /* See if we can write something. */
505 if (ttydisc_write_poll(tp) > 0)
506 revents |= events & (POLLOUT|POLLWRNORM);
508 if (tp->t_flags & TF_ZOMBIE)
509 /* Hangup flag on zombie state. */
510 revents |= events & POLLHUP;
512 if (revents == 0) {
513 if (events & (POLLIN|POLLRDNORM))
514 selrecord(td, &tp->t_inpoll);
515 if (events & (POLLOUT|POLLWRNORM))
516 selrecord(td, &tp->t_outpoll);
519 ttydev_leave(tp);
521 return (revents);
524 static int
525 ttydev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
527 struct tty *tp = dev->si_drv1;
528 int error;
530 /* Handle mmap() through the driver. */
532 error = ttydev_enter(tp);
533 if (error)
534 return (-1);
535 error = ttydevsw_mmap(tp, offset, paddr, nprot);
536 ttydev_leave(tp);
538 return (error);
542 * kqueue support.
545 static void
546 tty_kqops_read_detach(struct knote *kn)
548 struct tty *tp = kn->kn_hook;
550 knlist_remove(&tp->t_inpoll.si_note, kn, 0);
553 static int
554 tty_kqops_read_event(struct knote *kn, long hint)
556 struct tty *tp = kn->kn_hook;
558 tty_lock_assert(tp, MA_OWNED);
560 if (tty_gone(tp) || tp->t_flags & TF_ZOMBIE) {
561 kn->kn_flags |= EV_EOF;
562 return (1);
563 } else {
564 kn->kn_data = ttydisc_read_poll(tp);
565 return (kn->kn_data > 0);
569 static void
570 tty_kqops_write_detach(struct knote *kn)
572 struct tty *tp = kn->kn_hook;
574 knlist_remove(&tp->t_outpoll.si_note, kn, 0);
577 static int
578 tty_kqops_write_event(struct knote *kn, long hint)
580 struct tty *tp = kn->kn_hook;
582 tty_lock_assert(tp, MA_OWNED);
584 if (tty_gone(tp)) {
585 kn->kn_flags |= EV_EOF;
586 return (1);
587 } else {
588 kn->kn_data = ttydisc_write_poll(tp);
589 return (kn->kn_data > 0);
593 static struct filterops tty_kqops_read =
594 { 1, NULL, tty_kqops_read_detach, tty_kqops_read_event };
595 static struct filterops tty_kqops_write =
596 { 1, NULL, tty_kqops_write_detach, tty_kqops_write_event };
598 static int
599 ttydev_kqfilter(struct cdev *dev, struct knote *kn)
601 struct tty *tp = dev->si_drv1;
602 int error;
604 error = ttydev_enter(tp);
605 if (error)
606 return (error);
608 switch (kn->kn_filter) {
609 case EVFILT_READ:
610 kn->kn_hook = tp;
611 kn->kn_fop = &tty_kqops_read;
612 knlist_add(&tp->t_inpoll.si_note, kn, 1);
613 break;
614 case EVFILT_WRITE:
615 kn->kn_hook = tp;
616 kn->kn_fop = &tty_kqops_write;
617 knlist_add(&tp->t_outpoll.si_note, kn, 1);
618 break;
619 default:
620 error = EINVAL;
621 break;
624 ttydev_leave(tp);
625 return (error);
628 static struct cdevsw ttydev_cdevsw = {
629 .d_version = D_VERSION,
630 .d_open = ttydev_open,
631 .d_close = ttydev_close,
632 .d_read = ttydev_read,
633 .d_write = ttydev_write,
634 .d_ioctl = ttydev_ioctl,
635 .d_kqfilter = ttydev_kqfilter,
636 .d_poll = ttydev_poll,
637 .d_mmap = ttydev_mmap,
638 .d_name = "ttydev",
639 .d_flags = D_TTY,
643 * Init/lock-state devices
646 static int
647 ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
649 struct tty *tp = dev->si_drv1;
650 int error = 0;
652 tty_lock(tp);
653 if (tty_gone(tp))
654 error = ENODEV;
655 tty_unlock(tp);
657 return (error);
660 static int
661 ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td)
663 return (0);
666 static int
667 ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
669 return (ENODEV);
672 static int
673 ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
674 struct thread *td)
676 struct tty *tp = dev->si_drv1;
677 int error = 0;
679 tty_lock(tp);
680 if (tty_gone(tp)) {
681 error = ENODEV;
682 goto done;
685 switch (cmd) {
686 case TIOCGETA:
687 /* Obtain terminal flags through tcgetattr(). */
688 bcopy(dev->si_drv2, data, sizeof(struct termios));
689 break;
690 case TIOCSETA:
691 /* Set terminal flags through tcsetattr(). */
692 error = priv_check(td, PRIV_TTY_SETA);
693 if (error)
694 break;
695 bcopy(data, dev->si_drv2, sizeof(struct termios));
696 break;
697 case TIOCGETD:
698 *(int *)data = TTYDISC;
699 break;
700 case TIOCGWINSZ:
701 bzero(data, sizeof(struct winsize));
702 break;
703 default:
704 error = ENOTTY;
707 done: tty_unlock(tp);
708 return (error);
711 static struct cdevsw ttyil_cdevsw = {
712 .d_version = D_VERSION,
713 .d_open = ttyil_open,
714 .d_close = ttyil_close,
715 .d_read = ttyil_rdwr,
716 .d_write = ttyil_rdwr,
717 .d_ioctl = ttyil_ioctl,
718 .d_name = "ttyil",
719 .d_flags = D_TTY,
722 static void
723 tty_init_termios(struct tty *tp)
725 struct termios *t = &tp->t_termios_init_in;
727 t->c_cflag = TTYDEF_CFLAG;
728 t->c_iflag = TTYDEF_IFLAG;
729 t->c_lflag = TTYDEF_LFLAG;
730 t->c_oflag = TTYDEF_OFLAG;
731 t->c_ispeed = TTYDEF_SPEED;
732 t->c_ospeed = TTYDEF_SPEED;
733 bcopy(ttydefchars, &t->c_cc, sizeof ttydefchars);
735 tp->t_termios_init_out = *t;
738 void
739 tty_init_console(struct tty *tp, speed_t s)
741 struct termios *ti = &tp->t_termios_init_in;
742 struct termios *to = &tp->t_termios_init_out;
744 if (s != 0) {
745 ti->c_ispeed = ti->c_ospeed = s;
746 to->c_ispeed = to->c_ospeed = s;
749 ti->c_cflag |= CLOCAL;
750 to->c_cflag |= CLOCAL;
754 * Standard device routine implementations, mostly meant for
755 * pseudo-terminal device drivers. When a driver creates a new terminal
756 * device class, missing routines are patched.
759 static int
760 ttydevsw_defopen(struct tty *tp)
763 return (0);
766 static void
767 ttydevsw_defclose(struct tty *tp)
771 static void
772 ttydevsw_defoutwakeup(struct tty *tp)
775 panic("Terminal device has output, while not implemented");
778 static void
779 ttydevsw_definwakeup(struct tty *tp)
783 static int
784 ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
787 return (ENOIOCTL);
790 static int
791 ttydevsw_defparam(struct tty *tp, struct termios *t)
794 /* Use a fake baud rate, we're not a real device. */
795 t->c_ispeed = t->c_ospeed = TTYDEF_SPEED_PSEUDO;
797 return (0);
800 static int
801 ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
804 /* Simulate a carrier to make the TTY layer happy. */
805 return (SER_DCD);
808 static int
809 ttydevsw_defmmap(struct tty *tp, vm_offset_t offset, vm_paddr_t *paddr,
810 int nprot)
813 return (-1);
816 static void
817 ttydevsw_defpktnotify(struct tty *tp, char event)
821 static void
822 ttydevsw_deffree(void *softc)
825 panic("Terminal device freed without a free-handler");
829 * TTY allocation and deallocation. TTY devices can be deallocated when
830 * the driver doesn't use it anymore, when the TTY isn't a session's
831 * controlling TTY and when the device node isn't opened through devfs.
834 struct tty *
835 tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
837 struct tty *tp;
839 /* Make sure the driver defines all routines. */
840 #define PATCH_FUNC(x) do { \
841 if (tsw->tsw_ ## x == NULL) \
842 tsw->tsw_ ## x = ttydevsw_def ## x; \
843 } while (0)
844 PATCH_FUNC(open);
845 PATCH_FUNC(close);
846 PATCH_FUNC(outwakeup);
847 PATCH_FUNC(inwakeup);
848 PATCH_FUNC(ioctl);
849 PATCH_FUNC(param);
850 PATCH_FUNC(modem);
851 PATCH_FUNC(mmap);
852 PATCH_FUNC(pktnotify);
853 PATCH_FUNC(free);
854 #undef PATCH_FUNC
856 tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
857 tp->t_devsw = tsw;
858 tp->t_softc = sc;
859 tp->t_flags = tsw->tsw_flags;
861 tty_init_termios(tp);
863 cv_init(&tp->t_inwait, "tty input");
864 cv_init(&tp->t_outwait, "tty output");
865 cv_init(&tp->t_bgwait, "tty background");
866 cv_init(&tp->t_dcdwait, "tty dcd");
868 ttyinq_init(&tp->t_inq);
869 ttyoutq_init(&tp->t_outq);
871 /* Allow drivers to use a custom mutex to lock the TTY. */
872 if (mutex != NULL) {
873 tp->t_mtx = mutex;
874 } else {
875 tp->t_mtx = &tp->t_mtxobj;
876 mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
879 knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
880 knlist_init(&tp->t_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
882 sx_xlock(&tty_list_sx);
883 TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
884 tty_list_count++;
885 sx_xunlock(&tty_list_sx);
887 return (tp);
890 static void
891 tty_dealloc(void *arg)
893 struct tty *tp = arg;
895 sx_xlock(&tty_list_sx);
896 TAILQ_REMOVE(&tty_list, tp, t_list);
897 tty_list_count--;
898 sx_xunlock(&tty_list_sx);
900 /* Make sure we haven't leaked buffers. */
901 MPASS(ttyinq_getsize(&tp->t_inq) == 0);
902 MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
904 knlist_destroy(&tp->t_inpoll.si_note);
905 knlist_destroy(&tp->t_outpoll.si_note);
907 cv_destroy(&tp->t_inwait);
908 cv_destroy(&tp->t_outwait);
909 cv_destroy(&tp->t_bgwait);
910 cv_destroy(&tp->t_dcdwait);
912 if (tp->t_mtx == &tp->t_mtxobj)
913 mtx_destroy(&tp->t_mtxobj);
914 ttydevsw_free(tp);
915 free(tp, M_TTY);
918 static void
919 tty_rel_free(struct tty *tp)
921 struct cdev *dev;
923 tty_lock_assert(tp, MA_OWNED);
925 if (tp->t_sessioncnt != 0 ||
926 (tp->t_flags & (TF_GONE|TF_OPENED)) != TF_GONE) {
927 /* TTY is still in use. */
928 tty_unlock(tp);
929 return;
932 /* TTY can be deallocated. */
933 dev = tp->t_dev;
934 tp->t_dev = NULL;
935 tty_unlock(tp);
937 destroy_dev_sched_cb(dev, tty_dealloc, tp);
940 void
941 tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
943 tty_lock_assert(tp, MA_OWNED);
945 if (tp->t_pgrp == pg)
946 tp->t_pgrp = NULL;
949 void
950 tty_rel_sess(struct tty *tp, struct session *sess)
952 MPASS(tp->t_sessioncnt > 0);
954 /* Current session has left. */
955 if (tp->t_session == sess) {
956 tp->t_session = NULL;
957 MPASS(tp->t_pgrp == NULL);
959 tp->t_sessioncnt--;
960 tty_rel_free(tp);
963 void
964 tty_rel_gone(struct tty *tp)
966 MPASS(!tty_gone(tp));
968 /* Simulate carrier removal. */
969 ttydisc_modem(tp, 0);
971 /* Wake up misc. blocked threads. */
972 cv_broadcast(&tp->t_bgwait);
973 cv_broadcast(&tp->t_dcdwait);
975 tp->t_flags |= TF_GONE;
976 tty_rel_free(tp);
980 * Exposing information about current TTY's through sysctl
983 static void
984 tty_to_xtty(struct tty *tp, struct xtty *xt)
986 tty_lock_assert(tp, MA_OWNED);
988 xt->xt_size = sizeof(struct xtty);
989 xt->xt_insize = ttyinq_getsize(&tp->t_inq);
990 xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq);
991 xt->xt_inlc = ttyinq_bytesline(&tp->t_inq);
992 xt->xt_inlow = tp->t_inlow;
993 xt->xt_outsize = ttyoutq_getsize(&tp->t_outq);
994 xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq);
995 xt->xt_outlow = tp->t_outlow;
996 xt->xt_column = tp->t_column;
997 xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
998 xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
999 xt->xt_flags = tp->t_flags;
1000 xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
1003 static int
1004 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
1006 unsigned long lsize;
1007 struct xtty *xtlist, *xt;
1008 struct tty *tp;
1009 int error;
1011 sx_slock(&tty_list_sx);
1012 lsize = tty_list_count * sizeof(struct xtty);
1013 if (lsize == 0) {
1014 sx_sunlock(&tty_list_sx);
1015 return (0);
1018 xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK);
1020 TAILQ_FOREACH(tp, &tty_list, t_list) {
1021 tty_lock(tp);
1022 tty_to_xtty(tp, xt);
1023 tty_unlock(tp);
1024 xt++;
1026 sx_sunlock(&tty_list_sx);
1028 error = SYSCTL_OUT(req, xtlist, lsize);
1029 free(xtlist, M_TEMP);
1030 return (error);
1033 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
1034 0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs");
1037 * Device node creation. Device has been set up, now we can expose it to
1038 * the user.
1041 void
1042 tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
1044 va_list ap;
1045 struct cdev *dev;
1046 const char *prefix = "tty";
1047 char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
1048 uid_t uid;
1049 gid_t gid;
1050 mode_t mode;
1052 /* Remove "tty" prefix from devices like PTY's. */
1053 if (tp->t_flags & TF_NOPREFIX)
1054 prefix = "";
1056 va_start(ap, fmt);
1057 vsnrprintf(name, sizeof name, 32, fmt, ap);
1058 va_end(ap);
1060 if (cred == NULL) {
1061 /* System device. */
1062 uid = UID_ROOT;
1063 gid = GID_WHEEL;
1064 mode = S_IRUSR|S_IWUSR;
1065 } else {
1066 /* User device. */
1067 uid = cred->cr_ruid;
1068 gid = GID_TTY;
1069 mode = S_IRUSR|S_IWUSR|S_IWGRP;
1072 /* Master call-in device. */
1073 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1074 uid, gid, mode, "%s%s", prefix, name);
1075 dev->si_drv1 = tp;
1076 tp->t_dev = dev;
1078 /* Slave call-in devices. */
1079 if (tp->t_flags & TF_INITLOCK) {
1080 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1081 uid, gid, mode, "%s%s.init", prefix, name);
1082 dev_depends(tp->t_dev, dev);
1083 dev->si_drv1 = tp;
1084 dev->si_drv2 = &tp->t_termios_init_in;
1086 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1087 uid, gid, mode, "%s%s.lock", prefix, name);
1088 dev_depends(tp->t_dev, dev);
1089 dev->si_drv1 = tp;
1090 dev->si_drv2 = &tp->t_termios_lock_in;
1093 /* Call-out devices. */
1094 if (tp->t_flags & TF_CALLOUT) {
1095 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1096 UID_UUCP, GID_DIALER, 0660, "cua%s", name);
1097 dev_depends(tp->t_dev, dev);
1098 dev->si_drv1 = tp;
1100 /* Slave call-out devices. */
1101 if (tp->t_flags & TF_INITLOCK) {
1102 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1103 UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
1104 dev_depends(tp->t_dev, dev);
1105 dev->si_drv1 = tp;
1106 dev->si_drv2 = &tp->t_termios_init_out;
1108 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1109 UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
1110 dev_depends(tp->t_dev, dev);
1111 dev->si_drv1 = tp;
1112 dev->si_drv2 = &tp->t_termios_lock_out;
1118 * Signalling processes.
1121 void
1122 tty_signal_sessleader(struct tty *tp, int sig)
1124 struct proc *p;
1126 tty_lock_assert(tp, MA_OWNED);
1127 MPASS(sig >= 1 && sig < NSIG);
1129 /* Make signals start output again. */
1130 tp->t_flags &= ~TF_STOPPED;
1132 if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
1133 p = tp->t_session->s_leader;
1134 PROC_LOCK(p);
1135 psignal(p, sig);
1136 PROC_UNLOCK(p);
1140 void
1141 tty_signal_pgrp(struct tty *tp, int sig)
1143 tty_lock_assert(tp, MA_OWNED);
1144 MPASS(sig >= 1 && sig < NSIG);
1146 /* Make signals start output again. */
1147 tp->t_flags &= ~TF_STOPPED;
1149 if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
1150 tty_info(tp);
1151 if (tp->t_pgrp != NULL) {
1152 PGRP_LOCK(tp->t_pgrp);
1153 pgsignal(tp->t_pgrp, sig, 1);
1154 PGRP_UNLOCK(tp->t_pgrp);
1158 void
1159 tty_wakeup(struct tty *tp, int flags)
1161 if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
1162 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
1164 if (flags & FWRITE) {
1165 cv_broadcast(&tp->t_outwait);
1166 selwakeup(&tp->t_outpoll);
1167 KNOTE_LOCKED(&tp->t_outpoll.si_note, 0);
1169 if (flags & FREAD) {
1170 cv_broadcast(&tp->t_inwait);
1171 selwakeup(&tp->t_inpoll);
1172 KNOTE_LOCKED(&tp->t_inpoll.si_note, 0);
1177 tty_wait(struct tty *tp, struct cv *cv)
1179 int error;
1180 int revokecnt = tp->t_revokecnt;
1182 #if 0
1183 /* XXX: /dev/console also picks up Giant. */
1184 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1185 #endif
1186 tty_lock_assert(tp, MA_OWNED);
1188 error = cv_wait_sig(cv, tp->t_mtx);
1190 /* Restart the system call when we may have been revoked. */
1191 if (tp->t_revokecnt != revokecnt)
1192 return (ERESTART);
1194 /* Bail out when the device slipped away. */
1195 if (tty_gone(tp))
1196 return (ENXIO);
1198 return (error);
1202 tty_timedwait(struct tty *tp, struct cv *cv, int hz)
1204 int error;
1205 int revokecnt = tp->t_revokecnt;
1207 #if 0
1208 /* XXX: /dev/console also picks up Giant. */
1209 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1210 #endif
1211 tty_lock_assert(tp, MA_OWNED);
1213 error = cv_timedwait_sig(cv, tp->t_mtx, hz);
1215 /* Restart the system call when we may have been revoked. */
1216 if (tp->t_revokecnt != revokecnt)
1217 return (ERESTART);
1219 /* Bail out when the device slipped away. */
1220 if (tty_gone(tp))
1221 return (ENXIO);
1223 return (error);
1226 void
1227 tty_flush(struct tty *tp, int flags)
1229 if (flags & FWRITE) {
1230 tp->t_flags &= ~TF_HIWAT_OUT;
1231 ttyoutq_flush(&tp->t_outq);
1232 tty_wakeup(tp, FWRITE);
1233 ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE);
1235 if (flags & FREAD) {
1236 tty_hiwat_in_unblock(tp);
1237 ttyinq_flush(&tp->t_inq);
1238 ttydevsw_inwakeup(tp);
1239 ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD);
1243 static int
1244 tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1246 int error;
1248 switch (cmd) {
1250 * Modem commands.
1251 * The SER_* and TIOCM_* flags are the same, but one bit
1252 * shifted. I don't know why.
1254 case TIOCSDTR:
1255 ttydevsw_modem(tp, SER_DTR, 0);
1256 return (0);
1257 case TIOCCDTR:
1258 ttydevsw_modem(tp, 0, SER_DTR);
1259 return (0);
1260 case TIOCMSET: {
1261 int bits = *(int *)data;
1262 ttydevsw_modem(tp,
1263 (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1,
1264 ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1265 return (0);
1267 case TIOCMBIS: {
1268 int bits = *(int *)data;
1269 ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0);
1270 return (0);
1272 case TIOCMBIC: {
1273 int bits = *(int *)data;
1274 ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1275 return (0);
1277 case TIOCMGET:
1278 *(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1);
1279 return (0);
1281 case FIOASYNC:
1282 if (*(int *)data)
1283 tp->t_flags |= TF_ASYNC;
1284 else
1285 tp->t_flags &= ~TF_ASYNC;
1286 return (0);
1287 case FIONBIO:
1288 /* This device supports non-blocking operation. */
1289 return (0);
1290 case FIONREAD:
1291 *(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
1292 return (0);
1293 case FIOSETOWN:
1294 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1295 /* Not allowed to set ownership. */
1296 return (ENOTTY);
1298 /* Temporarily unlock the TTY to set ownership. */
1299 tty_unlock(tp);
1300 error = fsetown(*(int *)data, &tp->t_sigio);
1301 tty_lock(tp);
1302 return (error);
1303 case FIOGETOWN:
1304 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1305 /* Not allowed to set ownership. */
1306 return (ENOTTY);
1308 /* Get ownership. */
1309 *(int *)data = fgetown(&tp->t_sigio);
1310 return (0);
1311 case TIOCGETA:
1312 /* Obtain terminal flags through tcgetattr(). */
1313 bcopy(&tp->t_termios, data, sizeof(struct termios));
1314 return (0);
1315 case TIOCSETA:
1316 case TIOCSETAW:
1317 case TIOCSETAF: {
1318 struct termios *t = data;
1321 * Who makes up these funny rules? According to POSIX,
1322 * input baud rate is set equal to the output baud rate
1323 * when zero.
1325 if (t->c_ispeed == 0)
1326 t->c_ispeed = t->c_ospeed;
1328 /* Discard any unsupported bits. */
1329 t->c_iflag &= TTYSUP_IFLAG;
1330 t->c_oflag &= TTYSUP_OFLAG;
1331 t->c_lflag &= TTYSUP_LFLAG;
1332 t->c_cflag &= TTYSUP_CFLAG;
1334 /* Set terminal flags through tcsetattr(). */
1335 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1336 error = tty_drain(tp);
1337 if (error)
1338 return (error);
1339 if (cmd == TIOCSETAF)
1340 tty_flush(tp, FREAD);
1344 * Only call param() when the flags really change.
1346 if ((t->c_cflag & CIGNORE) == 0 &&
1347 (tp->t_termios.c_cflag != t->c_cflag ||
1348 tp->t_termios.c_ispeed != t->c_ispeed ||
1349 tp->t_termios.c_ospeed != t->c_ospeed)) {
1350 error = ttydevsw_param(tp, t);
1351 if (error)
1352 return (error);
1354 /* XXX: CLOCAL? */
1356 tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE;
1357 tp->t_termios.c_ispeed = t->c_ispeed;
1358 tp->t_termios.c_ospeed = t->c_ospeed;
1360 /* Baud rate has changed - update watermarks. */
1361 tty_watermarks(tp);
1364 /* Copy new non-device driver parameters. */
1365 tp->t_termios.c_iflag = t->c_iflag;
1366 tp->t_termios.c_oflag = t->c_oflag;
1367 tp->t_termios.c_lflag = t->c_lflag;
1368 bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc));
1370 ttydisc_optimize(tp);
1372 if ((t->c_lflag & ICANON) == 0) {
1374 * When in non-canonical mode, wake up all
1375 * readers. Canonicalize any partial input. VMIN
1376 * and VTIME could also be adjusted.
1378 ttyinq_canonicalize(&tp->t_inq);
1379 tty_wakeup(tp, FREAD);
1383 * For packet mode: notify the PTY consumer that VSTOP
1384 * and VSTART may have been changed.
1386 if (tp->t_termios.c_iflag & IXON &&
1387 tp->t_termios.c_cc[VSTOP] == CTRL('S') &&
1388 tp->t_termios.c_cc[VSTART] == CTRL('Q'))
1389 ttydevsw_pktnotify(tp, TIOCPKT_DOSTOP);
1390 else
1391 ttydevsw_pktnotify(tp, TIOCPKT_NOSTOP);
1392 return (0);
1394 case TIOCGETD:
1395 /* For compatibility - we only support TTYDISC. */
1396 *(int *)data = TTYDISC;
1397 return (0);
1398 case TIOCGPGRP:
1399 if (!tty_is_ctty(tp, td->td_proc))
1400 return (ENOTTY);
1402 if (tp->t_pgrp != NULL)
1403 *(int *)data = tp->t_pgrp->pg_id;
1404 else
1405 *(int *)data = NO_PID;
1406 return (0);
1407 case TIOCGSID:
1408 if (!tty_is_ctty(tp, td->td_proc))
1409 return (ENOTTY);
1411 MPASS(tp->t_session);
1412 *(int *)data = tp->t_session->s_sid;
1413 return (0);
1414 case TIOCSCTTY: {
1415 struct proc *p = td->td_proc;
1417 /* XXX: This looks awful. */
1418 tty_unlock(tp);
1419 sx_xlock(&proctree_lock);
1420 tty_lock(tp);
1422 if (!SESS_LEADER(p)) {
1423 /* Only the session leader may do this. */
1424 sx_xunlock(&proctree_lock);
1425 return (EPERM);
1428 if (tp->t_session != NULL && tp->t_session == p->p_session) {
1429 /* This is already our controlling TTY. */
1430 sx_xunlock(&proctree_lock);
1431 return (0);
1434 if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL ||
1435 (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) {
1437 * There is already a relation between a TTY and
1438 * a session, or the caller is not the session
1439 * leader.
1441 * Allow the TTY to be stolen when the vnode is
1442 * NULL, but the reference to the TTY is still
1443 * active.
1445 sx_xunlock(&proctree_lock);
1446 return (EPERM);
1449 /* Connect the session to the TTY. */
1450 tp->t_session = p->p_session;
1451 tp->t_session->s_ttyp = tp;
1452 tp->t_sessioncnt++;
1453 sx_xunlock(&proctree_lock);
1455 /* Assign foreground process group. */
1456 tp->t_pgrp = p->p_pgrp;
1457 PROC_LOCK(p);
1458 p->p_flag |= P_CONTROLT;
1459 PROC_UNLOCK(p);
1461 return (0);
1463 case TIOCSPGRP: {
1464 struct pgrp *pg;
1467 * XXX: Temporarily unlock the TTY to locate the process
1468 * group. This code would be lot nicer if we would ever
1469 * decompose proctree_lock.
1471 tty_unlock(tp);
1472 sx_slock(&proctree_lock);
1473 pg = pgfind(*(int *)data);
1474 if (pg != NULL)
1475 PGRP_UNLOCK(pg);
1476 if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
1477 sx_sunlock(&proctree_lock);
1478 tty_lock(tp);
1479 return (EPERM);
1481 tty_lock(tp);
1484 * Determine if this TTY is the controlling TTY after
1485 * relocking the TTY.
1487 if (!tty_is_ctty(tp, td->td_proc)) {
1488 sx_sunlock(&proctree_lock);
1489 return (ENOTTY);
1491 tp->t_pgrp = pg;
1492 sx_sunlock(&proctree_lock);
1494 /* Wake up the background process groups. */
1495 cv_broadcast(&tp->t_bgwait);
1496 return (0);
1498 case TIOCFLUSH: {
1499 int flags = *(int *)data;
1501 if (flags == 0)
1502 flags = (FREAD|FWRITE);
1503 else
1504 flags &= (FREAD|FWRITE);
1505 tty_flush(tp, flags);
1506 return (0);
1508 case TIOCDRAIN:
1509 /* Drain TTY output. */
1510 return tty_drain(tp);
1511 case TIOCCONS:
1512 /* Set terminal as console TTY. */
1513 if (*(int *)data) {
1514 error = priv_check(td, PRIV_TTY_CONSOLE);
1515 if (error)
1516 return (error);
1519 * XXX: constty should really need to be locked!
1520 * XXX: allow disconnected constty's to be stolen!
1523 if (constty == tp)
1524 return (0);
1525 if (constty != NULL)
1526 return (EBUSY);
1528 tty_unlock(tp);
1529 constty_set(tp);
1530 tty_lock(tp);
1531 } else if (constty == tp) {
1532 constty_clear();
1534 return (0);
1535 case TIOCGWINSZ:
1536 /* Obtain window size. */
1537 bcopy(&tp->t_winsize, data, sizeof(struct winsize));
1538 return (0);
1539 case TIOCSWINSZ:
1540 /* Set window size. */
1541 if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0)
1542 return (0);
1543 bcopy(data, &tp->t_winsize, sizeof(struct winsize));
1544 tty_signal_pgrp(tp, SIGWINCH);
1545 return (0);
1546 case TIOCEXCL:
1547 tp->t_flags |= TF_EXCLUDE;
1548 return (0);
1549 case TIOCNXCL:
1550 tp->t_flags &= ~TF_EXCLUDE;
1551 return (0);
1552 case TIOCOUTQ:
1553 *(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq);
1554 return (0);
1555 case TIOCSTOP:
1556 tp->t_flags |= TF_STOPPED;
1557 ttydevsw_pktnotify(tp, TIOCPKT_STOP);
1558 return (0);
1559 case TIOCSTART:
1560 tp->t_flags &= ~TF_STOPPED;
1561 ttydevsw_outwakeup(tp);
1562 ttydevsw_pktnotify(tp, TIOCPKT_START);
1563 return (0);
1564 case TIOCSTAT:
1565 tty_info(tp);
1566 return (0);
1569 #ifdef COMPAT_43TTY
1570 return tty_ioctl_compat(tp, cmd, data, td);
1571 #else /* !COMPAT_43TTY */
1572 return (ENOIOCTL);
1573 #endif /* COMPAT_43TTY */
1577 tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1579 int error;
1581 tty_lock_assert(tp, MA_OWNED);
1583 if (tty_gone(tp))
1584 return (ENXIO);
1586 error = ttydevsw_ioctl(tp, cmd, data, td);
1587 if (error == ENOIOCTL)
1588 error = tty_generic_ioctl(tp, cmd, data, td);
1590 return (error);
1593 dev_t
1594 tty_udev(struct tty *tp)
1596 if (tp->t_dev)
1597 return dev2udev(tp->t_dev);
1598 else
1599 return NODEV;
1603 tty_checkoutq(struct tty *tp)
1606 /* 256 bytes should be enough to print a log message. */
1607 return (ttyoutq_bytesleft(&tp->t_outq) >= 256);
1610 void
1611 tty_hiwat_in_block(struct tty *tp)
1614 if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1615 tp->t_termios.c_iflag & IXOFF &&
1616 tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) {
1618 * Input flow control. Only enter the high watermark when we
1619 * can successfully store the VSTOP character.
1621 if (ttyoutq_write_nofrag(&tp->t_outq,
1622 &tp->t_termios.c_cc[VSTOP], 1) == 0)
1623 tp->t_flags |= TF_HIWAT_IN;
1624 } else {
1625 /* No input flow control. */
1626 tp->t_flags |= TF_HIWAT_IN;
1630 void
1631 tty_hiwat_in_unblock(struct tty *tp)
1634 if (tp->t_flags & TF_HIWAT_IN &&
1635 tp->t_termios.c_iflag & IXOFF &&
1636 tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) {
1638 * Input flow control. Only leave the high watermark when we
1639 * can successfully store the VSTART character.
1641 if (ttyoutq_write_nofrag(&tp->t_outq,
1642 &tp->t_termios.c_cc[VSTART], 1) == 0)
1643 tp->t_flags &= ~TF_HIWAT_IN;
1644 } else {
1645 /* No input flow control. */
1646 tp->t_flags &= ~TF_HIWAT_IN;
1649 if (!tty_gone(tp))
1650 ttydevsw_inwakeup(tp);
1653 #include "opt_ddb.h"
1654 #ifdef DDB
1655 #include <ddb/ddb.h>
1657 static struct {
1658 int flag;
1659 char val;
1660 } ttystates[] = {
1661 #if 0
1662 { TF_NOPREFIX, 'N' },
1663 #endif
1664 { TF_INITLOCK, 'I' },
1665 { TF_CALLOUT, 'C' },
1667 /* Keep these together -> 'Oi' and 'Oo'. */
1668 { TF_OPENED, 'O' },
1669 { TF_OPENED_IN, 'i' },
1670 { TF_OPENED_OUT,'o' },
1672 { TF_GONE, 'G' },
1673 { TF_OPENCLOSE, 'B' },
1674 { TF_ASYNC, 'Y' },
1675 { TF_LITERAL, 'L' },
1677 /* Keep these together -> 'Hi' and 'Ho'. */
1678 { TF_HIWAT, 'H' },
1679 { TF_HIWAT_IN, 'i' },
1680 { TF_HIWAT_OUT, 'o' },
1682 { TF_STOPPED, 'S' },
1683 { TF_EXCLUDE, 'X' },
1684 { TF_BYPASS, 'l' },
1685 { TF_ZOMBIE, 'Z' },
1687 { 0, '\0' },
1690 /* DDB command to show TTY statistics. */
1691 DB_SHOW_COMMAND(ttys, db_show_ttys)
1693 struct tty *tp;
1694 size_t isiz, osiz;
1695 int i, j;
1697 /* Make the output look like `pstat -t'. */
1698 db_printf(" LINE INQ CAN LIN LOW OUTQ USE LOW "
1699 "COL SESS PGID STATE\n");
1701 TAILQ_FOREACH(tp, &tty_list, t_list) {
1702 isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
1703 osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
1705 db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1706 tty_devname(tp),
1707 isiz,
1708 tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
1709 tp->t_inq.ti_end - tp->t_inq.ti_linestart,
1710 isiz - tp->t_inlow,
1711 osiz,
1712 tp->t_outq.to_end - tp->t_outq.to_begin,
1713 osiz - tp->t_outlow,
1714 tp->t_column,
1715 tp->t_session ? tp->t_session->s_sid : 0,
1716 tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
1718 /* Flag bits. */
1719 for (i = j = 0; ttystates[i].flag; i++)
1720 if (tp->t_flags & ttystates[i].flag) {
1721 db_printf("%c", ttystates[i].val);
1722 j++;
1724 if (j == 0)
1725 db_printf("-");
1726 db_printf("\n");
1729 #endif /* DDB */