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