138620Skarels /* 238620Skarels * Datakit driver 338620Skarels * SCCSID[] = "@(#)dk.c 2.1 DKHOST 84/07/03" 438620Skarels */ 538620Skarels 638620Skarels #include "datakit.h" 738620Skarels #if NDATAKIT>0 838620Skarels 9*45800Sbostic #include "../include/pte.h" 10*45800Sbostic #include "sys/param.h" 11*45800Sbostic #include "sys/signal.h" 12*45800Sbostic #include "sys/errno.h" 13*45800Sbostic #include "sys/conf.h" 14*45800Sbostic #include "sys/user.h" 15*45800Sbostic #include "sys/ioctl.h" 16*45800Sbostic #include "sys/tty.h" 17*45800Sbostic #include "sys/vnode.h" 18*45800Sbostic #include "sys/file.h" 19*45800Sbostic #include "sys/systm.h" 20*45800Sbostic #include "sys/proc.h" 21*45800Sbostic #include "sys/mbuf.h" 22*45800Sbostic #include "sys/buf.h" 23*45800Sbostic #include "sys/uio.h" 24*45800Sbostic #include "sys/kernel.h" 25*45800Sbostic #include "sys/dkit.h" 26*45800Sbostic #include "sys/dkcmc.h" 27*45800Sbostic #include "sys/dk.h" 28*45800Sbostic #include "sys/dkdev.h" 29*45800Sbostic #include "sys/syslog.h" 3038620Skarels 3138620Skarels extern int dkdebug ; 3238620Skarels 3338620Skarels #define DKBUFUSE 5 /* max buffers /channel */ 3438620Skarels 3538620Skarels 3638620Skarels int dk_nchan = NDATAKIT; 3738620Skarels struct dkdev dkdev[NDATAKIT]; 3838620Skarels struct dksetupreq *dkreq[NDATAKIT]; 3938620Skarels 4038620Skarels 4138620Skarels 4238620Skarels 4338620Skarels #ifdef MONITOR 4438620Skarels int dummy ; 4538620Skarels int *DKP2 = &dummy ; 4638620Skarels #define M_ON(a) *DKP2 |= (a) 4738620Skarels #define M_OFF(a) *DKP2 &= ~(a) 4838620Skarels 4938620Skarels #define Mread 0400 5038620Skarels #define Mrslp 01000 5138620Skarels #define Mrcpy 02000 5238620Skarels #define Mwrite 04000 5338620Skarels #define Mwcpy 010000 5438620Skarels 5538620Skarels #else 5638620Skarels #define M_ON(a) 5738620Skarels #define M_OFF(a) 5838620Skarels #endif 5938620Skarels 6038620Skarels 6138620Skarels 6238620Skarels /*ARGSUSED*/ 6338620Skarels dkioctl(dev, cmd, data, flag) 6438620Skarels register caddr_t data; 6538620Skarels { 6638620Skarels register struct dkdev *tp; 6738620Skarels register chanstat ; 6838620Skarels int chan, sp_chan; 6943390Smckusick int s, error = 0; 7038620Skarels register short *pp ; 7138620Skarels struct dkdev *tsp; 7238620Skarels extern dkidone() ; 7338620Skarels struct diocdial dialreq; 7438620Skarels extern int commchan; 7538620Skarels 7638620Skarels chan = dev = minor(dev); 7738620Skarels tp = &dkdev[chan]; 7838620Skarels pp = (short *) data; 7938620Skarels switch(cmd) { 8038620Skarels case DIOCEXCL: 8138620Skarels tp->d_state |= DKXCLUDE ; 8238620Skarels break ; 8338620Skarels case DIOCNXCL: 8438620Skarels tp->d_state &= ~DKXCLUDE ; 8538620Skarels break ; 8638620Skarels case DIOCSETK: 8738620Skarels dkdebug = pp[0] ; 8838620Skarels break; 8938620Skarels case DIOCQQABO: 9038620Skarels pp[0] = tp->d_rresid; 9138620Skarels pp[1] = tp->d_rdone; 9238620Skarels pp[2] = tp->d_rctl; 9338620Skarels break ; 9438620Skarels case DIOCRMODE: 9538620Skarels if (pp[0] & DKR_TIME) 9638620Skarels tp->d_rmode = (DKR_TIME | DKR_BLOCK); 9738620Skarels else tp->d_rmode = pp[0] ; 9838620Skarels break ; 9938620Skarels case DIOCXCTL: 10038620Skarels tp->d_xctl = pp[0] ; 10138620Skarels break ; 10238620Skarels case DIOCFLUSH: 10338620Skarels dk_cmd(chan, DKC_XINIT|DKC_FLUSH); 10438620Skarels break; 10538620Skarels case KIOCINIT: 10638620Skarels dk_cmd(chan, DKC_XINIT); 10738620Skarels break; 10838620Skarels case DIOCXWIN: 10938620Skarels return dk_winsize(chan, (struct diocxwin *)data); 11038620Skarels case DIOCRESET: 11138620Skarels if (chan != 1 && chan != pp[0]) return EACCES; 11238620Skarels if (pp[0] > 1 && pp[0] < commchan) return EINVAL; 11338620Skarels if (pp[0] < 0 || pp[0] >= dk_nchan) return EINVAL; 11438620Skarels if (pp[0] == 0) return -dk_close(0); 11538620Skarels else dk_reset(pp[0]); 11638620Skarels break; 11738620Skarels case DIOCCTYPE: 11838620Skarels if (tp->d_ctype == NULL) { 11938620Skarels struct mbuf *m; 12038620Skarels 12138620Skarels MGET(m, M_WAIT, DKMT_CTYPE); 12238620Skarels if (m == NULL) 12338620Skarels return ENOBUFS; 12438620Skarels tp->d_ctype = mtod(m, struct diocctype *); 12538620Skarels } 12638620Skarels return bcopy(data, (caddr_t) tp->d_ctype, sizeof (struct diocctype)); 12738620Skarels case DIOCINFO: 12838620Skarels ((struct diocinfo *)data)->dioc_nchan = dk_nchan; 12938620Skarels ((struct diocinfo *)data)->dioc_channum = chan; 13038620Skarels ((struct diocinfo *)data)->dioc_commchan = commchan; 13138620Skarels break; 13238620Skarels case DIOCSTAT: 13338620Skarels if (*((int *)data) < 0 || *((int *)data) >= dk_nchan) 13438620Skarels return EINVAL; 13538620Skarels *((int *)data) = dk_status(*((int *)data)); 13638620Skarels break; 13738620Skarels case FIONBIO: 13838620Skarels if (*(int *)data) 13938620Skarels tp->dc_state |= DK_NDELAY; 14038620Skarels else 14138620Skarels tp->dc_state &= ~DK_NDELAY; 14238620Skarels break; 14338620Skarels case FIOASYNC: 14438620Skarels if (*(int *)data) 14538620Skarels tp->dc_state |= DK_ASYNC; 14638620Skarels else 14738620Skarels tp->dc_state &= ~DK_ASYNC; 14838620Skarels break; 14938620Skarels case TIOCGPGRP: 15038620Skarels *(int *)data = tp->d_pgrp; 15138620Skarels break; 15238620Skarels case TIOCSPGRP: 15338620Skarels tp->d_pgrp = *(int *)data; 15438620Skarels break; 15538620Skarels 15638620Skarels /* splice chan to file descriptor */ 15738620Skarels case DKIOCSPL: 15843390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 15938620Skarels 3*sizeof (short)); 16043390Smckusick if (error) return error; 16143390Smckusick if ((error = dkgetdev(tp->d_param[0], &sp_chan)) <= 0) 16243390Smckusick return error ; 16338620Skarels if (sp_chan == chan) 16438620Skarels return EINVAL ; 16538620Skarels tsp = &dkdev[sp_chan] ; 16638620Skarels tp->dc_state |= DKSETUP ; 16738620Skarels tsp->dc_state |= DKSETUP ; 16838620Skarels if (dk_splice(chan, sp_chan, dkidone, (caddr_t) tp, 16938620Skarels (caddr_t) tsp)) { 17038620Skarels tp->dc_state &= ~DKSETUP ; 17138620Skarels tsp->dc_state &= ~DKSETUP ; 17238620Skarels return EIO ; 17338620Skarels } 17438620Skarels s = spl5() ; 17545184Skarels error = 0; 17645184Skarels while (error == 0 && tp->dc_state & DKSETUP) 17745184Skarels error = tsleep((caddr_t)tp, TTOPRI, ttopen, 0); 17845184Skarels while (error == 0 && tsp->dc_state & DKSETUP) 17945184Skarels error = tsleep((caddr_t)tsp, TTOPRI, ttopen, 0); 18038620Skarels splx(s) ; 18145184Skarels if (error) 18245184Skarels return (error); 18338620Skarels if ((dk_status(chan) & DK_RESET) || (dk_status(sp_chan) & DK_RESET)) 18438620Skarels return EIO ; 18538620Skarels if (tp->d_error || tsp->d_error) 18638620Skarels return EIO ; 18743390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 18838620Skarels 3*sizeof (short)); 18943390Smckusick if (error) return error; 19038620Skarels break ; 19138620Skarels 19238620Skarels case DIOCSWAIT: 19345184Skarels error = dksplwait(chan); 19438620Skarels break ; 19538620Skarels 19638620Skarels default: 19738620Skarels if ((cmd & DKIOCMASK) != DKIOCVAL) { 19838620Skarels return ENOTTY ; 19938620Skarels } 20038620Skarels if (cmd == DKIODIAL) { 20143390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) &dialreq, 20238620Skarels sizeof (struct diocdial)); 20343390Smckusick if (error) return error; 20443390Smckusick if (error = dkiodial(chan, dialreq.dialstring)) 20543390Smckusick return error; 20638620Skarels tp->dc_state |= DKSETUP ; 20738620Skarels chanstat = dk_setup(minor(dev), (int) DKIOCREQ, 0, 20838620Skarels 0, 0, (int) u.u_uid, dkidone, (caddr_t)tp) ; 20938620Skarels } 21038620Skarels else { 21143390Smckusick error = copyin(*(caddr_t *)data, (caddr_t) tp->d_param, 21238620Skarels 3*sizeof (short)); 21343390Smckusick if (error) return error; 21438620Skarels tp->dc_state |= DKSETUP ; 21538625Skarels chanstat = dk_setup(minor(dev), cmd, 0, 0, 0, 21638620Skarels (int) u.u_uid, dkidone, (caddr_t)tp) ; 21738620Skarels } 21838620Skarels if (chanstat) { 21938620Skarels tp->dc_state &= ~DKSETUP ; 22038620Skarels return (chanstat < 0 ? ECONNREFUSED : chanstat); 22138620Skarels } 22238620Skarels s = spl5() ; 22345184Skarels error = 0; 22445184Skarels while (error == 0 && tp->dc_state & DKSETUP) 22545184Skarels error = tsleep((caddr_t)(tp), TTOPRI, ttyout, 0) ; 22638620Skarels splx(s) ; 22745184Skarels if (error) 22845184Skarels return error; 22943390Smckusick error = copyout((caddr_t) tp->d_param, *(caddr_t *)data, 23038620Skarels 3*sizeof (short)); 23143390Smckusick if (error) return error; 23238620Skarels if (dk_status(minor(dev)) & DK_RESET) 23338620Skarels return ENETRESET ; 23438620Skarels if (tp->d_error) 23538620Skarels return EIO ; 23638620Skarels break ; 23738620Skarels } 23843390Smckusick return error; 23938620Skarels } 24038620Skarels 24138620Skarels #define DS_SIZE 64 24238620Skarels static 24338620Skarels dkiodial(chan, user_ds) 24438620Skarels register char *user_ds; 24538620Skarels { 24638620Skarels register caddr_t ds; 24738620Skarels register n; 24838620Skarels register struct mbuf *mb; 24938620Skarels int u_count; 25038620Skarels 25138620Skarels mb = m_get(M_WAIT, DKMT_DATA); 25238620Skarels if (mb == NULL) return ENOBUFS; 25338620Skarels ds = mtod(mb, caddr_t); 25438620Skarels for (u_count = 0; u_count < MLEN - 6; u_count++) { 25538620Skarels *ds = *user_ds; 25638620Skarels if (*ds == '\n' || *ds == '\0') break; 25738620Skarels ds++; 25838620Skarels user_ds++; 25938620Skarels } 26038620Skarels *ds = '\n'; 26138620Skarels u_count++; 26238620Skarels 26338620Skarels /* add uid in char decimal */ 26438620Skarels 26538620Skarels ds++; 26638620Skarels u_count++; 26738620Skarels for (n = u.u_uid; n /= 10; ds++) u_count++; 26838620Skarels for (n = u.u_uid;; ds--) { 26938620Skarels *ds = n % 10 + '0'; 27038620Skarels if ((n /= 10) == 0) break; 27138620Skarels } 27238620Skarels 27338620Skarels mb->m_len = u_count; 27438620Skarels if (dk_xmit(chan, mb, 1, 0, (int (*)()) 0, (caddr_t) 0) == 0) { 27538620Skarels return(EIO); 27638620Skarels } 27738620Skarels else return(0); 27838620Skarels } 27938620Skarels /* 28038620Skarels * End action for ioctl completion 28138620Skarels */ 28238620Skarels /*ARGSUSED*/ 28338620Skarels dkidone(tp, chan, err, p0, p1, p2) 28438620Skarels register struct dkdev *tp ; 28538620Skarels short chan, p0, p1, p2 ; 28638620Skarels { 28738620Skarels tp->d_error = err ; 28838620Skarels tp->d_param[0] = p0 ; 28938620Skarels tp->d_param[1] = p1 ; 29038620Skarels tp->d_param[2] = p2 ; 29138620Skarels tp->dc_state &= ~DKSETUP ; 29238620Skarels wakeup((caddr_t)tp) ; 29338620Skarels } 29438620Skarels 29538620Skarels 29638620Skarels 29738620Skarels 29838620Skarels /*ARGSUSED*/ 29938620Skarels dkopen(dev, flag) 30038620Skarels { 30138620Skarels register struct dkdev *tp; 30238620Skarels register chan; 30345203Smckusick register struct nameidata *ndp = &u.u_nd; /* XXX */ 30445203Smckusick struct proc *p = u.u_procp; /* XXX */ 30545203Smckusick struct vnode *vp; 30638620Skarels struct file *fp; 30745203Smckusick int m, error; 30838620Skarels 30938620Skarels #ifdef lint 31038620Skarels (void) dk_xint(0, 0); 31138620Skarels #endif 31238620Skarels dev = minor(dev); 31338620Skarels if (dev == 1) { 31438620Skarels return 0; /* Maintenance channel */ 31538620Skarels } 31638620Skarels 31738620Skarels chan = dev; 31838620Skarels if (chan >= dk_nchan) { 31938620Skarels /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan); 32038620Skarels return ENXIO; 32138620Skarels } 32238620Skarels 32338620Skarels tp = &dkdev[chan]; 32438620Skarels if ((tp->d_state & DKOPEN) == 0) 32538620Skarels tp->dc_state = 0 ; 32641516Smckusick if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) { 32738620Skarels return EBUSY; 32838620Skarels } 32938620Skarels 33038620Skarels if ((m = dk_open(chan, (int (*)()) NULL)) < 0) 33138620Skarels return -m; 33238620Skarels 33338620Skarels 33438620Skarels /* 33538620Skarels * Channel 0 is reserved for maintenance. 33638620Skarels * An open on channel 0 is interpreted as a request 33738620Skarels * for an unused channel. 33838620Skarels */ 33938620Skarels if (chan==0) { 34038620Skarels char dname[30]; 34138620Skarels 34238620Skarels chan = m ; 34338620Skarels tp = &dkdev[chan] ; 34438620Skarels tp->dc_state = 0 ; 34538620Skarels /* 34643390Smckusick * throw away vnode for dk0. (/dev/dk/dial) 34738620Skarels * Build standard name of new one, and ask namei for it. 34838620Skarels */ 34945203Smckusick fp = u.u_ofile[-1 - p->p_dupfd]; 35038620Skarels 35138620Skarels dksnamer(dname, chan); 35238620Skarels /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */ 35343390Smckusick ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF; 35438620Skarels ndp->ni_segflg = UIO_SYSSPACE; 35538620Skarels ndp->ni_dirp = dname; 35643390Smckusick if (error = namei(ndp)) { 35738620Skarels (void) dk_close(chan) ; 35843390Smckusick return (error); 35938620Skarels } 36038620Skarels 36138620Skarels /* Give back old one */ 36243390Smckusick vp = (struct vnode *) fp->f_data; 36343390Smckusick VOP_LOCK(vp); 36443390Smckusick vput(vp); 36538620Skarels 36643390Smckusick vp = ndp->ni_vp; 36743390Smckusick fp->f_data = (caddr_t) vp; 36843390Smckusick VOP_UNLOCK(vp); 36938620Skarels } 37038620Skarels if ((tp->d_state & DKOPEN) == 0) { 37138620Skarels tp->d_state |= DKOPEN ; 37238620Skarels tp->dc_state = 0; 37338620Skarels tp->d_rmode = 0 ; 37438620Skarels tp->d_xctl = 0 ; 37538620Skarels tp->d_pgrp = 0; 37638620Skarels } 37738620Skarels tp->d_prot |= DpURP; 37838620Skarels return 0; 37938620Skarels } 38038620Skarels 38138620Skarels /* Policy decision here -- standard name of dk file known to this routine */ 38238620Skarels dksnamer(s, n) register char *s; 38338620Skarels { 38438620Skarels register char *p = "/dev/dk/dk"; 38538620Skarels 38638620Skarels while (*s++ = *p++) 38738620Skarels ; 38838620Skarels s--; 38938620Skarels *s++ = '0' + (n/100); n %= 100; 39038620Skarels *s++ = '0' + (n/10); n %= 10; 39138620Skarels *s++ = '0' + n; 39238620Skarels *s = '\0'; 39338620Skarels } 39438620Skarels 39538620Skarels /* 39638620Skarels * Close a channel: 39738620Skarels */ 39838620Skarels 39938620Skarels /*ARGSUSED*/ 40038620Skarels dkclose(dev, flag) 40138620Skarels dev_t dev; 40238620Skarels int flag; 40338620Skarels { 40438620Skarels register struct dkdev *tp; 40538620Skarels extern wakeup() ; 40638620Skarels extern brelse() ; 40738620Skarels short s, chan ; 40838620Skarels int i, cl = 0; 40938620Skarels 41038620Skarels chan = minor(dev); 41138620Skarels tp = &dkdev[chan]; 41238620Skarels if (chan == 1) { 41338620Skarels return 0; /* Maintenance channel */ 41438620Skarels } 41538620Skarels s = spl5() ; 41638620Skarels if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */ 41738620Skarels while (tp->d_bufct) { 41838620Skarels tp->d_state |= DKWAIT ; 41945184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, 0)) 42045184Skarels break; 42138620Skarels } 42238620Skarels } 42338620Skarels else if (tp->d_bufct) 42438620Skarels /* Hmm -- buffers queued. Let's wait 15 seconds max */ 42538620Skarels for (i = 0; tp->d_bufct && i < 15; i++) { 42638620Skarels tp->d_state |= DKWAIT ; 42745184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, hz)) 42845184Skarels break; 42938620Skarels } 43038620Skarels splx(s) ; 43138620Skarels tp->dc_state = 0; 43238620Skarels tp->d_rmode = 0; 43338620Skarels tp->d_prot &= ~DpURP; 43438620Skarels if(!tp->d_prot){ 43538620Skarels cl = dk_close(chan); 43638620Skarels (void) dk_takedown(chan); 43738620Skarels tp->d_state = 0; 43838620Skarels } 43938620Skarels return -cl; 44038620Skarels } 44138620Skarels 44238620Skarels dkread(dev, uio) 44338620Skarels dev_t dev ; 44438620Skarels struct uio *uio; 44538620Skarels { 44638620Skarels register struct dkdev *tp ; 44738620Skarels int err; 44838620Skarels 44938620Skarels M_ON(Mread) ; 45038620Skarels tp = &dkdev[minor(dev)] ; 45138620Skarels err = dkuread(minor(dev), uio) ; 45238620Skarels tp->d_rresid = uio->uio_resid ; 45338620Skarels M_OFF(Mread) ; 45438620Skarels return err; 45538620Skarels } 45638620Skarels 45738620Skarels 45838620Skarels dkwrite(dev, uio) 45938620Skarels struct uio *uio; 46038620Skarels dev_t dev ; 46138620Skarels { 46238620Skarels int err; 46338620Skarels 46438620Skarels M_ON(Mwrite) ; 46538620Skarels err = dkuwrite(minor(dev), uio) ; 46638620Skarels M_OFF(Mwrite) ; 46738620Skarels return err; 46838620Skarels } 46938620Skarels 47038620Skarels #endif 471