138624Skarels /* 238624Skarels * Datakit terminal driver 338624Skarels * SCCSID[] = "@(#)dktty.c 1.8 Garage 84/05/14" 4*45800Sbostic * "@(#)dktty.c 1.5 (Berkeley) 12/16/90" 538624Skarels */ 638624Skarels 738624Skarels #include "dktty.h" 838624Skarels #if NDKTTY>0 938624Skarels #include "datakit.h" 1038624Skarels 11*45800Sbostic #include "../include/pte.h" 12*45800Sbostic #include "sys/param.h" 13*45800Sbostic #include "sys/syslog.h" 14*45800Sbostic #include "sys/errno.h" 15*45800Sbostic #include "sys/signal.h" 16*45800Sbostic #include "sys/conf.h" 17*45800Sbostic #include "sys/user.h" 18*45800Sbostic #include "sys/proc.h" 19*45800Sbostic #include "sys/ioctl.h" 20*45800Sbostic #include "sys/tty.h" 21*45800Sbostic #include "sys/file.h" 22*45800Sbostic #include "sys/mbuf.h" 23*45800Sbostic #include "sys/uio.h" 24*45800Sbostic #include "sys/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 */ 3545182Skarels 3645182Skarels #ifdef notdef 3745182Skarels 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 } ; 4645182Skarels #endif 4738624Skarels 4845182Skarels int dktstart(); 4938624Skarels 5045182Skarels 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) { 9845182Skarels tp->t_iflag = TTYDEF_IFLAG; 9945182Skarels tp->t_oflag = TTYDEF_OFLAG; 10045182Skarels tp->t_lflag = TTYDEF_LFLAG; 10145182Skarels tp->t_cflag = TTYDEF_CFLAG; 10245182Skarels tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 10345182Skarels 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; 14845182Skarels #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 } 15445182Skarels #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); 16845184Skarels return (0); 16938624Skarels } 17038624Skarels 17138624Skarels static 17238624Skarels dktcflush(tp) 17338624Skarels struct tty *tp; 17438624Skarels { 17538624Skarels ttyflush(tp, (FREAD|FWRITE)) ; 17638624Skarels } 17738624Skarels 17838624Skarels /* 17938624Skarels * Read from a DKT line. 18038624Skarels */ 18145182Skarels dktread(dev, uio, flag) 18245182Skarels dev_t dev; 18338624Skarels struct uio *uio; 18438624Skarels { 18538624Skarels register struct tty *tp; 18638624Skarels int err; 18738624Skarels 18838624Skarels if (devDEBUG) log(LOG_ERR, "dktread(%x) %d\n", dev, uio->uio_resid) ; 18938624Skarels tp = &dkt[minor(dev)]; 19045182Skarels err = (*linesw[tp->t_line].l_read)(tp, uio, flag); 19138624Skarels if (devDEBUG) 19238624Skarels log(LOG_ERR, "dktread done(%x) %d err=%d\n", dev, uio->uio_resid, err) ; 19338624Skarels dktfcon(tp); 19438624Skarels return err; 19538624Skarels } 19638624Skarels 19738624Skarels /* 19838624Skarels * Write on a DKT line 19938624Skarels */ 20045182Skarels dktwrite(dev, uio, flag) 20145182Skarels dev_t dev; 20238624Skarels struct uio *uio; 20338624Skarels { 20438624Skarels register struct tty *tp; 20538624Skarels 20638624Skarels if (devDEBUG) log(LOG_ERR, "dktwrite(%x)\n",dev); 20738624Skarels tp = &dkt[minor(dev)]; 20845182Skarels return (*linesw[tp->t_line].l_write)(tp, uio, flag); 20938624Skarels } 21038624Skarels 21138624Skarels /* 21238624Skarels * Receive a packet 21338624Skarels */ 21438624Skarels /*ARGSUSED*/ 21538624Skarels dktrcv(tp, chan, resid, rmode, rctl) 21638624Skarels register struct tty *tp ; 21738624Skarels { 21838624Skarels register c ; 21938624Skarels register char *cp ; 22038624Skarels register count ; 22138624Skarels 22238624Skarels if ((rmode & DKR_ABORT) || (dk_status(chan) & DK_RESET)) { 22338624Skarels dktshut(tp) ; 22438624Skarels return ; 22538624Skarels } 22638624Skarels /* Process input data */ 22738624Skarels if (tp->t_state&TS_ISOPEN) { 22838624Skarels cp = dktibuf[tp-dkt]; 22938624Skarels count = MLEN - resid ; 23038624Skarels if (count) { 23138624Skarels do { 23238624Skarels /* Should really do parity checking... */ 23338624Skarels (*linesw[tp->t_line].l_rint)((*cp++)&0377, tp) ; 23438624Skarels } while (--count); 23538624Skarels } 23638624Skarels if ((c = (rctl & 0377)) != 0) { 23738624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_ctl 0%o on %d\n",c,chan); 23845182Skarels if (c==D_BREAK) 23945182Skarels (*linesw[tp->t_line].l_rint)(TTY_FE, tp) ; 24038624Skarels } 24138624Skarels } 24238624Skarels dktfcon(tp) ; 24338624Skarels } 24438624Skarels 24538624Skarels 24638624Skarels /* 24738624Skarels * Input flow control: queue another receive unless to many chars waiting 24838624Skarels */ 24938624Skarels dktfcon(tp) 25038624Skarels register struct tty *tp; 25138624Skarels { 25238624Skarels register int d = tp - dkt; 25338624Skarels register x; 25438624Skarels 25538624Skarels if ((dk_status(d) & (DK_RCV|DK_OPEN)) != DK_OPEN) 25638624Skarels return ; 25738624Skarels if (dktibuf[d] == NULL) return; 25838624Skarels x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 25945182Skarels if (x >= TTYHOG/2 && (!(tp->t_lflag&ICANON) || tp->t_canq.c_cc)) 26038624Skarels return; 26138624Skarels (void) dk_recv(d, dktibuf[d], MLEN, 26245182Skarels #ifdef notdef 26338624Skarels DKR_BLOCK | DKR_TIME | (dkt_tmr[tp->t_ispeed]<<8), 26445182Skarels #endif 26545182Skarels DKR_BLOCK | DKR_TIME | (1<<8), 26638624Skarels dktrcv, (caddr_t) tp) ; 26738624Skarels } 26838624Skarels 26938624Skarels /* 27038624Skarels * stty/gtty for DKT 27138624Skarels */ 27238624Skarels dktioctl(dev, cmd, data, flag) 27338624Skarels caddr_t data; 27438624Skarels { 27538624Skarels register struct tty *tp; 27638624Skarels int error; 27738624Skarels 27838624Skarels tp = &dkt[minor(dev)]; 27938624Skarels error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 28038624Skarels if (error >= 0) 28138624Skarels return error; 28238624Skarels error = ttioctl(tp, cmd, data, flag); 28345184Skarels if (error >= 0) 28438624Skarels return (error); 28538624Skarels 28638624Skarels switch(cmd) { 28738624Skarels case TIOCSBRK: 28838624Skarels dktxpack(tp-dkt, D_BREAK) ; 28938624Skarels return 0; 29038624Skarels case TIOCCBRK: 29138624Skarels return 0; 29238624Skarels } 29338624Skarels return ENOTTY; 29438624Skarels } 29538624Skarels 29638624Skarels /* 29738624Skarels * Start (restart) transmission on the given DKT line. 29838624Skarels */ 29938624Skarels dktstart(tp) 30038624Skarels register struct tty *tp; 30138624Skarels { 30238624Skarels register d; 30338624Skarels char delay; 30438624Skarels extern dktxdun() ; 30538624Skarels int s, c; 30638624Skarels register int nch; 30738624Skarels register struct mbuf *m; 30838624Skarels extern ttrstrt(); 30938624Skarels 31038624Skarels d = tp - dkt; 31138624Skarels s = spl5() ; 31238624Skarels 31338624Skarels #ifdef notdef 31438624Skarels if (dk_status(d) & DK_SPND) 31538624Skarels dk_cmd(d, DKC_RSME) ; 31638624Skarels #endif 31738624Skarels 31838624Skarels if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 31938624Skarels goto out; 32038624Skarels 32138624Skarels /* 32238624Skarels * If the writer was sleeping on output overflow, 32338624Skarels * wake the process when low tide is reached. 32438624Skarels */ 32545182Skarels if (tp->t_outq.c_cc<=tp->t_lowat) { 32638624Skarels if (tp->t_state&TS_ASLEEP) { 32738624Skarels tp->t_state &= ~TS_ASLEEP; 32838624Skarels wakeup((caddr_t)&tp->t_outq); 32938624Skarels } 33038624Skarels if (tp->t_wsel) { 33138624Skarels selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 33238624Skarels tp->t_wsel = 0; 33338624Skarels tp->t_state &= ~TS_WCOLL; 33438624Skarels } 33538624Skarels } 33638624Skarels /* 33738624Skarels * Now restart transmission unless the output queue is 33838624Skarels * empty. 33938624Skarels */ 34038624Skarels if (tp->t_outq.c_cc == 0) 34138624Skarels goto out; 34238624Skarels 34338624Skarels m = m_get(M_DONTWAIT, DKMT_OTTY); 34438624Skarels if (m == NULL) { 34538624Skarels /* No buffers; arrange to retry in .5 seconds */ 34638624Skarels dktpaused[d]++; 34738624Skarels tp->t_state |= TS_TIMEOUT; 34838624Skarels timeout(ttrstrt, (caddr_t) tp, hz/2); 34938624Skarels goto out; 35038624Skarels } 35145182Skarels if (1 || !(tp->t_oflag&OPOST)) 35238624Skarels nch = ndqb(&tp->t_outq, 0); 35338624Skarels else { 35438624Skarels nch = ndqb(&tp->t_outq, 0200); 35538624Skarels /* 35638624Skarels * If first thing on queue is a delay process it. 35738624Skarels */ 35838624Skarels if (nch == 0) { 35938624Skarels nch = getc(&tp->t_outq); 36038624Skarels c = MIN((nch & 0xff) + 6, 0x7f); 36138624Skarels delay = D_DELAY; 36238624Skarels if (tpDEBUG) 36338624Skarels log(LOG_ERR, "DKT_delay %d\n", c) ; 36438624Skarels while (c) { 36538624Skarels delay++; 36638624Skarels c >>= 1; 36738624Skarels } 36838624Skarels if (dk_xmit(d, (struct mbuf *) NULL, 1, delay, dktxdun, (caddr_t) 0)) 36938624Skarels tp->t_state |= TS_BUSY; 37038624Skarels (void) m_free(m); 37138624Skarels goto out; 37238624Skarels } 37338624Skarels } 37438624Skarels /* 37538624Skarels * If characters to transmit, restart transmission. 37638624Skarels */ 37738624Skarels if (nch) { 37838624Skarels bcopy((caddr_t)tp->t_outq.c_cf, mtod(m, caddr_t), (unsigned) nch); 37938624Skarels m->m_len = nch; 38038624Skarels if (dk_xmit(d, m, 1, 0, dktxdun, (caddr_t) nch)) 38138624Skarels tp->t_state |= TS_BUSY; 38238624Skarels } 38338624Skarels else (void) m_free(m); 38438624Skarels out: ; 38538624Skarels splx(s) ; 38638624Skarels } 38738624Skarels 38838624Skarels dktxpack(chan, cmd) 38938624Skarels char cmd; 39038624Skarels { 39138624Skarels (void) dk_xmit(chan, (struct mbuf *) NULL, 1, cmd, (int (*)()) 0, (caddr_t) 0); 39238624Skarels if (chanDEBUG) log(LOG_ERR, "DKT_sent %o on %d\n",cmd&0377,chan); 39338624Skarels } 39438624Skarels 39538624Skarels /*ARGSUSED*/ 39638624Skarels dktstop(tp, rw) 39738624Skarels register struct tty *tp; 39838624Skarels { 39938624Skarels register int s, d; 40038624Skarels 40138624Skarels d = tp - dkt; 40238624Skarels s = spl5(); 40338624Skarels if (tp->t_state & TS_BUSY) { 40438624Skarels #ifdef notdef 40538624Skarels dk_cmd(d, DKC_SPND); 40638624Skarels #endif 40738624Skarels if ((tp->t_state & TS_TTSTOP) == 0) { 40838624Skarels tp->t_state |= TS_FLUSH; 40938624Skarels dk_cmd(d, DKC_FLUSH); 41038624Skarels } 41138624Skarels } 41238624Skarels splx(s); 41338624Skarels } 41438624Skarels 41538624Skarels dktshut(tp) 41638624Skarels register struct tty *tp; 41738624Skarels { 41838624Skarels if (tpDEBUG) log(LOG_ERR, "dktshut %d\n", tp-dkt); 41945184Skarels if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_CARR_ON)) 42045184Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 0); 42138624Skarels tp->t_state &= ~TS_CARR_ON; 42238624Skarels ttyflush(tp, (FREAD|FWRITE)) ; 42338624Skarels dk_cmd((tp - dkt), DKC_FLUSH); 42438624Skarels } 42538624Skarels 42638624Skarels 42738624Skarels dktxdun(cnt, chan) 42838624Skarels { 42938624Skarels register struct tty *tp ; 43038624Skarels 43138624Skarels tp = &dkt[chan]; 43238624Skarels if (tp->t_state & TS_FLUSH) tp->t_state &= ~TS_FLUSH; 43338624Skarels else ndflush(&tp->t_outq, cnt); 43438624Skarels tp->t_state &= ~TS_BUSY; 43538624Skarels if (tp->t_line) 43638624Skarels (*linesw[tp->t_line].l_start)(tp); 43738624Skarels else 43838624Skarels dktstart(tp); 43938624Skarels } 44038624Skarels #endif 441