xref: /original-bsd/sys/hp/hpux/hpux_tty.c (revision 333da485)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1990, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: hpux_tty.c 1.14 93/08/05$
13  *
14  *	@(#)hpux_tty.c	8.3 (Berkeley) 01/12/94
15  */
16 
17 /*
18  * stty/gtty/termio emulation stuff
19  */
20 #ifdef HPUXCOMPAT
21 #ifndef COMPAT_43
22 #define COMPAT_43
23 #endif
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/filedesc.h>
28 #include <sys/ioctl.h>
29 #include <sys/proc.h>
30 #include <sys/tty.h>
31 #include <sys/file.h>
32 #include <sys/conf.h>
33 #include <sys/buf.h>
34 #include <sys/kernel.h>
35 
36 #include <hp/hpux/hpux.h>
37 #include <hp/hpux/hpux_termio.h>
38 
39 /*
40  * Map BSD/POSIX style termios info to and from SYS5 style termio stuff.
41  */
42 hpuxtermio(fd, com, data, p)
43 	int fd, com;
44 	caddr_t data;
45 	struct proc *p;
46 {
47 	struct file *fp;
48 	struct termios tios;
49 	struct hpuxtermios htios;
50 	int line, error, (*ioctlrout)();
51 	int newi = 0;
52 
53 	fp = p->p_fd->fd_ofiles[fd];
54 	ioctlrout = fp->f_ops->fo_ioctl;
55 	switch (com) {
56 	case HPUXTCGETATTR:
57 		newi = 1;
58 		/* fall into ... */
59 	case HPUXTCGETA:
60 		/*
61 		 * Get BSD terminal state
62 		 */
63 		if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p))
64 			break;
65 		bzero((char *)&htios, sizeof htios);
66 		/*
67 		 * Set iflag.
68 		 * Same through ICRNL, no BSD equivs for IUCLC, IENQAK
69 		 */
70 		htios.c_iflag = tios.c_iflag & 0x1ff;
71 		if (tios.c_iflag & IXON)
72 			htios.c_iflag |= TIO_IXON;
73 		if (tios.c_iflag & IXOFF)
74 			htios.c_iflag |= TIO_IXOFF;
75 		if (tios.c_iflag & IXANY)
76 			htios.c_iflag |= TIO_IXANY;
77 		/*
78 		 * Set oflag.
79 		 * No BSD equivs for OLCUC/OCRNL/ONOCR/ONLRET/OFILL/OFDEL
80 		 * or any of the delays.
81 		 */
82 		if (tios.c_oflag & OPOST)
83 			htios.c_oflag |= TIO_OPOST;
84 		if (tios.c_oflag & ONLCR)
85 			htios.c_oflag |= TIO_ONLCR;
86 		if (tios.c_oflag & OXTABS)
87 			htios.c_oflag |= TIO_TAB3;
88 		/*
89 		 * Set cflag.
90 		 * Baud from ospeed, rest from cflag.
91 		 */
92 		htios.c_cflag = bsdtohpuxbaud(tios.c_ospeed);
93 		switch (tios.c_cflag & CSIZE) {
94 		case CS5:
95 			htios.c_cflag |= TIO_CS5; break;
96 		case CS6:
97 			htios.c_cflag |= TIO_CS6; break;
98 		case CS7:
99 			htios.c_cflag |= TIO_CS7; break;
100 		case CS8:
101 			htios.c_cflag |= TIO_CS8; break;
102 		}
103 		if (tios.c_cflag & CSTOPB)
104 			htios.c_cflag |= TIO_CSTOPB;
105 		if (tios.c_cflag & CREAD)
106 			htios.c_cflag |= TIO_CREAD;
107 		if (tios.c_cflag & PARENB)
108 			htios.c_cflag |= TIO_PARENB;
109 		if (tios.c_cflag & PARODD)
110 			htios.c_cflag |= TIO_PARODD;
111 		if (tios.c_cflag & HUPCL)
112 			htios.c_cflag |= TIO_HUPCL;
113 		if (tios.c_cflag & CLOCAL)
114 			htios.c_cflag |= TIO_CLOCAL;
115 		/*
116 		 * Set lflag.
117 		 * No BSD equiv for XCASE.
118 		 */
119 		if (tios.c_lflag & ECHOE)
120 			htios.c_lflag |= TIO_ECHOE;
121 		if (tios.c_lflag & ECHOK)
122 			htios.c_lflag |= TIO_ECHOK;
123 		if (tios.c_lflag & ECHO)
124 			htios.c_lflag |= TIO_ECHO;
125 		if (tios.c_lflag & ECHONL)
126 			htios.c_lflag |= TIO_ECHONL;
127 		if (tios.c_lflag & ISIG)
128 			htios.c_lflag |= TIO_ISIG;
129 		if (tios.c_lflag & ICANON)
130 			htios.c_lflag |= TIO_ICANON;
131 		if (tios.c_lflag & NOFLSH)
132 			htios.c_lflag |= TIO_NOFLSH;
133 		/*
134 		 * Line discipline
135 		 */
136 		if (!newi) {
137 			line = 0;
138 			(void) (*ioctlrout)(fp, TIOCGETD, (caddr_t)&line, p);
139 			htios.c_reserved = line;
140 		}
141 		/*
142 		 * Set editing chars.
143 		 * No BSD equiv for VSWTCH.
144 		 */
145 		htios.c_cc[HPUXVINTR] = tios.c_cc[VINTR];
146 		htios.c_cc[HPUXVQUIT] = tios.c_cc[VQUIT];
147 		htios.c_cc[HPUXVERASE] = tios.c_cc[VERASE];
148 		htios.c_cc[HPUXVKILL] = tios.c_cc[VKILL];
149 		htios.c_cc[HPUXVEOF] = tios.c_cc[VEOF];
150 		htios.c_cc[HPUXVEOL] = tios.c_cc[VEOL];
151 		htios.c_cc[HPUXVEOL2] = tios.c_cc[VEOL2];
152 		htios.c_cc[HPUXVSWTCH] = 0;
153 #if 1
154 		/*
155 		 * XXX since VMIN and VTIME are not implemented,
156 		 * we need to return something reasonable.
157 		 * Otherwise a GETA/SETA combo would always put
158 		 * the tty in non-blocking mode (since VMIN == VTIME == 0).
159 		 */
160 		if (fp->f_flag & FNONBLOCK) {
161 			htios.c_cc[HPUXVMINS] = 0;
162 			htios.c_cc[HPUXVTIMES] = 0;
163 		} else {
164 			htios.c_cc[HPUXVMINS] = 6;
165 			htios.c_cc[HPUXVTIMES] = 1;
166 		}
167 #else
168 		htios.c_cc[HPUXVMINS] = tios.c_cc[VMIN];
169 		htios.c_cc[HPUXVTIMES] = tios.c_cc[VTIME];
170 #endif
171 		htios.c_cc[HPUXVSUSP] = tios.c_cc[VSUSP];
172 		htios.c_cc[HPUXVSTART] = tios.c_cc[VSTART];
173 		htios.c_cc[HPUXVSTOP] = tios.c_cc[VSTOP];
174 		if (newi)
175 			bcopy((char *)&htios, data, sizeof htios);
176 		else
177 			termiostotermio(&htios, (struct hpuxtermio *)data);
178 		break;
179 
180 	case HPUXTCSETATTR:
181 	case HPUXTCSETATTRD:
182 	case HPUXTCSETATTRF:
183 		newi = 1;
184 		/* fall into ... */
185 	case HPUXTCSETA:
186 	case HPUXTCSETAW:
187 	case HPUXTCSETAF:
188 		/*
189 		 * Get old characteristics and determine if we are a tty.
190 		 */
191 		if (error = (*ioctlrout)(fp, TIOCGETA, (caddr_t)&tios, p))
192 			break;
193 		if (newi)
194 			bcopy(data, (char *)&htios, sizeof htios);
195 		else
196 			termiototermios((struct termio *)data, &htios, &tios);
197 		/*
198 		 * Set iflag.
199 		 * Same through ICRNL, no HP-UX equiv for IMAXBEL
200 		 */
201 		tios.c_iflag &= ~(IXON|IXOFF|IXANY|0x1ff);
202 		tios.c_iflag |= htios.c_iflag & 0x1ff;
203 		if (htios.c_iflag & TIO_IXON)
204 			tios.c_iflag |= IXON;
205 		if (htios.c_iflag & TIO_IXOFF)
206 			tios.c_iflag |= IXOFF;
207 		if (htios.c_iflag & TIO_IXANY)
208 			tios.c_iflag |= IXANY;
209 		/*
210 		 * Set oflag.
211 		 * No HP-UX equiv for ONOEOT
212 		 */
213 		tios.c_oflag &= ~(OPOST|ONLCR|OXTABS);
214 		if (htios.c_oflag & TIO_OPOST)
215 			tios.c_oflag |= OPOST;
216 		if (htios.c_oflag & TIO_ONLCR)
217 			tios.c_oflag |= ONLCR;
218 		if (htios.c_oflag & TIO_TAB3)
219 			tios.c_oflag |= OXTABS;
220 		/*
221 		 * Set cflag.
222 		 * No HP-UX equiv for CCTS_OFLOW/CCTS_IFLOW/MDMBUF
223 		 */
224 		tios.c_cflag &=
225 			~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL);
226 		switch (htios.c_cflag & TIO_CSIZE) {
227 		case TIO_CS5:
228 			tios.c_cflag |= CS5; break;
229 		case TIO_CS6:
230 			tios.c_cflag |= CS6; break;
231 		case TIO_CS7:
232 			tios.c_cflag |= CS7; break;
233 		case TIO_CS8:
234 			tios.c_cflag |= CS8; break;
235 		}
236 		if (htios.c_cflag & TIO_CSTOPB)
237 			tios.c_cflag |= CSTOPB;
238 		if (htios.c_cflag & TIO_CREAD)
239 			tios.c_cflag |= CREAD;
240 		if (htios.c_cflag & TIO_PARENB)
241 			tios.c_cflag |= PARENB;
242 		if (htios.c_cflag & TIO_PARODD)
243 			tios.c_cflag |= PARODD;
244 		if (htios.c_cflag & TIO_HUPCL)
245 			tios.c_cflag |= HUPCL;
246 		if (htios.c_cflag & TIO_CLOCAL)
247 			tios.c_cflag |= CLOCAL;
248 		/*
249 		 * Set lflag.
250 		 * No HP-UX equiv for ECHOKE/ECHOPRT/ECHOCTL
251 		 * IEXTEN treated as part of ICANON
252 		 */
253 		tios.c_lflag &= ~(ECHOE|ECHOK|ECHO|ISIG|ICANON|IEXTEN|NOFLSH);
254 		if (htios.c_lflag & TIO_ECHOE)
255 			tios.c_lflag |= ECHOE;
256 		if (htios.c_lflag & TIO_ECHOK)
257 			tios.c_lflag |= ECHOK;
258 		if (htios.c_lflag & TIO_ECHO)
259 			tios.c_lflag |= ECHO;
260 		if (htios.c_lflag & TIO_ECHONL)
261 			tios.c_lflag |= ECHONL;
262 		if (htios.c_lflag & TIO_ISIG)
263 			tios.c_lflag |= ISIG;
264 		if (htios.c_lflag & TIO_ICANON)
265 			tios.c_lflag |= (ICANON|IEXTEN);
266 		if (htios.c_lflag & TIO_NOFLSH)
267 			tios.c_lflag |= NOFLSH;
268 		/*
269 		 * Set editing chars.
270 		 * No HP-UX equivs of VWERASE/VREPRINT/VDSUSP/VLNEXT
271 		 * /VDISCARD/VSTATUS/VERASE2
272 		 */
273 		tios.c_cc[VINTR] = htios.c_cc[HPUXVINTR];
274 		tios.c_cc[VQUIT] = htios.c_cc[HPUXVQUIT];
275 		tios.c_cc[VERASE] = htios.c_cc[HPUXVERASE];
276 		tios.c_cc[VKILL] = htios.c_cc[HPUXVKILL];
277 		tios.c_cc[VEOF] = htios.c_cc[HPUXVEOF];
278 		tios.c_cc[VEOL] = htios.c_cc[HPUXVEOL];
279 		tios.c_cc[VEOL2] = htios.c_cc[HPUXVEOL2];
280 		tios.c_cc[VMIN] = htios.c_cc[HPUXVMINS];
281 		tios.c_cc[VTIME] = htios.c_cc[HPUXVTIMES];
282 		tios.c_cc[VSUSP] = htios.c_cc[HPUXVSUSP];
283 		tios.c_cc[VSTART] = htios.c_cc[HPUXVSTART];
284 		tios.c_cc[VSTOP] = htios.c_cc[HPUXVSTOP];
285 
286 		/*
287 		 * Set the new stuff
288 		 */
289 		if (com == HPUXTCSETA || com == HPUXTCSETATTR)
290 			com = TIOCSETA;
291 		else if (com == HPUXTCSETAW || com == HPUXTCSETATTRD)
292 			com = TIOCSETAW;
293 		else
294 			com = TIOCSETAF;
295 		error = (*ioctlrout)(fp, com, (caddr_t)&tios, p);
296 		if (error == 0) {
297 			/*
298 			 * Set line discipline
299 			 */
300 			if (!newi) {
301 				line = htios.c_reserved;
302 				(void) (*ioctlrout)(fp, TIOCSETD,
303 						    (caddr_t)&line, p);
304 			}
305 			/*
306 			 * Set non-blocking IO if VMIN == VTIME == 0, clear
307 			 * if not.  Should handle the other cases as well.
308 			 * Note it isn't correct to just turn NBIO off like
309 			 * we do as it could be on as the result of a fcntl
310 			 * operation.
311 			 *
312 			 * XXX - wouldn't need to do this at all if VMIN/VTIME
313 			 * were implemented.
314 			 */
315 			{
316 				struct hpuxfcntl_args {
317 					int fdes, cmd, arg;
318 				} args;
319 				int flags, nbio;
320 
321 				nbio = (htios.c_cc[HPUXVMINS] == 0 &&
322 					htios.c_cc[HPUXVTIMES] == 0);
323 				if (nbio && (fp->f_flag & FNONBLOCK) == 0 ||
324 				    !nbio && (fp->f_flag & FNONBLOCK)) {
325 					args.fdes = fd;
326 					args.cmd = F_GETFL;
327 					args.arg = 0;
328 					(void) hpuxfcntl(p, &args, &flags);
329 					if (nbio)
330 						flags |= HPUXNDELAY;
331 					else
332 						flags &= ~HPUXNDELAY;
333 					args.cmd = F_SETFL;
334 					args.arg = flags;
335 					(void) hpuxfcntl(p, &args, &flags);
336 				}
337 			}
338 		}
339 		break;
340 
341 	default:
342 		error = EINVAL;
343 		break;
344 	}
345 	return(error);
346 }
347 
348 termiototermios(tio, tios, bsdtios)
349 	struct hpuxtermio *tio;
350 	struct hpuxtermios *tios;
351 	struct termios *bsdtios;
352 {
353 	int i;
354 
355 	bzero((char *)tios, sizeof *tios);
356 	tios->c_iflag = tio->c_iflag;
357 	tios->c_oflag = tio->c_oflag;
358 	tios->c_cflag = tio->c_cflag;
359 	tios->c_lflag = tio->c_lflag;
360 	tios->c_reserved = tio->c_line;
361 	for (i = 0; i <= HPUXVSWTCH; i++)
362 		tios->c_cc[i] = tio->c_cc[i];
363 	if (tios->c_lflag & TIO_ICANON) {
364 		tios->c_cc[HPUXVEOF] = tio->c_cc[HPUXVEOF];
365 		tios->c_cc[HPUXVEOL] = tio->c_cc[HPUXVEOL];
366 		tios->c_cc[HPUXVMINS] = 0;
367 		tios->c_cc[HPUXVTIMES] = 0;
368 	} else {
369 		tios->c_cc[HPUXVEOF] = 0;
370 		tios->c_cc[HPUXVEOL] = 0;
371 		tios->c_cc[HPUXVMINS] = tio->c_cc[HPUXVMIN];
372 		tios->c_cc[HPUXVTIMES] = tio->c_cc[HPUXVTIME];
373 	}
374 	tios->c_cc[HPUXVSUSP] = bsdtios->c_cc[VSUSP];
375 	tios->c_cc[HPUXVSTART] = bsdtios->c_cc[VSTART];
376 	tios->c_cc[HPUXVSTOP] = bsdtios->c_cc[VSTOP];
377 }
378 
379 termiostotermio(tios, tio)
380 	struct hpuxtermios *tios;
381 	struct hpuxtermio *tio;
382 {
383 	int i;
384 
385 	tio->c_iflag = tios->c_iflag;
386 	tio->c_oflag = tios->c_oflag;
387 	tio->c_cflag = tios->c_cflag;
388 	tio->c_lflag = tios->c_lflag;
389 	tio->c_line = tios->c_reserved;
390 	for (i = 0; i <= HPUXVSWTCH; i++)
391 		tio->c_cc[i] = tios->c_cc[i];
392 	if (tios->c_lflag & TIO_ICANON) {
393 		tio->c_cc[HPUXVEOF] = tios->c_cc[HPUXVEOF];
394 		tio->c_cc[HPUXVEOL] = tios->c_cc[HPUXVEOL];
395 	} else {
396 		tio->c_cc[HPUXVMIN] = tios->c_cc[HPUXVMINS];
397 		tio->c_cc[HPUXVTIME] = tios->c_cc[HPUXVTIMES];
398 	}
399 }
400 
401 bsdtohpuxbaud(bsdspeed)
402 	long bsdspeed;
403 {
404 	switch (bsdspeed) {
405 	case B0:     return(TIO_B0);
406 	case B50:    return(TIO_B50);
407 	case B75:    return(TIO_B75);
408 	case B110:   return(TIO_B110);
409 	case B134:   return(TIO_B134);
410 	case B150:   return(TIO_B150);
411 	case B200:   return(TIO_B200);
412 	case B300:   return(TIO_B300);
413 	case B600:   return(TIO_B600);
414 	case B1200:  return(TIO_B1200);
415 	case B1800:  return(TIO_B1800);
416 	case B2400:  return(TIO_B2400);
417 	case B4800:  return(TIO_B4800);
418 	case B9600:  return(TIO_B9600);
419 	case B19200: return(TIO_B19200);
420 	case B38400: return(TIO_B38400);
421 	default:     return(TIO_B0);
422 	}
423 }
424 
425 hpuxtobsdbaud(hpuxspeed)
426 	int hpuxspeed;
427 {
428 	static char hpuxtobsdbaudtab[32] = {
429 		B0,	B50,	B75,	B110,	B134,	B150,	B200,	B300,
430 		B600,	B0,	B1200,	B1800,	B2400,	B0,	B4800,	B0,
431 		B9600,	B19200,	B38400,	B0,	B0,	B0,	B0,	B0,
432 		B0,	B0,	B0,	B0,	B0,	B0,	EXTA,	EXTB
433 	};
434 
435 	return(hpuxtobsdbaudtab[hpuxspeed & TIO_CBAUD]);
436 }
437 
438 #ifdef COMPAT_OHPUX
439 struct ohpuxsgtty_args {
440 	int	fdes;
441 	caddr_t	cmarg;
442 };
443 ohpuxgtty(p, uap, retval)
444 	struct proc *p;
445 	struct ohpuxsgtty_args *uap;
446 	int *retval;
447 {
448 
449 	return (getsettty(p, uap->fdes, HPUXTIOCGETP, uap->cmarg));
450 }
451 
452 ohpuxstty(p, uap, retval)
453 	struct proc *p;
454 	struct ohpuxsgtty_args *uap;
455 	int *retval;
456 {
457 
458 	return (getsettty(p, uap->fdes, HPUXTIOCSETP, uap->cmarg));
459 }
460 
461 /*
462  * Simplified version of ioctl() for use by
463  * gtty/stty and TIOCGETP/TIOCSETP.
464  */
465 getsettty(p, fdes, com, cmarg)
466 	struct proc *p;
467 	int fdes, com;
468 	caddr_t cmarg;
469 {
470 	register struct filedesc *fdp = p->p_fd;
471 	register struct file *fp;
472 	struct hpuxsgttyb hsb;
473 	struct sgttyb sb;
474 	int error;
475 
476 	if (((unsigned)fdes) >= fdp->fd_nfiles ||
477 	    (fp = fdp->fd_ofiles[fdes]) == NULL)
478 		return (EBADF);
479 	if ((fp->f_flag & (FREAD|FWRITE)) == 0)
480 		return (EBADF);
481 	if (com == HPUXTIOCSETP) {
482 		if (error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb))
483 			return (error);
484 		sb.sg_ispeed = hsb.sg_ispeed;
485 		sb.sg_ospeed = hsb.sg_ospeed;
486 		sb.sg_erase = hsb.sg_erase;
487 		sb.sg_kill = hsb.sg_kill;
488 		sb.sg_flags = hsb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL);
489 		if (hsb.sg_flags & V7_XTABS)
490 			sb.sg_flags |= XTABS;
491 		if (hsb.sg_flags & V7_HUPCL)
492 			(void)(*fp->f_ops->fo_ioctl)
493 				(fp, TIOCHPCL, (caddr_t)0, p);
494 		com = TIOCSETP;
495 	} else {
496 		bzero((caddr_t)&hsb, sizeof hsb);
497 		com = TIOCGETP;
498 	}
499 	error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb, p);
500 	if (error == 0 && com == TIOCGETP) {
501 		hsb.sg_ispeed = sb.sg_ispeed;
502 		hsb.sg_ospeed = sb.sg_ospeed;
503 		hsb.sg_erase = sb.sg_erase;
504 		hsb.sg_kill = sb.sg_kill;
505 		hsb.sg_flags = sb.sg_flags & ~(V7_HUPCL|V7_XTABS|V7_NOAL);
506 		if (sb.sg_flags & XTABS)
507 			hsb.sg_flags |= V7_XTABS;
508 		error = copyout((caddr_t)&hsb, cmarg, sizeof hsb);
509 	}
510 	return (error);
511 }
512 #endif
513 #endif
514