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