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.7 89/04/11$ 13 * 14 * @(#)hpux_tty.c 7.1 (Berkeley) 05/08/90 15 */ 16 17 /* 18 * stty/gtty/termio emulation stuff 19 */ 20 #ifdef HPUXCOMPAT 21 22 #include "param.h" 23 #include "systm.h" 24 #include "user.h" 25 #include "ioctl.h" 26 #include "tty.h" 27 #include "proc.h" 28 #include "file.h" 29 #include "conf.h" 30 #include "buf.h" 31 #include "uio.h" 32 #include "kernel.h" 33 34 #include "hpux.h" 35 #include "hpux_termio.h" 36 37 char hpuxtobsdbaud[32] = { 38 B0, B50, B75, B110, B134, B150, B200, B300, 39 B600, B0, B1200, B1800, B2400, B0, B4800, B0, 40 B9600, EXTA, EXTB, B0, B0, B0, B0, B0, 41 B0, B0, B0, B0, B0, B0, B0, B0 42 }; 43 44 char bsdtohpuxbaud[16] = { 45 TIO_B0, TIO_B50, TIO_B75, TIO_B110, 46 TIO_B134, TIO_B150, TIO_B200, TIO_B300, 47 TIO_B600, TIO_B1200, TIO_B1800, TIO_B2400, 48 TIO_B4800, TIO_B9600, TIO_B19200, TIO_B38400 49 }; 50 51 /* 52 * Map BSD style sgtty info to and from SYS5 style termio stuff. 53 * Map BSD style sgtty info to and from V7 style sgtty stuff. 54 */ 55 hpuxtermio(fp, com, data) 56 struct file *fp; 57 caddr_t data; 58 { 59 struct sgttyb sg; 60 struct bsdtchars { /* avoid problem with ttychars.h */ 61 char bsdt_intrc; 62 char bsdt_quitc; 63 char bsdt_startc; 64 char bsdt_stopc; 65 char bsdt_eofc; 66 char bsdt_brkc; 67 } tc; 68 struct bsdltchars { /* avoid problem with ttychars.h */ 69 char bsdt_suspc; 70 char bsdt_dsuspc; 71 char bsdt_rprntc; 72 char bsdt_flushc; 73 char bsdt_werasc; 74 char bsdt_lnextc; 75 } ltc; 76 int lmode, (*ioctlrout)(); 77 register u_short flag; 78 register struct hpuxtermio *tiop; 79 80 ioctlrout = fp->f_ops->fo_ioctl; 81 tiop = (struct hpuxtermio *)data; 82 switch (com) { 83 case HPUXTCGETA: 84 /* get everything we might need */ 85 bzero(data, sizeof(struct hpuxtermio)); 86 if (u.u_error = ioctlrout(fp, TIOCGETP, (caddr_t)&sg)) 87 break; 88 (void) ioctlrout(fp, TIOCGETC, (caddr_t)&tc); 89 (void) ioctlrout(fp, TIOCLGET, (caddr_t)&lmode); 90 91 /* set baud rate */ 92 tiop->c_cflag = (u_short)bsdtohpuxbaud[sg.sg_ispeed&0xF]; 93 94 /* set editing chars except for EOF/EOL (set below) */ 95 tiop->c_cc[HPUXVINTR] = tc.bsdt_intrc; 96 tiop->c_cc[HPUXVQUIT] = tc.bsdt_quitc; 97 tiop->c_cc[HPUXVERASE] = sg.sg_erase; 98 tiop->c_cc[HPUXVKILL] = sg.sg_kill; 99 100 /* set flags */ 101 flag = sg.sg_flags; 102 if ((flag & TBDELAY) == XTABS) 103 tiop->c_oflag |= TIO_TAB3; 104 else if (flag & TBDELAY) 105 tiop->c_oflag |= TIO_TAB1; 106 if (flag & LCASE) { 107 tiop->c_iflag |= TIO_IUCLC; 108 tiop->c_oflag |= TIO_OLCUC; 109 tiop->c_lflag |= TIO_XCASE; 110 } 111 if (flag & ECHO) 112 tiop->c_lflag |= TIO_ECHO; 113 if (flag & CRMOD) { 114 tiop->c_iflag |= TIO_ICRNL; 115 tiop->c_oflag |= TIO_ONLCR; 116 if (flag & CR1) 117 tiop->c_oflag |= TIO_CR1; 118 if (flag & CR2) 119 tiop->c_oflag |= TIO_CR2|TIO_ONOCR; 120 } else { 121 tiop->c_oflag |= TIO_ONLRET; 122 if (flag & NL1) 123 tiop->c_oflag |= TIO_CR1; 124 if (flag & NL2) 125 tiop->c_oflag |= TIO_CR2; 126 } 127 if (flag & RAW) { 128 tiop->c_cflag |= TIO_CS8; 129 tiop->c_iflag &= ~(TIO_ICRNL|TIO_IUCLC); 130 tiop->c_cc[HPUXVMIN] = 6; 131 tiop->c_cc[HPUXVTIME] = 1; 132 } else { 133 tiop->c_iflag |= TIO_BRKINT; 134 if (tc.bsdt_startc == CSTART && tc.bsdt_stopc == CSTOP) 135 tiop->c_iflag |= TIO_IXON; 136 if (flag & TANDEM) 137 tiop->c_iflag |= TIO_IXOFF; 138 else if ((lmode & LDECCTQ) == 0) 139 tiop->c_iflag |= TIO_IXANY; 140 if ((lmode & LLITOUT) == 0) { 141 tiop->c_iflag |= TIO_IGNPAR; 142 tiop->c_oflag |= TIO_OPOST; 143 } 144 if (lmode & LPASS8) 145 tiop->c_cflag |= TIO_CS8; 146 else 147 tiop->c_iflag |= TIO_ISTRIP; 148 tiop->c_cflag |= TIO_CS7|TIO_PARENB; 149 tiop->c_lflag |= TIO_ISIG; 150 if (flag & CBREAK) { 151 tiop->c_cc[HPUXVMIN] = 6; 152 tiop->c_cc[HPUXVTIME] = 1; 153 } else { 154 tiop->c_lflag |= TIO_ICANON|TIO_ECHOK; 155 if (lmode & LCRTERA) 156 tiop->c_lflag |= TIO_ECHOE; 157 tiop->c_cc[HPUXVEOF] = tc.bsdt_eofc; 158 tiop->c_cc[HPUXVEOL] = tc.bsdt_brkc; 159 } 160 } 161 tiop->c_cflag |= TIO_PARENB; 162 if (flag & ODDP) { 163 if (flag & EVENP) 164 tiop->c_cflag &= ~TIO_PARENB; 165 tiop->c_cflag |= TIO_PARODD; 166 } 167 if (tiop->c_cflag & TIO_PARENB) 168 tiop->c_iflag |= TIO_INPCK; 169 if (flag & VTDELAY) 170 tiop->c_oflag |= TIO_FFDLY; 171 if (flag & BSDELAY) 172 tiop->c_oflag |= TIO_BSDLY; 173 break; 174 175 case HPUXTCSETA: 176 case HPUXTCSETAW: 177 case HPUXTCSETAF: 178 /* get old lmode and determine if we are a tty */ 179 if (u.u_error = ioctlrout(fp, TIOCLGET, (caddr_t)&lmode)) 180 break; 181 (void) ioctlrout(fp, TIOCGLTC, (caddr_t)<c); 182 183 /* set baud rate */ 184 sg.sg_ispeed = hpuxtobsdbaud[tiop->c_cflag&TIO_CBAUD]; 185 sg.sg_ospeed = sg.sg_ispeed; 186 187 /* set special chars to defaults for cooked mode */ 188 sg.sg_erase = tiop->c_cc[HPUXVERASE]; 189 sg.sg_kill = tiop->c_cc[HPUXVKILL]; 190 tc.bsdt_intrc = tiop->c_cc[HPUXVINTR]; 191 tc.bsdt_quitc = tiop->c_cc[HPUXVQUIT]; 192 tc.bsdt_startc = CSTART; 193 tc.bsdt_stopc = CSTOP; 194 tc.bsdt_eofc = tiop->c_cc[HPUXVEOF]; 195 tc.bsdt_brkc = tiop->c_cc[HPUXVEOL]; 196 ltc.bsdt_suspc = CSUSP; 197 ltc.bsdt_dsuspc = CDSUSP; 198 ltc.bsdt_flushc = CFLUSH; 199 ltc.bsdt_lnextc = CLNEXT; 200 201 /* set flags */ 202 flag = 0; 203 if (tiop->c_oflag & TIO_BSDLY) 204 flag |= BSDELAY; 205 if (tiop->c_oflag & TIO_FFDLY) 206 flag |= VTDELAY; 207 if (tiop->c_oflag & TIO_TAB1) { 208 if (tiop->c_oflag & TIO_TAB2) 209 flag |= XTABS; 210 else 211 flag |= TAB1; 212 } else if (tiop->c_oflag & TIO_TAB2) 213 flag |= TAB2; 214 if (tiop->c_oflag & TIO_CR1) { 215 flag |= CR1; 216 if (tiop->c_oflag & TIO_ONLRET) 217 flag |= NL1; 218 } 219 if (tiop->c_oflag & TIO_CR2) { 220 flag |= CR2; 221 if (tiop->c_oflag & TIO_ONLRET) 222 flag |= NL2; 223 } 224 if ((tiop->c_oflag & (TIO_NLDLY|TIO_ONLRET)) == TIO_NLDLY) 225 flag |= NL2; 226 if ((tiop->c_cflag & TIO_PARENB) == 0) 227 flag |= ODDP|EVENP; 228 else if (tiop->c_cflag & TIO_PARODD) 229 flag |= ODDP; 230 else 231 flag |= EVENP; 232 if ((tiop->c_iflag & TIO_ICRNL) || (tiop->c_oflag & TIO_ONLCR)) 233 flag |= CRMOD; 234 if (tiop->c_lflag & TIO_ECHO) 235 flag |= ECHO; 236 if (tiop->c_iflag & TIO_IUCLC) 237 flag |= LCASE; 238 if (tiop->c_iflag & TIO_IXOFF) 239 flag |= TANDEM; 240 if ((tiop->c_lflag & TIO_ICANON) == 0) { 241 if (tiop->c_lflag & TIO_ISIG) 242 flag |= CBREAK; 243 else 244 flag |= RAW; 245 } 246 if (flag & CBREAK) { 247 ltc.bsdt_suspc = ltc.bsdt_dsuspc = -1; 248 ltc.bsdt_flushc = ltc.bsdt_lnextc = -1; 249 if ((tiop->c_iflag & TIO_IXON) == 0) 250 tc.bsdt_startc = tc.bsdt_stopc = -1; 251 } 252 sg.sg_flags = flag; 253 lmode &= ~(LCRTERA|LLITOUT|LDECCTQ|LPASS8); 254 if (tiop->c_lflag & TIO_ECHOE) 255 lmode |= LCRTERA; 256 if ((tiop->c_oflag & TIO_OPOST) == 0) 257 lmode |= LLITOUT; 258 if ((tiop->c_iflag & TIO_IXANY) == 0) 259 lmode |= LDECCTQ; 260 if ((tiop->c_cflag & TIO_CS8) && 261 (tiop->c_iflag & TIO_ISTRIP) == 0) 262 lmode |= LPASS8; 263 264 /* set the new stuff */ 265 if (com == HPUXTCSETA) 266 com = TIOCSETN; 267 else 268 com = TIOCSETP; 269 (void) ioctlrout(fp, com, (caddr_t)&sg); 270 (void) ioctlrout(fp, TIOCSETC, (caddr_t)&tc); 271 (void) ioctlrout(fp, TIOCSLTC, (caddr_t)<c); 272 (void) ioctlrout(fp, TIOCLSET, (caddr_t)&lmode); 273 if (tiop->c_cflag & TIO_HUPCL) 274 (void) ioctlrout(fp, TIOCHPCL, (caddr_t)0); 275 break; 276 277 case HPUXTIOCGETP: 278 u.u_error = ioctlrout(fp, TIOCGETP, (caddr_t)&sg); 279 if (u.u_error) 280 break; 281 flag = sg.sg_flags; 282 sg.sg_flags &= ~(V7_HUPCL|V7_XTABS|V7_NOAL); 283 if (flag & XTABS) 284 sg.sg_flags |= V7_XTABS; 285 bcopy((caddr_t)&sg, data, sizeof sg); 286 break; 287 288 case HPUXTIOCSETP: 289 bcopy(data, (caddr_t)&sg, sizeof sg); 290 flag = sg.sg_flags; 291 sg.sg_flags &= ~(V7_HUPCL|V7_XTABS|V7_NOAL); 292 if (flag & V7_XTABS) 293 sg.sg_flags |= XTABS; 294 u.u_error = ioctlrout(fp, TIOCSETP, (caddr_t)&sg); 295 if (flag & V7_HUPCL) 296 (void) ioctlrout(fp, TIOCHPCL, (caddr_t)0); 297 break; 298 299 default: 300 break; 301 } 302 return(u.u_error); 303 } 304 305 /* #ifdef COMPAT */ 306 ohpuxgtty() 307 { 308 struct a { 309 int fdes; 310 caddr_t cmarg; 311 } *uap = (struct a *)u.u_ap; 312 313 getsettty(uap->fdes, HPUXTIOCGETP, uap->cmarg); 314 } 315 316 ohpuxstty() 317 { 318 struct a { 319 int fdes; 320 caddr_t cmarg; 321 } *uap = (struct a *)u.u_ap; 322 323 getsettty(uap->fdes, HPUXTIOCSETP, uap->cmarg); 324 } 325 326 /* 327 * Simplified version of ioctl() for use by 328 * gtty/stty and TIOCGETP/TIOCSETP. 329 */ 330 getsettty(fdes, com, cmarg) 331 int fdes, com; 332 caddr_t cmarg; 333 { 334 register struct file *fp; 335 struct hpuxsgttyb hsb; 336 struct sgttyb sb; 337 338 if ((unsigned)fdes >= NOFILE || (fp = u.u_ofile[fdes]) == NULL) { 339 u.u_error = EBADF; 340 return; 341 } 342 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 343 u.u_error = EBADF; 344 return; 345 } 346 if (com == HPUXTIOCSETP) { 347 u.u_error = copyin(cmarg, (caddr_t)&hsb, sizeof hsb); 348 if (u.u_error) 349 return; 350 sb.sg_ispeed = hsb.sg_ispeed; 351 sb.sg_ospeed = hsb.sg_ospeed; 352 sb.sg_erase = hsb.sg_erase; 353 sb.sg_kill = hsb.sg_kill; 354 sb.sg_flags = (short) hsb.sg_flags; 355 com = TIOCSETP; 356 } else { 357 bzero((caddr_t)&hsb, sizeof hsb); 358 com = TIOCGETP; 359 } 360 u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, (caddr_t)&sb); 361 if (u.u_error == 0 && com == TIOCGETP) { 362 hsb.sg_ispeed = sb.sg_ispeed; 363 hsb.sg_ospeed = sb.sg_ospeed; 364 hsb.sg_erase = sb.sg_erase; 365 hsb.sg_kill = sb.sg_kill; 366 hsb.sg_flags = (int) sb.sg_flags; 367 u.u_error = copyout((caddr_t)&hsb, cmarg, sizeof hsb); 368 } 369 } 370 /* #endif */ 371 #endif 372