138624Skarels /* 238624Skarels * Datakit driver 338624Skarels * Common subroutines for all drivers 438624Skarels * SCCSID[] = "@(#)dksub.c 1.2 Garage 84/03/27" 5*43388Skarels * "@(#)dksub.c 1.3 (Berkeley) 06/21/90" 638624Skarels */ 738624Skarels 838624Skarels #include "datakit.h" 938624Skarels #if NDATAKIT>0 1038624Skarels 1138624Skarels #include "param.h" 1238624Skarels #include "../machine/pte.h" 1338624Skarels #include "signal.h" 1438624Skarels #include "errno.h" 1538624Skarels #include "seg.h" 1638624Skarels #include "user.h" 1738624Skarels #include "ioctl.h" 1838624Skarels #include "tty.h" 1938624Skarels #include "syslog.h" 2038624Skarels #include "conf.h" 2138624Skarels #include "file.h" 2238624Skarels #include "inode.h" 2338624Skarels #include "systm.h" 2438624Skarels #include "proc.h" 2538624Skarels #include "mbuf.h" 2638624Skarels #include "buf.h" 2738624Skarels #include "uio.h" 2838624Skarels #include "dkit.h" 2938624Skarels #include "dk.h" 3038624Skarels #include "dkdev.h" 3138624Skarels 3238624Skarels #define DKBUFUSE 5 /* max buffers /channel */ 3338624Skarels 3438624Skarels 3538624Skarels extern struct dkdev dkdev[] ; 3638624Skarels 3738624Skarels int dksubdebug = 512; 3838624Skarels 3938624Skarels 4038624Skarels dkuread(chan, uio) 4138624Skarels register struct uio *uio; 4238624Skarels { 4338624Skarels register int len, blen ; 4438624Skarels register struct dkdev *tp ; 4538624Skarels short chanstat ; 4638624Skarels struct mbuf *mm ; 4738624Skarels int err = 0, s; 4838624Skarels extern wakeup() ; 4938624Skarels extern dkrdone() ; 5038624Skarels 5138624Skarels tp = &dkdev[chan]; 5238624Skarels MGET(mm, M_WAIT, DKMT_DATA); 5338624Skarels if (mm == NULL) 5438624Skarels return ENOBUFS; 5538624Skarels if (uio->uio_resid >= MLEN) { 56*43388Skarels MCLGET(mm, M_WAIT); 57*43388Skarels if ((mm->m_flags & M_EXT) == 0) 5838624Skarels goto nopages; 59*43388Skarels blen = MCLBYTES; 6038624Skarels } else { 6138624Skarels nopages: 6238624Skarels blen = MIN(MLEN, uio->uio_resid); 6338624Skarels } 6438624Skarels 6538624Skarels if (setjmp(&u.u_qsave)) { 6638624Skarels s = spl5(); 6738624Skarels if (dk_status(chan) & DK_RCV) 6838624Skarels (void) dk_rabort(chan, dkrdone, (caddr_t) tp) ; 6938624Skarels splx(s); 7038624Skarels m_freem(mm); 7138624Skarels u.u_error = EINTR; 7238624Skarels return EINTR ; 7338624Skarels } 7438624Skarels 7538624Skarels while (uio->uio_resid && !err) { 7638624Skarels len = MIN(uio->uio_resid, blen) ; 7738624Skarels chanstat = dk_recv(chan, mtod(mm, caddr_t), len, tp->d_rmode, dkrdone, (caddr_t) tp) ; 7838624Skarels if (chanstat == 0) { 7938624Skarels if ((dk_status(chan) & DK_RESET) == 0) 8038624Skarels err = EIO ; 8138624Skarels break; 8238624Skarels } 8338624Skarels if ((tp->dc_state & DK_NDELAY) && (dk_status(chan) & DK_RCV)) { 8438624Skarels err = EWOULDBLOCK; 8538624Skarels break; 8638624Skarels } 8738624Skarels 8838624Skarels s = spl5() ; 8938624Skarels while (dk_status(chan) & DK_RCV) 9038624Skarels sleep((caddr_t)(tp), TTOPRI) ; 9138624Skarels splx(s) ; 9238624Skarels 9338624Skarels len -= tp->d_rresid ; 9438624Skarels if (len) 9538624Skarels err = uiomove(mtod(mm, caddr_t), len, UIO_READ, uio); 9638624Skarels if (tp->d_rdone != DKR_FULL) 9738624Skarels break ; 9838624Skarels } 9938624Skarels m_freem(mm) ; 10038624Skarels return err; 10138624Skarels } 10238624Skarels 10338624Skarels 10438624Skarels /*ARGSUSED*/ 10538624Skarels dkrdone(tp, chan, resid, rdone, rctl) 10638624Skarels register struct dkdev *tp ; 10738624Skarels { 10838624Skarels tp->d_rresid = resid ; 10938624Skarels tp->d_rdone = rdone ; 11038624Skarels tp->d_rctl = rctl ; 11138624Skarels wakeup((caddr_t) tp) ; 11238624Skarels } 11338624Skarels 11438624Skarels 11538624Skarels 11638624Skarels 11738624Skarels dkuwrite(chan, uio) register struct uio *uio; 11838624Skarels { 11938624Skarels extern wakeup() ; 12038624Skarels extern dkwdone() ; 12138624Skarels register struct dkdev *tp ; 12238624Skarels register len ; 12338624Skarels register struct mbuf *m; 12438624Skarels register struct iovec *iov; 12538624Skarels int s, error, eob; 12638624Skarels short xc; 12738624Skarels 12838624Skarels tp = &dkdev[chan] ; 12938624Skarels do { 13038624Skarels s = spl5() ; 13138624Skarels while (tp->d_bufct > DKBUFUSE) { 13238624Skarels if (tp->dc_state & DK_NDELAY) { 13338624Skarels splx(s); 13438624Skarels return EWOULDBLOCK; 13538624Skarels } 13638624Skarels tp->d_state |= DKWAIT ; 13738624Skarels sleep((caddr_t)(&tp->d_state), TTOPRI) ; 13838624Skarels } 13938624Skarels splx(s) ; 14038624Skarels 14138624Skarels iov = uio->uio_iov; 14238624Skarels if (iov->iov_len) { 14338624Skarels MGET(m, M_WAIT, DKMT_DATA); 14438624Skarels if (m == NULL) 14538624Skarels return ENOBUFS; 14638624Skarels if (iov->iov_len >= MLEN) { 147*43388Skarels MCLGET(m, M_WAIT); 148*43388Skarels if ((m->m_flags & M_EXT) == 0) 14938624Skarels goto nopages; 150*43388Skarels len = MIN(MCLBYTES, iov->iov_len); 15138624Skarels } else { 15238624Skarels nopages: 15338624Skarels len = MIN(MLEN, iov->iov_len); 15438624Skarels } 15538624Skarels error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio); 15638624Skarels if (error) { 15738624Skarels (void) m_free(m); 15838624Skarels return error; 15938624Skarels } 16038624Skarels m->m_len = len; 16138624Skarels } 16238624Skarels else m = NULL; 16338624Skarels 16438624Skarels s = spl5(); 16538624Skarels tp->d_bufct++; 16638624Skarels eob = (uio->uio_resid == 0); 16738624Skarels if (eob) { 16838624Skarels xc = tp->d_xctl; 16938624Skarels tp->d_xctl = 0; 17038624Skarels } 17138624Skarels else xc = 0; 17238624Skarels if (dk_xmit(chan, m, eob, xc, dkwdone, (caddr_t) 0) == 0) { 17338624Skarels tp->d_bufct-- ; 17438624Skarels return EIO ; 17538624Skarels } 17638624Skarels splx(s); 17738624Skarels } while (uio->uio_resid); 17838624Skarels return 0; 17938624Skarels } 18038624Skarels 18138624Skarels /*ARGSUSED*/ 18238624Skarels dkwdone(x, chan) 18338624Skarels { 18438624Skarels register struct dkdev *tp ; 18538624Skarels 18638624Skarels tp = &dkdev[chan] ; 18738624Skarels if (chan > dksubdebug) 18838624Skarels log(LOG_ERR, "dkwdone %d: state=0%o bufct=%d\n", chan, tp->d_state, 18938624Skarels tp->d_bufct); 19038624Skarels if (tp->d_bufct) 19138624Skarels tp->d_bufct-- ; 19238624Skarels if (tp->d_state & DKWAIT) { 19338624Skarels tp->d_state &= ~DKWAIT ; 19438624Skarels wakeup((caddr_t) &tp->d_state) ; 19538624Skarels } 19638624Skarels } 19738624Skarels 19838624Skarels /* wakeup and reinitialize channel upon receipt of reconnection message */ 19938624Skarels dkrsplice(chan) 20038624Skarels { 20138624Skarels register struct dkdev *tp ; 20238624Skarels 20338624Skarels tp = &dkdev[chan] ; 20438624Skarels tp->d_state |= DKSPLICED ; 20538624Skarels wakeup((caddr_t) tp) ; 20638624Skarels dk_cmd(chan, DKC_XINIT) ; 20738624Skarels } 20838624Skarels 20938624Skarels /* wait for reconnection message indicating that splice completed */ 21038624Skarels dksplwait(chan) 21138624Skarels { 21238624Skarels register struct dkdev *tp ; 21338624Skarels 21438624Skarels tp = &dkdev[chan] ; 21538624Skarels while ((tp->d_state & DKSPLICED) == 0) 21638624Skarels sleep((caddr_t) tp, TTOPRI) ; 21738624Skarels } 21838624Skarels 21938624Skarels /* convert file desciptor to Datakit channel */ 22038624Skarels dkgetdev(fildes) 22138624Skarels { 22238624Skarels extern struct file *getinode(); 22338624Skarels register struct file *fp; 22438624Skarels register struct inode *ip ; 22538624Skarels 22638624Skarels fp = getinode(fildes) ; 22738624Skarels ip = (struct inode *)fp->f_data; 22838624Skarels if ((ip->i_mode & IFMT) != IFCHR ) { 22938624Skarels u.u_error = ENOTTY ; 23038624Skarels return(-1) ; 23138624Skarels } 23238624Skarels if (dkdevtype((dev_t) ip->i_rdev)) 23338624Skarels return(minor(ip->i_rdev)) ; 23438624Skarels u.u_error = EINVAL ; 23538624Skarels return(-1) ; 23638624Skarels } 23738624Skarels 23838624Skarels /* validate device number as belonging to Datakit */ 23938624Skarels dkdevtype(dev) dev_t dev; 24038624Skarels { 24138624Skarels extern dkopen(); 24238624Skarels #if NDKTTY > 0 24338624Skarels extern dktopen(); 24438624Skarels #endif 24538624Skarels #if NDKXQT > 0 24638624Skarels extern dkxopen(); 24738624Skarels #endif 24838624Skarels #if NDKI > 0 24938624Skarels extern dkiopen(); 25038624Skarels #endif 25138624Skarels register md = major(dev) ; 25238624Skarels 25338624Skarels if ((cdevsw[md].d_open == dkopen) 25438624Skarels #if NDKTTY > 0 25538624Skarels || (cdevsw[md].d_open == dktopen) 25638624Skarels #endif 25738624Skarels #if NDKI > 0 25838624Skarels || (cdevsw[md].d_open == dkiopen && md > 0) 25938624Skarels #endif 26038624Skarels #if NDKXQT > 0 26138624Skarels || (cdevsw[md].d_open == dkxopen) 26238624Skarels #endif 26338624Skarels ) 26438624Skarels return(1); 26538624Skarels else 26638624Skarels return(0); 26738624Skarels } 26838624Skarels 26938624Skarels #endif 270