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