change %cpu constant; new disk monitoring/cpu scheme
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
e7c0dc62 1/* tty.c 3.20 %G% */
89dc6dfb
BJ
2
3/*
50e2732b 4 * TTY subroutines common to more than one line discipline
89dc6dfb
BJ
5 */
6#include "../h/param.h"
7#include "../h/systm.h"
8#include "../h/dir.h"
9#include "../h/user.h"
10#include "../h/tty.h"
11#include "../h/proc.h"
12#include "../h/mx.h"
13#include "../h/inode.h"
14#include "../h/file.h"
15#include "../h/reg.h"
16#include "../h/conf.h"
17#include "../h/buf.h"
d1778415 18#include "../h/dk.h"
89dc6dfb
BJ
19
20char partab[];
21
d3ebf5ee
BJ
22/*
23 * When running dz's using only SAE (silo alarm) on input
24 * it is necessary to call dzrint() at clock interrupt time.
25 * This is unsafe unless spl5()s in tty code are changed to
26 * spl6()s to block clock interrupts. Note that the dh driver
27 * currently in use works the same way as the dz, even though
28 * we could try to more intelligently manage its silo.
29 * Thus don't take this out if you have no dz's unless you
30 * change clock.c and dhtimer().
31 */
32#define spl5 spl6
89dc6dfb
BJ
33
34/*
35 * Input mapping table-- if an entry is non-zero, when the
36 * corresponding character is typed preceded by "\" the escape
37 * sequence is replaced by the table value. Mostly used for
38 * upper-case only terminals.
39 */
40
41char maptab[] ={
42 000,000,000,000,000,000,000,000,
43 000,000,000,000,000,000,000,000,
44 000,000,000,000,000,000,000,000,
45 000,000,000,000,000,000,000,000,
46 000,'|',000,000,000,000,000,'`',
47 '{','}',000,000,000,000,000,000,
48 000,000,000,000,000,000,000,000,
49 000,000,000,000,000,000,000,000,
50 000,000,000,000,000,000,000,000,
51 000,000,000,000,000,000,000,000,
52 000,000,000,000,000,000,000,000,
53 000,000,000,000,000,000,'~',000,
54 000,'A','B','C','D','E','F','G',
55 'H','I','J','K','L','M','N','O',
56 'P','Q','R','S','T','U','V','W',
57 'X','Y','Z',000,000,000,000,000,
58};
59
0d65848d
BJ
60short tthiwat[16] =
61 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
62short ttlowat[16] =
63 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
64
89dc6dfb
BJ
65#define OBUFSIZ 100
66
89dc6dfb
BJ
67/*
68 * set default control characters.
69 */
70ttychars(tp)
71register struct tty *tp;
72{
8062c8a7 73
89dc6dfb
BJ
74 tun.t_intrc = CINTR;
75 tun.t_quitc = CQUIT;
76 tun.t_startc = CSTART;
77 tun.t_stopc = CSTOP;
78 tun.t_eofc = CEOT;
79 tun.t_brkc = CBRK;
80 tp->t_erase = CERASE;
81 tp->t_kill = CKILL;
8062c8a7 82/* begin local */
6fdc0335
BJ
83 tlun.t_suspc = CTRL(z);
84 tlun.t_dsuspc = CTRL(y);
8062c8a7
BJ
85 tlun.t_rprntc = CTRL(r);
86 tlun.t_flushc = CTRL(o);
87 tlun.t_werasc = CTRL(w);
88 tlun.t_lnextc = CTRL(v);
8062c8a7
BJ
89 tp->t_local = 0;
90 tp->t_lstate = 0;
91/* end local */
89dc6dfb
BJ
92}
93
94/*
50e2732b 95 * Wait for output to drain, then flush input waiting.
89dc6dfb 96 */
50e2732b 97wflushtty(tp)
89dc6dfb
BJ
98register struct tty *tp;
99{
100
50e2732b
BJ
101 (void) spl5();
102 while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
103 (*tp->t_oproc)(tp);
104 tp->t_state |= ASLEEP;
105 sleep((caddr_t)&tp->t_outq, TTOPRI);
106 }
107 flushtty(tp, FREAD|FWRITE);
108 (void) spl0();
89dc6dfb
BJ
109}
110
111/*
50e2732b 112 * flush all TTY queues
89dc6dfb 113 */
50e2732b
BJ
114flushtty(tp, rw)
115register struct tty *tp;
89dc6dfb 116{
50e2732b
BJ
117 register s;
118
119 if (tp->t_line == NETLDISC)
120 return;
121 s = spl6();
122 if (rw & FREAD) {
123 while (getc(&tp->t_canq) >= 0)
124 ;
125 wakeup((caddr_t)&tp->t_rawq);
126 }
127 if (rw & FWRITE) {
128 wakeup((caddr_t)&tp->t_outq);
129 tp->t_state &= ~TTSTOP;
130 (*cdevsw[major(tp->t_dev)].d_stop)(tp);
131 while (getc(&tp->t_outq) >= 0)
132 ;
133 }
134 if (rw & FREAD) {
135 while (getc(&tp->t_rawq) >= 0)
136 ;
137 tp->t_delct = 0;
138 tp->t_rocount = 0; /* local */
139 tp->t_rocol = 0;
140 tp->t_lstate = 0;
141 }
142 splx(s);
89dc6dfb
BJ
143}
144
50e2732b
BJ
145/*
146 * Send stop character on input overflow.
147 */
148ttyblock(tp)
149register struct tty *tp;
89dc6dfb 150{
50e2732b
BJ
151 register x;
152 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
153 if (tp->t_rawq.c_cc > TTYHOG) {
154 flushtty(tp, FREAD|FWRITE);
155 tp->t_state &= ~TBLOCK;
156 }
157 if (x >= TTYHOG/2) {
158 if (putc(tun.t_stopc, &tp->t_outq)==0) {
159 tp->t_state |= TBLOCK;
160 tp->t_char++;
161 ttstart(tp);
162 }
163 }
89dc6dfb
BJ
164}
165
101ba270 166/*
50e2732b
BJ
167 * Restart typewriter output following a delay
168 * timeout.
169 * The name of the routine is passed to the timeout
170 * subroutine and it is called during a clock interrupt.
101ba270 171 */
50e2732b 172ttrstrt(tp)
101ba270 173register struct tty *tp;
101ba270
BJ
174{
175
50e2732b
BJ
176 tp->t_state &= ~TIMEOUT;
177 ttstart(tp);
101ba270
BJ
178}
179
89dc6dfb 180/*
50e2732b
BJ
181 * Start output on the typewriter. It is used from the top half
182 * after some characters have been put on the output queue,
183 * from the interrupt routine to transmit the next
184 * character, and after a timeout has finished.
89dc6dfb 185 */
50e2732b
BJ
186ttstart(tp)
187register struct tty *tp;
89dc6dfb 188{
50e2732b 189 register s;
8062c8a7 190
50e2732b
BJ
191 s = spl5();
192 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
193 (*tp->t_oproc)(tp);
194 splx(s);
89dc6dfb
BJ
195}
196
197/*
50e2732b 198 * Common code for tty ioctls.
89dc6dfb 199 */
50e2732b 200ttioctl(com, tp, addr, dev, flag)
89dc6dfb
BJ
201register struct tty *tp;
202caddr_t addr;
203{
204 unsigned t;
8062c8a7 205 struct sgttyb iocb;
de857265 206 struct clist tq;
89dc6dfb 207 extern int nldisp;
50450a20 208 register c;
da1392b6 209 int temp;
89dc6dfb 210
c6fe3a50
BJ
211 /*
212 * This is especially so that isatty() will
213 * fail when carrier is gone.
214 */
215 if ((tp->t_state&CARR_ON) == 0) {
216 u.u_error = EBADF;
217 return (1);
218 }
219
50e2732b
BJ
220 /*
221 * If the ioctl involves modification,
222 * insist on being able to write the device,
223 * and hang if in the background.
224 */
225 switch(com) {
226
c6fe3a50
BJ
227 case TIOCSETD:
228 case TIOCSETP:
229 case TIOCSETN:
50e2732b
BJ
230 case TIOCFLUSH:
231 case TIOCSETC:
232 case TIOCSLTC:
233 case TIOCSPGRP:
234 case TIOCLBIS:
235 case TIOCLBIC:
236 case TIOCLSET:
237 case TIOCSTI:
c6fe3a50 238/* this is reasonable, but impractical...
50e2732b
BJ
239 if ((flag & FWRITE) == 0) {
240 u.u_error = EBADF;
241 return (1);
242 }
c6fe3a50 243 */
50e2732b
BJ
244 while (tp->t_line == NTTYDISC &&
245 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
246 (u.u_procp->p_flag&SVFORK) == 0 &&
247 u.u_signal[SIGTTOU] != SIG_IGN &&
248 u.u_signal[SIGTTOU] != SIG_HOLD &&
249 (u.u_procp->p_flag&SDETACH)==0) {
250 gsignal(u.u_procp->p_pgrp, SIGTTOU);
251 sleep((caddr_t)&lbolt, TTOPRI);
252 }
253 break;
254 }
255
256 /*
257 * Process the ioctl.
258 */
89dc6dfb
BJ
259 switch(com) {
260
261 /*
50e2732b 262 * Get discipline number
89dc6dfb
BJ
263 */
264 case TIOCGETD:
265 t = tp->t_line;
266 if (copyout((caddr_t)&t, addr, sizeof(t)))
267 u.u_error = EFAULT;
268 break;
269
270 /*
50e2732b 271 * Set line discipline
89dc6dfb
BJ
272 */
273 case TIOCSETD:
274 if (copyin(addr, (caddr_t)&t, sizeof(t))) {
275 u.u_error = EFAULT;
276 break;
277 }
278 if (t >= nldisp) {
279 u.u_error = ENXIO;
280 break;
281 }
8062c8a7 282 (void) spl5();
89dc6dfb
BJ
283 if (tp->t_line)
284 (*linesw[tp->t_line].l_close)(tp);
285 if (t)
286 (*linesw[t].l_open)(dev, tp, addr);
287 if (u.u_error==0)
288 tp->t_line = t;
8062c8a7 289 (void) spl0();
89dc6dfb
BJ
290 break;
291
292 /*
50e2732b 293 * Prevent more opens on channel
89dc6dfb
BJ
294 */
295 case TIOCEXCL:
296 tp->t_state |= XCLUDE;
297 break;
298
299 case TIOCNXCL:
300 tp->t_state &= ~XCLUDE;
301 break;
302
303 /*
304 * Set new parameters
305 */
306 case TIOCSETP:
de857265 307 case TIOCSETN:
89dc6dfb
BJ
308 if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
309 u.u_error = EFAULT;
310 return(1);
311 }
101ba270 312 (void) spl5();
8062c8a7
BJ
313 if (tp->t_line == 0) {
314 if (com == TIOCSETP)
315 wflushtty(tp);
316 while (canon(tp)>=0)
317 ;
e7c0dc62
BJ
318#ifdef notdef
319 wakeup((caddr_t)&tp->t_rawq);
320#endif
8062c8a7
BJ
321 } else if (tp->t_line == NTTYDISC) {
322 if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
323 com == TIOCSETP)
324 wflushtty(tp);
325 else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
326 if (iocb.sg_flags & CBREAK) {
327 catq(&tp->t_rawq, &tp->t_canq);
328 tq = tp->t_rawq;
329 tp->t_rawq = tp->t_canq;
330 tp->t_canq = tq;
331 } else {
332 tp->t_local |= LPENDIN;
333 if (tp->t_canq.c_cc)
334 panic("ioccom canq");
e7c0dc62 335#ifdef notdef
8062c8a7
BJ
336 if (tp->t_chan)
337 (void) sdata(tp->t_chan);
338 else
e7c0dc62 339#endif
8062c8a7
BJ
340 wakeup((caddr_t)&tp->t_rawq);
341 }
342 }
343 }
89dc6dfb 344 if ((tp->t_state&SPEEDS)==0) {
8062c8a7
BJ
345 tp->t_ispeed = iocb.sg_ispeed;
346 tp->t_ospeed = iocb.sg_ospeed;
89dc6dfb 347 }
8062c8a7
BJ
348 tp->t_erase = iocb.sg_erase;
349 tp->t_kill = iocb.sg_kill;
350 tp->t_flags = iocb.sg_flags;
101ba270 351 (void) spl0();
89dc6dfb
BJ
352 break;
353
354 /*
50e2732b 355 * Send current parameters to user
89dc6dfb
BJ
356 */
357 case TIOCGETP:
8062c8a7
BJ
358 iocb.sg_ispeed = tp->t_ispeed;
359 iocb.sg_ospeed = tp->t_ospeed;
360 iocb.sg_erase = tp->t_erase;
361 iocb.sg_kill = tp->t_kill;
362 iocb.sg_flags = tp->t_flags;
89dc6dfb
BJ
363 if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
364 u.u_error = EFAULT;
365 break;
366
367 /*
368 * Hang up line on last close
369 */
89dc6dfb
BJ
370 case TIOCHPCL:
371 tp->t_state |= HUPCLS;
372 break;
373
374 case TIOCFLUSH:
07f8c7d2 375 flushtty(tp, FREAD|FWRITE);
89dc6dfb
BJ
376 break;
377
378 /*
50e2732b 379 * Ioctl entries to line discipline
89dc6dfb
BJ
380 */
381 case DIOCSETP:
382 case DIOCGETP:
101ba270
BJ
383 if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
384 u.u_error = ENOTTY;
89dc6dfb
BJ
385 break;
386
387 /*
50e2732b 388 * Set and fetch special characters
89dc6dfb
BJ
389 */
390 case TIOCSETC:
8062c8a7 391 if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
89dc6dfb
BJ
392 u.u_error = EFAULT;
393 break;
394
395 case TIOCGETC:
8062c8a7
BJ
396 if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
397 u.u_error = EFAULT;
398 break;
399
400/* local ioctls */
50e2732b
BJ
401 /*
402 * Set/get local special characters.
403 */
8062c8a7
BJ
404 case TIOCSLTC:
405 if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
406 u.u_error = EFAULT;
407 break;
408
409 case TIOCGLTC:
410 if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
411 u.u_error = EFAULT;
412 break;
413
50e2732b
BJ
414 /*
415 * Return number of characters immediately available.
416 */
8062c8a7 417 case FIONREAD: {
d1778415 418 off_t nread;
8062c8a7 419
d1778415
BJ
420 switch (tp->t_line) {
421
422 case NETLDISC:
423 nread = tp->t_rec ? tp->t_inbuf : 0;
424 break;
425
6d27b2c6
BJ
426 case 0:
427 (void) spl5();
428 while (canon(tp)>=0)
429 ;
430 (void) spl0();
431 /* fall into ... */
432
d1778415
BJ
433 case NTTYDISC:
434 nread = tp->t_canq.c_cc;
435 if (tp->t_flags & (RAW|CBREAK))
436 nread += tp->t_rawq.c_cc;
437 break;
438
d1778415 439 }
8062c8a7
BJ
440 if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
441 u.u_error = EFAULT;
442 break;
443 }
444
445 /*
446 * Should allow SPGRP and GPGRP only if tty open for reading.
447 */
448 case TIOCSPGRP:
da1392b6
BJ
449 if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
450 u.u_error = EFAULT;
8062c8a7
BJ
451 break;
452
453 case TIOCGPGRP:
454 if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
455 u.u_error = EFAULT;
456 break;
457
458 /*
459 * Modify local mode word.
460 */
461 case TIOCLBIS:
da1392b6
BJ
462 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
463 u.u_error = EFAULT;
464 else
465 tp->t_local |= temp;
8062c8a7
BJ
466 break;
467
468 case TIOCLBIC:
da1392b6
BJ
469 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
470 u.u_error = EFAULT;
471 else
472 tp->t_local &= ~temp;
8062c8a7
BJ
473 break;
474
475 case TIOCLSET:
da1392b6
BJ
476 if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
477 u.u_error = EFAULT;
478 else
479 tp->t_local = temp;
8062c8a7
BJ
480 break;
481
482 case TIOCLGET:
483 if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
89dc6dfb
BJ
484 u.u_error = EFAULT;
485 break;
486
50e2732b
BJ
487 /*
488 * Return number of characters in
489 * the output.
490 */
0dde1c43
BJ
491 case TIOCOUTQ:
492 if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
493 u.u_error = EFAULT;
494 break;
495
50e2732b
BJ
496 /*
497 * Simulate typing of a character at the terminal.
498 */
50450a20
BJ
499 case TIOCSTI:
500 c = fubyte(addr);
501 if (u.u_uid && u.u_ttyp != tp || c < 0)
502 u.u_error = EFAULT;
503 else
504 (*linesw[tp->t_line].l_rint)(c, tp);
505 break;
8062c8a7 506/* end of locals */
50450a20 507
89dc6dfb
BJ
508 default:
509 return(0);
510 }
511 return(1);
512}