1 /* 2 * Datakit terminal driver 3 * SCCSID[] = "@(#)dktty.c 1.8 Garage 84/05/14" 4 */ 5 6 #include "dktty.h" 7 #if NDKTTY>0 8 #include "datakit.h" 9 10 #include "param.h" 11 #include "../machine/pte.h" 12 #include "syslog.h" 13 #include "errno.h" 14 #include "signal.h" 15 #include "conf.h" 16 #include "dir.h" 17 #include "user.h" 18 #include "proc.h" 19 #include "ioctl.h" 20 #include "tty.h" 21 #include "file.h" 22 #include "mbuf.h" 23 #include "uio.h" 24 #include "kernel.h" 25 #include "dkit.h" 26 #include "dk.h" 27 #include "dkdev.h" 28 29 extern int dk_nchan; 30 extern struct dkdev dkdev[]; 31 32 struct tty dkt[NDATAKIT]; 33 caddr_t dktibuf[NDATAKIT]; /* Input buffer pointers */ 34 int dktpaused[NDATAKIT]; /* delays for no output mbuf */ 35 int dktdelay[] = { /* Time to wait on close before dropping line */ 36 4, 15, 15, 15, 15, 15, 15, 8, /* B0-B300 */ 37 4, 2, 2, 2, 1, 1, 1, 1 38 }; 39 40 int dktstart(); 41 42 static char dkt_tmr[16] = { 43 15, 15, 15, 15, 15, 15, 15, 15, 44 15, 9, 6, 4, 2, 1, 15, 15 45 } ; 46 47 48 /* 49 * DKT control messages 50 */ 51 #define D_BREAK 0110 52 #define D_DELAY 0100 53 54 #define DKTSPEED B9600 55 #define DKTFLAGS (EVENP|ODDP|ECHO) 56 57 extern int dkdebug ; 58 59 #define DEBUG (dkdebug < 512) 60 #define devDEBUG (minor(dev) >= dkdebug) 61 #define chanDEBUG (chan >= dkdebug) 62 #define tpDEBUG ((tp - dkt) >= dkdebug) 63 64 /* 65 * Open a DKT line. 66 */ 67 dktopen(dev, flag) 68 { 69 register struct tty *tp; 70 register struct dkdev *dv; 71 register d; 72 int chan; 73 74 d = minor(dev); 75 if (d >= dk_nchan) { 76 if (DEBUG) log(LOG_ERR, "dkt_open(%d) error\n", dev); 77 return ENXIO; 78 } 79 tp = &dkt[d]; 80 if ((tp->t_state&TS_XCLUDE) && u.u_uid!=0) 81 return (EBUSY); 82 if (!dktibuf[d]) { 83 struct mbuf *mb; 84 mb = m_get(M_WAIT, DKMT_ITTY); 85 if (mb == NULL) return ENOBUFS; 86 dktibuf[d] = mtod(mb, caddr_t); 87 } 88 if ((chan = dk_open(d, (int (*)()) NULL)) < 0) { 89 return -chan; 90 } 91 92 tp->t_oproc = dktstart; 93 tp->t_state |= (TS_WOPEN|TS_CARR_ON); 94 dv = &dkdev[d]; 95 if ((tp->t_state&TS_ISOPEN) == 0) { 96 ttychars(tp) ; 97 if (tp->t_ispeed == 0) { 98 tp->t_ispeed = tp->t_ospeed = DKTSPEED; 99 tp->t_flags = DKTFLAGS; 100 } 101 if (devDEBUG) log(LOG_ERR, "DKT_open(%x,%o)\n",dev,flag); 102 } 103 dktfcon(tp); 104 if (devDEBUG) log(LOG_ERR, "DKT_open(%x, %x) ok\n", dev, tp); 105 dv->d_prot |= DpTTY; 106 return (*linesw[tp->t_line].l_open)(dev, tp); 107 } 108 109 /* 110 * Close a DKT line. 111 */ 112 /*ARGSUSED*/ 113 dktclose(dev, flag) 114 dev_t dev; 115 int flag; 116 { 117 register struct tty *tp; 118 register struct dkdev *dv; 119 register int d, s; 120 extern int dktcflush(), dktrcv(), wakeup(); 121 122 d = minor(dev); 123 tp = &dkt[d]; 124 dv = &dkdev[d]; 125 /* 126 * If called from exit(), give output 30 seconds to drain. 127 * Otherwise let output drain first. 128 */ 129 if(u.u_signal[SIGKILL] == SIG_IGN){ 130 s = spl5(); 131 timeout(dktcflush, (caddr_t) tp, 30*hz); 132 ttywflush(tp) ; 133 untimeout(dktcflush, (caddr_t) tp); 134 tp->t_state &= ~TS_CARR_ON; 135 if(dv->d_prot == DpTTY) /* no other protocols open */ 136 dk_reset(d); 137 splx(s); 138 } 139 140 (*linesw[tp->t_line].l_close)(tp); 141 if (devDEBUG) log(LOG_ERR, "DKT_clos(%x)\n",dev); 142 dv->d_prot &= ~DpTTY; 143 tp->t_state &= ~TS_CARR_ON; 144 /* Wait for output to drain on far end */ 145 if (dktdelay[tp->t_ispeed] > 0) { 146 timeout(wakeup, (caddr_t) tp, dktdelay[tp->t_ispeed] * hz); 147 sleep((caddr_t) tp, TTIPRI); 148 } 149 if(!dv->d_prot){ 150 (void) dk_close(d); 151 (void) dk_takedown(d); 152 dv->d_state = 0; 153 } 154 else (void) dk_rabort(d, dktrcv, (caddr_t) tp); 155 ttyclose(tp); 156 s = spl5(); 157 if (dktibuf[d]) { 158 (void) m_free(dtom(dktibuf[d])); 159 dktibuf[d] = NULL; 160 } 161 splx(s); 162 } 163 164 static 165 dktcflush(tp) 166 struct tty *tp; 167 { 168 ttyflush(tp, (FREAD|FWRITE)) ; 169 } 170 171 /* 172 * Read from a DKT line. 173 */ 174 dktread(dev, uio) 175 struct uio *uio; 176 { 177 register struct tty *tp; 178 int err; 179 180 if (devDEBUG) log(LOG_ERR, "dktread(%x) %d\n", dev, uio->uio_resid) ; 181 tp = &dkt[minor(dev)]; 182 err = (*linesw[tp->t_line].l_read)(tp, uio); 183 if (devDEBUG) 184 log(LOG_ERR, "dktread done(%x) %d err=%d\n", dev, uio->uio_resid, err) ; 185 dktfcon(tp); 186 return err; 187 } 188 189 /* 190 * Write on a DKT line 191 */ 192 dktwrite(dev, uio) 193 struct uio *uio; 194 { 195 register struct tty *tp; 196 197 if (devDEBUG) log(LOG_ERR, "dktwrite(%x)\n",dev); 198 tp = &dkt[minor(dev)]; 199 return (*linesw[tp->t_line].l_write)(tp, uio); 200 } 201 202 /* 203 * Receive a packet 204 */ 205 /*ARGSUSED*/ 206 dktrcv(tp, chan, resid, rmode, rctl) 207 register struct tty *tp ; 208 { 209 register c ; 210 register char *cp ; 211 register count ; 212 213 if ((rmode & DKR_ABORT) || (dk_status(chan) & DK_RESET)) { 214 dktshut(tp) ; 215 return ; 216 } 217 /* Process input data */ 218 if (tp->t_state&TS_ISOPEN) { 219 cp = dktibuf[tp-dkt]; 220 count = MLEN - resid ; 221 if (count) { 222 do { 223 /* Should really do parity checking... */ 224 (*linesw[tp->t_line].l_rint)((*cp++)&0377, tp) ; 225 } while (--count); 226 } 227 if ((c = (rctl & 0377)) != 0) { 228 if (chanDEBUG) log(LOG_ERR, "DKT_ctl 0%o on %d\n",c,chan); 229 if (c==D_BREAK) { 230 /* 231 * At framing error (break) generate 232 * a null (in raw mode, for getty), or a 233 * interrupt (in cooked/cbreak mode). 234 */ 235 if (tp->t_flags&RAW) 236 c = 0; 237 else 238 c = tp->t_intrc; 239 (*linesw[tp->t_line].l_rint)(c, tp) ; 240 } 241 } 242 } 243 dktfcon(tp) ; 244 } 245 246 247 /* 248 * Input flow control: queue another receive unless to many chars waiting 249 */ 250 dktfcon(tp) 251 register struct tty *tp; 252 { 253 register int d = tp - dkt; 254 register x; 255 256 if ((dk_status(d) & (DK_RCV|DK_OPEN)) != DK_OPEN) 257 return ; 258 if (dktibuf[d] == NULL) return; 259 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 260 if (x >= TTYHOG/2 && (tp->t_delct>0 || (tp->t_flags&(RAW|CBREAK)))) 261 return; 262 (void) dk_recv(d, dktibuf[d], MLEN, 263 DKR_BLOCK | DKR_TIME | (dkt_tmr[tp->t_ispeed]<<8), 264 dktrcv, (caddr_t) tp) ; 265 } 266 267 /* 268 * stty/gtty for DKT 269 */ 270 dktioctl(dev, cmd, data, flag) 271 caddr_t data; 272 { 273 register struct tty *tp; 274 int error; 275 276 tp = &dkt[minor(dev)]; 277 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 278 if (error >= 0) 279 return error; 280 error = ttioctl(tp, cmd, data, flag); 281 if (error >= 0) { 282 if (tp->t_ispeed == 0) { 283 tp->t_state &= ~TS_CARR_ON; 284 if (devDEBUG) log(LOG_ERR, "DKT_ioctl carr off\n"); 285 gsignal(tp->t_pgrp, SIGHUP); 286 gsignal(tp->t_pgrp, SIGCONT); 287 } 288 return (error); 289 } 290 291 switch(cmd) { 292 case TIOCSBRK: 293 dktxpack(tp-dkt, D_BREAK) ; 294 return 0; 295 case TIOCCBRK: 296 return 0; 297 } 298 return ENOTTY; 299 } 300 301 /* 302 * Start (restart) transmission on the given DKT line. 303 */ 304 dktstart(tp) 305 register struct tty *tp; 306 { 307 register d; 308 char delay; 309 extern dktxdun() ; 310 int s, c; 311 register int nch; 312 register struct mbuf *m; 313 extern ttrstrt(); 314 315 d = tp - dkt; 316 s = spl5() ; 317 318 #ifdef notdef 319 if (dk_status(d) & DK_SPND) 320 dk_cmd(d, DKC_RSME) ; 321 #endif 322 323 if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 324 goto out; 325 326 /* 327 * If the writer was sleeping on output overflow, 328 * wake the process when low tide is reached. 329 */ 330 if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 331 if (tp->t_state&TS_ASLEEP) { 332 tp->t_state &= ~TS_ASLEEP; 333 wakeup((caddr_t)&tp->t_outq); 334 } 335 if (tp->t_wsel) { 336 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 337 tp->t_wsel = 0; 338 tp->t_state &= ~TS_WCOLL; 339 } 340 } 341 /* 342 * Now restart transmission unless the output queue is 343 * empty. 344 */ 345 if (tp->t_outq.c_cc == 0) 346 goto out; 347 348 m = m_get(M_DONTWAIT, DKMT_OTTY); 349 if (m == NULL) { 350 /* No buffers; arrange to retry in .5 seconds */ 351 dktpaused[d]++; 352 tp->t_state |= TS_TIMEOUT; 353 timeout(ttrstrt, (caddr_t) tp, hz/2); 354 goto out; 355 } 356 if (tp->t_flags & (RAW|LITOUT)) 357 nch = ndqb(&tp->t_outq, 0); 358 else { 359 nch = ndqb(&tp->t_outq, 0200); 360 /* 361 * If first thing on queue is a delay process it. 362 */ 363 if (nch == 0) { 364 nch = getc(&tp->t_outq); 365 c = MIN((nch & 0xff) + 6, 0x7f); 366 delay = D_DELAY; 367 if (tpDEBUG) 368 log(LOG_ERR, "DKT_delay %d\n", c) ; 369 while (c) { 370 delay++; 371 c >>= 1; 372 } 373 if (dk_xmit(d, (struct mbuf *) NULL, 1, delay, dktxdun, (caddr_t) 0)) 374 tp->t_state |= TS_BUSY; 375 (void) m_free(m); 376 goto out; 377 } 378 } 379 /* 380 * If characters to transmit, restart transmission. 381 */ 382 if (nch) { 383 bcopy((caddr_t)tp->t_outq.c_cf, mtod(m, caddr_t), (unsigned) nch); 384 m->m_len = nch; 385 if (dk_xmit(d, m, 1, 0, dktxdun, (caddr_t) nch)) 386 tp->t_state |= TS_BUSY; 387 } 388 else (void) m_free(m); 389 out: ; 390 splx(s) ; 391 } 392 393 dktxpack(chan, cmd) 394 char cmd; 395 { 396 (void) dk_xmit(chan, (struct mbuf *) NULL, 1, cmd, (int (*)()) 0, (caddr_t) 0); 397 if (chanDEBUG) log(LOG_ERR, "DKT_sent %o on %d\n",cmd&0377,chan); 398 } 399 400 /*ARGSUSED*/ 401 dktstop(tp, rw) 402 register struct tty *tp; 403 { 404 register int s, d; 405 406 d = tp - dkt; 407 s = spl5(); 408 if (tp->t_state & TS_BUSY) { 409 #ifdef notdef 410 dk_cmd(d, DKC_SPND); 411 #endif 412 if ((tp->t_state & TS_TTSTOP) == 0) { 413 tp->t_state |= TS_FLUSH; 414 dk_cmd(d, DKC_FLUSH); 415 } 416 } 417 splx(s); 418 } 419 420 dktshut(tp) 421 register struct tty *tp; 422 { 423 if (tpDEBUG) log(LOG_ERR, "dktshut %d\n", tp-dkt); 424 if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_CARR_ON)) { 425 if (tpDEBUG) log(LOG_ERR, "DKT_sighup %d\n",tp->t_pgrp); 426 gsignal(tp->t_pgrp, SIGHUP); 427 gsignal(tp->t_pgrp, SIGCONT); 428 } 429 tp->t_state &= ~TS_CARR_ON; 430 ttyflush(tp, (FREAD|FWRITE)) ; 431 dk_cmd((tp - dkt), DKC_FLUSH); 432 } 433 434 435 dktxdun(cnt, chan) 436 { 437 register struct tty *tp ; 438 439 tp = &dkt[chan]; 440 if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; 441 else ndflush(&tp->t_outq, cnt); 442 tp->t_state &= ~TS_BUSY; 443 if (tp->t_line) 444 (*linesw[tp->t_line].l_start)(tp); 445 else 446 dktstart(tp); 447 } 448 #endif 449