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