00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include "../drivers.h"
00060 #include "../drivers.h"
00061 #include <termios.h>
00062 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
00063 #include <sgtty.h>
00064 #endif
00065 #include <sys/ioc_tty.h>
00066 #include <signal.h>
00067 #include <minix/callnr.h>
00068 #if (CHIP == INTEL)
00069 #include <minix/keymap.h>
00070 #endif
00071 #include "tty.h"
00072
00073 #include <sys/time.h>
00074 #include <sys/select.h>
00075
00076 extern int irq_hook_id;
00077
00078 unsigned long kbd_irq_set = 0;
00079 unsigned long rs_irq_set = 0;
00080
00081
00082 #define tty_addr(line) (&tty_table[line])
00083
00084
00085 #define isconsole(tp) ((tp) < tty_addr(NR_CONS))
00086 #define ispty(tp) ((tp) >= tty_addr(NR_CONS+NR_RS_LINES))
00087
00088
00089 #define FIRST_TTY tty_addr(0)
00090 #define END_TTY tty_addr(sizeof(tty_table) / sizeof(tty_table[0]))
00091
00092
00093 #define tty_active(tp) ((tp)->tty_devread != NULL)
00094
00095
00096 #if NR_RS_LINES == 0
00097 #define rs_init(tp) ((void) 0)
00098 #endif
00099 #if NR_PTYS == 0
00100 #define pty_init(tp) ((void) 0)
00101 #define do_pty(tp, mp) ((void) 0)
00102 #endif
00103
00104 struct kmessages kmess;
00105
00106 FORWARD _PROTOTYPE( void tty_timed_out, (timer_t *tp) );
00107 FORWARD _PROTOTYPE( void expire_timers, (void) );
00108 FORWARD _PROTOTYPE( void settimer, (tty_t *tty_ptr, int enable) );
00109 FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr) );
00110 FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr) );
00111 FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr) );
00112 FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr) );
00113 FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr) );
00114 FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr) );
00115 FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr) );
00116 FORWARD _PROTOTYPE( void do_status, (message *m_ptr) );
00117 FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp) );
00118 FORWARD _PROTOTYPE( int tty_echo, (tty_t *tp, int ch) );
00119 FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch) );
00120 FORWARD _PROTOTYPE( int back_over, (tty_t *tp) );
00121 FORWARD _PROTOTYPE( void reprint, (tty_t *tp) );
00122 FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp) );
00123 FORWARD _PROTOTYPE( void setattr, (tty_t *tp) );
00124 FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp) );
00125 FORWARD _PROTOTYPE( void tty_init, (void) );
00126 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
00127 FORWARD _PROTOTYPE( int compat_getp, (tty_t *tp, struct sgttyb *sg) );
00128 FORWARD _PROTOTYPE( int compat_getc, (tty_t *tp, struct tchars *sg) );
00129 FORWARD _PROTOTYPE( int compat_setp, (tty_t *tp, struct sgttyb *sg) );
00130 FORWARD _PROTOTYPE( int compat_setc, (tty_t *tp, struct tchars *sg) );
00131 FORWARD _PROTOTYPE( int tspd2sgspd, (speed_t tspd) );
00132 FORWARD _PROTOTYPE( speed_t sgspd2tspd, (int sgspd) );
00133 #if ENABLE_BINCOMPAT
00134 FORWARD _PROTOTYPE( void do_ioctl_compat, (tty_t *tp, message *m_ptr) );
00135 #endif
00136 #endif
00137
00138
00139 PRIVATE struct termios termios_defaults = {
00140 TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF,
00141 {
00142 TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF,
00143 TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF,
00144 TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF,
00145 },
00146 };
00147 PRIVATE struct winsize winsize_defaults;
00148
00149
00150 PUBLIC tty_t tty_table[NR_CONS+NR_RS_LINES+NR_PTYS];
00151 PUBLIC int ccurrent;
00152 PUBLIC timer_t *tty_timers;
00153 PUBLIC clock_t tty_next_timeout;
00154 PUBLIC struct machine machine;
00155
00156
00157
00158
00159 PUBLIC void main(void)
00160 {
00161
00162
00163 message tty_mess;
00164 unsigned line;
00165 int r, s;
00166 register struct proc *rp;
00167 register tty_t *tp;
00168
00169 #if DEBUG
00170 kputc('H');
00171 kputc('e');
00172 kputc('l');
00173 kputc('l');
00174 kputc('o');
00175 kputc(',');
00176 kputc(' ');
00177 printf("TTY\n");
00178 #endif
00179
00180
00181 if (OK != (s=sys_getmachine(&machine))) {
00182 panic("TTY","Couldn't obtain kernel environment.", s);
00183 }
00184
00185
00186 tty_init();
00187
00188
00189 kb_init_once();
00190
00191 printf("\n");
00192
00193 while (TRUE) {
00194
00195
00196 for (tp = FIRST_TTY; tp < END_TTY; tp++) {
00197 if (tp->tty_events) handle_events(tp);
00198 }
00199
00200
00201 r= receive(ANY, &tty_mess);
00202 if (r != 0)
00203 panic("TTY", "receive failed with %d", r);
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 switch (tty_mess.m_type) {
00215 case SYN_ALARM:
00216 expire_timers();
00217 continue;
00218 case DEV_PING:
00219 notify(tty_mess.m_source);
00220 continue;
00221 case HARD_INT: {
00222 if (tty_mess.NOTIFY_ARG & kbd_irq_set)
00223 kbd_interrupt(&tty_mess);
00224 #if NR_RS_LINES > 0
00225 if (tty_mess.NOTIFY_ARG & rs_irq_set)
00226 rs_interrupt(&tty_mess);
00227 #endif
00228 expire_timers();
00229 continue;
00230 }
00231 case PROC_EVENT: {
00232 cons_stop();
00233 printf("TTY got PROC_EVENT, assuming SIGTERM\n");
00234 #if DEAD_CODE
00235 if (irq_hook_id != -1) {
00236 sys_irqdisable(&irq_hook_id);
00237 sys_irqrmpolicy(KEYBOARD_IRQ, &irq_hook_id);
00238 }
00239 #endif
00240 continue;
00241 }
00242 case SYS_SIG: {
00243 sigset_t sigset = (sigset_t) tty_mess.NOTIFY_ARG;
00244 if (sigismember(&sigset, SIGKMESS)) do_new_kmess(&tty_mess);
00245 continue;
00246 }
00247 case DIAGNOSTICS:
00248 do_diagnostics(&tty_mess);
00249 continue;
00250 case GET_KMESS:
00251 do_get_kmess(&tty_mess);
00252 continue;
00253 case FKEY_CONTROL:
00254 do_fkey_ctl(&tty_mess);
00255 continue;
00256 default:
00257 ;
00258 }
00259
00260
00261
00262
00263
00264 if (tty_mess.m_type == DEV_STATUS) {
00265 do_status(&tty_mess);
00266 continue;
00267 }
00268 line = tty_mess.TTY_LINE;
00269 if (line == KBD_MINOR) {
00270 do_kbd(&tty_mess);
00271 continue;
00272 } else if (line == KBDAUX_MINOR) {
00273 do_kbdaux(&tty_mess);
00274 continue;
00275 } else if (line == VIDEO_MINOR) {
00276 do_video(&tty_mess);
00277 continue;
00278 } else if ((line - CONS_MINOR) < NR_CONS) {
00279 tp = tty_addr(line - CONS_MINOR);
00280 } else if (line == LOG_MINOR) {
00281 tp = tty_addr(0);
00282 } else if ((line - RS232_MINOR) < NR_RS_LINES) {
00283 tp = tty_addr(line - RS232_MINOR + NR_CONS);
00284 } else if ((line - TTYPX_MINOR) < NR_PTYS) {
00285 tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
00286 } else if ((line - PTYPX_MINOR) < NR_PTYS) {
00287 tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
00288 if (tty_mess.m_type != DEV_IOCTL) {
00289 do_pty(tp, &tty_mess);
00290 continue;
00291 }
00292 } else {
00293 tp = NULL;
00294 }
00295
00296
00297 if (tp == NULL || ! tty_active(tp)) {
00298 printf("Warning, TTY got illegal request %d from %d\n",
00299 tty_mess.m_type, tty_mess.m_source);
00300 if (tty_mess.m_source != LOG_PROC_NR)
00301 {
00302 tty_reply(TASK_REPLY, tty_mess.m_source,
00303 tty_mess.IO_ENDPT, ENXIO);
00304 }
00305 continue;
00306 }
00307
00308
00309 switch (tty_mess.m_type) {
00310 case DEV_READ: do_read(tp, &tty_mess); break;
00311 case DEV_WRITE: do_write(tp, &tty_mess); break;
00312 case DEV_IOCTL: do_ioctl(tp, &tty_mess); break;
00313 case DEV_OPEN: do_open(tp, &tty_mess); break;
00314 case DEV_CLOSE: do_close(tp, &tty_mess); break;
00315 case DEV_SELECT: do_select(tp, &tty_mess); break;
00316 case CANCEL: do_cancel(tp, &tty_mess); break;
00317 default:
00318 printf("Warning, TTY got unexpected request %d from %d\n",
00319 tty_mess.m_type, tty_mess.m_source);
00320 tty_reply(TASK_REPLY, tty_mess.m_source,
00321 tty_mess.IO_ENDPT, EINVAL);
00322 }
00323 }
00324 }
00325
00326
00327
00328
00329 PRIVATE void do_status(m_ptr)
00330 message *m_ptr;
00331 {
00332 register struct tty *tp;
00333 int event_found;
00334 int status;
00335 int ops;
00336
00337
00338
00339
00340
00341 event_found = 0;
00342 for (tp = FIRST_TTY; tp < END_TTY; tp++) {
00343 if ((ops = select_try(tp, tp->tty_select_ops)) &&
00344 tp->tty_select_proc == m_ptr->m_source) {
00345
00346
00347 m_ptr->m_type = DEV_IO_READY;
00348 m_ptr->DEV_MINOR = tp->tty_minor;
00349 m_ptr->DEV_SEL_OPS = ops;
00350
00351 tp->tty_select_ops &= ~ops;
00352 event_found = 1;
00353 break;
00354 }
00355 else if (tp->tty_inrevived && tp->tty_incaller == m_ptr->m_source) {
00356
00357
00358 m_ptr->m_type = DEV_REVIVE;
00359 m_ptr->REP_ENDPT = tp->tty_inproc;
00360 m_ptr->REP_STATUS = tp->tty_incum;
00361
00362 tp->tty_inleft = tp->tty_incum = 0;
00363 tp->tty_inrevived = 0;
00364 event_found = 1;
00365 break;
00366 }
00367 else if (tp->tty_outrevived && tp->tty_outcaller == m_ptr->m_source) {
00368
00369
00370 m_ptr->m_type = DEV_REVIVE;
00371 m_ptr->REP_ENDPT = tp->tty_outproc;
00372 m_ptr->REP_STATUS = tp->tty_outcum;
00373
00374 tp->tty_outcum = 0;
00375 tp->tty_outrevived = 0;
00376 event_found = 1;
00377 break;
00378 }
00379 }
00380
00381 #if NR_PTYS > 0
00382 if (!event_found)
00383 event_found = pty_status(m_ptr);
00384 #endif
00385 if (!event_found)
00386 event_found= kbd_status(m_ptr);
00387
00388 if (! event_found) {
00389
00390 m_ptr->m_type = DEV_NO_STATUS;
00391 }
00392
00393
00394 if ((status = send(m_ptr->m_source, m_ptr)) != OK) {
00395 panic("TTY","send in do_status failed, status\n", status);
00396 }
00397 }
00398
00399
00400
00401
00402 PRIVATE void do_read(tp, m_ptr)
00403 register tty_t *tp;
00404 register message *m_ptr;
00405 {
00406
00407 int r, status;
00408 phys_bytes phys_addr;
00409 int more_verbose= (tp == tty_addr(NR_CONS));
00410
00411
00412
00413
00414 if (tp->tty_inleft > 0) {
00415 if (more_verbose) printf("do_read: EIO\n");
00416 r = EIO;
00417 } else
00418 if (m_ptr->COUNT <= 0) {
00419 if (more_verbose) printf("do_read: EINVAL\n");
00420 r = EINVAL;
00421 } else
00422 if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
00423 &phys_addr) != OK) {
00424 if (more_verbose) printf("do_read: EFAULT\n");
00425 r = EFAULT;
00426 } else {
00427
00428 tp->tty_inrepcode = TASK_REPLY;
00429 tp->tty_incaller = m_ptr->m_source;
00430 tp->tty_inproc = m_ptr->IO_ENDPT;
00431 tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
00432 tp->tty_inleft = m_ptr->COUNT;
00433
00434 if (!(tp->tty_termios.c_lflag & ICANON)
00435 && tp->tty_termios.c_cc[VTIME] > 0) {
00436 if (tp->tty_termios.c_cc[VMIN] == 0) {
00437
00438
00439
00440 settimer(tp, TRUE);
00441 tp->tty_min = 1;
00442 } else {
00443
00444
00445
00446 if (tp->tty_eotct == 0) {
00447 settimer(tp, FALSE);
00448 tp->tty_min = tp->tty_termios.c_cc[VMIN];
00449 }
00450 }
00451 }
00452
00453
00454 in_transfer(tp);
00455
00456 handle_events(tp);
00457 if (tp->tty_inleft == 0) {
00458 if (tp->tty_select_ops)
00459 select_retry(tp);
00460 return;
00461 }
00462
00463
00464
00465
00466 if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
00467 r = EAGAIN;
00468 tp->tty_inleft = tp->tty_incum = 0;
00469 } else {
00470 r = SUSPEND;
00471 tp->tty_inrepcode = REVIVE;
00472 }
00473 }
00474 if (more_verbose) printf("do_read: replying %d\n", r);
00475 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
00476 if (tp->tty_select_ops)
00477 select_retry(tp);
00478 }
00479
00480
00481
00482
00483 PRIVATE void do_write(tp, m_ptr)
00484 register tty_t *tp;
00485 register message *m_ptr;
00486 {
00487
00488 int r;
00489 phys_bytes phys_addr;
00490
00491
00492
00493
00494 if (tp->tty_outleft > 0) {
00495 r = EIO;
00496 } else
00497 if (m_ptr->COUNT <= 0) {
00498 r = EINVAL;
00499 } else
00500 if (sys_umap(m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT,
00501 &phys_addr) != OK) {
00502 r = EFAULT;
00503 } else {
00504
00505 tp->tty_outrepcode = TASK_REPLY;
00506 tp->tty_outcaller = m_ptr->m_source;
00507 tp->tty_outproc = m_ptr->IO_ENDPT;
00508 tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
00509 tp->tty_outleft = m_ptr->COUNT;
00510
00511
00512 handle_events(tp);
00513 if (tp->tty_outleft == 0)
00514 return;
00515
00516
00517
00518
00519 if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
00520 r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
00521 tp->tty_outleft = tp->tty_outcum = 0;
00522 } else {
00523 r = SUSPEND;
00524 tp->tty_outrepcode = REVIVE;
00525 }
00526 }
00527 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
00528 }
00529
00530
00531
00532
00533 PRIVATE void do_ioctl(tp, m_ptr)
00534 register tty_t *tp;
00535 message *m_ptr;
00536 {
00537
00538
00539
00540
00541 int r;
00542 union {
00543 int i;
00544 #if ENABLE_SRCCOMPAT
00545 struct sgttyb sg;
00546 struct tchars tc;
00547 #endif
00548 } param;
00549 size_t size;
00550
00551
00552 switch (m_ptr->TTY_REQUEST) {
00553 case TCGETS:
00554 case TCSETS:
00555 case TCSETSW:
00556 case TCSETSF:
00557 size = sizeof(struct termios);
00558 break;
00559
00560 case TCSBRK:
00561 case TCFLOW:
00562 case TCFLSH:
00563 case TIOCGPGRP:
00564 case TIOCSPGRP:
00565 size = sizeof(int);
00566 break;
00567
00568 case TIOCGWINSZ:
00569 case TIOCSWINSZ:
00570 size = sizeof(struct winsize);
00571 break;
00572
00573 #if ENABLE_SRCCOMPAT
00574 case TIOCGETP:
00575 case TIOCSETP:
00576 size = sizeof(struct sgttyb);
00577 break;
00578
00579 case TIOCGETC:
00580 case TIOCSETC:
00581 size = sizeof(struct tchars);
00582 break;
00583 #endif
00584 #if (MACHINE == IBM_PC)
00585 case KIOCSMAP:
00586 size = sizeof(keymap_t);
00587 break;
00588
00589 case TIOCSFON:
00590 size = sizeof(u8_t [8192]);
00591 break;
00592
00593 #endif
00594 case TCDRAIN:
00595 default: size = 0;
00596 }
00597
00598 r = OK;
00599 switch (m_ptr->TTY_REQUEST) {
00600 case TCGETS:
00601
00602 r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_termios,
00603 m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00604 (vir_bytes) size);
00605 break;
00606
00607 case TCSETSW:
00608 case TCSETSF:
00609 case TCDRAIN:
00610 if (tp->tty_outleft > 0) {
00611
00612 tp->tty_iocaller = m_ptr->m_source;
00613 tp->tty_ioproc = m_ptr->IO_ENDPT;
00614 tp->tty_ioreq = m_ptr->REQUEST;
00615 tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
00616 r = SUSPEND;
00617 break;
00618 }
00619 if (m_ptr->TTY_REQUEST == TCDRAIN) break;
00620 if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);
00621
00622 case TCSETS:
00623
00624 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00625 SELF, D, (vir_bytes) &tp->tty_termios, (vir_bytes) size);
00626 if (r != OK) break;
00627 setattr(tp);
00628 break;
00629
00630 case TCFLSH:
00631 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00632 SELF, D, (vir_bytes) ¶m.i, (vir_bytes) size);
00633 if (r != OK) break;
00634 switch (param.i) {
00635 case TCIFLUSH: tty_icancel(tp); break;
00636 case TCOFLUSH: (*tp->tty_ocancel)(tp, 0); break;
00637 case TCIOFLUSH: tty_icancel(tp); (*tp->tty_ocancel)(tp, 0); break;
00638 default: r = EINVAL;
00639 }
00640 break;
00641
00642 case TCFLOW:
00643 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00644 SELF, D, (vir_bytes) ¶m.i, (vir_bytes) size);
00645 if (r != OK) break;
00646 switch (param.i) {
00647 case TCOOFF:
00648 case TCOON:
00649 tp->tty_inhibited = (param.i == TCOOFF);
00650 tp->tty_events = 1;
00651 break;
00652 case TCIOFF:
00653 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);
00654 break;
00655 case TCION:
00656 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);
00657 break;
00658 default:
00659 r = EINVAL;
00660 }
00661 break;
00662
00663 case TCSBRK:
00664 if (tp->tty_break != NULL) (*tp->tty_break)(tp,0);
00665 break;
00666
00667 case TIOCGWINSZ:
00668 r = sys_vircopy(SELF, D, (vir_bytes) &tp->tty_winsize,
00669 m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00670 (vir_bytes) size);
00671 break;
00672
00673 case TIOCSWINSZ:
00674 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00675 SELF, D, (vir_bytes) &tp->tty_winsize, (vir_bytes) size);
00676 sigchar(tp, SIGWINCH);
00677 break;
00678
00679 #if ENABLE_SRCCOMPAT
00680 case TIOCGETP:
00681 compat_getp(tp, ¶m.sg);
00682 r = sys_vircopy(SELF, D, (vir_bytes) ¶m.sg,
00683 m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00684 (vir_bytes) size);
00685 break;
00686
00687 case TIOCSETP:
00688 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00689 SELF, D, (vir_bytes) ¶m.sg, (vir_bytes) size);
00690 if (r != OK) break;
00691 compat_setp(tp, ¶m.sg);
00692 break;
00693
00694 case TIOCGETC:
00695 compat_getc(tp, ¶m.tc);
00696 r = sys_vircopy(SELF, D, (vir_bytes) ¶m.tc,
00697 m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00698 (vir_bytes) size);
00699 break;
00700
00701 case TIOCSETC:
00702 r = sys_vircopy( m_ptr->IO_ENDPT, D, (vir_bytes) m_ptr->ADDRESS,
00703 SELF, D, (vir_bytes) ¶m.tc, (vir_bytes) size);
00704 if (r != OK) break;
00705 compat_setc(tp, ¶m.tc);
00706 break;
00707 #endif
00708
00709 #if (MACHINE == IBM_PC)
00710 case KIOCSMAP:
00711
00712 if (isconsole(tp)) r = kbd_loadmap(m_ptr);
00713 break;
00714
00715 case TIOCSFON:
00716
00717 if (isconsole(tp)) r = con_loadfont(m_ptr);
00718 break;
00719 #endif
00720
00721 #if (MACHINE == ATARI)
00722 case VDU_LOADFONT:
00723 r = vdu_loadfont(m_ptr);
00724 break;
00725 #endif
00726
00727
00728
00729
00730 case TIOCGPGRP:
00731 case TIOCSPGRP:
00732 default:
00733 #if ENABLE_BINCOMPAT
00734 do_ioctl_compat(tp, m_ptr);
00735 return;
00736 #else
00737 r = ENOTTY;
00738 #endif
00739 }
00740
00741
00742 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
00743 }
00744
00745
00746
00747
00748 PRIVATE void do_open(tp, m_ptr)
00749 register tty_t *tp;
00750 message *m_ptr;
00751 {
00752
00753
00754
00755
00756 int r = OK;
00757
00758 if (m_ptr->TTY_LINE == LOG_MINOR) {
00759
00760 if (m_ptr->COUNT & R_BIT) r = EACCES;
00761 } else {
00762 if (!(m_ptr->COUNT & O_NOCTTY)) {
00763 tp->tty_pgrp = m_ptr->IO_ENDPT;
00764 r = 1;
00765 }
00766 tp->tty_openct++;
00767 }
00768 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, r);
00769 }
00770
00771
00772
00773
00774 PRIVATE void do_close(tp, m_ptr)
00775 register tty_t *tp;
00776 message *m_ptr;
00777 {
00778
00779
00780 if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
00781 tp->tty_pgrp = 0;
00782 tty_icancel(tp);
00783 (*tp->tty_ocancel)(tp, 0);
00784 (*tp->tty_close)(tp, 0);
00785 tp->tty_termios = termios_defaults;
00786 tp->tty_winsize = winsize_defaults;
00787 setattr(tp);
00788 }
00789 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, OK);
00790 }
00791
00792
00793
00794
00795 PRIVATE void do_cancel(tp, m_ptr)
00796 register tty_t *tp;
00797 message *m_ptr;
00798 {
00799
00800
00801
00802
00803 int proc_nr;
00804 int mode;
00805
00806
00807 proc_nr = m_ptr->IO_ENDPT;
00808 mode = m_ptr->COUNT;
00809 if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
00810
00811 tty_icancel(tp);
00812 tp->tty_inleft = tp->tty_incum = 0;
00813 }
00814 if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
00815
00816 (*tp->tty_ocancel)(tp, 0);
00817 tp->tty_outleft = tp->tty_outcum = 0;
00818 }
00819 if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
00820
00821 tp->tty_ioreq = 0;
00822 }
00823 tp->tty_events = 1;
00824 tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
00825 }
00826
00827 PUBLIC int select_try(struct tty *tp, int ops)
00828 {
00829 int ready_ops = 0;
00830
00831
00832
00833
00834 if (tp->tty_termios.c_ospeed == B0) {
00835 ready_ops |= ops;
00836 }
00837
00838 if (ops & SEL_RD) {
00839
00840 if (tp->tty_inleft > 0) {
00841 ready_ops |= SEL_RD;
00842 } else if (tp->tty_incount > 0) {
00843
00844
00845
00846
00847 if (!(tp->tty_termios.c_lflag & ICANON) ||
00848 tp->tty_eotct > 0) {
00849 ready_ops |= SEL_RD;
00850 }
00851 }
00852 }
00853
00854 if (ops & SEL_WR) {
00855 if (tp->tty_outleft > 0) ready_ops |= SEL_WR;
00856 else if ((*tp->tty_devwrite)(tp, 1)) ready_ops |= SEL_WR;
00857 }
00858 return ready_ops;
00859 }
00860
00861 PUBLIC int select_retry(struct tty *tp)
00862 {
00863 if (tp->tty_select_ops && select_try(tp, tp->tty_select_ops))
00864 notify(tp->tty_select_proc);
00865 return OK;
00866 }
00867
00868
00869
00870
00871 PUBLIC void handle_events(tp)
00872 tty_t *tp;
00873 {
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 char *buf;
00888 unsigned count;
00889 int status;
00890
00891 do {
00892 tp->tty_events = 0;
00893
00894
00895 (*tp->tty_devread)(tp, 0);
00896
00897
00898 (*tp->tty_devwrite)(tp, 0);
00899
00900
00901 if (tp->tty_ioreq != 0) dev_ioctl(tp);
00902 } while (tp->tty_events);
00903
00904
00905 in_transfer(tp);
00906
00907
00908 if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
00909 if (tp->tty_inrepcode == REVIVE) {
00910 notify(tp->tty_incaller);
00911 tp->tty_inrevived = 1;
00912 } else {
00913 tty_reply(tp->tty_inrepcode, tp->tty_incaller,
00914 tp->tty_inproc, tp->tty_incum);
00915 tp->tty_inleft = tp->tty_incum = 0;
00916 }
00917 }
00918 if (tp->tty_select_ops)
00919 {
00920 select_retry(tp);
00921 }
00922 #if NR_PTYS > 0
00923 if (ispty(tp))
00924 select_retry_pty(tp);
00925 #endif
00926 }
00927
00928
00929
00930
00931 PRIVATE void in_transfer(tp)
00932 register tty_t *tp;
00933 {
00934
00935
00936 int ch;
00937 int count;
00938 char buf[64], *bp;
00939
00940
00941 if (tp->tty_termios.c_ospeed == B0) tp->tty_min = 0;
00942
00943
00944 if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;
00945
00946 bp = buf;
00947 while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {
00948 ch = *tp->tty_intail;
00949
00950 if (!(ch & IN_EOF)) {
00951
00952 *bp = ch & IN_CHAR;
00953 tp->tty_inleft--;
00954 if (++bp == bufend(buf)) {
00955
00956 sys_vircopy(SELF, D, (vir_bytes) buf,
00957 tp->tty_inproc, D, tp->tty_in_vir,
00958 (vir_bytes) buflen(buf));
00959 tp->tty_in_vir += buflen(buf);
00960 tp->tty_incum += buflen(buf);
00961 bp = buf;
00962 }
00963 }
00964
00965
00966 if (++tp->tty_intail == bufend(tp->tty_inbuf))
00967 tp->tty_intail = tp->tty_inbuf;
00968 tp->tty_incount--;
00969 if (ch & IN_EOT) {
00970 tp->tty_eotct--;
00971
00972 if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;
00973 }
00974 }
00975
00976 if (bp > buf) {
00977
00978 count = bp - buf;
00979 sys_vircopy(SELF, D, (vir_bytes) buf,
00980 tp->tty_inproc, D, tp->tty_in_vir, (vir_bytes) count);
00981 tp->tty_in_vir += count;
00982 tp->tty_incum += count;
00983 }
00984
00985
00986 if (tp->tty_inleft == 0) {
00987 if (tp->tty_inrepcode == REVIVE) {
00988 notify(tp->tty_incaller);
00989 tp->tty_inrevived = 1;
00990 } else {
00991 tty_reply(tp->tty_inrepcode, tp->tty_incaller,
00992 tp->tty_inproc, tp->tty_incum);
00993 tp->tty_inleft = tp->tty_incum = 0;
00994 }
00995 }
00996 }
00997
00998
00999
01000
01001 PUBLIC int in_process(tp, buf, count)
01002 register tty_t *tp;
01003 char *buf;
01004 int count;
01005 {
01006
01007
01008
01009
01010 int ch, sig, ct;
01011 int timeset = FALSE;
01012 static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
01013
01014 for (ct = 0; ct < count; ct++) {
01015
01016 ch = *buf++ & BYTE;
01017
01018
01019 if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;
01020
01021
01022 if (tp->tty_termios.c_lflag & IEXTEN) {
01023
01024
01025 if (tp->tty_escaped) {
01026 tp->tty_escaped = NOT_ESCAPED;
01027 ch |= IN_ESC;
01028 }
01029
01030
01031 if (ch == tp->tty_termios.c_cc[VLNEXT]) {
01032 tp->tty_escaped = ESCAPED;
01033 rawecho(tp, '^');
01034 rawecho(tp, '\b');
01035 continue;
01036 }
01037
01038
01039 if (ch == tp->tty_termios.c_cc[VREPRINT]) {
01040 reprint(tp);
01041 continue;
01042 }
01043 }
01044
01045
01046 if (ch == _POSIX_VDISABLE) ch |= IN_ESC;
01047
01048
01049 if (ch == '\r') {
01050 if (tp->tty_termios.c_iflag & IGNCR) continue;
01051 if (tp->tty_termios.c_iflag & ICRNL) ch = '\n';
01052 } else
01053 if (ch == '\n') {
01054 if (tp->tty_termios.c_iflag & INLCR) ch = '\r';
01055 }
01056
01057
01058 if (tp->tty_termios.c_lflag & ICANON) {
01059
01060
01061 if (ch == tp->tty_termios.c_cc[VERASE]) {
01062 (void) back_over(tp);
01063 if (!(tp->tty_termios.c_lflag & ECHOE)) {
01064 (void) tty_echo(tp, ch);
01065 }
01066 continue;
01067 }
01068
01069
01070 if (ch == tp->tty_termios.c_cc[VKILL]) {
01071 while (back_over(tp)) {}
01072 if (!(tp->tty_termios.c_lflag & ECHOE)) {
01073 (void) tty_echo(tp, ch);
01074 if (tp->tty_termios.c_lflag & ECHOK)
01075 rawecho(tp, '\n');
01076 }
01077 continue;
01078 }
01079
01080
01081 if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;
01082
01083
01084 if (ch == '\n') ch |= IN_EOT;
01085
01086
01087 if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;
01088 }
01089
01090
01091 if (tp->tty_termios.c_iflag & IXON) {
01092
01093
01094 if (ch == tp->tty_termios.c_cc[VSTOP]) {
01095 tp->tty_inhibited = STOPPED;
01096 tp->tty_events = 1;
01097 continue;
01098 }
01099
01100
01101 if (tp->tty_inhibited) {
01102 if (ch == tp->tty_termios.c_cc[VSTART]
01103 || (tp->tty_termios.c_iflag & IXANY)) {
01104 tp->tty_inhibited = RUNNING;
01105 tp->tty_events = 1;
01106 if (ch == tp->tty_termios.c_cc[VSTART])
01107 continue;
01108 }
01109 }
01110 }
01111
01112 if (tp->tty_termios.c_lflag & ISIG) {
01113
01114 if (ch == tp->tty_termios.c_cc[VINTR]
01115 || ch == tp->tty_termios.c_cc[VQUIT]) {
01116 sig = SIGINT;
01117 if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;
01118 sigchar(tp, sig);
01119 (void) tty_echo(tp, ch);
01120 continue;
01121 }
01122 }
01123
01124
01125 if (tp->tty_incount == buflen(tp->tty_inbuf)) {
01126
01127 if (tp->tty_termios.c_lflag & ICANON) continue;
01128 break;
01129 }
01130
01131 if (!(tp->tty_termios.c_lflag & ICANON)) {
01132
01133 ch |= IN_EOT;
01134
01135
01136 if (!timeset && tp->tty_termios.c_cc[VMIN] > 0
01137 && tp->tty_termios.c_cc[VTIME] > 0) {
01138 settimer(tp, TRUE);
01139 timeset = TRUE;
01140 }
01141 }
01142
01143
01144 if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = tty_echo(tp, ch);
01145
01146
01147 *tp->tty_inhead++ = ch;
01148 if (tp->tty_inhead == bufend(tp->tty_inbuf))
01149 tp->tty_inhead = tp->tty_inbuf;
01150 tp->tty_incount++;
01151 if (ch & IN_EOT) tp->tty_eotct++;
01152
01153
01154 if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);
01155 }
01156 return ct;
01157 }
01158
01159
01160
01161
01162 PRIVATE int tty_echo(tp, ch)
01163 register tty_t *tp;
01164 register int ch;
01165 {
01166
01167
01168
01169
01170
01171
01172 int len, rp;
01173
01174 ch &= ~IN_LEN;
01175 if (!(tp->tty_termios.c_lflag & ECHO)) {
01176 if (ch == ('\n' | IN_EOT) && (tp->tty_termios.c_lflag
01177 & (ICANON|ECHONL)) == (ICANON|ECHONL))
01178 (*tp->tty_echo)(tp, '\n');
01179 return(ch);
01180 }
01181
01182
01183 rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;
01184
01185 if ((ch & IN_CHAR) < ' ') {
01186 switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {
01187 case '\t':
01188 len = 0;
01189 do {
01190 (*tp->tty_echo)(tp, ' ');
01191 len++;
01192 } while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);
01193 break;
01194 case '\r' | IN_EOT:
01195 case '\n' | IN_EOT:
01196 (*tp->tty_echo)(tp, ch & IN_CHAR);
01197 len = 0;
01198 break;
01199 default:
01200 (*tp->tty_echo)(tp, '^');
01201 (*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));
01202 len = 2;
01203 }
01204 } else
01205 if ((ch & IN_CHAR) == '\177') {
01206
01207 (*tp->tty_echo)(tp, '^');
01208 (*tp->tty_echo)(tp, '?');
01209 len = 2;
01210 } else {
01211 (*tp->tty_echo)(tp, ch & IN_CHAR);
01212 len = 1;
01213 }
01214 if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, '\b'); len--; }
01215
01216 tp->tty_reprint = rp;
01217 return(ch | (len << IN_LSHIFT));
01218 }
01219
01220
01221
01222
01223 PRIVATE void rawecho(tp, ch)
01224 register tty_t *tp;
01225 int ch;
01226 {
01227
01228 int rp = tp->tty_reprint;
01229 if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);
01230 tp->tty_reprint = rp;
01231 }
01232
01233
01234
01235
01236 PRIVATE int back_over(tp)
01237 register tty_t *tp;
01238 {
01239
01240 u16_t *head;
01241 int len;
01242
01243 if (tp->tty_incount == 0) return(0);
01244 head = tp->tty_inhead;
01245 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
01246 if (*--head & IN_EOT) return(0);
01247 if (tp->tty_reprint) reprint(tp);
01248 tp->tty_inhead = head;
01249 tp->tty_incount--;
01250 if (tp->tty_termios.c_lflag & ECHOE) {
01251 len = (*head & IN_LEN) >> IN_LSHIFT;
01252 while (len > 0) {
01253 rawecho(tp, '\b');
01254 rawecho(tp, ' ');
01255 rawecho(tp, '\b');
01256 len--;
01257 }
01258 }
01259 return(1);
01260 }
01261
01262
01263
01264
01265 PRIVATE void reprint(tp)
01266 register tty_t *tp;
01267 {
01268
01269
01270
01271 int count;
01272 u16_t *head;
01273
01274 tp->tty_reprint = FALSE;
01275
01276
01277 head = tp->tty_inhead;
01278 count = tp->tty_incount;
01279 while (count > 0) {
01280 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
01281 if (head[-1] & IN_EOT) break;
01282 head--;
01283 count--;
01284 }
01285 if (count == tp->tty_incount) return;
01286
01287
01288 (void) tty_echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);
01289 rawecho(tp, '\r');
01290 rawecho(tp, '\n');
01291
01292
01293 do {
01294 if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;
01295 *head = tty_echo(tp, *head);
01296 head++;
01297 count++;
01298 } while (count < tp->tty_incount);
01299 }
01300
01301
01302
01303
01304 PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
01305 tty_t *tp;
01306 char *bstart, *bpos, *bend;
01307 int *icount;
01308 int *ocount;
01309 {
01310
01311
01312
01313
01314
01315
01316
01317 int tablen;
01318 int ict = *icount;
01319 int oct = *ocount;
01320 int pos = tp->tty_position;
01321
01322 while (ict > 0) {
01323 switch (*bpos) {
01324 case '\7':
01325 break;
01326 case '\b':
01327 pos--;
01328 break;
01329 case '\r':
01330 pos = 0;
01331 break;
01332 case '\n':
01333 if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
01334 == (OPOST|ONLCR)) {
01335
01336
01337
01338
01339 if (oct >= 2) {
01340 *bpos = '\r';
01341 if (++bpos == bend) bpos = bstart;
01342 *bpos = '\n';
01343 pos = 0;
01344 ict--;
01345 oct -= 2;
01346 }
01347 goto out_done;
01348 }
01349 break;
01350 case '\t':
01351
01352 tablen = TAB_SIZE - (pos & TAB_MASK);
01353
01354 if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
01355 == (OPOST|XTABS)) {
01356
01357 if (oct >= tablen) {
01358 pos += tablen;
01359 ict--;
01360 oct -= tablen;
01361 do {
01362 *bpos = ' ';
01363 if (++bpos == bend) bpos = bstart;
01364 } while (--tablen != 0);
01365 }
01366 goto out_done;
01367 }
01368
01369 pos += tablen;
01370 break;
01371 default:
01372
01373 pos++;
01374 }
01375 if (++bpos == bend) bpos = bstart;
01376 ict--;
01377 oct--;
01378 }
01379 out_done:
01380 tp->tty_position = pos & TAB_MASK;
01381
01382 *icount -= ict;
01383 *ocount -= oct;
01384 }
01385
01386
01387
01388
01389 PRIVATE void dev_ioctl(tp)
01390 tty_t *tp;
01391 {
01392
01393
01394
01395
01396 int result;
01397
01398 if (tp->tty_outleft > 0) return;
01399
01400 if (tp->tty_ioreq != TCDRAIN) {
01401 if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
01402 result = sys_vircopy(tp->tty_ioproc, D, tp->tty_iovir,
01403 SELF, D, (vir_bytes) &tp->tty_termios,
01404 (vir_bytes) sizeof(tp->tty_termios));
01405 setattr(tp);
01406 }
01407 tp->tty_ioreq = 0;
01408 tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, result);
01409 }
01410
01411
01412
01413
01414 PRIVATE void setattr(tp)
01415 tty_t *tp;
01416 {
01417
01418 u16_t *inp;
01419 int count;
01420
01421 if (!(tp->tty_termios.c_lflag & ICANON)) {
01422
01423
01424
01425
01426
01427
01428 count = tp->tty_eotct = tp->tty_incount;
01429 inp = tp->tty_intail;
01430 while (count > 0) {
01431 *inp |= IN_EOT;
01432 if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
01433 --count;
01434 }
01435 }
01436
01437
01438 settimer(tp, FALSE);
01439 if (tp->tty_termios.c_lflag & ICANON) {
01440
01441 tp->tty_min = 1;
01442 } else {
01443
01444
01445
01446 tp->tty_min = tp->tty_termios.c_cc[VMIN];
01447 if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
01448 tp->tty_min = 1;
01449 }
01450
01451 if (!(tp->tty_termios.c_iflag & IXON)) {
01452
01453 tp->tty_inhibited = RUNNING;
01454 tp->tty_events = 1;
01455 }
01456
01457
01458 if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
01459
01460
01461 (*tp->tty_ioctl)(tp, 0);
01462 }
01463
01464
01465
01466
01467 PUBLIC void tty_reply(code, replyee, proc_nr, status)
01468 int code;
01469 int replyee;
01470 int proc_nr;
01471 int status;
01472 {
01473
01474 message tty_mess;
01475
01476 tty_mess.m_type = code;
01477 tty_mess.REP_ENDPT = proc_nr;
01478 tty_mess.REP_STATUS = status;
01479
01480 if ((status = send(replyee, &tty_mess)) != OK) {
01481 printf("TTY: couldn't reply to %d\n", replyee);
01482 panic("TTY","tty_reply failed, status\n", status);
01483 }
01484 }
01485
01486
01487
01488
01489 PUBLIC void sigchar(tp, sig)
01490 register tty_t *tp;
01491 int sig;
01492 {
01493
01494
01495
01496
01497
01498 int status;
01499
01500 if (tp->tty_pgrp != 0)
01501 if (OK != (status = sys_kill(tp->tty_pgrp, sig)))
01502 panic("TTY","Error, call to sys_kill failed", status);
01503
01504 if (!(tp->tty_termios.c_lflag & NOFLSH)) {
01505 tp->tty_incount = tp->tty_eotct = 0;
01506 tp->tty_intail = tp->tty_inhead;
01507 (*tp->tty_ocancel)(tp, 0);
01508 tp->tty_inhibited = RUNNING;
01509 tp->tty_events = 1;
01510 }
01511 }
01512
01513
01514
01515
01516 PRIVATE void tty_icancel(tp)
01517 register tty_t *tp;
01518 {
01519
01520
01521 tp->tty_incount = tp->tty_eotct = 0;
01522 tp->tty_intail = tp->tty_inhead;
01523 (*tp->tty_icancel)(tp, 0);
01524 }
01525
01526
01527
01528
01529 PRIVATE void tty_init()
01530 {
01531
01532
01533 register tty_t *tp;
01534 int s;
01535 struct sigaction sa;
01536
01537
01538 for (tp = FIRST_TTY,s=0; tp < END_TTY; tp++,s++) {
01539
01540 tp->tty_index = s;
01541
01542 tmr_inittimer(&tp->tty_tmr);
01543
01544 tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
01545 tp->tty_min = 1;
01546 tp->tty_termios = termios_defaults;
01547 tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
01548 tty_devnop;
01549 if (tp < tty_addr(NR_CONS)) {
01550 scr_init(tp);
01551
01552
01553 kb_init(tp);
01554
01555 tp->tty_minor = CONS_MINOR + s;
01556 } else
01557 if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
01558 rs_init(tp);
01559 tp->tty_minor = RS232_MINOR + s-NR_CONS;
01560 } else {
01561 pty_init(tp);
01562 tp->tty_minor = s - (NR_CONS+NR_RS_LINES) + TTYPX_MINOR;
01563 }
01564 }
01565
01566 #if DEAD_CODE
01567
01568 sa.sa_handler = SIG_MESS;
01569 sigemptyset(&sa.sa_mask);
01570 sa.sa_flags = 0;
01571 if (sigaction(SIGTERM,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
01572 if (sigaction(SIGKMESS,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
01573 if (sigaction(SIGKSTOP,&sa,NULL)<0) panic("TTY","sigaction failed", errno);
01574 #endif
01575 #if DEBUG
01576 printf("end of tty_init\n");
01577 #endif
01578 }
01579
01580
01581
01582
01583 PRIVATE void tty_timed_out(timer_t *tp)
01584 {
01585
01586 tty_t *tty_ptr;
01587 tty_ptr = &tty_table[tmr_arg(tp)->ta_int];
01588 tty_ptr->tty_min = 0;
01589 tty_ptr->tty_events = 1;
01590 }
01591
01592
01593
01594
01595 PRIVATE void expire_timers(void)
01596 {
01597
01598
01599
01600 clock_t now;
01601 int s;
01602
01603
01604 if ((s=getuptime(&now)) != OK)
01605 panic("TTY","Couldn't get uptime from clock.", s);
01606
01607
01608
01609
01610 tmrs_exptimers(&tty_timers, now, NULL);
01611 if (tty_timers == NULL) tty_next_timeout = TMR_NEVER;
01612 else {
01613 tty_next_timeout = tty_timers->tmr_exp_time;
01614 if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
01615 panic("TTY","Couldn't set synchronous alarm.", s);
01616 }
01617 }
01618
01619
01620
01621
01622 PRIVATE void settimer(tty_ptr, enable)
01623 tty_t *tty_ptr;
01624 int enable;
01625 {
01626 clock_t now;
01627 clock_t exp_time;
01628 int s;
01629
01630
01631 if ((s=getuptime(&now)) != OK)
01632 panic("TTY","Couldn't get uptime from clock.", s);
01633 if (enable) {
01634 exp_time = now + tty_ptr->tty_termios.c_cc[VTIME] * (HZ/10);
01635
01636 tmrs_settimer(&tty_timers, &tty_ptr->tty_tmr,
01637 exp_time, tty_timed_out, NULL);
01638 } else {
01639
01640 tmrs_clrtimer(&tty_timers, &tty_ptr->tty_tmr, NULL);
01641 }
01642
01643
01644
01645
01646
01647 if (tty_timers == NULL) tty_next_timeout = TMR_NEVER;
01648 else if (tty_timers->tmr_exp_time != tty_next_timeout) {
01649 tty_next_timeout = tty_timers->tmr_exp_time;
01650 if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
01651 panic("TTY","Couldn't set synchronous alarm.", s);
01652 }
01653 }
01654
01655
01656
01657
01658 PUBLIC int tty_devnop(tp, try)
01659 tty_t *tp;
01660 int try;
01661 {
01662
01663 }
01664
01665
01666
01667
01668 PRIVATE void do_select(tp, m_ptr)
01669 register tty_t *tp;
01670 register message *m_ptr;
01671 {
01672 int ops, ready_ops = 0, watch;
01673
01674 ops = m_ptr->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
01675 watch = (m_ptr->IO_ENDPT & SEL_NOTIFY) ? 1 : 0;
01676
01677 ready_ops = select_try(tp, ops);
01678
01679 if (!ready_ops && ops && watch) {
01680 tp->tty_select_ops |= ops;
01681 tp->tty_select_proc = m_ptr->m_source;
01682 }
01683
01684 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->IO_ENDPT, ready_ops);
01685
01686 return;
01687 }
01688
01689 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
01690
01691
01692
01693 PRIVATE int compat_getp(tp, sg)
01694 tty_t *tp;
01695 struct sgttyb *sg;
01696 {
01697
01698 int flgs;
01699
01700 sg->sg_erase = tp->tty_termios.c_cc[VERASE];
01701 sg->sg_kill = tp->tty_termios.c_cc[VKILL];
01702 sg->sg_ospeed = tspd2sgspd(cfgetospeed(&tp->tty_termios));
01703 sg->sg_ispeed = tspd2sgspd(cfgetispeed(&tp->tty_termios));
01704
01705 flgs = 0;
01706
01707
01708 if ((tp->tty_termios.c_oflag & (OPOST|XTABS)) == (OPOST|XTABS))
01709 flgs |= 0006000;
01710
01711
01712 flgs |= (tp->tty_termios.c_cflag & CSIZE) << (8-2);
01713
01714
01715 if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == PARENB)
01716 flgs |= 0000200;
01717
01718
01719 if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == (PARENB|PARODD))
01720 flgs |= 0000100;
01721
01722
01723 if (!(tp->tty_termios.c_lflag & (ICANON|ISIG)))
01724 flgs |= 0000040;
01725
01726
01727 if (tp->tty_termios.c_iflag & ICRNL)
01728 flgs |= 0000020;
01729
01730
01731 if (tp->tty_termios.c_lflag & ECHO)
01732 flgs |= 0000010;
01733
01734
01735 if ((tp->tty_termios.c_lflag & (ICANON|ISIG)) == ISIG)
01736 flgs |= 0000002;
01737
01738 sg->sg_flags = flgs;
01739 return(OK);
01740 }
01741
01742
01743
01744
01745 PRIVATE int compat_getc(tp, tc)
01746 tty_t *tp;
01747 struct tchars *tc;
01748 {
01749
01750
01751 tc->t_intrc = tp->tty_termios.c_cc[VINTR];
01752 tc->t_quitc = tp->tty_termios.c_cc[VQUIT];
01753 tc->t_startc = tp->tty_termios.c_cc[VSTART];
01754 tc->t_stopc = tp->tty_termios.c_cc[VSTOP];
01755 tc->t_brkc = tp->tty_termios.c_cc[VEOL];
01756 tc->t_eofc = tp->tty_termios.c_cc[VEOF];
01757 return(OK);
01758 }
01759
01760
01761
01762
01763 PRIVATE int compat_setp(tp, sg)
01764 tty_t *tp;
01765 struct sgttyb *sg;
01766 {
01767
01768 struct termios termios;
01769 int flags;
01770
01771 termios = tp->tty_termios;
01772
01773 termios.c_cc[VERASE] = sg->sg_erase;
01774 termios.c_cc[VKILL] = sg->sg_kill;
01775 cfsetispeed(&termios, sgspd2tspd(sg->sg_ispeed & BYTE));
01776 cfsetospeed(&termios, sgspd2tspd(sg->sg_ospeed & BYTE));
01777 flags = sg->sg_flags;
01778
01779
01780
01781
01782
01783
01784 termios.c_iflag &= ~ICRNL;
01785 if ((flags & 0000020) && !(flags & 0000040))
01786 termios.c_iflag |= ICRNL;
01787
01788
01789
01790 termios.c_iflag &= ~IGNCR;
01791
01792
01793
01794 termios.c_iflag &= ~INLCR;
01795
01796
01797
01798
01799
01800 termios.c_iflag &= ~IXON;
01801 if (!(flags & 0000040))
01802 termios.c_iflag |= IXON;
01803
01804
01805
01806
01807
01808
01809 termios.c_oflag &= ~OPOST;
01810 if (!(flags & 0000040))
01811 termios.c_oflag |= OPOST;
01812
01813
01814 termios.c_oflag &= ~ONLCR;
01815 if (flags & 0000020)
01816 termios.c_oflag |= ONLCR;
01817
01818
01819 termios.c_oflag &= ~XTABS;
01820 if (flags & 0006000)
01821 termios.c_oflag |= XTABS;
01822
01823
01824
01825 termios.c_cflag |= CREAD;
01826
01827
01828 termios.c_cflag = (termios.c_cflag & ~CSIZE) | ((flags & 0001400) >> (8-2));
01829
01830
01831
01832
01833 termios.c_cflag &= ~PARENB;
01834 if (flags & (0000200|0000100))
01835 termios.c_cflag |= PARENB;
01836
01837
01838 termios.c_cflag &= ~PARODD;
01839 if (flags & 0000100)
01840 termios.c_cflag |= PARODD;
01841
01842
01843
01844
01845 termios.c_lflag &= ~ECHO;
01846 if (flags & 0000010)
01847 termios.c_lflag |= ECHO;
01848
01849
01850
01851
01852
01853 termios.c_lflag &= ~ICANON;
01854 if (!(flags & (0000002|0000040)))
01855 termios.c_lflag |= ICANON;
01856
01857
01858
01859 termios.c_lflag &= ~(IEXTEN|ISIG);
01860 if (!(flags & 0000040))
01861 termios.c_lflag |= (IEXTEN|ISIG);
01862
01863
01864
01865
01866 tp->tty_termios = termios;
01867 setattr(tp);
01868 return(OK);
01869 }
01870
01871
01872
01873
01874 PRIVATE int compat_setc(tp, tc)
01875 tty_t *tp;
01876 struct tchars *tc;
01877 {
01878
01879 struct termios termios;
01880
01881 termios = tp->tty_termios;
01882
01883 termios.c_cc[VINTR] = tc->t_intrc;
01884 termios.c_cc[VQUIT] = tc->t_quitc;
01885 termios.c_cc[VSTART] = tc->t_startc;
01886 termios.c_cc[VSTOP] = tc->t_stopc;
01887 termios.c_cc[VEOL] = tc->t_brkc;
01888 termios.c_cc[VEOF] = tc->t_eofc;
01889
01890 tp->tty_termios = termios;
01891 setattr(tp);
01892 return(OK);
01893 }
01894
01895
01896
01897
01898 PRIVATE struct s2s {
01899 speed_t tspd;
01900 u8_t sgspd;
01901 } ts2sgs[] = {
01902 { B0, 0 },
01903 { B50, 50 },
01904 { B75, 75 },
01905 { B110, 1 },
01906 { B134, 134 },
01907 { B200, 2 },
01908 { B300, 3 },
01909 { B600, 6 },
01910 { B1200, 12 },
01911 { B1800, 18 },
01912 { B2400, 24 },
01913 { B4800, 48 },
01914 { B9600, 96 },
01915 { B19200, 192 },
01916 { B38400, 195 },
01917 { B57600, 194 },
01918 { B115200, 193 },
01919 };
01920
01921
01922
01923
01924 PRIVATE int tspd2sgspd(tspd)
01925 speed_t tspd;
01926 {
01927
01928 struct s2s *s;
01929
01930 for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
01931 if (s->tspd == tspd) return(s->sgspd);
01932 }
01933 return 96;
01934 }
01935
01936
01937
01938
01939 PRIVATE speed_t sgspd2tspd(sgspd)
01940 int sgspd;
01941 {
01942
01943 struct s2s *s;
01944
01945 for (s = ts2sgs; s < ts2sgs + sizeof(ts2sgs)/sizeof(ts2sgs[0]); s++) {
01946 if (s->sgspd == sgspd) return(s->tspd);
01947 }
01948 return B9600;
01949 }
01950
01951 #if ENABLE_BINCOMPAT
01952
01953
01954
01955 PRIVATE void do_ioctl_compat(tp, m_ptr)
01956 tty_t *tp;
01957 message *m_ptr;
01958 {
01959
01960
01961
01962 int minor, proc, func, result, r;
01963 long flags, erki, spek;
01964 u8_t erase, kill, intr, quit, xon, xoff, brk, eof, ispeed, ospeed;
01965 struct sgttyb sg;
01966 struct tchars tc;
01967 message reply_mess;
01968
01969 minor = m_ptr->TTY_LINE;
01970 proc = m_ptr->IO_ENDPT;
01971 func = m_ptr->REQUEST;
01972 spek = m_ptr->m2_l1;
01973 flags = m_ptr->m2_l2;
01974
01975 switch(func)
01976 {
01977 case (('t'<<8) | 8):
01978 r = compat_getp(tp, &sg);
01979 erase = sg.sg_erase;
01980 kill = sg.sg_kill;
01981 ispeed = sg.sg_ispeed;
01982 ospeed = sg.sg_ospeed;
01983 flags = sg.sg_flags;
01984 erki = ((long)ospeed<<24) | ((long)ispeed<<16) | ((long)erase<<8) |kill;
01985 break;
01986 case (('t'<<8) | 18):
01987 r = compat_getc(tp, &tc);
01988 intr = tc.t_intrc;
01989 quit = tc.t_quitc;
01990 xon = tc.t_startc;
01991 xoff = tc.t_stopc;
01992 brk = tc.t_brkc;
01993 eof = tc.t_eofc;
01994 erki = ((long)intr<<24) | ((long)quit<<16) | ((long)xon<<8) | xoff;
01995 flags = (eof << 8) | brk;
01996 break;
01997 case (('t'<<8) | 17):
01998 tc.t_stopc = (spek >> 0) & 0xFF;
01999 tc.t_startc = (spek >> 8) & 0xFF;
02000 tc.t_quitc = (spek >> 16) & 0xFF;
02001 tc.t_intrc = (spek >> 24) & 0xFF;
02002 tc.t_brkc = (flags >> 0) & 0xFF;
02003 tc.t_eofc = (flags >> 8) & 0xFF;
02004 r = compat_setc(tp, &tc);
02005 break;
02006 case (('t'<<8) | 9):
02007 sg.sg_erase = (spek >> 8) & 0xFF;
02008 sg.sg_kill = (spek >> 0) & 0xFF;
02009 sg.sg_ispeed = (spek >> 16) & 0xFF;
02010 sg.sg_ospeed = (spek >> 24) & 0xFF;
02011 sg.sg_flags = flags;
02012 r = compat_setp(tp, &sg);
02013 break;
02014 default:
02015 r = ENOTTY;
02016 }
02017 reply_mess.m_type = TASK_REPLY;
02018 reply_mess.REP_ENDPT = m_ptr->IO_ENDPT;
02019 reply_mess.REP_STATUS = r;
02020 reply_mess.m2_l1 = erki;
02021 reply_mess.m2_l2 = flags;
02022 send(m_ptr->m_source, &reply_mess);
02023 }
02024 #endif
02025 #endif
02026