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 938620Skarels #include "param.h" 1038620Skarels #include "../machine/pte.h" 1138620Skarels #include "signal.h" 1238620Skarels #include "errno.h" 1338620Skarels #include "conf.h" 1438620Skarels #include "user.h" 1538620Skarels #include "ioctl.h" 1638620Skarels #include "tty.h" 1743390Smckusick #include "vnode.h" 1838620Skarels #include "file.h" 1938620Skarels #include "systm.h" 2038620Skarels #include "proc.h" 2138620Skarels #include "mbuf.h" 2238620Skarels #include "buf.h" 2338620Skarels #include "uio.h" 2438620Skarels #include "kernel.h" 2538620Skarels #include "dkit.h" 2638620Skarels #include "dkcmc.h" 2738620Skarels #include "dk.h" 2838620Skarels #include "dkdev.h" 2938620Skarels #include "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() ; 175*45184Skarels error = 0; 176*45184Skarels while (error == 0 && tp->dc_state & DKSETUP) 177*45184Skarels error = tsleep((caddr_t)tp, TTOPRI, ttopen, 0); 178*45184Skarels while (error == 0 && tsp->dc_state & DKSETUP) 179*45184Skarels error = tsleep((caddr_t)tsp, TTOPRI, ttopen, 0); 18038620Skarels splx(s) ; 181*45184Skarels if (error) 182*45184Skarels 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: 193*45184Skarels 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() ; 223*45184Skarels error = 0; 224*45184Skarels while (error == 0 && tp->dc_state & DKSETUP) 225*45184Skarels error = tsleep((caddr_t)(tp), TTOPRI, ttyout, 0) ; 22638620Skarels splx(s) ; 227*45184Skarels if (error) 228*45184Skarels 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; 30338620Skarels register struct nameidata *ndp = &u.u_nd; 30438620Skarels struct file *fp; 30538620Skarels int m; 30638620Skarels 30738620Skarels #ifdef lint 30838620Skarels (void) dk_xint(0, 0); 30938620Skarels #endif 31038620Skarels dev = minor(dev); 31138620Skarels if (dev == 1) { 31238620Skarels return 0; /* Maintenance channel */ 31338620Skarels } 31438620Skarels 31538620Skarels chan = dev; 31638620Skarels if (chan >= dk_nchan) { 31738620Skarels /* debug */ log(LOG_ERR, "dkopen bad: chan>=NDKCHANS : %d\n",chan); 31838620Skarels return ENXIO; 31938620Skarels } 32038620Skarels 32138620Skarels tp = &dkdev[chan]; 32238620Skarels if ((tp->d_state & DKOPEN) == 0) 32338620Skarels tp->dc_state = 0 ; 32441516Smckusick if (tp->d_state&DKXCLUDE && u.u_procp->p_ruid!=0) { 32538620Skarels return EBUSY; 32638620Skarels } 32738620Skarels 32838620Skarels if ((m = dk_open(chan, (int (*)()) NULL)) < 0) 32938620Skarels return -m; 33038620Skarels 33138620Skarels 33238620Skarels /* 33338620Skarels * Channel 0 is reserved for maintenance. 33438620Skarels * An open on channel 0 is interpreted as a request 33538620Skarels * for an unused channel. 33638620Skarels */ 33738620Skarels if (chan==0) { 33838620Skarels char dname[30]; 33938620Skarels 34038620Skarels chan = m ; 34138620Skarels tp = &dkdev[chan] ; 34238620Skarels tp->dc_state = 0 ; 34338620Skarels /* 34443390Smckusick * throw away vnode for dk0. (/dev/dk/dial) 34538620Skarels * Build standard name of new one, and ask namei for it. 34638620Skarels */ 34738620Skarels fp = u.u_ofile[u.u_r.r_val1]; 34838620Skarels 34938620Skarels dksnamer(dname, chan); 35038620Skarels /* log(LOG_ERR, "dname=%s chan=%d\n", dname, chan); */ 35143390Smckusick ndp->ni_nameiop = FOLLOW | LOOKUP | LOCKLEAF; 35238620Skarels ndp->ni_segflg = UIO_SYSSPACE; 35338620Skarels ndp->ni_dirp = dname; 35443390Smckusick if (error = namei(ndp)) { 35538620Skarels (void) dk_close(chan) ; 35643390Smckusick return (error); 35738620Skarels } 35838620Skarels 35938620Skarels /* Give back old one */ 36043390Smckusick vp = (struct vnode *) fp->f_data; 36143390Smckusick VOP_LOCK(vp); 36243390Smckusick vput(vp); 36338620Skarels 36443390Smckusick vp = ndp->ni_vp; 36543390Smckusick fp->f_data = (caddr_t) vp; 36643390Smckusick VOP_UNLOCK(vp); 36738620Skarels } 36838620Skarels if ((tp->d_state & DKOPEN) == 0) { 36938620Skarels tp->d_state |= DKOPEN ; 37038620Skarels tp->dc_state = 0; 37138620Skarels tp->d_rmode = 0 ; 37238620Skarels tp->d_xctl = 0 ; 37338620Skarels tp->d_pgrp = 0; 37438620Skarels } 37538620Skarels tp->d_prot |= DpURP; 37638620Skarels return 0; 37738620Skarels } 37838620Skarels 37938620Skarels /* Policy decision here -- standard name of dk file known to this routine */ 38038620Skarels dksnamer(s, n) register char *s; 38138620Skarels { 38238620Skarels register char *p = "/dev/dk/dk"; 38338620Skarels 38438620Skarels while (*s++ = *p++) 38538620Skarels ; 38638620Skarels s--; 38738620Skarels *s++ = '0' + (n/100); n %= 100; 38838620Skarels *s++ = '0' + (n/10); n %= 10; 38938620Skarels *s++ = '0' + n; 39038620Skarels *s = '\0'; 39138620Skarels } 39238620Skarels 39338620Skarels /* 39438620Skarels * Close a channel: 39538620Skarels */ 39638620Skarels 39738620Skarels /*ARGSUSED*/ 39838620Skarels dkclose(dev, flag) 39938620Skarels dev_t dev; 40038620Skarels int flag; 40138620Skarels { 40238620Skarels register struct dkdev *tp; 40338620Skarels extern wakeup() ; 40438620Skarels extern brelse() ; 40538620Skarels short s, chan ; 40638620Skarels int i, cl = 0; 40738620Skarels 40838620Skarels chan = minor(dev); 40938620Skarels tp = &dkdev[chan]; 41038620Skarels if (chan == 1) { 41138620Skarels return 0; /* Maintenance channel */ 41238620Skarels } 41338620Skarels s = spl5() ; 41438620Skarels if (u.u_signal[SIGKILL] != SIG_IGN) { /* detect close from exit() */ 41538620Skarels while (tp->d_bufct) { 41638620Skarels tp->d_state |= DKWAIT ; 417*45184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, 0)) 418*45184Skarels break; 41938620Skarels } 42038620Skarels } 42138620Skarels else if (tp->d_bufct) 42238620Skarels /* Hmm -- buffers queued. Let's wait 15 seconds max */ 42338620Skarels for (i = 0; tp->d_bufct && i < 15; i++) { 42438620Skarels tp->d_state |= DKWAIT ; 425*45184Skarels if (tsleep((caddr_t)(&tp->d_state), TTOPRI, ttyout, hz)) 426*45184Skarels break; 42738620Skarels } 42838620Skarels splx(s) ; 42938620Skarels tp->dc_state = 0; 43038620Skarels tp->d_rmode = 0; 43138620Skarels tp->d_prot &= ~DpURP; 43238620Skarels if(!tp->d_prot){ 43338620Skarels cl = dk_close(chan); 43438620Skarels (void) dk_takedown(chan); 43538620Skarels tp->d_state = 0; 43638620Skarels } 43738620Skarels return -cl; 43838620Skarels } 43938620Skarels 44038620Skarels dkread(dev, uio) 44138620Skarels dev_t dev ; 44238620Skarels struct uio *uio; 44338620Skarels { 44438620Skarels register struct dkdev *tp ; 44538620Skarels int err; 44638620Skarels 44738620Skarels M_ON(Mread) ; 44838620Skarels tp = &dkdev[minor(dev)] ; 44938620Skarels err = dkuread(minor(dev), uio) ; 45038620Skarels tp->d_rresid = uio->uio_resid ; 45138620Skarels M_OFF(Mread) ; 45238620Skarels return err; 45338620Skarels } 45438620Skarels 45538620Skarels 45638620Skarels dkwrite(dev, uio) 45738620Skarels struct uio *uio; 45838620Skarels dev_t dev ; 45938620Skarels { 46038620Skarels int err; 46138620Skarels 46238620Skarels M_ON(Mwrite) ; 46338620Skarels err = dkuwrite(minor(dev), uio) ; 46438620Skarels M_OFF(Mwrite) ; 46538620Skarels return err; 46638620Skarels } 46738620Skarels 46838620Skarels #endif 469