138624Skarels /* 238624Skarels * Datakit terminal driver 338624Skarels * SCCSID[] = "@(#)dktty.c 1.8 Garage 84/05/14" 4*45182Skarels * "@(#)dktty.c 1.3 (Berkeley) 09/03/90" 538624Skarels */ 638624Skarels 738624Skarels #include "dktty.h" 838624Skarels #if NDKTTY>0 938624Skarels #include "datakit.h" 1038624Skarels 1138624Skarels #include "param.h" 1238624Skarels #include "../machine/pte.h" 1338624Skarels #include "syslog.h" 1438624Skarels #include "errno.h" 1538624Skarels #include "signal.h" 1638624Skarels #include "conf.h" 1738624Skarels #include "user.h" 1838624Skarels #include "proc.h" 1938624Skarels #include "ioctl.h" 2038624Skarels #include "tty.h" 2138624Skarels #include "file.h" 2238624Skarels #include "mbuf.h" 2338624Skarels #include "uio.h" 2438624Skarels #include "kernel.h" 2538624Skarels #include "dkit.h" 2638624Skarels #include "dk.h" 2738624Skarels #include "dkdev.h" 2838624Skarels 2938624Skarels extern int dk_nchan; 3038624Skarels extern struct dkdev dkdev[]; 3138624Skarels 3238624Skarels struct tty dkt[NDATAKIT]; 3338624Skarels caddr_t dktibuf[NDATAKIT]; /* Input buffer pointers */ 3438624Skarels int dktpaused[NDATAKIT]; /* delays for no output mbuf */ 35*45182Skarels 36*45182Skarels #ifdef notdef 37*45182Skarels speeds aren't used, don't bother 3838624Skarels int dktdelay[] = { /* Time to wait on close before dropping line */ 3938624Skarels 4, 15, 15, 15, 15, 15, 15, 8, /* B0-B300 */ 4038624Skarels 4, 2, 2, 2, 1, 1, 1, 1 4138624Skarels }; 4238624Skarels static char dkt_tmr[16] = { 4338624Skarels 15, 15, 15, 15, 15, 15, 15, 15, 4438624Skarels 15, 9, 6, 4, 2, 1, 15, 15 4538624Skarels } ; 46*45182Skarels #endif 4738624Skarels 48*45182Skarels int dktstart(); 4938624Skarels 50*45182Skarels 5138624Skarels /* 5238624Skarels * DKT control messages 5338624Skarels */ 5438624Skarels #define D_BREAK 0110 5538624Skarels #define D_DELAY 0100 5638624Skarels 5738624Skarels extern int dkdebug ; 5838624Skarels 5938624Skarels #define DEBUG (dkdebug < 512) 6038624Skarels #define devDEBUG (minor(dev) >= dkdebug) 6138624Skarels #define chanDEBUG (chan >= dkdebug) 6238624Skarels #define tpDEBUG ((tp - dkt) >= dkdebug) 6338624Skarels 6438624Skarels /* 6538624Skarels * Open a DKT line. 6638624Skarels */ 6738624Skarels dktopen(dev, flag) 6838624Skarels { 6938624Skarels register struct tty *tp; 7038624Skarels register struct dkdev *dv; 7138624Skarels register d; 7238624Skarels int chan; 7338624Skarels 7438624Skarels d = minor(dev); 7538624Skarels if (d >= dk_nchan) { 7638624Skarels if (DEBUG) log(LOG_ERR, "dkt_open(%d) error\n", dev); 7738624Skarels return ENXIO; 7838624Skarels } 7938624Skarels tp = &dkt[d]; 8038624Skarels if ((tp->t_state&TS_XCLUDE) && u.u_uid!=0) 8138624Skarels return (EBUSY); 8238624Skarels if (!dktibuf[d]) { 8338624Skarels struct mbuf *mb; 8438624Skarels mb = m_get(M_WAIT, DKMT_ITTY); 8538624Skarels if (mb == NULL) return ENOBUFS; 8638624Skarels dktibuf[d] = mtod(mb, caddr_t); 8738624Skarels } 8838624Skarels if ((chan = dk_open(d, (int (*)()) NULL)) < 0) { 8938624Skarels return -chan; 9038624Skarels } 9138624Skarels 9238624Skarels tp->t_oproc = dktstart; 9338624Skarels tp->t_state |= (TS_WOPEN|TS_CARR_ON); 9438624Skarels dv = &dkdev[d]; 9538624Skarels if ((tp->t_state&TS_ISOPEN) == 0) { 9638624Skarels ttychars(tp) ; 9738624Skarels if (tp->t_ispeed == 0) { 98*45182Skarels tp->t_iflag = TTYDEF_IFLAG; 99*45182Skarels tp->t_oflag = TTYDEF_OFLAG; 100*45182Skarels tp->t_lflag = TTYDEF_LFLAG; 101*45182Skarels tp->t_cflag = TTYDEF_CFLAG; 102*45182Skarels tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 103*45182Skarels ttsetwater(tp); 10438624Skarels } 10538624Skarels if (devDEBUG) log(LOG_ERR, "DKT_open(%x,%o)\n",dev,flag); 10638624Skarels } 10738624Skarels dktfcon(tp); 10838624Skarels if (devDEBUG) log(LOG_ERR, "DKT_open(%x, %x) ok\n", dev, tp); 10938624Skarels dv->d_prot |= DpTTY; 11038624Skarels return (*linesw[tp->t_line].l_open)(dev, tp); 11138624Skarels } 11238624Skarels 11338624Skarels /* 11438624Skarels * Close a DKT line. 11538624Skarels */ 11638624Skarels /*ARGSUSED*/ 11738624Skarels dktclose(dev, flag) 11838624Skarels dev_t dev; 11938624Skarels int flag; 12038624Skarels { 12138624Skarels register struct tty *tp; 12238624Skarels register struct dkdev *dv; 12338624Skarels register int d, s; 12438624Skarels extern int dktcflush(), dktrcv(), wakeup(); 12538624Skarels 12638624Skarels d = minor(dev); 12738624Skarels tp = &dkt[d]; 12838624Skarels dv = &dkdev[d]; 12938624Skarels /* 13038624Skarels * If called from exit(), give output 30 seconds to drain. 13138624Skarels * Otherwise let output drain first. 13238624Skarels */ 13338624Skarels if(u.u_signal[SIGKILL] == SIG_IGN){ 13438624Skarels s = spl5(); 13538624Skarels timeout(dktcflush, (caddr_t) tp, 30*hz); 13638624Skarels ttywflush(tp) ; 13738624Skarels untimeout(dktcflush, (caddr_t) tp); 13838624Skarels tp->t_state &= ~TS_CARR_ON; 13938624Skarels if(dv->d_prot == DpTTY) /* no other protocols open */ 14038624Skarels dk_reset(d); 14138624Skarels splx(s); 14238624Skarels } 14338624Skarels 14438624Skarels (*linesw[tp->t_line].l_close)(tp); 14538624Skarels if (devDEBUG) log(LOG_ERR, "DKT_clos(%x)\n",dev); 14638624Skarels dv->d_prot &= ~DpTTY; 14738624Skarels tp->t_state &= ~TS_CARR_ON; 148*45182Skarels #ifdef notdef 14938624Skarels /* Wait for output to drain on far end */ 15038624Skarels if (dktdelay[tp->t_ispeed] > 0) { 15138624Skarels timeout(wakeup, (caddr_t) tp, dktdelay[tp->t_ispeed] * hz); 15238624Skarels sleep((caddr_t) tp, TTIPRI); 15338624Skarels } 154*45182Skarels #endif 15538624Skarels if(!dv->d_prot){ 15638624Skarels (void) dk_close(d); 15738624Skarels (void) dk_takedown(d); 15838624Skarels dv->d_state = 0; 15938624Skarels } 16038624Skarels else (void) dk_rabort(d, dktrcv, (caddr_t) tp); 16138624Skarels ttyclose(tp); 16238624Skarels s = spl5(); 16338624Skarels if (dktibuf[d]) { 16438624Skarels (void) m_free(dtom(dktibuf[d])); 16538624Skarels dktibuf[d] = NULL; 16638624Skarels } 16738624Skarels splx(s); 16838624Skarels } 16938624Skarels 17038624Skarels static 17138624Skarels dktcflush(tp) 17238624Skarels struct tty *tp; 17338624Skarels { 17438624Skarels ttyflush(tp, (FREAD|FWRITE)) ; 17538624Skarels } 17638624Skarels 17738624Skarels /* 17838624Skarels * Read from a DKT line. 17938624Skarels */ 180*45182Skarels dktread(dev, uio, flag) 181*45182Skarels dev_t dev; 18238624Skarels struct uio *uio; 18338624Skarels { 18438624Skarels register struct tty *tp; 18538624Skarels int err; 18638624Skarels 18738624Skarels if (devDEBUG) log(LOG_ERR, "dktread(%x) %d\n", dev, uio->uio_resid) ; 18838624Skarels tp = &dkt[minor(dev)]; 189*45182Skarels err = (*linesw[tp->t_line].l_read)(tp, uio, flag); 19038624Skarels if (devDEBUG) 19138624Skarels log(LOG_ERR, "dktread done(%x) %d err=%d\n", dev, uio->uio_resid, err) ; 19238624Skarels dktfcon(tp); 19338624Skarels return err; 19438624Skarels } 19538624Skarels 19638624Skarels /* 19738624Skarels * Write on a DKT line 19838624Skarels */ 199*45182Skarels dktwrite(dev, uio, flag) 200*45182Skarels dev_t dev; 20138624Skarels struct uio *uio; 20238624Skarels { 20338624Skarels register struct tty *tp; 20438624Skarels 20538624Skarels if (devDEBUG) log(LOG_ERR, "dktwrite(%x)\n",dev); 20638624Skarels tp = &dkt[minor(dev)]; 207*45182Skarels return (*linesw[tp->t_line].l_write)(tp, uio, flag); 20838624Skarels } 20938624Skarels 21038624Skarels /* 21138624Skarels * Receive a packet 21238624Skarels */ 21338624Skarels /*ARGSUSED*/ 21438624Skarels dktrcv(tp, chan, resid, rmode, rctl) 21538624Skarels register struct tty *tp ; 21638624Skarels { 21738624Skarels register c ; 21838624Skarels register char *cp ; 21938624Skarels register count ; 22038624Skarels 22138624Skarels if ((rmode & DKR_ABORT) || (dk_status(chan) & DK_RESET)) { 22238624Skarels dktshut(tp) ; 22338624Skarels return ; 22438624Skarels } 22538624Skarels /* Process input data */ 22638624Skarels if (tp->t_state&TS_ISOPEN) { 22738624Skarels cp = dktibuf[tp-dkt]; 22838624Skarels count = MLEN - resid ; 22938624Skarels if (count) { 23038624Skarels do { 23138624Skarels /* Should really do parity checking... */ 23238624Skarels (*linesw[tp->t_line].l_rint)((*cp++)&0377, tp) ; 23338624Skarels } while (--count); 23438624Skarels } 23538624Skarels if ((c = (rctl & 0377)) != 0) { 23638624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_ctl 0%o on %d\n",c,chan); 237*45182Skarels if (c==D_BREAK) 238*45182Skarels (*linesw[tp->t_line].l_rint)(TTY_FE, tp) ; 23938624Skarels } 24038624Skarels } 24138624Skarels dktfcon(tp) ; 24238624Skarels } 24338624Skarels 24438624Skarels 24538624Skarels /* 24638624Skarels * Input flow control: queue another receive unless to many chars waiting 24738624Skarels */ 24838624Skarels dktfcon(tp) 24938624Skarels register struct tty *tp; 25038624Skarels { 25138624Skarels register int d = tp - dkt; 25238624Skarels register x; 25338624Skarels 25438624Skarels if ((dk_status(d) & (DK_RCV|DK_OPEN)) != DK_OPEN) 25538624Skarels return ; 25638624Skarels if (dktibuf[d] == NULL) return; 25738624Skarels x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 258*45182Skarels if (x >= TTYHOG/2 && (!(tp->t_lflag&ICANON) || tp->t_canq.c_cc)) 25938624Skarels return; 26038624Skarels (void) dk_recv(d, dktibuf[d], MLEN, 261*45182Skarels #ifdef notdef 26238624Skarels DKR_BLOCK | DKR_TIME | (dkt_tmr[tp->t_ispeed]<<8), 263*45182Skarels #endif 264*45182Skarels DKR_BLOCK | DKR_TIME | (1<<8), 26538624Skarels dktrcv, (caddr_t) tp) ; 26638624Skarels } 26738624Skarels 26838624Skarels /* 26938624Skarels * stty/gtty for DKT 27038624Skarels */ 27138624Skarels dktioctl(dev, cmd, data, flag) 27238624Skarels caddr_t data; 27338624Skarels { 27438624Skarels register struct tty *tp; 27538624Skarels int error; 27638624Skarels 27738624Skarels tp = &dkt[minor(dev)]; 27838624Skarels error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 27938624Skarels if (error >= 0) 28038624Skarels return error; 28138624Skarels error = ttioctl(tp, cmd, data, flag); 28238624Skarels if (error >= 0) { 28338624Skarels if (tp->t_ispeed == 0) { 28438624Skarels tp->t_state &= ~TS_CARR_ON; 28538624Skarels if (devDEBUG) log(LOG_ERR, "DKT_ioctl carr off\n"); 286*45182Skarels gsignal(tp->t_pgid, SIGHUP); 287*45182Skarels gsignal(tp->t_pgid, SIGCONT); 28838624Skarels } 28938624Skarels return (error); 29038624Skarels } 29138624Skarels 29238624Skarels switch(cmd) { 29338624Skarels case TIOCSBRK: 29438624Skarels dktxpack(tp-dkt, D_BREAK) ; 29538624Skarels return 0; 29638624Skarels case TIOCCBRK: 29738624Skarels return 0; 29838624Skarels } 29938624Skarels return ENOTTY; 30038624Skarels } 30138624Skarels 30238624Skarels /* 30338624Skarels * Start (restart) transmission on the given DKT line. 30438624Skarels */ 30538624Skarels dktstart(tp) 30638624Skarels register struct tty *tp; 30738624Skarels { 30838624Skarels register d; 30938624Skarels char delay; 31038624Skarels extern dktxdun() ; 31138624Skarels int s, c; 31238624Skarels register int nch; 31338624Skarels register struct mbuf *m; 31438624Skarels extern ttrstrt(); 31538624Skarels 31638624Skarels d = tp - dkt; 31738624Skarels s = spl5() ; 31838624Skarels 31938624Skarels #ifdef notdef 32038624Skarels if (dk_status(d) & DK_SPND) 32138624Skarels dk_cmd(d, DKC_RSME) ; 32238624Skarels #endif 32338624Skarels 32438624Skarels if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 32538624Skarels goto out; 32638624Skarels 32738624Skarels /* 32838624Skarels * If the writer was sleeping on output overflow, 32938624Skarels * wake the process when low tide is reached. 33038624Skarels */ 331*45182Skarels if (tp->t_outq.c_cc<=tp->t_lowat) { 33238624Skarels if (tp->t_state&TS_ASLEEP) { 33338624Skarels tp->t_state &= ~TS_ASLEEP; 33438624Skarels wakeup((caddr_t)&tp->t_outq); 33538624Skarels } 33638624Skarels if (tp->t_wsel) { 33738624Skarels selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 33838624Skarels tp->t_wsel = 0; 33938624Skarels tp->t_state &= ~TS_WCOLL; 34038624Skarels } 34138624Skarels } 34238624Skarels /* 34338624Skarels * Now restart transmission unless the output queue is 34438624Skarels * empty. 34538624Skarels */ 34638624Skarels if (tp->t_outq.c_cc == 0) 34738624Skarels goto out; 34838624Skarels 34938624Skarels m = m_get(M_DONTWAIT, DKMT_OTTY); 35038624Skarels if (m == NULL) { 35138624Skarels /* No buffers; arrange to retry in .5 seconds */ 35238624Skarels dktpaused[d]++; 35338624Skarels tp->t_state |= TS_TIMEOUT; 35438624Skarels timeout(ttrstrt, (caddr_t) tp, hz/2); 35538624Skarels goto out; 35638624Skarels } 357*45182Skarels if (1 || !(tp->t_oflag&OPOST)) 35838624Skarels nch = ndqb(&tp->t_outq, 0); 35938624Skarels else { 36038624Skarels nch = ndqb(&tp->t_outq, 0200); 36138624Skarels /* 36238624Skarels * If first thing on queue is a delay process it. 36338624Skarels */ 36438624Skarels if (nch == 0) { 36538624Skarels nch = getc(&tp->t_outq); 36638624Skarels c = MIN((nch & 0xff) + 6, 0x7f); 36738624Skarels delay = D_DELAY; 36838624Skarels if (tpDEBUG) 36938624Skarels log(LOG_ERR, "DKT_delay %d\n", c) ; 37038624Skarels while (c) { 37138624Skarels delay++; 37238624Skarels c >>= 1; 37338624Skarels } 37438624Skarels if (dk_xmit(d, (struct mbuf *) NULL, 1, delay, dktxdun, (caddr_t) 0)) 37538624Skarels tp->t_state |= TS_BUSY; 37638624Skarels (void) m_free(m); 37738624Skarels goto out; 37838624Skarels } 37938624Skarels } 38038624Skarels /* 38138624Skarels * If characters to transmit, restart transmission. 38238624Skarels */ 38338624Skarels if (nch) { 38438624Skarels bcopy((caddr_t)tp->t_outq.c_cf, mtod(m, caddr_t), (unsigned) nch); 38538624Skarels m->m_len = nch; 38638624Skarels if (dk_xmit(d, m, 1, 0, dktxdun, (caddr_t) nch)) 38738624Skarels tp->t_state |= TS_BUSY; 38838624Skarels } 38938624Skarels else (void) m_free(m); 39038624Skarels out: ; 39138624Skarels splx(s) ; 39238624Skarels } 39338624Skarels 39438624Skarels dktxpack(chan, cmd) 39538624Skarels char cmd; 39638624Skarels { 39738624Skarels (void) dk_xmit(chan, (struct mbuf *) NULL, 1, cmd, (int (*)()) 0, (caddr_t) 0); 39838624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_sent %o on %d\n",cmd&0377,chan); 39938624Skarels } 40038624Skarels 40138624Skarels /*ARGSUSED*/ 40238624Skarels dktstop(tp, rw) 40338624Skarels register struct tty *tp; 40438624Skarels { 40538624Skarels register int s, d; 40638624Skarels 40738624Skarels d = tp - dkt; 40838624Skarels s = spl5(); 40938624Skarels if (tp->t_state & TS_BUSY) { 41038624Skarels #ifdef notdef 41138624Skarels dk_cmd(d, DKC_SPND); 41238624Skarels #endif 41338624Skarels if ((tp->t_state & TS_TTSTOP) == 0) { 41438624Skarels tp->t_state |= TS_FLUSH; 41538624Skarels dk_cmd(d, DKC_FLUSH); 41638624Skarels } 41738624Skarels } 41838624Skarels splx(s); 41938624Skarels } 42038624Skarels 42138624Skarels dktshut(tp) 42238624Skarels register struct tty *tp; 42338624Skarels { 42438624Skarels if (tpDEBUG) log(LOG_ERR, "dktshut %d\n", tp-dkt); 42538624Skarels if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_CARR_ON)) { 426*45182Skarels if (tpDEBUG) log(LOG_ERR, "DKT_sighup %d\n",tp->t_pgid); 427*45182Skarels gsignal(tp->t_pgid, SIGHUP); 428*45182Skarels gsignal(tp->t_pgid, SIGCONT); 42938624Skarels } 43038624Skarels tp->t_state &= ~TS_CARR_ON; 43138624Skarels ttyflush(tp, (FREAD|FWRITE)) ; 43238624Skarels dk_cmd((tp - dkt), DKC_FLUSH); 43338624Skarels } 43438624Skarels 43538624Skarels 43638624Skarels dktxdun(cnt, chan) 43738624Skarels { 43838624Skarels register struct tty *tp ; 43938624Skarels 44038624Skarels tp = &dkt[chan]; 44138624Skarels if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; 44238624Skarels else ndflush(&tp->t_outq, cnt); 44338624Skarels tp->t_state &= ~TS_BUSY; 44438624Skarels if (tp->t_line) 44538624Skarels (*linesw[tp->t_line].l_start)(tp); 44638624Skarels else 44738624Skarels dktstart(tp); 44838624Skarels } 44938624Skarels #endif 450