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