138624Skarels /*
238624Skarels * Datakit driver
338624Skarels * Common subroutines for all drivers
438624Skarels * SCCSID[] = "@(#)dksub.c 1.2 Garage 84/03/27"
5*45800Sbostic * "@(#)dksub.c 1.7 (Berkeley) 12/16/90"
638624Skarels */
738624Skarels
838624Skarels #include "datakit.h"
938624Skarels #if NDATAKIT>0
1038624Skarels
11*45800Sbostic #include "../include/pte.h"
12*45800Sbostic #include "sys/param.h"
13*45800Sbostic #include "sys/signal.h"
14*45800Sbostic #include "sys/errno.h"
15*45800Sbostic #include "sys/seg.h"
16*45800Sbostic #include "sys/user.h"
17*45800Sbostic #include "sys/ioctl.h"
18*45800Sbostic #include "sys/tty.h"
19*45800Sbostic #include "sys/syslog.h"
20*45800Sbostic #include "sys/conf.h"
21*45800Sbostic #include "sys/file.h"
22*45800Sbostic #include "sys/systm.h"
23*45800Sbostic #include "sys/proc.h"
24*45800Sbostic #include "sys/mbuf.h"
25*45800Sbostic #include "sys/buf.h"
26*45800Sbostic #include "sys/uio.h"
27*45800Sbostic #include "sys/vnode.h"
28*45800Sbostic #include "sys/specdev.h"
2938624Skarels #include "dkit.h"
3038624Skarels #include "dk.h"
3138624Skarels #include "dkdev.h"
3238624Skarels
3338624Skarels #define DKBUFUSE 5 /* max buffers /channel */
3438624Skarels
3538624Skarels
3638624Skarels extern struct dkdev dkdev[] ;
3738624Skarels
3838624Skarels int dksubdebug = 512;
3938624Skarels
4038624Skarels
dkuread(chan,uio)4138624Skarels dkuread(chan, uio)
4238624Skarels register struct uio *uio;
4338624Skarels {
4438624Skarels register int len, blen ;
4538624Skarels register struct dkdev *tp ;
4638624Skarels short chanstat ;
4738624Skarels struct mbuf *mm ;
4838624Skarels int err = 0, s;
4938624Skarels extern wakeup() ;
5038624Skarels extern dkrdone() ;
5138624Skarels
5238624Skarels tp = &dkdev[chan];
5338624Skarels MGET(mm, M_WAIT, DKMT_DATA);
5438624Skarels if (mm == NULL)
5538624Skarels return ENOBUFS;
5638624Skarels if (uio->uio_resid >= MLEN) {
5743388Skarels MCLGET(mm, M_WAIT);
5843388Skarels if ((mm->m_flags & M_EXT) == 0)
5938624Skarels goto nopages;
6043388Skarels blen = MCLBYTES;
6138624Skarels } else {
6238624Skarels nopages:
6338624Skarels blen = MIN(MLEN, uio->uio_resid);
6438624Skarels }
6538624Skarels
6638624Skarels while (uio->uio_resid && !err) {
6738624Skarels len = MIN(uio->uio_resid, blen) ;
6838624Skarels chanstat = dk_recv(chan, mtod(mm, caddr_t), len, tp->d_rmode, dkrdone, (caddr_t) tp) ;
6938624Skarels if (chanstat == 0) {
7038624Skarels if ((dk_status(chan) & DK_RESET) == 0)
7138624Skarels err = EIO ;
7238624Skarels break;
7338624Skarels }
7438624Skarels if ((tp->dc_state & DK_NDELAY) && (dk_status(chan) & DK_RCV)) {
7538624Skarels err = EWOULDBLOCK;
7638624Skarels break;
7738624Skarels }
7838624Skarels
7938624Skarels s = spl5() ;
8038624Skarels while (dk_status(chan) & DK_RCV)
8145184Skarels if (err = tsleep((caddr_t)(tp), TTIPRI, ttyin, 0)) {
8245184Skarels if (dk_status(chan) & DK_RCV)
8345184Skarels (void) dk_rabort(chan, dkrdone,
8445184Skarels (caddr_t) tp);
8545184Skarels splx(s);
8645184Skarels goto done;
8745184Skarels }
8838624Skarels splx(s) ;
8938624Skarels
9038624Skarels len -= tp->d_rresid ;
9138624Skarels if (len)
9238624Skarels err = uiomove(mtod(mm, caddr_t), len, UIO_READ, uio);
9338624Skarels if (tp->d_rdone != DKR_FULL)
9438624Skarels break ;
9538624Skarels }
9645184Skarels done:
9738624Skarels m_freem(mm) ;
9838624Skarels return err;
9938624Skarels }
10038624Skarels
10138624Skarels
10238624Skarels /*ARGSUSED*/
dkrdone(tp,chan,resid,rdone,rctl)10338624Skarels dkrdone(tp, chan, resid, rdone, rctl)
10438624Skarels register struct dkdev *tp ;
10538624Skarels {
10638624Skarels tp->d_rresid = resid ;
10738624Skarels tp->d_rdone = rdone ;
10838624Skarels tp->d_rctl = rctl ;
10938624Skarels wakeup((caddr_t) tp) ;
11038624Skarels }
11138624Skarels
11238624Skarels
11338624Skarels
11438624Skarels
dkuwrite(chan,uio)11538624Skarels dkuwrite(chan, uio) register struct uio *uio;
11638624Skarels {
11738624Skarels extern wakeup() ;
11838624Skarels extern dkwdone() ;
11938624Skarels register struct dkdev *tp ;
12038624Skarels register len ;
12138624Skarels register struct mbuf *m;
12238624Skarels register struct iovec *iov;
12338624Skarels int s, error, eob;
12438624Skarels short xc;
12538624Skarels
12638624Skarels tp = &dkdev[chan] ;
12738624Skarels do {
12838624Skarels s = spl5() ;
12938624Skarels while (tp->d_bufct > DKBUFUSE) {
13038624Skarels if (tp->dc_state & DK_NDELAY) {
13138624Skarels splx(s);
13238624Skarels return EWOULDBLOCK;
13338624Skarels }
13438624Skarels tp->d_state |= DKWAIT ;
13545184Skarels if (error = tsleep((caddr_t)(&tp->d_state), TTOPRI,
13645184Skarels ttyout, 0)) {
13745184Skarels splx(s);
13845184Skarels return (error);
13945184Skarels }
14038624Skarels }
14138624Skarels splx(s) ;
14238624Skarels
14338624Skarels iov = uio->uio_iov;
14438624Skarels if (iov->iov_len) {
14538624Skarels MGET(m, M_WAIT, DKMT_DATA);
14638624Skarels if (m == NULL)
14738624Skarels return ENOBUFS;
14838624Skarels if (iov->iov_len >= MLEN) {
14943388Skarels MCLGET(m, M_WAIT);
15043388Skarels if ((m->m_flags & M_EXT) == 0)
15138624Skarels goto nopages;
15243388Skarels len = MIN(MCLBYTES, iov->iov_len);
15338624Skarels } else {
15438624Skarels nopages:
15538624Skarels len = MIN(MLEN, iov->iov_len);
15638624Skarels }
15738624Skarels error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
15838624Skarels if (error) {
15938624Skarels (void) m_free(m);
16038624Skarels return error;
16138624Skarels }
16238624Skarels m->m_len = len;
16338624Skarels }
16438624Skarels else m = NULL;
16538624Skarels
16638624Skarels s = spl5();
16738624Skarels tp->d_bufct++;
16838624Skarels eob = (uio->uio_resid == 0);
16938624Skarels if (eob) {
17038624Skarels xc = tp->d_xctl;
17138624Skarels tp->d_xctl = 0;
17238624Skarels }
17338624Skarels else xc = 0;
17438624Skarels if (dk_xmit(chan, m, eob, xc, dkwdone, (caddr_t) 0) == 0) {
17538624Skarels tp->d_bufct-- ;
17638624Skarels return EIO ;
17738624Skarels }
17838624Skarels splx(s);
17938624Skarels } while (uio->uio_resid);
18038624Skarels return 0;
18138624Skarels }
18238624Skarels
18338624Skarels /*ARGSUSED*/
dkwdone(x,chan)18438624Skarels dkwdone(x, chan)
18538624Skarels {
18638624Skarels register struct dkdev *tp ;
18738624Skarels
18838624Skarels tp = &dkdev[chan] ;
18938624Skarels if (chan > dksubdebug)
19038624Skarels log(LOG_ERR, "dkwdone %d: state=0%o bufct=%d\n", chan, tp->d_state,
19138624Skarels tp->d_bufct);
19238624Skarels if (tp->d_bufct)
19338624Skarels tp->d_bufct-- ;
19438624Skarels if (tp->d_state & DKWAIT) {
19538624Skarels tp->d_state &= ~DKWAIT ;
19638624Skarels wakeup((caddr_t) &tp->d_state) ;
19738624Skarels }
19838624Skarels }
19938624Skarels
20038624Skarels /* wakeup and reinitialize channel upon receipt of reconnection message */
dkrsplice(chan)20138624Skarels dkrsplice(chan)
20238624Skarels {
20338624Skarels register struct dkdev *tp ;
20438624Skarels
20538624Skarels tp = &dkdev[chan] ;
20638624Skarels tp->d_state |= DKSPLICED ;
20738624Skarels wakeup((caddr_t) tp) ;
20838624Skarels dk_cmd(chan, DKC_XINIT) ;
20938624Skarels }
21038624Skarels
21138624Skarels /* wait for reconnection message indicating that splice completed */
dksplwait(chan)21238624Skarels dksplwait(chan)
21338624Skarels {
21438624Skarels register struct dkdev *tp ;
21545184Skarels int error;
21638624Skarels
21738624Skarels tp = &dkdev[chan] ;
21838624Skarels while ((tp->d_state & DKSPLICED) == 0)
21945184Skarels if (error = tsleep((caddr_t) tp, TTOPRI, ttopen, 0))
22045184Skarels return (error);
22145184Skarels return (0);
22238624Skarels }
22338624Skarels
22438624Skarels /* convert file desciptor to Datakit channel */
dkgetdev(fildes,devnop)22543390Smckusick dkgetdev(fildes, devnop)
22643390Smckusick int fildes, *devnop;
22738624Skarels {
22843390Smckusick struct file *fp;
22943390Smckusick register struct vnode *vp ;
23043390Smckusick int error;
23138624Skarels
23243390Smckusick if (error = getvnode(u.u_ofile, fildes, &fp))
23343390Smckusick return error;
23443390Smckusick vp = (struct vnode *)fp->f_data;
23543390Smckusick if (vp->v_type != VCHR)
23643390Smckusick return ENOTTY;
23745199Smckusick if (dkdevtype(vp->v_rdev)) {
23845199Smckusick *devnop = minor(vp->v_rdev);
23943390Smckusick return 0;
24038624Skarels }
24143390Smckusick return EINVAL;
24238624Skarels }
24338624Skarels
24438624Skarels /* validate device number as belonging to Datakit */
dkdevtype(dev)24538624Skarels dkdevtype(dev) dev_t dev;
24638624Skarels {
24738624Skarels extern dkopen();
24838624Skarels #if NDKTTY > 0
24938624Skarels extern dktopen();
25038624Skarels #endif
25138624Skarels #if NDKXQT > 0
25238624Skarels extern dkxopen();
25338624Skarels #endif
25438624Skarels #if NDKI > 0
25538624Skarels extern dkiopen();
25638624Skarels #endif
25738624Skarels register md = major(dev) ;
25838624Skarels
25938624Skarels if ((cdevsw[md].d_open == dkopen)
26038624Skarels #if NDKTTY > 0
26138624Skarels || (cdevsw[md].d_open == dktopen)
26238624Skarels #endif
26338624Skarels #if NDKI > 0
26438624Skarels || (cdevsw[md].d_open == dkiopen && md > 0)
26538624Skarels #endif
26638624Skarels #if NDKXQT > 0
26738624Skarels || (cdevsw[md].d_open == dkxopen)
26838624Skarels #endif
26938624Skarels )
27038624Skarels return(1);
27138624Skarels else
27238624Skarels return(0);
27338624Skarels }
27438624Skarels
27538624Skarels #endif
276